Author: Brian Kearns <bdkea...@gmail.com> Branch: py3k Changeset: r62046:3306e356c360 Date: 2013-03-04 22:19 -0500 http://bitbucket.org/pypy/pypy/changeset/3306e356c360/
Log: merge default diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py --- a/lib_pypy/_sqlite3.py +++ b/lib_pypy/_sqlite3.py @@ -40,7 +40,7 @@ except OSError: continue else: - raise ImportError("Could not load C-library, tried: %s" %(names,)) + raise ImportError("Could not load C-library, tried: %s" % (names,)) # pysqlite version information version = "2.6.0" @@ -158,7 +158,7 @@ sqlite.sqlite3_value_type.argtypes = [c_void_p] sqlite.sqlite3_value_type.restype = c_int -sqlite.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int,c_void_p] +sqlite.sqlite3_bind_blob.argtypes = [c_void_p, c_int, c_void_p, c_int, c_void_p] sqlite.sqlite3_bind_blob.restype = c_int sqlite.sqlite3_bind_double.argtypes = [c_void_p, c_int, c_double] sqlite.sqlite3_bind_double.restype = c_int @@ -174,7 +174,7 @@ sqlite.sqlite3_bind_parameter_index.restype = c_int sqlite.sqlite3_bind_parameter_name.argtypes = [c_void_p, c_int] sqlite.sqlite3_bind_parameter_name.restype = c_char_p -sqlite.sqlite3_bind_text.argtypes = [c_void_p, c_int, TEXT, c_int,c_void_p] +sqlite.sqlite3_bind_text.argtypes = [c_void_p, c_int, TEXT, c_int, c_void_p] sqlite.sqlite3_bind_text.restype = c_int sqlite.sqlite3_busy_timeout.argtypes = [c_void_p, c_int] sqlite.sqlite3_busy_timeout.restype = c_int @@ -311,17 +311,18 @@ class Connection(object): + db = None + def __init__(self, database, timeout=5.0, detect_types=0, isolation_level="", check_same_thread=True, factory=None, cached_statements=100): self.db = c_void_p() if sqlite.sqlite3_open(database, byref(self.db)) != SQLITE_OK: raise OperationalError("Could not open database") if timeout is not None: - timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds + timeout = int(timeout * 1000) # pysqlite2 uses timeout in seconds sqlite.sqlite3_busy_timeout(self.db, timeout) self.text_factory = unicode_text_factory - self.closed = False self.statements = [] self.statement_counter = 0 self.row_factory = None @@ -349,7 +350,11 @@ if check_same_thread: self.thread_ident = thread_get_ident() - def _get_exception(self, error_code = None): + def __del__(self): + if self.db: + sqlite.sqlite3_close(self.db) + + def _get_exception(self, error_code=None): if error_code is None: error_code = sqlite.sqlite3_errcode(self.db) error_message = sqlite.sqlite3_errmsg(self.db) @@ -362,8 +367,8 @@ elif error_code == SQLITE_NOMEM: exc = MemoryError elif error_code in (SQLITE_ERROR, SQLITE_PERM, SQLITE_ABORT, SQLITE_BUSY, SQLITE_LOCKED, - SQLITE_READONLY, SQLITE_INTERRUPT, SQLITE_IOERR, SQLITE_FULL, SQLITE_CANTOPEN, - SQLITE_PROTOCOL, SQLITE_EMPTY, SQLITE_SCHEMA): + SQLITE_READONLY, SQLITE_INTERRUPT, SQLITE_IOERR, SQLITE_FULL, SQLITE_CANTOPEN, + SQLITE_PROTOCOL, SQLITE_EMPTY, SQLITE_SCHEMA): exc = OperationalError elif error_code == SQLITE_CORRUPT: exc = DatabaseError @@ -441,6 +446,7 @@ def _get_isolation_level(self): return self._isolation_level + def _set_isolation_level(self, val): if val is None: self.commit() @@ -517,7 +523,9 @@ self._reset_cursors() def _check_closed(self): - if getattr(self, 'closed', True): + if self.db is None: + raise ProgrammingError("Base Connection.__init__ not called.") + if not self.db: raise ProgrammingError("Cannot operate on a closed database.") def __enter__(self): @@ -530,23 +538,23 @@ self.rollback() def _get_total_changes(self): + self._check_closed() return sqlite.sqlite3_total_changes(self.db) total_changes = property(_get_total_changes) def close(self): self._check_thread() - if self.closed: - return + for statement in self.statements: obj = statement() if obj is not None: obj.finalize() - self.closed = True - ret = sqlite.sqlite3_close(self.db) - self._reset_cursors() - if ret != SQLITE_OK: - raise self._get_exception(ret) + if self.db: + ret = sqlite.sqlite3_close(self.db) + if ret != SQLITE_OK: + raise self._get_exception(ret) + self.db.value = 0 def create_collation(self, name, callback): self._check_thread() @@ -571,7 +579,6 @@ c_collation_callback = COLLATION(collation_callback) self._collations[name] = c_collation_callback - ret = sqlite.sqlite3_create_collation(self.db, name, SQLITE_UTF8, None, @@ -655,7 +662,7 @@ aggregate_ptr = cast( sqlite.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), + context, sizeof(c_ssize_t)), POINTER(c_ssize_t)) if not aggregate_ptr[0]: @@ -684,7 +691,7 @@ aggregate_ptr = cast( sqlite.sqlite3_aggregate_context( - context, sizeof(c_ssize_t)), + context, sizeof(c_ssize_t)), POINTER(c_ssize_t)) if aggregate_ptr[0]: @@ -729,6 +736,7 @@ DML, DQL, DDL = range(3) + class CursorLock(object): def __init__(self, cursor): self.cursor = cursor @@ -743,6 +751,8 @@ class Cursor(object): + initialized = False + def __init__(self, con): if not isinstance(con, Connection): raise TypeError @@ -757,9 +767,13 @@ self.statement = None self.reset = False self.locked = False + self.closed = False + self.initialized = True def _check_closed(self): - if not getattr(self, 'connection', None): + if not self.initialized: + raise ProgrammingError("Base Cursor.__init__ not called.") + if self.closed: raise ProgrammingError("Cannot operate on a closed cursor.") self.connection._check_thread() self.connection._check_closed() @@ -915,31 +929,40 @@ return sqlite.sqlite3_last_insert_rowid(self.connection.db) def close(self): - if not self.connection: - return - self._check_closed() + self.connection._check_thread() + self.connection._check_closed() if self.statement: self.statement.reset() self.statement = None - self.connection.cursors.remove(weakref.ref(self)) - self.connection = None + self.closed = True + + def __del__(self): + if self.initialized: + if self.statement: + self.statement.reset() + try: + self.connection.cursors.remove(weakref.ref(self)) + except ValueError: + pass def setinputsizes(self, *args): pass + def setoutputsize(self, *args): pass - description = property(_getdescription) lastrowid = property(_getlastrowid) + class Statement(object): + statement = None + def __init__(self, connection, sql): - self.statement = None if not isinstance(sql, str): raise ValueError("sql must be a string") self.con = connection - self.sql = sql # DEBUG ONLY + self.sql = sql # DEBUG ONLY first_word = self._statement_kind = sql.lstrip().split(" ")[0].upper() if first_word in ("INSERT", "UPDATE", "DELETE", "REPLACE"): self.kind = DML @@ -1141,8 +1164,8 @@ self.in_use = True def __del__(self): - sqlite.sqlite3_finalize(self.statement) - self.statement = None + if self.statement: + sqlite.sqlite3_finalize(self.statement) def _get_description(self): if self.kind == DML: @@ -1154,6 +1177,7 @@ desc.append((name, None, None, None, None, None, None)) return desc + class Row(object): def __init__(self, cursor, values): self.description = cursor.description @@ -1187,6 +1211,7 @@ def __hash__(self): return hash(tuple(self.description)) ^ hash(tuple(self.values)) + def _check_remaining_sql(s): state = "NORMAL" for char in s: @@ -1229,8 +1254,9 @@ return 1 return 0 + def _convert_params(con, nargs, params): - _params = [] + _params = [] for i in range(nargs): typ = sqlite.sqlite3_value_type(params[i]) if typ == SQLITE_INTEGER: @@ -1254,6 +1280,7 @@ _params.append(val) return _params + def _convert_result(con, val): if val is None: sqlite.sqlite3_result_null(con) @@ -1270,6 +1297,7 @@ else: raise NotImplementedError + def function_callback(real_cb, context, nargs, c_params): params = _convert_params(context, nargs, c_params) try: @@ -1304,15 +1332,19 @@ converters = {} adapters = {} + class PrepareProtocol(object): pass + def register_adapter(typ, callable): adapters[typ, PrepareProtocol] = callable + def register_converter(name, callable): converters[name.upper()] = callable + def register_adapters_and_converters(): def adapt_date(val): return val.isoformat() @@ -1332,16 +1364,15 @@ microseconds = int(timepart_full[1]) else: microseconds = 0 - - val = datetime.datetime(year, month, day, hours, minutes, seconds, microseconds) - return val - + return datetime.datetime(year, month, day, + hours, minutes, seconds, microseconds) register_adapter(datetime.date, adapt_date) register_adapter(datetime.datetime, adapt_datetime) register_converter("date", convert_date) register_converter("timestamp", convert_timestamp) + def adapt(val, proto=PrepareProtocol): # look for an adapter in the registry adapter = adapters.get((type(val), proto), None) @@ -1372,6 +1403,7 @@ register_adapters_and_converters() + def OptimizedUnicode(s): try: val = str(s, "ascii").encode("ascii") diff --git a/pypy/module/test_lib_pypy/pyrepl/test_basic.py b/pypy/module/test_lib_pypy/pyrepl/test_basic.py --- a/pypy/module/test_lib_pypy/pyrepl/test_basic.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_basic.py @@ -76,6 +76,8 @@ ( 'accept', ['cd '])]) +# interrupt uses os.kill which doesn't go through signal handlers on windows +@pytest.mark.skipif("os.name == 'nt'") def test_interrupt(): with pytest.raises(KeyboardInterrupt): read_spec([('interrupt', [''])]) diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -45,6 +45,8 @@ ] read_spec(spec, HistoricalTestReader) + +@pytest.mark.skipif("os.name != 'posix'") def test_signal_failure(monkeypatch): import os import pty diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,9 +1,12 @@ -from pyrepl.readline import _ReadlineWrapper -import os -import pty +import pytest +@pytest.mark.skipif("os.name != 'posix'") def test_raw_input(): + import os + import pty + from pyrepl.readline import _ReadlineWrapper + master, slave = pty.openpty() readline_wrapper = _ReadlineWrapper(slave, slave) os.write(master, b'input\n') diff --git a/pypy/module/test_lib_pypy/test_sqlite3.py b/pypy/module/test_lib_pypy/test_sqlite3.py --- a/pypy/module/test_lib_pypy/test_sqlite3.py +++ b/pypy/module/test_lib_pypy/test_sqlite3.py @@ -4,10 +4,12 @@ if sys.version_info < (2, 7): skip("lib_pypy._sqlite3 doesn't work with python < 2.7") +import pytest +from lib_pypy import _sqlite3 + def test_list_ddl(): """From issue996. Mostly just looking for lack of exceptions.""" - from lib_pypy._sqlite3 import connect - connection = connect(':memory:') + connection = _sqlite3.connect(':memory:') cursor = connection.cursor() cursor.execute('CREATE TABLE foo (bar INTEGER)') result = list(cursor) @@ -18,3 +20,63 @@ cursor.execute('SELECT * FROM foo') result = list(cursor) assert result == [(42,)] + +def test_total_changes_after_close(): + con = _sqlite3.connect(':memory:') + con.close() + pytest.raises(_sqlite3.ProgrammingError, "con.total_changes") + +def test_connection_check_init(): + class Connection(_sqlite3.Connection): + def __init__(self, name): + pass + + con = Connection(":memory:") + e = pytest.raises(_sqlite3.ProgrammingError, "con.cursor()") + assert '__init__' in e.value.message + +def test_cursor_check_init(): + class Cursor(_sqlite3.Cursor): + def __init__(self, name): + pass + + con = _sqlite3.connect(":memory:") + cur = Cursor(con) + e = pytest.raises(_sqlite3.ProgrammingError, "cur.execute('select 1')") + assert '__init__' in e.value.message + +def test_cursor_after_close(): + con = _sqlite3.connect(':memory:') + cur = con.execute('select 1') + cur.close() + con.close() + pytest.raises(_sqlite3.ProgrammingError, "cur.close()") + +@pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") +def test_cursor_del(): + con = _sqlite3.connect(':memory:') + cur = con.execute('select 1') + stmt = cur.statement + cur.close() + cur = con.execute('select 1') + assert cur.statement is stmt + del cur; import gc; gc.collect(); gc.collect() + cur = con.execute('select 1') + assert cur.statement is stmt + +@pytest.mark.skipif("not hasattr(sys, 'pypy_translation_info')") +def test_connection_del(tmpdir): + """For issue1325.""" + import gc + + def open_many(cleanup): + con = [] + for i in range(1024): + con.append(_sqlite3.connect(str(tmpdir.join('test.db')))) + if cleanup: + con[i] = None + gc.collect(); gc.collect() + + pytest.raises(_sqlite3.OperationalError, open_many, False) + gc.collect(); gc.collect() + open_many(True) _______________________________________________ pypy-commit mailing list pypy-commit@python.org http://mail.python.org/mailman/listinfo/pypy-commit