Skip to content

Commit

Permalink
Release 2.0.2
Browse files Browse the repository at this point in the history
  • Loading branch information
pcisar committed Sep 30, 2021
1 parent ad4956f commit 1634fe1
Show file tree
Hide file tree
Showing 9 changed files with 103 additions and 82 deletions.
48 changes: 27 additions & 21 deletions fdb/fbcore.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@
PYTHON_MAJOR_VER = sys.version_info[0]

#: Current driver version
__version__ = '2.0.1'
__version__ = '2.0.2'

apilevel = '2.0'
threadsafety = 1
Expand Down Expand Up @@ -478,7 +478,10 @@ def tebarray_factory(size):

def is_dead_proxy(obj):
"Return True if object is a dead :func:`weakref.proxy`."
return isinstance(obj, weakref.ProxyType) and not dir(obj)
try:
return isinstance(obj, weakref.ProxyType) and not dir(obj)
except ReferenceError:
return True

def b2u(st, charset):
"Decode to unicode if charset is defined. For conversion of result set data."
Expand Down Expand Up @@ -811,7 +814,7 @@ def build_dpb(user, password, sql_dialect, role, charset, buffers,
raise ProgrammingError("SQl Dialect must be either 1, 2 or 3")

if ((not dsn and not host and not database) or
(dsn and (host or database)) or
(dsn and (host or database)) or
(host and not database)):
raise ProgrammingError("Must supply one of:\n"
" 1. keyword argument dsn='host:/path/to/database'\n"
Expand Down Expand Up @@ -935,7 +938,7 @@ def create_database(sql='', sql_dialect=3, dsn='', user=None, password=None,
raise ProgrammingError("SQl Dialect must be either 1, 2 or 3")

if ((not dsn and not host and not database) or
(dsn and (host or database)) or
(dsn and (host or database)) or
(host and not database)):
raise ProgrammingError("Must supply one of:\n"
" 1. keyword argument dsn='host:/path/to/database'\n"
Expand Down Expand Up @@ -1321,7 +1324,7 @@ def _determine_field_precision(self, sqlvar):
return 0
# Special case for automatic RDB$DB_KEY fields.
if ((sqlvar.sqlname_length == 6 and sqlvar.sqlname == 'DB_KEY') or
(sqlvar.sqlname_length == 10 and sqlvar.sqlname == 'RDB$DB_KEY')):
(sqlvar.sqlname_length == 10 and sqlvar.sqlname == 'RDB$DB_KEY')):
return 0
precision = self.__precision_cache.get((sqlvar.relname,
sqlvar.sqlname))
Expand Down Expand Up @@ -2563,7 +2566,7 @@ def __get_rowcount(self):
res_walk += short_size
count = bytes_to_uint(info[res_walk:res_walk + size])
if ((cur_count_type == isc_info_req_select_count and self.statement_type == isc_info_sql_stmt_select)
or (cur_count_type == isc_info_req_insert_count and self.statement_type == isc_info_sql_stmt_insert)
or (cur_count_type == isc_info_req_insert_count and self.statement_type == isc_info_sql_stmt_insert)
or (cur_count_type == isc_info_req_update_count and self.statement_type == isc_info_sql_stmt_update)
or (cur_count_type == isc_info_req_delete_count and self.statement_type == isc_info_sql_stmt_delete)):
result = count
Expand Down Expand Up @@ -2707,7 +2710,7 @@ def __xsqlda2tuple(self, xsqlda):
#value = sqlvar.sqldata[:sqlvar.sqllen]
### Todo: verify handling of P version differences
if ((self.__charset or PYTHON_MAJOR_VER == 3) and
sqlvar.sqlsubtype != 1): # non OCTETS
sqlvar.sqlsubtype != 1): # non OCTETS
value = b2u(value, self.__python_charset)
# CHAR with multibyte encoding requires special handling
if sqlvar.sqlsubtype in (4, 69): # UTF8 and GB18030
Expand All @@ -2726,7 +2729,7 @@ def __xsqlda2tuple(self, xsqlda):
else:
value = str(sqlvar.sqldata[2:2 + size])
if ((self.__charset or PYTHON_MAJOR_VER == 3) and
sqlvar.sqlsubtype != 1): # non OCTETS
sqlvar.sqlsubtype != 1): # non OCTETS
value = b2u(value, self.__python_charset)
elif vartype == SQL_BOOLEAN:
value = bool(bytes_to_int(sqlvar.sqldata.contents.value))
Expand Down Expand Up @@ -2810,7 +2813,7 @@ def __xsqlda2tuple(self, xsqlda):
offset += length + 2
# Does the blob size exceeds treshold for streamed one?
if ((self.__streamed_blob_treshold >= 0) and
(blob_length > self.__streamed_blob_treshold)):
(blob_length > self.__streamed_blob_treshold)):
# Stream BLOB
value = BlobReader(blobid, self.cursor._connection._db_handle,
self.cursor._transaction._tr_handle,
Expand Down Expand Up @@ -2905,7 +2908,7 @@ def __extract_db_array_to_list(self, esize, dtype, subtype, scale, dim, dimensio
val = ctypes.string_at(buf[bufpos:bufpos+esize], esize)
### Todo: verify handling of P version differences
if ((self.__charset or PYTHON_MAJOR_VER == 3)
and subtype != 1): # non OCTETS
and subtype != 1): # non OCTETS
val = b2u(val, self.__python_charset)
# CHAR with multibyte encoding requires special handling
if subtype in (4, 69): # UTF8 and GB18030
Expand All @@ -2918,7 +2921,7 @@ def __extract_db_array_to_list(self, esize, dtype, subtype, scale, dim, dimensio
elif dtype in (blr_varying, blr_varying2):
val = ctypes.string_at(buf[bufpos:bufpos+esize])
if ((self.__charset or PYTHON_MAJOR_VER == 3) and
subtype != 1): # non OCTETS
subtype != 1): # non OCTETS
val = b2u(val, self.__python_charset)
elif dtype in (blr_short, blr_long, blr_int64):
val = bytes_to_int(buf[bufpos:bufpos+esize])
Expand Down Expand Up @@ -3129,7 +3132,7 @@ def __tuple2xsqlda(self, xsqlda, parameters):
sqlvar.sqlind = ctypes.pointer(ISC_SHORT(0))
# Fill in value by type
if ((vartype != SQL_BLOB and isinstance(value, (StringType, UnicodeType)))
or vartype in [SQL_TEXT, SQL_VARYING]):
or vartype in [SQL_TEXT, SQL_VARYING]):
# Place for Implicit Conversion of Input Parameters
# to Strings
if not isinstance(value, (UnicodeType, StringType, ibase.mybytes)):
Expand Down Expand Up @@ -3341,7 +3344,7 @@ def _close(self):
if (not connection) or (connection and not connection.closed):
api.isc_dsql_free_statement(self._isc_status, stmt_handle, ibase.DSQL_drop)
if (db_api_error(self._isc_status) and
(self._isc_status[1] not in [335544528, 335544485])):
(self._isc_status[1] not in [335544528, 335544485])):
raise exception_from_status(DatabaseError, self._isc_status,
"Error while closing SQL statement:")
def _execute(self, parameters=None):
Expand All @@ -3364,7 +3367,7 @@ def _execute(self, parameters=None):
xsqlda_in = None
# Execute the statement
if ((self.statement_type == isc_info_sql_stmt_exec_procedure) and
(self._out_sqlda.sqld > 0)):
(self._out_sqlda.sqld > 0)):
# NOTE: We have to pass xsqlda_out only for statements that return
# single row
xsqlda_out = ctypes.cast(ctypes.pointer(self._out_sqlda), XSQLDA_PTR)
Expand Down Expand Up @@ -3548,8 +3551,11 @@ def next(self):
def __iter__(self):
return self
def __valid_ps(self):
return (self._ps is not None) and not (isinstance(self._ps, weakref.ProxyType)
and not dir(self._ps))
try:
return (self._ps is not None) and not (isinstance(self._ps, weakref.ProxyType)
and not dir(self._ps))
except ReferenceError:
return False
def __get_description(self):
if self.__valid_ps():
return self._ps.description
Expand Down Expand Up @@ -4094,11 +4100,11 @@ def execute_immediate(self, sql):
sql = b(sql, con._python_charset)
xsqlda = xsqlda_factory(1)

# For yet unknown reason, the isc_dsql_execute_immediate segfaults when
# NULL (None) is passed as XSQLDA, so we provide one here
# For yet unknown reason, the isc_dsql_execute_immediate segfaults when
# NULL (None) is passed as XSQLDA, so we provide one here
api.isc_dsql_execute_immediate(self._isc_status, con._db_handle, self._tr_handle,
len(sql), sql, con.sql_dialect,
ctypes.cast(ctypes.pointer(xsqlda), XSQLDA_PTR))
ctypes.cast(ctypes.pointer(xsqlda), XSQLDA_PTR))
if db_api_error(self._isc_status):
raise exception_from_status(DatabaseError, self._isc_status,
"Error while executing SQL statement:")
Expand Down Expand Up @@ -4636,7 +4642,7 @@ def __drop_transaction(self):
def __require_transaction_state(self, must_be_active, err_msg=''):
transaction = self._transaction
if ((must_be_active and transaction is None) or
(not must_be_active and (transaction is not None and transaction.active))):
(not must_be_active and (transaction is not None and transaction.active))):
raise ProgrammingError(err_msg)
def __require_non_empty_group(self, operation_name):
if self.count() == 0:
Expand Down Expand Up @@ -5486,7 +5492,7 @@ def __setitem__(self, key, value):
else:
other_values = None
if ((not isinstance(value, tuple))
or len(value) != 2
or len(value) != 2
or value[0] not in (isc_tpb_shared, isc_tpb_protected, isc_tpb_exclusive)
or value[1] not in (isc_tpb_lock_read, isc_tpb_lock_write)):
raise ValueError("""Table reservation entry must be a 2-tuple of the following form:
Expand Down
16 changes: 9 additions & 7 deletions fdb/gstat.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import datetime
import weakref
from collections import namedtuple
from locale import LC_ALL, getlocale, setlocale, resetlocale
from locale import LC_ALL, LC_CTYPE, getlocale, setlocale, resetlocale
import sys

GSTAT_25 = 2
Expand All @@ -52,6 +52,8 @@
FillDistribution = namedtuple('FillDistribution', 'd20,d40,d50,d80,d100')
Encryption = namedtuple('Encryption', 'pages,encrypted,unencrypted')

_LOCALE_ = LC_CTYPE if sys.version_info[0] == 3 else LC_ALL

def empty_str(str_):
"Return True if string is empty (whitespace don't count) or None"
return true if str_ is None else str_.strip() == ''
Expand Down Expand Up @@ -573,12 +575,12 @@ def parse_encryption(line):
#
line_no = 0
step = 0 # Look for sections and skip empty lines
locale = getlocale(_LOCALE_)
try:
locale = getlocale(LC_ALL)
if sys.platform == 'win32':
setlocale(LC_ALL, 'English_United States')
setlocale(_LOCALE_, 'English_United States')
else:
setlocale(LC_ALL, 'en_US')
setlocale(_LOCALE_, 'en_US')
# Skip empty lines at start
for line in (x.strip() for x in lines):
line_no += 1
Expand Down Expand Up @@ -654,9 +656,9 @@ def parse_encryption(line):
finally:
if locale[0] is None:
if sys.platform == 'win32':
setlocale(LC_ALL, '')
setlocale(_LOCALE_, '')
else:
resetlocale(LC_ALL)
resetlocale(_LOCALE_)
else:
setlocale(LC_ALL, locale)
setlocale(_LOCALE_, locale)
return db
16 changes: 9 additions & 7 deletions fdb/log.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,13 @@
from fdb import ParseError
from datetime import datetime
from collections import namedtuple
from locale import LC_ALL, getlocale, setlocale, resetlocale
from locale import LC_ALL, LC_CTYPE, getlocale, setlocale, resetlocale
import sys

LogEntry = namedtuple('LogEntry', 'source_id,timestamp,message')

_LOCALE_ = LC_CTYPE if sys.version_info[0] == 3 else LC_ALL

def parse(lines):
"""Parse Firebird server log and yield named tuples describing individual log entries/events.
Expand All @@ -38,11 +40,11 @@ def parse(lines):
fdb.ParseError: When any problem is found in input stream.
"""
line_no = 0
locale = getlocale() # (LC_ALL)
locale = getlocale() # (_LOCALE_)
if sys.platform == 'win32':
setlocale(LC_ALL, 'English_United States')
setlocale(_LOCALE_, 'English_United States')
else:
setlocale(LC_ALL, 'en_US')
setlocale(_LOCALE_, 'en_US')
try:
clean = (line.strip() for line in lines)
entry_lines = []
Expand Down Expand Up @@ -78,8 +80,8 @@ def parse(lines):
finally:
if locale[0] is None:
if sys.platform == 'win32':
setlocale(LC_ALL, '')
setlocale(_LOCALE_, '')
else:
resetlocale(LC_ALL)
resetlocale(_LOCALE_)
else:
setlocale(LC_ALL, locale)
setlocale(_LOCALE_, locale)
2 changes: 1 addition & 1 deletion fdb/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -1084,7 +1084,7 @@ def get_metadata_ddl(self, sections=SCRIPT_DEFAULT_ORDER):
Sections identifiers are represented by `SCRIPT_*` contants defined in schema module.
Sections are created in the order of occerence in list. Uses `SCRIPT_DEFAULT_ORDER` list when sections are not specified.
Sections are created in the order of occurence in list. Uses `SCRIPT_DEFAULT_ORDER` list when sections are not specified.
"""
def order_by_dependency(items, get_dependencies):
ordered = []
Expand Down
3 changes: 2 additions & 1 deletion fdb/services.py
Original file line number Diff line number Diff line change
Expand Up @@ -828,7 +828,8 @@ def get_statistics(self, database, show_only_db_log_pages=0,
tables = (tables,)
cmdline = ['-t']
cmdline.extend(tables)
req_buf.add_string(ibase.isc_spb_command_line, ' '.join(cmdline))
for item in cmdline:
req_buf.add_string(ibase.isc_spb_command_line, item)
self._act(req_buf)
self.__fetching = True
self.__eof = False
Expand Down
Empty file modified setup.py
100755 → 100644
Empty file.

0 comments on commit 1634fe1

Please sign in to comment.