Commit e66962b4 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Merge pull request #953 from kmod/sqlalchemy_5

Test against an old 0.5-series version of sqlalchemy
parents 3fc72257 d6152af1
......@@ -40,3 +40,7 @@
[submodule "test/lib/pyinotify"]
path = test/lib/pyinotify
url = https://github.com/seb-m/pyinotify.git
[submodule "test/lib/sqlalchemy_0.5"]
path = test/lib/sqlalchemy_0.5
url = https://github.com/zzzeek/sqlalchemy
ignore = untracked
......@@ -2266,8 +2266,116 @@ ConcreteCompilerVariable* doIs(IREmitter& emitter, CompilerVariable* lhs, Compil
return boolFromI1(emitter, cmp);
}
template <typename T> struct UnboxedVal {
T val;
ConcreteCompilerVariable* boxed;
};
template <typename T, typename D> class UnboxedType : public ValuedCompilerType<UnboxedVal<T>*> {
public:
typedef UnboxedVal<T> Unboxed;
typedef typename ValuedCompilerType<UnboxedVal<T>*>::VAR VAR;
void drop(IREmitter& emitter, VAR* var) override final {
Unboxed* v = var->getValue();
if (v->boxed)
v->boxed->decvref(emitter);
static_cast<D*>(this)->_drop(emitter, v->val);
}
void grab(IREmitter& emitter, VAR* var) override final { RELEASE_ASSERT(0, ""); }
CompilerVariable* dup(VAR* var, DupCache& cache) override final {
CompilerVariable*& rtn = cache[var];
if (rtn == NULL) {
Unboxed* orig_v = var->getValue();
T val_duped = static_cast<D*>(this)->_dup(orig_v->val, cache);
CompilerVariable* box_duped = orig_v->boxed ? orig_v->boxed->dup(cache) : NULL;
assert(!box_duped || box_duped->getType() == box_duped->getType()->getBoxType());
rtn = new VAR(this, new Unboxed{ std::move(val_duped), static_cast<ConcreteCompilerVariable*>(box_duped) },
var->isGrabbed());
while (rtn->getVrefs() < var->getVrefs())
rtn->incvref();
}
return rtn;
}
bool canConvertTo(ConcreteCompilerType* other_type) override final {
return (other_type == UNKNOWN || other_type == this->getBoxType());
}
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var,
ConcreteCompilerType* other_type) override final {
assert(canConvertTo(other_type));
Unboxed* val = var->getValue();
ConcreteCompilerVariable* boxed = val->boxed;
if (!boxed) {
boxed = static_cast<D*>(this)->_makeConverted(emitter, val->val, this->getBoxType());
ASSERT(boxed->getType() == this->getBoxType(), "%s %s", boxed->getType()->debugName().c_str(),
this->getBoxType()->debugName().c_str());
val->boxed = boxed;
}
if (boxed->getType() != other_type) {
assert(other_type == UNKNOWN);
return boxed->makeConverted(emitter, other_type);
}
boxed->incvref();
return boxed;
}
// Serialization strategy is a bit silly for now: we will emit a bool saying whether we emitted the
// boxed or unboxed value. There's no reason that has to be in the serialization though (it could
// be in the metadata), and we shouldn't have to pad the smaller version to the size of the larger one.
int numFrameArgs() override final {
return 1 + std::max(static_cast<D*>(this)->_numFrameArgs(), this->getBoxType()->numFrameArgs());
}
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override final {
Unboxed* v = var->getValue();
int total_args = numFrameArgs();
int needed_args = stackmap_args.size() + total_args;
if (v->boxed) {
stackmap_args.push_back(getConstantInt(1, g.i64));
v->boxed->serializeToFrame(stackmap_args);
} else {
stackmap_args.push_back(getConstantInt(0, g.i64));
static_cast<D*>(this)->_serializeToFrame(v->val, stackmap_args);
}
while (stackmap_args.size() < needed_args)
stackmap_args.push_back(getConstantInt(0, g.i64));
}
Box* deserializeFromFrame(const FrameVals& vals) override final {
assert(vals.size() == numFrameArgs());
bool is_boxed = vals[0];
if (is_boxed) {
// TODO: inefficient
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + this->getBoxType()->numFrameArgs());
return this->getBoxType()->deserializeFromFrame(sub_vals);
} else {
FrameVals sub_vals(vals.begin() + 1, vals.begin() + 1 + static_cast<D*>(this)->_numFrameArgs());
return static_cast<D*>(this)->_deserializeFromFrame(sub_vals);
}
}
};
ConcreteCompilerType* BOXED_TUPLE;
class TupleType : public ValuedCompilerType<const std::vector<CompilerVariable*>*> {
class TupleType : public UnboxedType<const std::vector<CompilerVariable*>, TupleType> {
private:
std::string name;
const std::vector<CompilerType*> elt_types;
......@@ -2287,56 +2395,39 @@ private:
public:
typedef const std::vector<CompilerVariable*> VEC;
void assertMatches(const std::vector<CompilerVariable*>* v) override {
assert(v->size() == elt_types.size());
void assertMatches(Unboxed* v) override {
assert(v->val.size() == elt_types.size());
for (int i = 0; i < v->size(); i++) {
assert((*v)[i]->getType() == elt_types[i]);
for (int i = 0; i < v->val.size(); i++) {
assert((v->val)[i]->getType() == elt_types[i]);
}
}
std::string debugName() override { return name; }
void drop(IREmitter& emitter, VAR* var) override {
const std::vector<CompilerVariable*>* elts = var->getValue();
for (int i = 0; i < elts->size(); i++) {
(*elts)[i]->decvref(emitter);
void _drop(IREmitter& emitter, const VEC& val) {
for (int i = 0; i < val.size(); i++) {
val[i]->decvref(emitter);
}
}
void grab(IREmitter& emitter, VAR* var) override { RELEASE_ASSERT(0, ""); }
VEC _dup(const VEC& orig_elts, DupCache& cache) {
std::vector<CompilerVariable*> elts;
CompilerVariable* dup(VAR* var, DupCache& cache) override {
CompilerVariable*& rtn = cache[var];
if (rtn == NULL) {
std::vector<CompilerVariable*>* elts = new std::vector<CompilerVariable*>();
const std::vector<CompilerVariable*>* orig_elts = var->getValue();
for (int i = 0; i < orig_elts->size(); i++) {
elts->push_back((*orig_elts)[i]->dup(cache));
}
rtn = new VAR(this, elts, var->isGrabbed());
while (rtn->getVrefs() < var->getVrefs())
rtn->incvref();
for (int i = 0; i < orig_elts.size(); i++) {
elts.push_back(orig_elts[i]->dup(cache));
}
return rtn;
}
bool canConvertTo(ConcreteCompilerType* other_type) override {
return (other_type == UNKNOWN || other_type == BOXED_TUPLE);
return std::move(elts);
}
ConcreteCompilerVariable* makeConverted(IREmitter& emitter, VAR* var, ConcreteCompilerType* other_type) override {
ConcreteCompilerVariable* _makeConverted(IREmitter& emitter, const VEC& v, ConcreteCompilerType* other_type) {
assert(other_type == UNKNOWN || other_type == BOXED_TUPLE);
VEC* v = var->getValue();
std::vector<ConcreteCompilerVariable*> converted_args;
llvm::Value* nelts = llvm::ConstantInt::get(g.i64, v->size(), false);
llvm::Value* nelts = llvm::ConstantInt::get(g.i64, v.size(), false);
llvm::Value* _scratch = emitter.getScratch(v->size() * sizeof(void*));
llvm::Value* _scratch = emitter.getScratch(v.size() * sizeof(void*));
auto scratch = emitter.getBuilder()->CreateBitCast(_scratch, g.llvm_value_type_ptr->getPointerTo());
// First, convert all the args, before putting any in the scratch.
......@@ -2345,12 +2436,12 @@ public:
// TODO could probably do this better: create a scratch reservation that gets released
// at some point, so that we know which scratch space is still in use, so that we can handle
// multiple concurrent scratch users.
for (int i = 0; i < v->size(); i++) {
ConcreteCompilerVariable* converted = (*v)[i]->makeConverted(emitter, (*v)[i]->getBoxType());
for (int i = 0; i < v.size(); i++) {
ConcreteCompilerVariable* converted = v[i]->makeConverted(emitter, v[i]->getBoxType());
converted_args.push_back(converted);
}
for (int i = 0; i < v->size(); i++) {
for (int i = 0; i < v.size(); i++) {
llvm::Value* ptr = emitter.getBuilder()->CreateConstGEP1_32(scratch, i);
emitter.getBuilder()->CreateStore(converted_args[i]->getValue(), ptr);
}
......@@ -2375,7 +2466,8 @@ public:
assert(v->getType() == g.i64);
if (llvm::ConstantInt* ci = llvm::dyn_cast<llvm::ConstantInt>(v)) {
int64_t i = ci->getSExtValue();
auto elts = var->getValue();
Unboxed* v = var->getValue();
const VEC* elts = &v->val;
if (i >= 0 && i < elts->size()) {
CompilerVariable* rtn = (*elts)[i];
rtn->incvref();
......@@ -2409,7 +2501,7 @@ public:
}
ConcreteCompilerVariable* len(IREmitter& emitter, const OpInfo& info, VAR* var) override {
return new ConcreteCompilerVariable(INT, getConstantInt(var->getValue()->size(), g.i64), true);
return new ConcreteCompilerVariable(INT, getConstantInt(var->getValue()->val.size(), g.i64), true);
}
CompilerType* getattrType(BoxedString* attr, bool cls_only) override {
......@@ -2431,7 +2523,7 @@ public:
ConcreteCompilerVariable* converted_lhs = lhs->makeConverted(emitter, lhs->getConcreteType());
for (CompilerVariable* e : *var->getValue()) {
for (CompilerVariable* e : var->getValue()->val) {
// TODO: we could potentially avoid the identity tests if we know that either type has
// an __eq__ that is reflexive (returns True for the same object).
{
......@@ -2483,14 +2575,14 @@ public:
->callattr(emitter, info, attr, flags, args, keyword_names);
}
void serializeToFrame(VAR* var, std::vector<llvm::Value*>& stackmap_args) override {
for (auto v : *var->getValue()) {
v->serializeToFrame(stackmap_args);
void _serializeToFrame(const VEC& val, std::vector<llvm::Value*>& stackmap_args) {
for (auto elt : val) {
elt->serializeToFrame(stackmap_args);
}
}
Box* deserializeFromFrame(const FrameVals& vals) override {
assert(vals.size() == numFrameArgs());
Box* _deserializeFromFrame(const FrameVals& vals) {
assert(vals.size() == _numFrameArgs());
BoxedTuple* rtn = BoxedTuple::create(elt_types.size());
int rtn_idx = 0;
......@@ -2508,7 +2600,7 @@ public:
return rtn;
}
int numFrameArgs() override {
int _numFrameArgs() {
int rtn = 0;
for (auto e : elt_types)
rtn += e->numFrameArgs();
......@@ -2521,10 +2613,10 @@ public:
}
// Not sure if this is right:
for (auto e : *var->getValue())
for (auto e : var->getValue()->val)
e->incvref();
return *var->getValue();
return var->getValue()->val;
}
std::vector<CompilerType*> unpackTypes(int num_into) override {
......@@ -2548,8 +2640,8 @@ CompilerVariable* makeTuple(const std::vector<CompilerVariable*>& elts) {
}
TupleType* type = TupleType::make(elt_types);
const std::vector<CompilerVariable*>* alloc_elts = new std::vector<CompilerVariable*>(elts);
return new TupleType::VAR(type, alloc_elts, true);
auto alloc_var = new TupleType::Unboxed({ elts, NULL });
return new TupleType::VAR(type, alloc_var, true);
}
class UndefType : public ConcreteCompilerType {
......
......@@ -213,6 +213,7 @@ void setupThread() {
thread_lock_cls = BoxedClass::create(type_cls, object_cls, NULL, 0, 0, sizeof(BoxedThreadLock), false, "lock");
thread_lock_cls->tp_dealloc = BoxedThreadLock::threadLockDestructor;
thread_lock_cls->has_safe_tp_dealloc = true;
thread_lock_cls->instances_are_nonzero = true;
thread_lock_cls->giveAttr("__module__", boxString("thread"));
thread_lock_cls->giveAttr(
......
......@@ -593,6 +593,13 @@ static Box* wrapperDescrRepr(Box* _o) {
return PyString_FromFormat("<slot wrapper '%s' of '%s' objects>", name, getNameOfClass(wd->type));
}
static Box* wrapperobjectGetDoc(Box* b, void*) {
assert(b->cls == wrapperobject_cls);
auto s = static_cast<BoxedWrapperObject*>(b)->descr->wrapper->doc;
assert(s.size());
return boxString(s);
}
static Box* wrapperObjectRepr(Box* _o) {
assert(_o->cls == wrapperobject_cls);
BoxedWrapperObject* wp = static_cast<BoxedWrapperObject*>(_o);
......@@ -765,6 +772,8 @@ void setupDescr() {
"__call__", new BoxedFunction(boxRTFunction((void*)BoxedWrapperObject::__call__, UNKNOWN, 1, true, true)));
wrapperobject_cls->tpp_call.capi_val = BoxedWrapperObject::tppCall<CAPI>;
wrapperobject_cls->tpp_call.cxx_val = BoxedWrapperObject::tppCall<CXX>;
wrapperobject_cls->giveAttr("__doc__",
new (pyston_getset_cls) BoxedGetsetDescriptor(wrapperobjectGetDoc, NULL, NULL));
wrapperobject_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)wrapperObjectRepr, UNKNOWN, 1)));
wrapperobject_cls->freeze();
}
......
......@@ -796,6 +796,9 @@ void setupDict() {
dict_items_cls = BoxedClass::create(type_cls, object_cls, &BoxedDictView::gcHandler, 0, 0, sizeof(BoxedDictView),
false, "dict_items");
dict_iterator_cls->instances_are_nonzero = dict_keys_cls->instances_are_nonzero
= dict_values_cls->instances_are_nonzero = dict_items_cls->instances_are_nonzero = true;
dict_cls->tp_dealloc = &BoxedDict::dealloc;
dict_cls->has_safe_tp_dealloc = true;
......
......@@ -786,7 +786,8 @@ Box* listIAdd(BoxedList* self, Box* _rhs) {
}
Box* listAdd(BoxedList* self, Box* _rhs) {
if (_rhs->cls != list_cls) {
if (!PyList_Check(_rhs)) {
return NotImplemented;
raiseExcHelper(TypeError, "can only concatenate list (not \"%s\") to list", getTypeName(_rhs));
}
......
......@@ -3134,7 +3134,8 @@ Box* _callattrEntry(Box* obj, BoxedString* attr, CallattrFlags flags, Box* arg1,
if (S == CXX && rtn == NULL && !flags.null_on_nonexistent) {
raiseAttributeError(obj, attr->s());
} else if (S == CAPI) {
assert(rtn || PyErr_Occurred());
if (!rtn && !PyErr_Occurred())
raiseAttributeErrorCapi(obj, attr->s());
}
return rtn;
......
......@@ -3864,6 +3864,7 @@ void setupRuntime() {
none_cls->giveAttr("__repr__", new BoxedFunction(boxRTFunction((void*)noneRepr, STR, 1)));
none_cls->giveAttr("__nonzero__", new BoxedFunction(boxRTFunction((void*)noneNonzero, BOXED_BOOL, 1)));
none_cls->giveAttr("__doc__", None);
none_cls->tp_hash = (hashfunc)_Py_HashPointer;
none_cls->freeze();
......
import gc
import os
import sys
import subprocess
import traceback
ENV_NAME = os.path.abspath("sqlalchemy_0_5_test_env_" + os.path.basename(sys.executable))
if not os.path.exists(ENV_NAME) or os.stat(sys.executable).st_mtime > os.stat(ENV_NAME + "/bin/python").st_mtime:
# if True:
print "Creating virtualenv to install testing dependencies..."
VIRTUALENV_SCRIPT = os.path.dirname(__file__) + "/../lib//virtualenv/virtualenv.py"
try:
args = [sys.executable, VIRTUALENV_SCRIPT, "-p", sys.executable, ENV_NAME]
print "Running", args
subprocess.check_call(args)
subprocess.check_call([ENV_NAME + "/bin/pip", "install", "mock==1.0.0", "nose", "py==1.4.30"])
except:
print "Error occurred; trying to remove partially-created directory"
ei = sys.exc_info()
try:
subprocess.check_call(["rm", "-rf", ENV_NAME])
except Exception as e:
print e
raise ei[0], ei[1], ei[2]
# subprocess.check_call([os.path.abspath("sqlalchemy_test_env/bin/python"), "-c", "import py; print type(py); print py.builtin"])
SQLALCHEMY_DIR = os.path.abspath(os.path.dirname(__file__) + "/../lib/sqlalchemy_0.5")
TEST_DIR = SQLALCHEMY_DIR + "/test"
python_exe = os.path.abspath(ENV_NAME + "/bin/python")
sys.path.append(SQLALCHEMY_DIR + "/lib")
sys.path.insert(0, SQLALCHEMY_DIR)
sys.path.append(ENV_NAME + "/site-packages")
sys.path.append(ENV_NAME + "/lib/python2.7/site-packages")
os.chdir(SQLALCHEMY_DIR)
class Options(object):
pass
options = Options()
options.__dict__.update({'cover_tests': None, 'enable_plugin_allmodules': None, 'multiprocess_restartworker': False, 'loggingConfig': None, 'doctestExtension': None, 'doctest_tests': None, 'enable_plugin_xunit': None, 'debugBoth': False, 'logcapture_clear': False, 'truthless': False, 'stopOnError': False, 'enable_plugin_id': None, 'testNames': None, 'doctestOptions': None, 'exclude': [], 'byteCompile': True, 'log_debug': None, 'ignoreFiles': [], 'logcapture': True, 'tableopts': [], 'capture': True, 'xunit_testsuite_name': 'nosetests', 'logcapture_level': 'NOTSET', 'noncomparable': False, 'py3where': None, 'noSkip': False, 'enable_plugin_isolation': None, 'logcapture_filters': None, 'collect_only': None, 'failed': False, 'version': False, 'mockpool': None, 'eval_attr': None, 'log_info': None, 'dropfirst': None, 'include': [], 'cover_xml': None, 'enable_plugin_profile': None, 'debugErrors': False, 'files': None, 'multiprocess_timeout': 10, 'logcapture_format': '%(name)s: %(levelname)s: %(message)s', 'testMatch': '(?:^|[\\b_\\./-])[Tt]est', 'enable_plugin_sqlalchemy': True, 'traverseNamespace': False, 'reversetop': False, 'firstPackageWins': False, 'db': 'sqlite', 'require': [], 'cover_branches': None, 'xunit_file': 'nosetests.xml', 'noDeprecated': False, 'cover_xml_file': 'coverage.xml', 'showPlugins': False, 'cover_erase': None, 'multiprocess_workers': 0, 'mysql_engine': None, 'addPaths': True, 'testIdFile': '.noseids', 'dburi': None, 'enable_plugin_coverage': None, 'attr': None, 'profile_sort': 'cumulative', 'doctestFixtures': None, 'logcapture_datefmt': None, 'cover_packages': None, 'verbosity': 1, 'enable_plugin_doctest': None, 'profile_stats_file': None, 'cover_inclusive': None, 'includeExe': False, 'unhashable': False, 'debugFailures': False, 'cover_html': None, 'detailedErrors': None, 'debugLog': None, 'doctest_result_var': None, 'enginestrategy': None, 'debug': None, 'cover_html_dir': 'cover', 'cover_min_percentage': None, 'where': None, 'profile_restrict': None})
import sqlalchemy.test.noseplugin
plugin = sqlalchemy.test.noseplugin.NoseSQLAlchemy()
import optparse
plugin.options(optparse.OptionParser())
plugin.configure(options, None)
# XXX: monkey-patch this so we can support it
import sqlalchemy.engine.url
def get_dialect(self):
"""Return the SQLAlchemy database dialect class corresponding to this URL's driver name."""
try:
module = getattr(__import__('sqlalchemy.databases.%s' % self.drivername).databases, self.drivername)
return module.dialect
except ImportError:
# if sys.exc_info()[2].tb_next is None:
if True:
import pkg_resources
for res in pkg_resources.iter_entry_points('sqlalchemy.databases'):
if res.name == self.drivername:
return res.load()
raise
sqlalchemy.engine.url.URL.get_dialect = get_dialect
import glob
test_files = glob.glob(TEST_DIR + "/test*.py") + glob.glob(TEST_DIR + "/*/test*.py")
test_files.sort()
# These are the ones that pass on CPython (ie that we've stubbed enough of their testing
# infrastructure to run):
CPYTHON_PASSING = [
'test.base.test_dependency',
'test.base.test_except',
'test.base.test_utils',
'test.dialect.test_access',
'test.dialect.test_informix',
'test.dialect.test_sybase',
'test.engine.test_bind',
'test.engine.test_ddlevents',
'test.engine.test_execute',
'test.engine.test_metadata',
'test.engine.test_parseconnect',
'test.engine.test_pool',
'test.engine.test_reconnect',
'test.ex.test_examples',
'test.ext.test_associationproxy',
'test.ext.test_compiler',
'test.ext.test_orderinglist',
'test.orm.test_association',
'test.orm.test_assorted_eager',
'test.orm.test_attributes',
'test.orm.test_backref_mutations',
'test.orm.test_bind',
'test.orm.test_collection',
'test.orm.test_compile',
'test.orm.test_deprecations',
'test.orm.test_dynamic',
'test.orm.test_extendedattr',
'test.orm.test_instrumentation',
'test.sql.test_columns',
'test.sql.test_constraints',
'test.sql.test_labels',
'test.sql.test_quote',
'test.sql.test_rowcount',
'test.sql.test_select',
'test.sql.test_selectable',
'test.zblog.test_zblog',
]
MODULES_TO_TEST = [
]
FAILING = [
]
class SkipTest(Exception):
pass
# XXX we don't support this yet
import sqlalchemy.test.testing
def resolve_artifact_names(fn):
raise SkipTest()
sqlalchemy.test.testing.resolve_artifact_names = resolve_artifact_names
_gc_collect = gc.collect
def gc_collect():
# Not quite safe it seems to throw a SkipTest, since for some tests that will leave
# things in an inconsistent state
raise SystemError("Need to skip this test.")
gc.collect = gc_collect
MODULES_TO_TEST = CPYTHON_PASSING
MODULES_TO_TEST.remove('test.orm.test_extendedattr') # wants to set an int in the class locals
# MODULES_TO_TEST = ['test.ext.test_associationproxy']
# MODULES_TO_TEST = FAILING[:1]
passed = []
failed = []
for run_idx in xrange(1):
for fn in test_files:
assert fn.startswith(TEST_DIR + '/')
assert fn.endswith(".py")
mname = fn[len(SQLALCHEMY_DIR) + 1:-3].replace('/', '.')
if mname not in MODULES_TO_TEST:
continue
if mname == 'test.sql.test_select' and run_idx > 0:
continue
'''
# These tests are slow:
if 'test_pool' in fn:
continue
if 'test_reconnect' in fn:
continue
if 'test_associationproxy' in fn:
continue
'''
print '=' * 50
print mname
try:
try:
m = __import__(mname, fromlist=["__all__"])
except SkipTest:
print "(skipping)"
continue
for clsname in dir(m):
cls = getattr(m, clsname)
if clsname.startswith('_') or not clsname.endswith("Test") or not isinstance(cls, type):
continue
print "Running", cls
if hasattr(cls, "setup_class"):
cls.setup_class()
n = cls()
for t in dir(n):
if not t.startswith("test_"):
continue
# These tests should be marked as requiring predictable_pc
if (clsname == "SubclassGrowthTest" and t == "test_subclass"):
continue
if (clsname == "PoolTest" and t == "test_listeners"):
continue
if (clsname == "QueuePoolTest" and t == "test_mixed_close"):
continue
if (clsname == "MockReconnectTest" and (t == "test_reconnect" or t == 'test_conn_reusable' or
t == 'test_invalidate_trans')):
continue
if 'weak' in t or t.endswith('_gc'):
continue
if (clsname == 'ReconstitutionTest' and t == 'test_copy'):
continue
# This test is flaky since it depends on set ordering.
# (It causes sporadic failures in cpython as well.)
if clsname == "SelectTest" and t == 'test_binds':
continue
# This test relies on quick destruction of cursor objects,
# since it's not getting freed explicitly.
if 'test_bind' in mname and t == 'test_clauseelement':
continue
print "Running", t
try:
try:
n.setup()
except AttributeError:
pass
getattr(n, t)()
try:
n.teardown()
except AttributeError:
pass
except SkipTest:
pass
if hasattr(cls, "teardown_class"):
cls.teardown_class()
_gc_collect()
except Exception:
# raise
print mname, "FAILED"
traceback.print_exc()
failed.append(mname)
else:
print mname, "PASSED"
passed.append(mname)
print "passing:", passed
print "failing:", failed
print
if failed:
print "FAILED"
sys.exit(1)
else:
print "PASSED"
Subproject commit 6dbd034ca688a1b04d54706da115cf1e2ed1797e
......@@ -41,3 +41,15 @@ def f4(a, b):
assert id(a) == id(b)
for i in xrange(11000):
f4(1000, 1000)
# This applies to other data types as well. (maybe should call this test file something else)
def ident(x):
return x
def f5():
t = (1, 2, 3)
print ident(t) is t
for i in xrange(10):
f5()
......@@ -39,6 +39,8 @@ print MyList((1,2,3)) <= MyList((1,2,3))
print type(MyList((1, 2, 3)) * 1)
print [1] + MyList([3])
class ListWithInit(list):
def __init__(self, *args, **kwargs):
print "ListWithInit.__init__", args, kwargs
......
print None.__class__
print type(None).__doc__, None.__doc__
......@@ -18,3 +18,7 @@ try:
except TypeError as e:
print e
print "" + D()
# This also applies to list:
print [] + D()
......@@ -7,3 +7,8 @@ try:
print "".__add__(1)
except TypeError as e:
print e
try:
print [].__add__(1)
except TypeError as e:
print e
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment