API Reference¶
The central object in Sibilla is the sibilla.Database
class. Any
application that wants to use Sibilla to extract and manipulate the data stored
in an Oracle database has to create an instance of this class, either directly
or via a subclass that implements the customisation described in this
reference.
sibilla module¶
-
exception
sibilla.
ConnectionError
¶ Database connection error.
-
class
sibilla.
CursorRow
(cursor, row, columns=None)¶ Turn a row of data into a dictionary/list-like object.
This default implementation of the
RowWrapper
abstract base class allows accessing row values both as attributes as well as tuple entries.For example, if a query returns the tuple
(10, None, "Hello")
and the corresponding columns are namedA
,B
andC
, by wrapping it withCursorRow
you get an objectrow
that gives you the attributesa
/A
,b
/B
andc
/C
for whichrow.a = row[0]
,row.B = row[1]
androw.c = row[2]
.-
static
from_cursor
(cursor)¶ Convert the rows of a cursor into richer Python objects.
Subclasses must implement this method in order to instruct the
Database.fetch_all()
method on how to wrap the result from the cursor.Parameters: cursor ( cx_Oracle.Cursor
) – The cursor with the results ready to be fetched.Returns: the wrapped rows. Return type: generator
-
static
from_list
(cursor, data)¶ Convert the elements in the data list into richer Python objects.
Subclasses must implement htis method in order to instruct the fetch_many method on how to wrap the results in the data list.
Parameters: - cursor (
cx_Oracle.Cursor
) – The cursor used to obtain the data. - data (
list
) – The list of rows obtained from the given cursor.
Returns: the wrapped rows.
Return type: list
- cursor (
-
static
-
exception
sibilla.
CursorRowError
¶ Cursor row wrapper error.
-
class
sibilla.
Database
(*args, **kwargs)¶ The Database class.
A subclass of the DB API specification-compliant cx_Oracle.Connection object, extended with additional features of Oracle Databases.
Objects of this kind identify the database connection with the database itself. This is because the
Database
class offers the capability of accessing Oracle stored object in a Pythonic way. Typical examples are data access from tables and views, which would normally require the user to embed “alien” SQL queries in Python code. The same would be true if the user wishes to call a stored function or procedure. Traditionally, this would be done by writing a block of PL/SQL code or via thecx_Oracle.Cursor.callfunc()
andcx_Oracle.Cursor.callproc()
methods. Sibilla allows you to call them as if they were plain Python methods of anyDatabase
instance.Example
To create an Database instance, import
Database
fromsibilla
and passusername
,password
anddsn
to it (plus any other optional argument accepted by the constructor ofcx_Oracle.Connection
):>>> from sibilla import Database >>> db = Database(username, password, dsn=TNS)
The
Database
class offers a built-in look-up for Oracle objects, like Tables, Views, Functions, Procedures and Packages.Example
To create a reference to a table called
COUNTRY
in the Oracle database, access the attributecountry
from theDatabase
instance:>>> db.country <table 'COUNTRY'>
A table is a special instance of a
sibilla.dataset.DataSet
object, which allows you to perform basic SQL queries in a Pythonic way, without writing a single line of SQL code. See the sections onsiblla.dataset.DataSet
andsibilla.table.Table
for more details.In a similar way one can access stored functions, procedures and packages. For functions and procedures stored in a package, the code will try to figure out whether the sought object is a function or a procedure. When there are overloaded objects that cannot be resolved, one can explicitly call a procedure or a function by accessing the
proc
andfunc
attributes of asibilla.package.Package
instance.Example
Assume that the database has a stored package called
foo
containing (overloaded) procedures and functions namedbar
. To getfoo.bar
as a procedure one has to use:>>> db.foo.proc.bar <procedure 'BAR' from <package 'FOO'>>
Similarly, to get bar as a function,
>>> db.foo.func.bar <function 'BAR' from <package 'FOO'>>
When there are no ambiguities like in the previous case (e.g. there are only functions or only procedures named
bar
), one can simply use>>> db.foo.bar
One can then call stored functions and procedures as normal Python functions/methods, using both positional and keyword arguments.
>>> db.foo.bar(42) 'The answer is 42. So long and thanks for all the fish!'
-
class
Scope
¶ Oracle Data Dictionary scopes.
This type is used to specify which scope the database look-up must use when looking up stored objects. Choose between
ALL
,DBA
andUSER
. For more details on the meaning of these scopes, please refer to the Oracle documentation.The
ALL
scope is set by default. However, if you do not make use of many objects from different schema other than the current one, consider using theUSER
scope instead. This will make object look-ups faster as the search is restricted to a smaller view.
-
fetch_all
(stmt: str, *args, **kwargs) → Generator[[Any, NoneType], NoneType]¶ Fetch all rows from the execution of the provided statement.
Bind variables can be provided both as positional and as keyword arguments to this method.
Parameters: - stmt (str) – The statement to execute.
- *args – Variable length argument list for positional bind variables.
- **kwargs – Arbitrary keyword arguments for named bind variables.
Returns: - A collection of all the records returned by the
provided statement, either wrapped in
__row_wrapper__
if notNone
or astuple
s otherwise.
Return type: generator
-
fetch_many
(stmt: str, n: int, *args, **kwargs) → list¶ Fetch (at most) n rows from the given query.
The number of raws returned as a list by this function is at most
n
for each call made.Parameters: - stmt (str) – The statement to execute.
- n (int) – The number of rows to fetch.
- *args – Variable length argument list for positional bind variables.
- **kwargs – Arbitrary keyword arguments for named bind variables.
Returns: A list of at most n records returned by the provided statement, either wrapped in
__row_wrapper__
if notNone
or astuple
s otherwise.Return type: list
-
fetch_one
(stmt: str, *args, **kwargs) → Any¶ Fetch a single row from the execution of the provided statement.
Bind variables can be provided both as positional and as keyword arguments to this method.
Parameters: - stmt (str) – The statement to execute.
- *args – Variable length argument list for positional bind variables.
- **kwargs – Arbitrary keyword arguments for named bind variables.
Returns: - An instance of the
__row_rapper__
class if not None
or tuple otherwise.
Return type: object
-
get_errors
(name: str = None, type: str = None) → list¶ Get Oracle errors.
Retrieves all the current errors for the logged user. Internally, this method performs a query on the inner join between
USER_ERRORS
andUSER_SOURCES
. The result is a collection of records with the fieldsname
,type
,line
,position
,error
andtext
.Parameters: - name (str) – Filter errors by object name. A pattern can be used (case sensitive)
- type (str) – Filter errors by object type. A pattern can be used (case insensitive)
Returns: - a list of CursorRow objects describing all the requested
error messages.
Return type: list
-
get_output
() → str¶ Get the output from the standard output stream buffer.
-
plsql
(stmt: str, *args, batch: list = None, **kwargs)¶ Execute (PL/)SQL code.
Bind variables can be provided both as positional and as keyword arguments to this method. Returns a cursor in case data needs to be fetched out of it.
If the provided statement is to be executed multiple times but with different values, the
batch
argument should be used instead of implementing a loop in Python in order to improve performance.Parameters: - stmt (str) – The (PL/)SQL statement to execute.
- *args – Variable length argument list for positional bind variables.
- batch (list) – A list of bind variables in the form of tuples to use iteratively with the given (PL/)SQL statement.
- **kwargs – Arbitrary keyword arguments for named bind variables.
Returns: - the cursor associated with the code
execution.
Return type: cx_Oracle.Cursor
-
session_user
¶ Returns the session user for the connection.
-
set_row_wrapper
(wrapper)¶ Set the row wrapper class.
This class is used to wrap the raw rows returned by a SQL query around richer Python objects. See
RowWrapper
for more details.
-
set_scope
(scope)¶ Set the Oracle Data Dictionary scope.
Use one of the
Database.Scope
attributes. By default, aDatabase
instance is created with theDatabase.Scope.ALL
scope. For applications that rely mostly or exclusively on the logged user schema, it is recommended that the scope be set toDatabase.Scope.USER
for better performance.
-
var
(var_type)¶ Create a PL/SQL variable reference.
One can either pass the name of the variable type as defined in the
cx_Oracle
package (e.g. STRING), or pass the type itself (e.g.cx_Oracle.STRING
).Parameters: var_type – The type of the variable to create. Returns: The requested variable reference. Return type: object
-
class
-
exception
sibilla.
DatabaseError
¶ Generic database error.
-
exception
sibilla.
IdentifierError
¶ SQL identifier error.
-
exception
sibilla.
LoginError
¶ Database login error.
-
class
sibilla.
RowWrapper
¶ Abstract wrapper class for cursor rows.
The results returned from a query are plain tuples and therefore lack some information like, e.g., column names. A row wrapper allows to wrap the results from a cursor or individual rows around a Python object that carries extra information as required.
-
static
from_cursor
(cursor) → Generator[[Any, NoneType], NoneType]¶ Convert the rows of a cursor into richer Python objects.
Subclasses must implement this method in order to instruct the
Database.fetch_all()
method on how to wrap the result from the cursor.Parameters: cursor ( cx_Oracle.Cursor
) – The cursor with the results ready to be fetched.Returns: the wrapped rows. Return type: generator
-
static
from_list
(cursor, data: list) → list¶ Convert the elements in the data list into richer Python objects.
Subclasses must implement htis method in order to instruct the fetch_many method on how to wrap the results in the data list.
Parameters: - cursor (
cx_Oracle.Cursor
) – The cursor used to obtain the data. - data (
list
) – The list of rows obtained from the given cursor.
Returns: the wrapped rows.
Return type: list
- cursor (
-
static
-
exception
sibilla.
SibillaError
¶ Base Sibilla exception.
-
sibilla.
sql_identifier
(name: str) → str¶ Treat string as SQL identifier.
SQL identifier are case insensitive, unless they are double-quoted. This helper function ensures that any identifier is treat consistently by returning an upper-case version of the given string if it is not double-quoted, otherwise it return the string itself.
Example
>>> sql_identifier('foo') 'FOO' >>> sql_identifier('"foo"') '"foo"'
Submodules¶
sibilla.caching module¶
-
class
sibilla.caching.
Cached
(cache=None)¶ Cache mixin for adding synchronised TTL caching support to objects.
-
class
sibilla.caching.
SynchronizedTTLCache
¶ Implement a synchronised TTL cache.
-
flush
()¶ Flush the cache.
-
-
sibilla.caching.
cachedmethod
(f)¶ Caching decorator for class and instance methods.
-
sibilla.caching.
set_maxsize
(size)¶ Set the maximum cache size when creating Cached objects.
-
sibilla.caching.
set_ttl
(ttl)¶ Set the TTL value to use when creating Cached objects.
sibilla.callable module¶
-
class
sibilla.callable.
Callable
(db, name, type, schema, package=None)¶ Base class for Procedures and Functions.
-
exception
sibilla.callable.
CallableError
¶ Database stored callable error.
-
class
sibilla.callable.
CallableFactory
(callable_class, schema, package=None)¶ Create a Python callable for a database stored callable.
This class should be considered as private as it is used internally to allow calling an object as a function or a procedure explicitly.
sibilla.dataset module¶
-
class
sibilla.dataset.
DataSet
¶ -
describe
()¶ Describe the table columns.
The return value is the same as the
description
attribute of a Cursor object from thecx_Oracle
module.
-
fetch_all
(select='*', where=None, order_by=None, **kwargs)¶
-
fetch_many
(n, select='*', where=None, order_by=None, **kwargs)¶
-
fetch_one
(select='*', where=None, order_by=None, **kwargs)¶
-
classmethod
set_row_class
(row_class)¶
-
-
exception
sibilla.dataset.
MultipleRowsError
¶ Multiple rows returned when only one expected.
Usually a consequence of a primary key defined on the table class that is not part of the actual table schema and that is violated by the retrieved data.
-
exception
sibilla.dataset.
NoSuchRowError
¶ Raised when no row matches the given conditions.
Similar to Oracle’s``NO_DATA_FOUND``
-
exception
sibilla.dataset.
QueryError
¶ Database query error.
-
class
sibilla.dataset.
Row
(dataset, kwargs)¶ -
db
¶ Get the underlying database.
-
get
(name, default=None)¶ Attribute getter hook.
This method provides a convenient customisation interface for subclasses of
Row
. Implement it to define custom behaviour when retrieving row attributes.When the requested attribute cannot be determined, this method should raise the
RowGetterError
exception.
-
-
exception
sibilla.dataset.
RowAttributeError
¶ Row attribute access error.
-
exception
sibilla.dataset.
RowError
¶ Dataset row error.
-
exception
sibilla.dataset.
RowGetterError
¶ Row getter method error.
Raised when the requested attribute on the row cannot be determined.
-
sibilla.dataset.
rowattribute
(func)¶
-
sibilla.dataset.
rowmethod
(func)¶
sibilla.function module¶
-
class
sibilla.function.
Function
(db, name, schema, package=None)¶ Oracle stored function.
This class implements Oracle stored functions, including those stored inside packages as Python callable objects so that they can be called as native Python functions and methods.
-
return_type
¶ The function return type.
-
sibilla.object module¶
-
exception
sibilla.object.
ObjectError
¶ Oracle object error.
Defines an error specific to object lookup within the Oracle database associated to an Database object.
-
class
sibilla.object.
ObjectLookup
(db)¶ Oracle object look-up.
Instances of this class allow customising the way objects (e.g. tables, views, packages, …) are looked up from the Oracle database.
Every instance of Database comes with a default ObjectLookup instance accessible through the read-only property
__lookup__
. This can be used to specify the custom classes to handle general Oracle object, as well as specific items, like individual tables, packages, etc…Example
Assume that the database we are connected to has families of tables with a certain prefix, say
DATA_
, that can be treated as a sort of namespace. One might want to be able to access such tables (e.g. theDATA_CUSTOMER
table) with an attribute access on a Database object as:>>> from sibilla import Database >>> db = Database("username", "password", "dsn") >>> db.data.customer
This can be achieved as shown below. First of all, one should subclass
ObjectLookup
and override therenaming
method:from sibilla import ObjectLookup class DataLookup(ObjectLookup): def renaming(self, name): return "data_" + name
Then, one either assigns a new instance of
DataLookup
todb.data
:>>> db.data = DataLookup()
or one subclasses Database and initializes
data
as an object attribute:class MyDB(Database): def __init__(self, *args, **kwargs): super(MyDB, self).__init__(*args, **kwargs) self.data = DataLookup(self) db = MyDB("username", "password", "dsn")
Thus,
db.data.customer
becomes equivalent todb.data_customer
.By default, the look-up will create an object of type
Table
fromsibilla
for the table accessed asdb.data_customer
. To change this behaviour, subclassTable
and pass the class to thereplace
method as a dictionary:from sibilla import ObjectType, Table
- MyTable(Table):
- pass
db.__lookup__.replace({ObjectType.TABLE: MyTable})
Custom table classes can also be assigned to general attributes of a Database object by passing the attribute name as key in the dictionary:
>>> db.__lookup__.replace({"customer": MyTable})
This way, the custom table class
MyTable
is used only when accessing the attribitecustomer
fromdb
rather than for every table. Observe that this is not the same as assigningMyTable
directly to the attributecustomer
ofdb
.-
get_class
(type_name)¶ The class assigned to an Oracle object type.
Returns the class associated with the given type or attribute.
Parameters: type_name (str) – The type name to whose associated class is to be retrieved. This is meant to be either one of the values exposed by the ObjectType
class, or a custom attribute.Returns: The class associated with the given type/attribute. Return type: class
-
renaming
(name: str) → str¶ Rename attribute before performing the look-up.
This methods offers a customisation interface for implementing naming patterns and character substitution in look-ups. Any attribute accessed on an
ObjectLookup
object is preprocessed by this method. This can be useful when database objects have characters which are not allowed in Python to appear in identifiers. For example,my_package#
is a valid Oracle package name, howeverdb.my_package#
does not produce the desired result in Python. To overcome this situation one can subclassObjectLookup
with an overridden methodrenaming
that does a suitable conversion.Example
To access the Oracle package
my_package#
from Python, one could use the convention of replacing any occurrence of # with __.from sibilla import ObjectLookup
- class MyLookup(ObjectLookup):
- def renaming(self, name):
- return name.replace(‘__’, ‘#’)
Any access to the attribute
my_package__
from aMyLookup
object is translated intomy_package#
before being actually looked up from the database.Parameters: name (str) – The attribute accessed on an instance of the class. Returns: The translated attribute for lookup on the database. Return type: str
-
replace
(types: dict)¶ Replace Python classes for Oracle objects.
Overrides the classes used to handle types/attributes on the lookup instance.
Parameters: types (dict) – A dictionary of key-value pairs where the key indicates the type/attribute and the value the class to use to handle the specified type/attribute. The standard Oracle object types can be overridden by using the constants exposed by the ObjectType
class as key values.
-
exception
sibilla.object.
ObjectLookupError
¶ Raised when an object look-up fails.
-
class
sibilla.object.
ObjectType
¶ Supported Oracle object types.
Their main purpose is to allow changing the default class used to wrap Oracle object with Python objects by
ObjectLookup
.-
FUNCTION
= 'FUNCTION'¶
-
PACKAGE
= 'PACKAGE'¶
-
PROCEDURE
= 'PROCEDURE'¶
-
RECORD
= 'RECORD'¶
-
TABLE
= 'TABLE'¶
-
VIEW
= 'VIEW'¶
-
-
exception
sibilla.object.
ObjectTypeError
¶ Problems with Oracle object types.
-
class
sibilla.object.
OracleObject
(db, object_name, object_type, schema)¶ Base Oracle object.
This abstract class represents a generic stored Oracle object and makes the base for concrete objects, like
sibilla.table.Table
,sibilla.package.Package
etc….-
db
¶
-
name
¶
-
object_type
¶
-
renaming
(name)¶
-
sibilla.package module¶
-
class
sibilla.package.
Package
(db, name, schema)¶ Oracle package class.
This class models a stored Oracle package, providing access to functions and procedures.
-
exception
sibilla.package.
PackageAttributeError
¶ Package attribute error.
Raised when unable to resolve the requested attribute from a package.
sibilla.procedure module¶
-
class
sibilla.procedure.
Procedure
(db, name, schema, package=None)¶ Oracle stored procedure.
This class implements Oracle stored procedures, including those stored inside packages as Python callable objects so that they can be called as native Python procedures and methods.
sibilla.schema module¶
-
exception
sibilla.schema.
SchemaError
¶ Database schema error.
Raised when unable to reference a schema.
sibilla.table module¶
-
exception
sibilla.table.
PrimaryKeyError
¶ Raised when unable to make use of a primary key.
-
class
sibilla.table.
SmartRow
(dataset, kwargs)¶ Smart row class.
A smart row is a table row that can follow foreign key references and return the referenced row instead of the raw value.
-
get
(name, default=None)¶ Attribute getter hook.
This method provides a convenient customisation interface for subclasses of
Row
. Implement it to define custom behaviour when retrieving row attributes.When the requested attribute cannot be determined, this method should raise the
RowGetterError
exception.
-
-
class
sibilla.table.
Table
(db, name=None, schema=None)¶ Oracle table class.
A table is a data set that can have primary and foreign key constraints. For tables with a primary key constraint, rows can be accessed from a table as if this was indexed by the primary key values.
-
drop
(flush_cache=True)¶ Drop the table.
By default, the internal table cache is flushed to allow changes to be synchronised with the database.
-
insert
(values)¶ Insert values into the table.
The passed values can either be a single row to add or a list of multiple row to insert as a batch. A row in this case is either a dictionary with the name of the columns and the corresponding values to set, or a tuple with as many entries as the columns of the table.
-
truncate
()¶ Truncate the table.
-
-
exception
sibilla.table.
TableEntryError
¶ Raised when failed to access a table entry.
-
exception
sibilla.table.
TableError
¶ Table-related database error.
-
exception
sibilla.table.
TableInsertError
¶
-
class
sibilla.table.
TableRow
(dataset, kwargs)¶ Table row class.
Contrary to a normal row, a table row can have a primary key associated to it.