copyright: | 2006-2011, Prometheus Research, LLC |
---|---|
authors: | Clark C. Evans <cce@clarkevans.com>, Kirill Simonov <xi@resolvent.net>; see AUTHORS file in the source distribution for the full list of contributors |
license: | See LICENSE file in the source distribution |
This package provides HTSQL, a query language for the accidental programmer.
HTSQL is implemented as a WSGI application. To create an application, run:
>>> from htsql import HTSQL
>>> app = HTSQL(db)
where db is a connection URI, a string of the form:
engine://username:password@host:port/database
To execute a WSGI request, run
>>> app(environ, start_response)
This module provides a mechanism for pluggable extensions.
A unit of extension in the HTSQL component architecture.
HTSQL component architecture allows you to:
Three types of interfaces are supported: utilities, adapters and protocols; see Utility, Adapter, Protocol respectively.
Produce a list of all components of the active application.
Produces a list of all components implementing the interface.
Produces a realization of the interface for the given dispatch key.
Tests if the component implements the interface.
Tests if the component dominates another component.
Tests if the component matches a dispatch key.
Extract the dispatch key from the constructor arguments.
A realization of an interface for some dispatch key.
Implements utility interfaces.
An utility is an interface with a single realization.
This is an abstract class; to declare an utility interface, create a subclass of Utility. To add an implementation of the interface, create a subclass of the interface class.
The following example declared an interface SayHello and provide an implementation PrintHello that prints 'Hello, World! to the standard output:
class SayHello(Utility):
def __call__(self):
raise NotImplementedError("interface is not implemented")
class PrintHello(SayHello):
def __call__(self):
print "Hello, World!"
def hello():
hello = SayHello()
hello()
>>> hello()
Hello, World!
Implements adapter interfaces.
An adapter interface provides mechanism for polymorphic dispatch based on the types of the arguments.
This is an abstract class; to declare an adapter interface, create a subclass of Adapter and indicate the most generic type signature of the polymorphic arguments using function adapts().
To add an implementation of an adapter interface, create a subclass of the interface class and indicate the matching type signatures using functions adapts(), adapts_many(), or adapts_none().
Class attributes:
The following example declares an adapter interface Format and implements it for several data types:
class Format(Adapter):
adapts(object)
def __init__(self, value):
self.value = value
def __call__(self):
# The default implementation.
return str(self.value)
class FormatString(Format):
adapts(str)
def __call__(self):
# Display alphanumeric values unquoted, the others quoted.
if self.value.isalnum():
return self.value
else:
return repr(self.value)
class FormatList(Format):
adapts(list)
def __call__(self):
# Apply `format` to the list elements.
return "[%s]" % ",".join(format(item) for item in self.value)
def format(value):
format = Format(value)
return format()
>>> print format(123)
123
>>> print format("ABC")
ABC
>>> print format("Hello, World!")
'Hello, World!'
>>> print format([123, "ABC", "Hello, World!"])
[123, ABC, 'Hello, World!']
Specifies the adapter signature.
The component matches the specified or any more specific signature.
Use it in the namespace of the component, for example:
class DoSmth(Adapter):
adapts(T1, T2, ...)
Indicates that the adapter does not match any signatures.
Use it in the namespace of the adapter, for example:
class DoSmth(Adapter):
adapts_none()
Specifies signatures of the adapter.
The component matches any of the specified signatures as well all more specific signatures.
Use it in the namespace of the adapter, for example:
class DoSmth(Adapter):
adapts_many((T11, T12, ...),
(T21, T22, ...),
...)
Implements protocol interfaces.
A protocol interface provides mechanism for name-based dispatch.
This is an abstract class; to declare a protocol interface, create a subclass of Protocol.
To add an implementation of a protocol interface, create a subclass of the interface class and specify its name using function named().
Class attributes:
The following example declares a protocol interface Weigh and adds several implementations:
class Weigh(Protocol):
def __init__(self, name):
self.name = name
def __call__(self):
# The default implementation.
return -1
class WeighAlice(Weigh):
named("Alice")
def __call__(self):
return 150
class WeighBob(Weigh):
named("Bob")
def __call__(self):
return 160
def weigh(name):
weigh = Weigh(name)
return weigh()
>>> weigh("Alice")
150
>>> weigh("Bob")
160
>>> weigh("Clark")
-1
Specifies the names of the protocol.
Use it in the namespace of the protocol, for example:
class DoSmth(Protocol):
named("...")
Contains cached components and realizations.
This module declares HTSQL addons.
Implements an addon for HTSQL applications.
This is an abstract class; to add a new addon, create a subclass of Addon.
Returns a short one-line description of the addon.
Returns a long description of the addon.
This module implements an HTSQL application.
Implements an HTSQL application.
This module declares the database connection adapter.
Raised when a database error occurred.
Guards against DBAPI exception.
This class converts DBAPI exceptions to DBError. It is designed to be used in a with clause.
Usage:
connect = Connect()
try:
with ErrorGuard():
connection = connect.open_connection()
cursor = connection.cursor()
...
except DBError:
...
Wraps a DBAPI connection object.
The proxy supports common DBAPI methods by passing them to the connection object. Any exceptions raised when the executing DBAPI methods are converted to DBError.
Returns a database cursor.
This method actually produces a CursorProxy instance.
Commit the current transaction.
Rollback the current transaction.
Close the connection.
Wraps a DBAPI cursor object.
The proxy supports common DBAPI methods by passing them to the cursor object. Any exceptions raised when the executing DBAPI methods are converted to DBError.
The format of the result rows.
The number of rows produced or affected by the last statement.
Execute one SQL statement.
Execute an SQL statement against all parameters.
Fetch the next row of the result.
Fetch the next set of rows of the result.
Fetch all remaining rows of the result.
Close the cursor.
Declares the connection interface.
The connection interface is a utility to open database connections.
Usage:
connect = Connect()
try:
connection = connect()
cursor = connection.cursor()
cursor.execute(...)
cursor.fetchall()
...
except DBError:
...
Returns a raw DBAPI connection object.
This module keeps the active HTSQL application in a thread-local variable.
This module exports one global variable:
This module defines HTSQL domains.
Represents an HTSQL domain (data type).
A domain indicates the type of an object. Most HTSQL domains correspond to SQL data types; some domains are special and used when the actual SQL data type is unknown or nonsensical.
A value of a specific domain could be represented in two forms:
Methods parse() and dump() translate values from one form to the other.
Converts an HTSQL literal to a native Python object.
Raises ValueError if the literal is not in a valid format.
Returns a native Python object representing the same value.
Converts a native Python object to an HTSQL literal.
Returns an HTSQL literal representing the same value.
Represents a domain without any valid values.
This domain is assigned to objects when the domain is structurally required, but does not have any semantics.
Represents an unknown type.
This domain is assigned to HTSQL literals temporarily until the actual domain could be derived from the context.
Represents a table domain.
This domain is assigned to table expressions.
Represents Boolean data type.
Valid literal values: true, false.
Valid native values: bool objects.
Represents a numeric data type.
This is an abstract data type, see IntegerDomain, FloatDomain, DecimalDomain for concrete subtypes.
Class attributes:
Represents a binary integer data type.
Valid literal values: integers (in base 2) with an optional sign.
Valid native values: int or long objects.
Represents an IEEE 754 float data type.
Valid literal values: floating-point numbers in decimal or scientific format.
Valid native values: float objects.
Represents an exact decimal data type.
Valid literal values: floating-point numbers in decimal or scientific format.
Valid native values: decimal.Decimal objects.
Represents a string data type.
Valid literal values: all literal values.
Valid native values: unicode objects; the NUL character is not allowed.
Represents an enumeration data type.
An enumeration domain has a predefined set of valid string values.
Represents a date data type.
Valid literal values: valid date values in the form YYYY-MM-DD.
Valid native values: datetime.date objects.
Represents a time data type.
Valid literal values: valid time values in the form HH:MM[:SS[.SSSSSS]].
Valid native values: datetime.time objects.
Represents a date and time data type.
Valid literal values: valid date and time values in the form YYYY-MM-DD HH:MM[:SS[.SSSSSS]].
Valid native values: datetime.datetime objects.
Represents an unsupported SQL data type.
Note: this is the only SQL domain with values that cannot be serialized using dump().
This module implements the HTSQL catalog and catalog entities.
Represents a join condition between two tables.
This is an abstract case class with two subclasses: DirectJoin and ReverseJoin.
Class attributes:
Attributes:
Represents a join condition corresponding to a foreign key.
Represents a join condition that joins tables in the opposite direction to some foreign key.
This module implements generic HTSQL exceptions.
An error associated with an HTSQL query.
An instance of HTTPError contains a pointer to an HTSQL expression that caused the error. The traceback produced by the exception includes the original HTSQL query and a pointer to the erroneous expression.
An instance of HTTPError could also serve as a simple WSGI application generating an appropriate HTTP error code and displaying the error message.
This is an abstract exception class. To implement a concrete exception, add a subclass of HTTPError and override the following class attributes:
The constructor of HTTPError accepts the following parameters:
Represents 400 Bad Request.
Represents 403 Forbidden.
Represents 404 Not Found.
Represents 409 Conflict.
Represents 500 Internal Server Error.
Represents 501 Not Implemented.
Represents an invalid syntax error.
This exception is raised by the scanner when it cannot tokenize the query, or by the parser when it finds an unexpected token.
This module declares the database introspector adapter.
Declares the introspection interface.
An introspector analyzes the database meta-data and generates an HTSQL catalog.
This module implements a Mark object.
A slice of an HTSQL query.
In the process of translation of an HTSQL query to SQL, intermediary nodes of different kinds are generated. Most of the nodes have a mark attribute that points to the original HTSQL expression from which the node was derived.
Note that a Mark object should only be used for presentational purposes such as error reporting. There is no guarantee that the slice mark.value[mark.start:mark.end] would represent a valid HTSQL expression.
Generates a new Mark object from a collection of separate marks. The returned mark will cover all the given marks.
Returns a list of lines that consists an except of the original query with ^ characters underlining the mark.
This module implements the request utility.
This module declares the SQL splitter adapter.
Declares a regular expression pattern to be used by the SQL splitter.
Declares the SQL splitter interface.
A SQL splitter takes a string containing one or more SQL statements separated by ; and produces a sequence of SQL statements.
Usage:
try:
split_sql = SplitSQL()
for sql in split_sql(input):
cursor.execute(sql)
except ValueError:
...
This is an abstract utility. To add a new splitter, create a subclass of SplitSQL and override the class variable tokens:
This module provides various hard-to-categorize utilities.
Represents parameters of a database connection.
The database name.
For SQLite, the path to the database file.
A dictionary containing extra connection parameters.
Currently ignored by all engines.
The parameters username, password, host, port are ignored by the SQLite engine.
Parses a connection URI and returns a corresponding DB instance.
A connection URI is a string of the form:
engine://username:password@host:port/database?options
The name of the database.
For SQLite, the path to the database file.
The parameters engine and database are required, all the other parameters are optional.
If a parameter contains a character which cannot be represented literally (such as :, /, @ or ?), it should be escaped using %-encoding.
If the connection URI is not in a valid format, ValueError is raised.
Besides a connection URI, the function also accepts instances of DB and dictionaries. An instance of DB is returned as is. A dictionary is assumed to contain connection parameters. The corresponding instance of DB is returned.
Checks if a value is either None or an instance of the specified type.
Usage:
isinstance(value, maybe(T))
Checks if a value is an instance of one of the specified types.
Usage:
isinstance(value, oneof(T1, T2, ...))
Checks if a value is a list containing elements of the specified type.
Usage:
isinstance(value, listof(T))
Checks if a value is a set containing elements of the specified type.
Usage:
isinstance(value, setof(T))
Checks if a value is a tuple with the fixed number of elements of the specified types.
Usage:
isinstance(value, tupleof(T1, T2, ..., TN))
Checks if a value is a dictionary with keys and elements of the specified types.
Usage:
isinstance(value, dictof(T1, T2))
Check if a value is a subclass of the specified class.
Usage:
isinstance(value, subclassof(T))
Checks if a value is a file or a file-like object.
Usage:
isinstance(value, filelike())
Takes two lists; checks if each element of the first list is a subclass of the corresponding element in the second list.
Returns True if the check succeeds; False otherwise.
Unindent and remove leading and trailing blank lines.
Useful for stripping indentation from docstrings.
Implements topological sort.
Takes a list of elements and a partial order relation. Returns the elements reordered to satisfy the given order.
A (finite) order relation is an acyclic directed graph.
This function raises RuntimeError if order is not a valid partial order (contains loops) or if is_total is set and order is not a valid total order.
Implements default string representation.
Implements an immutable clonable object.
Clones the node assigning new values to selected attributes.
Returns a new object of the same type keeping original attributes except those for which new values are specified.
Clones the node changing its type and assigning new values to selected attributes.
Returns a new object of the specified type which keeps the attributes of the original objects except those for which new values are specified.
Implements an object with by-value comparison semantics.
The constructor arguments:
Other attributes:
Imports all modules (including subpackages) in a package.
This module provides utilities for data validation and conversion.
Validators check if a given value conforms the specified format.
A validator acts as function that takes a value, checks if it conforms the format, normalizes and returns the value. Example:
validator = IntVal()
value = validator(value)
If the value does not conform the format, ValueError is raised.
Attribute hint gives a short textual description of the format.
Validator is the base abstract class for validators. Its subclasses provide validators for specific formats.
To create a validator for a new format, create a subclass of Validator and override the __call__() method. The method should accept values of any type. If the value does not conform to the format, ValueError should be raised; otherwise the value should be normalized and returned.
Example:
class IntVal(Validator):
hint = "an integer"
def __call__(self, value):
if isinstance(value, str):
value = int(value)
if not isinstance(value, int):
raise ValueError("an integer is expected")
return value
A no-op validator.
Verifies if the value is a UTF-8 encoded string.
Verifies if the value is a word.
A word is a string containing alphanumeric characters, dashes, underscores, or spaces. In the normalized form, underscores and spaces are replaced with dashes.
Verifies if the value belongs to a specified set of string constants.
Verifies if the value is Boolean.
Besides True and False constants, the following values are accepted:
Verifies if the value is an integer.
Strings containing numeric characters are also accepted.
Verifies if the value is a non-negative integer.
Verifies if the value is a positive integer.
Verifies if the value is an integer.
Strings representing numeric values in a decimal or a scientific format are also accepted.
Verifies if the value is a non-negative float number.
Verifies if the value is a list with each list item conforming the specified format.
Also accepted are strings that agree with the following grammar:
value ::= <empty> | item ( [,] value )*
item ::= <any non-space character or comma>+
| ['] ( <any non-quote character> | [']['] )* [']
That is, the string must represent a comma-separated list of elements. If an element contains no whitespace characters and no commas, it could be represented literally; otherwise it should be quited with ' and any single quote character should be duplicated.
Verifies if the value is a dictionary with keys and items conforming the specified formats.
Also accepted are strings that agree with the following grammar:
value ::= <empty> | key ( [:] | [=] ) item ( [,] value )*
key, item ::= <any non-space character except for [:], [=] or [,]>+
| ['] ( <any non-quote character> | [']['] )* [']
That is, the string must represent a comma-separated list of key=item pairs. The key and the item could be quoted or unquoted. An unquoted element contains no whitespace, :, =, , characters. A quoted element is enclosed with ' and has any single quote character duplicated.
Verifies if the value is an instance of the specified class.
Verifies if the value is a connection URI.
For description of the connection URI format, see htsql.util.DB.parse().
This module provides a handler for WSGI requests.
Declares the WSGI interface.
The WSGI interface is a utility to handle WSGI requests.
Usage:
wsgi = WSGI()
body = wsgi(environ, start_response)