From ad76b5ba3cc01b658e31fb3c4e94340ba0f884d9 Mon Sep 17 00:00:00 2001 From: Daniele Varrazzo Date: Sat, 26 Nov 2005 07:47:48 +0000 Subject: [PATCH] * psycopg/psycopgmodule.c: fixed exceptions refcount. * fixed lots of doctrings and added Epydoc-generated docs support. --- ChangeLog | 6 ++ doc/api-screen.css | 138 +++++++++++++++++++++++++++ doc/extensions.rst | 102 ++++++++++++-------- examples/dialtone.py | 11 +-- lib/extensions.py | 10 +- lib/tz.py | 2 +- psycopg/adapter_asis.h | 2 +- psycopg/adapter_binary.h | 2 +- psycopg/adapter_datetime.h | 20 ++-- psycopg/adapter_list.h | 2 +- psycopg/adapter_mxdatetime.h | 20 ++-- psycopg/adapter_pboolean.h | 2 +- psycopg/adapter_qstring.h | 2 +- psycopg/connection_type.c | 38 +++++--- psycopg/cursor_type.c | 73 +++++++------- psycopg/microprotocols.h | 2 +- psycopg/microprotocols_proto.c | 10 +- psycopg/psycopgmodule.c | 56 +++++++---- scripts/ext2html.py | 169 +++++++++++++++++++++++++++++++++ scripts/makedocs.py | 15 +++ 20 files changed, 530 insertions(+), 152 deletions(-) create mode 100644 doc/api-screen.css create mode 100755 scripts/ext2html.py create mode 100755 scripts/makedocs.py diff --git a/ChangeLog b/ChangeLog index 6923ec28..73cbbc1a 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-11-26 Daniele Varrazzo + + * psycopg/psycopgmodule.c: fixed exceptions refcount. + + * fixed lots of doctrings and added Epydoc-generated docs support. + 2005-11-24 Federico Di Gregorio * sandbox: added all the test and creash-me files to the repository. diff --git a/doc/api-screen.css b/doc/api-screen.css new file mode 100644 index 00000000..22e8f7ed --- /dev/null +++ b/doc/api-screen.css @@ -0,0 +1,138 @@ +/* Based on the Epydoc "default.css" +** with some missing reST-related classes +** and Python syntax support (from SilverCity) +*/ + +/* Body color */ +body { background: #ffffff; color: #000000; } + +/* Tables */ +table.summary, table.details, table.index + { background: #e8f0f8; color: #000000; } +tr.summary, tr.details, tr.index + { background: #70b0f0; color: #000000; + text-align: left; font-size: 120%; } +tr.group { background: #c0e0f8; color: #000000; + text-align: left; font-size: 120%; + font-style: italic; } + +/* Documentation page titles */ +h2.module { margin-top: 0.2em; } +h2.class { margin-top: 0.2em; } + +/* Headings */ +h1.heading { font-size: +140%; font-style: italic; + font-weight: bold; } +h2.heading { font-size: +125%; font-style: italic; + font-weight: bold; } +h3.heading { font-size: +110%; font-style: italic; + font-weight: normal; } + +/* Base tree */ +pre.base-tree { font-size: 80%; margin: 0; } + +/* TOC */ +p.toc { margin: 0; } + +/* Details Sections */ +table.func-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.func-detail { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +table.var-details { background: #e8f0f8; color: #000000; + border: 2px groove #c0d0d0; + padding: 0 1em 0 1em; margin: 0.4em 0 0 0; } +h3.var-details { background: transparent; color: #000000; + margin: 0 0 1em 0; } + +/* Function signatures */ +.sig { background: transparent; color: #000000; + font-weight: bold; } +.sig-name { background: transparent; color: #006080; } +.sig-arg, .sig-kwarg, .sig-vararg + { background: transparent; color: #008060; } +.sig-default { background: transparent; color: #602000; } +.summary-sig { background: transparent; color: #000000; } +.summary-sig-name { background: transparent; color: #204080; } +.summary-sig-arg, .summary-sig-kwarg, .summary-sig-vararg + { background: transparent; color: #008060; } + +/* Doctest blocks */ +.py-src { background: transparent; color: #000000; } +.py-prompt { background: transparent; color: #005050; + font-weight: bold;} +.py-string { background: transparent; color: #006030; } +.py-comment { background: transparent; color: #003060; } +.py-keyword { background: transparent; color: #600000; } +.py-output { background: transparent; color: #404040; } +div.code-block, +pre.literal-block, +pre.doctestblock { background: #f4faff; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } +table pre.doctestblock + { background: #dce4ec; color: #000000; + padding: .5em; margin: 1em; + border: 1px solid #708890; } +div.code-block { font-family: monospace; } + +/* Variable values */ +pre.variable { background: #dce4ec; color: #000000; + padding: .5em; margin: 0; + border: 1px solid #708890; } +.variable-linewrap { background: transparent; color: #604000; } +.variable-ellipsis { background: transparent; color: #604000; } +.variable-quote { background: transparent; color: #604000; } +.re { background: transparent; color: #000000; } +.re-char { background: transparent; color: #006030; } +.re-op { background: transparent; color: #600000; } +.re-group { background: transparent; color: #003060; } +.re-ref { background: transparent; color: #404040; } + +/* Navigation bar */ +table.navbar { background: #a0c0ff; color: #0000ff; + border: 2px groove #c0d0d0; } +th.navbar { background: #a0c0ff; color: #0000ff; } +th.navselect { background: #70b0ff; color: #000000; } +.nomargin { margin: 0; } + +/* Links */ +a:link { background: transparent; color: #0000ff; } +a:visited { background: transparent; color: #204080; } +a.navbar:link { background: transparent; color: #0000ff; + text-decoration: none; } +a.navbar:visited { background: transparent; color: #204080; + text-decoration: none; } + +/* Admonitions */ +div.warning, +div.note { background-color: #c0e0f8; + border: thin solid black; + padding: 1em; + margin-left: 1em; + margin-right: 1em; } +div.warning .first, +div.note .first { font-family: sans-serif; + font-size: 110%; + margin-right: 0.5em; } + +/* Lists */ +ul { margin-top: 0; } + +/* Python syntax */ +.p_character { color: olive; } +.p_classname { color: blue; font-weight: bold; } +.p_commentblock {color: gray; font-style: italic; } +.p_commentline { color: green; font-style: italic; } +.p_default {} +.p_defname { color: #009999; font-weight: bold; } +.p_identifier { color: black; } +.p_number { color: #009999; } +.p_operator { color: black; } +.p_string { color: #7F007F; } +.p_stringeol { color: #7F007F; } +.p_triple { color: #7F0000; } +.p_tripledouble { color: #7F0000; } +.p_word { color: navy; font-weight: bold; } diff --git a/doc/extensions.rst b/doc/extensions.rst index 68a97717..faf28d49 100644 --- a/doc/extensions.rst +++ b/doc/extensions.rst @@ -9,7 +9,7 @@ you already know how to program in Python using a DBAPI-2.0 compliant driver: basic concepts like opening a connection, executing queries and commiting or rolling back a transaction will not be explained but just used. -__ http://www.python.org/peps/pep-0249.html +.. __: http://www.python.org/peps/pep-0249.html Many objects and extension functions are defined in the `psycopg2.extensions` module. @@ -36,29 +36,26 @@ Setting transaction isolation levels psycopg2 connection objects hold informations about the PostgreSQL `transaction isolation level`_. The current transaction level can be read from the -`connection.isolation_level` attribute. The default isolation level is read -committed. A different isolation level con be set through the -`connection.set_isolation_level()` method. The method takes the new level as -parameter. Isolation levels are defined in the `psycopg2.extensions` module: +`.isolation_level` attribute. The default isolation level is ``READ +COMMITTED``. A different isolation level con be set through the +`.set_isolation_level()` method. The level can be set to one of the following +constants, defined in `psycopg2.extensions`: -ISOLATION_LEVEL_AUTOCOMMIT +`ISOLATION_LEVEL_AUTOCOMMIT` No transaction is started when command are issued and no `.commit()`/`.rollback()` is required. Some PostgreSQL command such as ``CREATE DATABASE`` can't run into a transaction: to run such command use `.set_isolation_level(ISOLATION_LEVEL_AUTOCOMMIT)`. -ISOLATION_LEVEL_READ_COMMITED +`ISOLATION_LEVEL_READ_COMMITTED` This is the default value. A new transaction is started at the first `.execute()` command on a cursor and at each new `.execute()` after a `.commit()` or a `.rollback()`. The transaction runs in the PostgreSQL ``READ COMMITTED`` isolation level. -ISOLATION_LEVEL_REPEATABLE_READ - Same as ISOLATION_LEVEL_SERIALIZABLE: PostgreSQL treats the SQL - ``REPEATABLE READ`` isolation level as ``SERIALIZABLE``. - -ISOLATION_LEVEL_SERIALIZABLE - Serializable. Transactions are run at a ``SERIALIZABLE`` isolation level. +`ISOLATION_LEVEL_SERIALIZABLE` + Transactions are run at a ``SERIALIZABLE`` isolation level. + .. _transaction isolation level: http://www.postgresql.org/docs/8.1/static/transaction-iso.html @@ -81,21 +78,22 @@ is converted into the SQL command:: INSERT INTO atable (anint, adate, astring) VALUES (10, '2005-11-18', 'O''Reilly'); -Notice that: +Named arguments are supported too with ``%(name)s`` placeholders. Notice that: - - The Python string operator ``%`` is not used: the `curs.execute()` function - accepts two parameters. + - The Python string operator ``%`` is not used: the `.execute()` function + accepts the values tuple or dictionary as second parameter. - - The variables placeholder must always be ``%s``, even if a different - placeholder (such as a %d for an integer) may look more appropriate. + - The variables placeholder must always be a ``%s``, even if a different + placeholder (such as a ``%d`` for an integer) may look more appropriate. - - The second argument must always be a tuple, even if it contains a single - parameter. + - For positional variables binding, the second argument must always be a + tuple, even if it contains a single variable. - Only variable values should be bound via this method: it shouldn't be used to set table or field names. For these elements, ordinary string formatting should be used before running `.execute()`. + Adapting new types ------------------ @@ -104,14 +102,14 @@ is similar to the Object Adaptation proposed in the `PEP-246`_ and is exposed by the `adapt()` function. psycopg2 `.execute()` method adapts its ``vars`` arguments to the `ISQLQuote` -protocol. Objects that conform to this protocol expose a `getquoted()` method +protocol. Objects that conform to this protocol expose a ``getquoted()`` method returning the SQL representation of the object as a string. The easiest way to adapt an object to an SQL string is to register an adapter function via the `register_adapter()` function. The adapter function must take the value to be adapted as argument and return a conform object. A convenient -object is the `AsIs` wrapper, whose `getquoted()` result is simply the `str()`\ -ingification of the wrapped object. +object is the `AsIs` wrapper, whose ``getquoted()`` result is simply the +``str()``\ ingification of the wrapped object. Example: mapping of a ``Point`` class into the ``point`` PostgreSQL geometric type:: @@ -141,13 +139,26 @@ The above function call results in the SQL command:: Type casting of SQL types into Python values ============================================ -PostgreSQL objects read from the database can be adapted to Python objects. To -create a new mapping from a PostgreSQL type (either standard or user-defined), -first its ``oid`` must be known. It can be retrieved either by the second -column of the cursor description:: +PostgreSQL objects read from the database can be adapted to Python objects +through an user-defined adapting function. An adapter function takes two +argments: the object string representation as returned by PostgreSQL and the +cursor currently being read, and should return a new Python object. For +example, the following function parses a PostgreSQL ``point`` into the +previously defined ``Point`` class:: + + def cast_point(value, curs): + if value is not None: + # Convert from (f1, f2) syntax using a regular expression. + m = re.match("\((.*),(.*)\)", value) + if m: + return Point(float(m.group(1)), float(m.group(2))) + +To create a mapping from the PostgreSQL type (either standard or user-defined), +its ``oid`` must be known. It can be retrieved either by the second column of +the cursor description:: curs.execute("SELECT NULL::point") - point_oid = cur.description[0][1] # usually returns 600 + point_oid = curs.description[0][1] # usually returns 600 or by querying the system catalogs for the type name and namespace (the namespace for system objects is ``pg_catalog``):: @@ -162,24 +173,15 @@ namespace for system objects is ``pg_catalog``):: point_oid = curs.fetchone()[0] -After you know the object ``oid``, you must create and register the new type -caster object:: +After you know the object ``oid``, you must can and register the new type:: - def cast_point(value, curs): - if value is not None: - # Convert from (f1, f2) syntax using a regular expression. - m = re.match("\((.*),(.*)\)", value) - if m: - return Point(float(m.group(1)), float(m.group(2))) - POINT = psycopg2.extensions.new_type((point_oid,), "POINT", cast_point) psycopg2.extensions.register_type(POINT) The `new_type()` function binds the object oids (more than one can be -specified) to a conversion function. The function is called by psycopg passing -it the string representation of the data as returned by PostgreSQL and the -cursor: it should perform the conversion and return a Python type. -`register_type()` completes the spell:: +specified) to the adapter function. `register_type()` completes the spell. +Conversion is automatically performed when a column whose type is a registered +``oid`` is read:: curs.execute("SELECT '(10.2,20.3)'::point") point = curs.fetchone()[0] @@ -198,6 +200,23 @@ Receiving NOTIFYs Using COPY TO and COPY FROM =========================== +psycopg2 `cursor` object provides an interface to the efficient `PostgreSQL +COPY command`__ to move data from files to tables and back. + +The `.copy_to(file, table)` method writes the content of the table +named ``table`` *to* the file-like object ``file``. ``file`` must have a +``write()`` method. + +The `.copy_from(file, table)` reads data *from* the file-like object +``file`` appending them to the table named ``table``. ``file`` must have both +``read()`` and ``readline()`` method. + +Both methods accept two optional arguments: ``sep`` (defaulting to a tab) is +the columns separator and ``null`` (defaulting to ``\N``) represents ``NULL`` +values in the file. + +.. __: http://www.postgresql.org/docs/8.1/static/sql-copy.html + PostgreSQL status message and executed query ============================================ @@ -214,4 +233,3 @@ PostgreSQL status message and executed query INSERT, UPDATE, ...) and some additional information like the number of rows updated and so on. Refer to the PostgreSQL manual for more information. - diff --git a/examples/dialtone.py b/examples/dialtone.py index a648e05c..3a55686d 100644 --- a/examples/dialtone.py +++ b/examples/dialtone.py @@ -112,17 +112,14 @@ insert completely new objects inside a database. As you can see objects do not know anything about the code that is handling them. We specify all the fields that we need for each object through the persistent_fields dict. -The most important line of this recipe is this one: - adapters.update({Album: ObjectMapper, Order: ObjectMapper}) +The most important lines of this recipe are: + register_adapter(Album, ObjectMapper) + register_adapter(Order, ObjectMapper) -In this line we notify the system that when we call adapt with an Album instance +In these line we notify the system that when we call adapt with an Album instance as an argument we want it to istantiate ObjectMapper passing the Album instance as argument (self.orig in the ObjectMapper class). -adapters is just a python dict with a Key that represents the type -we need to adapt from and a value that is the adapter -which will adapt to the wanted interface. - The output is something like this (for each call to generateInsert): ('INSERT INTO Album (album_id, binary_data, creation_time) VALUES diff --git a/lib/extensions.py b/lib/extensions.py index 258a4c84..3257a16e 100644 --- a/lib/extensions.py +++ b/lib/extensions.py @@ -2,10 +2,12 @@ This module holds all the extensions to the DBAPI-2.0 provided by psycopg. - - connection -- the new-type inheritable connection class - - cursor -- the new-type inheritable cursor class - - adapt() -- exposes the PEP-246 compatile adapting machanism used - by psycopg to adapt Python types to PostgreSQL ones +- `connection` -- the new-type inheritable connection class +- `cursor` -- the new-type inheritable cursor class +- `adapt()` -- exposes the PEP-246_ compatile adapting machanism used + by psycopg to adapt Python types to PostgreSQL ones + +.. _PEP-246: http://www.python.org/peps/pep-0246.html """ # psycopg/extensions.py - DBAPI-2.0 extensions specific to psycopg # diff --git a/lib/tz.py b/lib/tz.py index 8b923182..e521b6dc 100644 --- a/lib/tz.py +++ b/lib/tz.py @@ -1,6 +1,6 @@ """tzinfo implementations for psycopg2 -This module holds twi different tzinfo implementations that can be used as +This module holds two different tzinfo implementations that can be used as the 'tzinfo' argument to datetime constructors, directly passed to psycopg functions or used to set the .tzinfo_factory attribute in cursors. """ diff --git a/psycopg/adapter_asis.h b/psycopg/adapter_asis.h index 79e7ec44..9495c581 100644 --- a/psycopg/adapter_asis.h +++ b/psycopg/adapter_asis.h @@ -42,7 +42,7 @@ typedef struct { extern PyObject *psyco_AsIs(PyObject *module, PyObject *args); #define psyco_AsIs_doc \ - "psycopg.AsIs(obj) -> new AsIs wrapper object" + "AsIs(obj) -> new AsIs wrapper object" #ifdef __cplusplus } diff --git a/psycopg/adapter_binary.h b/psycopg/adapter_binary.h index adc57c6c..4cbd12ab 100644 --- a/psycopg/adapter_binary.h +++ b/psycopg/adapter_binary.h @@ -43,7 +43,7 @@ typedef struct { extern PyObject *psyco_Binary(PyObject *module, PyObject *args); #define psyco_Binary_doc \ - "psycopg.Binary(buffer) -> new binary object" + "Binary(buffer) -> new binary object" #ifdef __cplusplus } diff --git a/psycopg/adapter_datetime.h b/psycopg/adapter_datetime.h index 11ef0084..9fbed3d3 100644 --- a/psycopg/adapter_datetime.h +++ b/psycopg/adapter_datetime.h @@ -48,45 +48,45 @@ typedef struct { extern PyObject *psyco_Date(PyObject *module, PyObject *args); #define psyco_Date_doc \ - "psycopg.Date(year, month, day) -> new date" + "Date(year, month, day) -> new date" extern PyObject *psyco_Time(PyObject *module, PyObject *args); #define psyco_Time_doc \ - "psycopg.Time(hour, minutes, seconds, tzinfo=None) -> new time" + "Time(hour, minutes, seconds, tzinfo=None) -> new time" extern PyObject *psyco_Timestamp(PyObject *module, PyObject *args); #define psyco_Timestamp_doc \ - "psycopg.Time(year, month, day, hour, minutes, seconds, tzinfo=None) -> new timestamp" + "Timestamp(year, month, day, hour, minutes, seconds, tzinfo=None) -> new timestamp" extern PyObject *psyco_DateFromTicks(PyObject *module, PyObject *args); #define psyco_DateFromTicks_doc \ - "psycopg.DateFromTicks(ticks) -> new date" + "DateFromTicks(ticks) -> new date" extern PyObject *psyco_TimeFromTicks(PyObject *module, PyObject *args); #define psyco_TimeFromTicks_doc \ - "psycopg.TimeFromTicks(ticks) -> new date" + "TimeFromTicks(ticks) -> new time" extern PyObject *psyco_TimestampFromTicks(PyObject *module, PyObject *args); #define psyco_TimestampFromTicks_doc \ - "psycopg.TimestampFromTicks(ticks) -> new date" + "TimestampFromTicks(ticks) -> new timestamp" #endif /* PSYCOPG_DEFAULT_PYDATETIME */ extern PyObject *psyco_DateFromPy(PyObject *module, PyObject *args); #define psyco_DateFromPy_doc \ - "psycopg.DateFromPy(datetime.date) -> new wrapper" + "DateFromPy(datetime.date) -> new wrapper" extern PyObject *psyco_TimeFromPy(PyObject *module, PyObject *args); #define psyco_TimeFromPy_doc \ - "psycopg.TimeFromPy(datetime.time) -> new wrapper" + "TimeFromPy(datetime.time) -> new wrapper" extern PyObject *psyco_TimestampFromPy(PyObject *module, PyObject *args); #define psyco_TimestampFromPy_doc \ - "psycopg.TimestampFromPy(datetime.datetime) -> new wrapper" + "TimestampFromPy(datetime.datetime) -> new wrapper" extern PyObject *psyco_IntervalFromPy(PyObject *module, PyObject *args); #define psyco_IntervalFromPy_doc \ - "psycopg.IntervalFromPy(datetime.timedelta) -> new wrapper" + "IntervalFromPy(datetime.timedelta) -> new wrapper" #ifdef __cplusplus } diff --git a/psycopg/adapter_list.h b/psycopg/adapter_list.h index a6850284..71b4286c 100644 --- a/psycopg/adapter_list.h +++ b/psycopg/adapter_list.h @@ -40,7 +40,7 @@ typedef struct { extern PyObject *psyco_List(PyObject *module, PyObject *args); #define psyco_List_doc \ - "psycopg.List(list, enc) -> new quoted list" + "List(list, enc) -> new quoted list" #ifdef __cplusplus } diff --git a/psycopg/adapter_mxdatetime.h b/psycopg/adapter_mxdatetime.h index b5e4b130..c4857073 100644 --- a/psycopg/adapter_mxdatetime.h +++ b/psycopg/adapter_mxdatetime.h @@ -47,45 +47,45 @@ typedef struct { extern PyObject *psyco_Date(PyObject *module, PyObject *args); #define psyco_Date_doc \ - "psycopg.Date(year, month, day) -> new date" + "Date(year, month, day) -> new date" extern PyObject *psyco_Time(PyObject *module, PyObject *args); #define psyco_Time_doc \ - "psycopg.Time(hour, minutes, seconds) -> new time" + "Time(hour, minutes, seconds) -> new time" extern PyObject *psyco_Timestamp(PyObject *module, PyObject *args); #define psyco_Timestamp_doc \ - "psycopg.Time(year, month, day, hour, minutes, seconds) -> new timestamp" + "Time(year, month, day, hour, minutes, seconds) -> new timestamp" extern PyObject *psyco_DateFromTicks(PyObject *module, PyObject *args); #define psyco_DateFromTicks_doc \ - "psycopg.DateFromTicks(ticks) -> new date" + "DateFromTicks(ticks) -> new date" extern PyObject *psyco_TimeFromTicks(PyObject *module, PyObject *args); #define psyco_TimeFromTicks_doc \ - "psycopg.TimeFromTicks(ticks) -> new time" + "TimeFromTicks(ticks) -> new time" extern PyObject *psyco_TimestampFromTicks(PyObject *module, PyObject *args); #define psyco_TimestampFromTicks_doc \ - "psycopg.TimestampFromTicks(ticks) -> new timestamp" + "TimestampFromTicks(ticks) -> new timestamp" #endif /* PSYCOPG_DEFAULT_MXDATETIME */ extern PyObject *psyco_DateFromMx(PyObject *module, PyObject *args); #define psyco_DateFromMx_doc \ - "psycopg.DateFromMx(mx) -> new date" + "DateFromMx(mx) -> new date" extern PyObject *psyco_TimeFromMx(PyObject *module, PyObject *args); #define psyco_TimeFromMx_doc \ - "psycopg.TimeFromMx(mx) -> new time" + "TimeFromMx(mx) -> new time" extern PyObject *psyco_TimestampFromMx(PyObject *module, PyObject *args); #define psyco_TimestampFromMx_doc \ - "psycopg.TimestampFromMx(mx) -> new timestamp" + "TimestampFromMx(mx) -> new timestamp" extern PyObject *psyco_IntervalFromMx(PyObject *module, PyObject *args); #define psyco_IntervalFromMx_doc \ - "psycopg.IntervalFromMx(mx) -> new interval" + "IntervalFromMx(mx) -> new interval" #ifdef __cplusplus } diff --git a/psycopg/adapter_pboolean.h b/psycopg/adapter_pboolean.h index 1aa61b5b..efdfe56a 100644 --- a/psycopg/adapter_pboolean.h +++ b/psycopg/adapter_pboolean.h @@ -42,7 +42,7 @@ typedef struct { extern PyObject *psyco_Boolean(PyObject *module, PyObject *args); #define psyco_Boolean_doc \ - "psycopg.Boolean(obj) -> new boolean value" + "Boolean(obj) -> new boolean value" #ifdef __cplusplus } diff --git a/psycopg/adapter_qstring.h b/psycopg/adapter_qstring.h index 6fd21e70..9e6c33dd 100644 --- a/psycopg/adapter_qstring.h +++ b/psycopg/adapter_qstring.h @@ -42,7 +42,7 @@ typedef struct { extern PyObject *psyco_QuotedString(PyObject *module, PyObject *args); #define psyco_QuotedString_doc \ - "psycopg.QuotedString(str, enc) -> new quoted string" + "QuotedString(str, enc) -> new quoted string" #ifdef __cplusplus } diff --git a/psycopg/connection_type.c b/psycopg/connection_type.c index 0af2d335..e44f55af 100644 --- a/psycopg/connection_type.c +++ b/psycopg/connection_type.c @@ -37,11 +37,11 @@ /* cursor method - allocate a new cursor */ #define psyco_conn_cursor_doc \ -"cursor(cursor_factory=psycopg2.extensions.cursor) -> new cursor\n\n" \ -"Return a new cursor. The 'cursor_factory' argument can be used to\n" \ -"create non-standard cursors by passing a class different from the\n" \ -"default. Note that the new class *should* be a sub-class of\n" \ -"'psycopg2.extensions.cursor'.\n" +"cursor(cursor_factory=psycopg2.extensions.cursor) -> new cursor\n\n" \ +"Return a new cursor.\n\nThe ``cursor_factory`` argument can be used to\n" \ +"create non-standard cursors by passing a class different from the\n" \ +"default. Note that the new class *should* be a sub-class of\n" \ +"``psycopg2.extensions.cursor``." static PyObject * psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds) @@ -83,7 +83,7 @@ psyco_conn_cursor(connectionObject *self, PyObject *args, PyObject *keywds) /* close method - close the connection and all related cursors */ -#define psyco_conn_close_doc "close() -> close the connection" +#define psyco_conn_close_doc "close() -- Close the connection." static PyObject * psyco_conn_close(connectionObject *self, PyObject *args) @@ -103,7 +103,7 @@ psyco_conn_close(connectionObject *self, PyObject *args) /* commit method - commit all changes to the database */ -#define psyco_conn_commit_doc "commit() -> commit all changes to database" +#define psyco_conn_commit_doc "commit() -- Commit all changes to database." static PyObject * psyco_conn_commit(connectionObject *self, PyObject *args) @@ -123,7 +123,7 @@ psyco_conn_commit(connectionObject *self, PyObject *args) /* rollback method - roll back all changes done to the database */ #define psyco_conn_rollback_doc \ -"rollback() -> roll back all changes done to database" +"rollback() -- Roll back all changes done to database." static PyObject * psyco_conn_rollback(connectionObject *self, PyObject *args) @@ -144,7 +144,7 @@ psyco_conn_rollback(connectionObject *self, PyObject *args) /* set_isolation_level method - switch connection isolation level */ #define psyco_conn_set_isolation_level_doc \ -"set_isolation_level(level) -> switch isolation level to 'level'" +"set_isolation_level(level) -- Switch isolation level to ``level``." static PyObject * psyco_conn_set_isolation_level(connectionObject *self, PyObject *args) @@ -173,7 +173,7 @@ psyco_conn_set_isolation_level(connectionObject *self, PyObject *args) /* set_isolation_level method - switch connection isolation level */ #define psyco_conn_set_client_encoding_doc \ -"set_client_encoding(encoding) -> set client encoding to 'encoding'" +"set_client_encoding(encoding) -- Set client encoding to ``encoding``." static PyObject * psyco_conn_set_client_encoding(connectionObject *self, PyObject *args) @@ -241,13 +241,17 @@ static struct PyMemberDef connectionObject_members[] = { {"NotSupportedError", T_OBJECT, offsetof(connectionObject, exc_NotSupportedError), RO}, #ifdef PSYCOPG_EXTENSIONS - {"closed", T_LONG, offsetof(connectionObject, closed), RO}, + {"closed", T_LONG, offsetof(connectionObject, closed), RO, + "True if the connection is closed."}, {"isolation_level", T_LONG, - offsetof(connectionObject, isolation_level), RO}, - {"encoding", T_STRING, offsetof(connectionObject, encoding), RO}, + offsetof(connectionObject, isolation_level), RO, + "The current isolation level."}, + {"encoding", T_STRING, offsetof(connectionObject, encoding), RO, + "The current client encoding."}, {"notices", T_OBJECT, offsetof(connectionObject, notice_list), RO}, {"notifies", T_OBJECT, offsetof(connectionObject, notifies), RO}, - {"dsn", T_STRING, offsetof(connectionObject, dsn), RO}, + {"dsn", T_STRING, offsetof(connectionObject, dsn), RO, + "The current connection string."}, #endif {NULL} }; @@ -340,7 +344,11 @@ connection_repr(connectionObject *self) /* object type */ #define connectionType_doc \ -"connection(dsn, ...) -> new connection object" +"connection(dsn, ...) -> new connection object\n\n" \ +":Groups:\n" \ +" * `DBAPI-2.0 errors`: `Error`, `Warning`, `InterfaceError`,\n" \ +" `DatabaseError`, `InternalError`, `OperationalError`,\n" \ +" `ProgrammingError`, `IntegrityError`, `DataError`, `NotSupportedError`" PyTypeObject connectionType = { PyObject_HEAD_INIT(NULL) diff --git a/psycopg/cursor_type.c b/psycopg/cursor_type.c index eddab93a..6f84ca4e 100644 --- a/psycopg/cursor_type.c +++ b/psycopg/cursor_type.c @@ -43,7 +43,7 @@ extern PyObject *pyPsycopgTzFixedOffsetTimezone; /* close method - close the cursor */ #define psyco_curs_close_doc \ -"close() -> close the cursor" +"close() -- Close the cursor." static PyObject * psyco_curs_close(cursorObject *self, PyObject *args) @@ -228,7 +228,7 @@ _mogrify(PyObject *var, PyObject *fmt, connectionObject *conn, PyObject **new) } #define psyco_curs_execute_doc \ -"execute(query, vars=None, async=0) -> execute query with bound vars" +"execute(query, vars=None, async=0) -- Execute query with bound vars." static int _psyco_curs_execute(cursorObject *self, @@ -431,7 +431,7 @@ psyco_curs_execute(cursorObject *self, PyObject *args, PyObject *kwargs) } #define psyco_curs_executemany_doc \ -"execute(query, vars_list=(), async=0) -> execute many queries with bound vars" +"executemany(query, vars_list=(), async=0) -- Execute many queries with bound vars." static PyObject * psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs) @@ -477,7 +477,7 @@ psyco_curs_executemany(cursorObject *self, PyObject *args, PyObject *kwargs) #ifdef PSYCOPG_EXTENSIONS #define psyco_curs_mogrify_doc \ -"mogrify(query, vars=None) -> return query after binding vars" +"mogrify(query, vars=None) -> str -- Return query after vars binding." static PyObject * psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs) @@ -569,10 +569,10 @@ psyco_curs_mogrify(cursorObject *self, PyObject *args, PyObject *kwargs) /* fetchone method - fetch one row of results */ #define psyco_curs_fetchone_doc \ -"fetchone() -> next tuple of data or None\n\n" \ +"fetchone() -> tuple or None\n\n" \ "Return the next row of a query result set in the form of a tuple (by\n" \ -"default) or using the sequence factory previously set in the tuplefactory\n" \ -"attribute. Return None when no more data is available.\n" +"default) or using the sequence factory previously set in the\n" \ +"`row_factory` attribute. Return `None` when no more data is available.\n" static int _psyco_curs_prefetch(cursorObject *self) @@ -721,10 +721,10 @@ psyco_curs_fetchone(cursorObject *self, PyObject *args) /* fetch many - fetch some results */ #define psyco_curs_fetchmany_doc \ -"fetchone(size=10000) -> next size tuples of data or None\n\n" \ -"Return the next 'size' rows of a query result set in the form of a tuple\n" \ +"fetchmany(size=self.arraysize) -> list of tuple\n\n" \ +"Return the next `size` rows of a query result set in the form of a list\n" \ "of tuples (by default) or using the sequence factory previously set in\n" \ -"the tuplefactory attribute. Return None when no more data is available.\n" +"the `row_factory` attribute. Return `None` when no more data is available.\n" PyObject * psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords) @@ -795,11 +795,11 @@ psyco_curs_fetchmany(cursorObject *self, PyObject *args, PyObject *kwords) /* fetch all - fetch all results */ #define psyco_curs_fetchall_doc \ -"fetchall() -> all remaining tuples of data or None\n\n" \ -"Return all the remaining rows of a query result set in the form of a\n" \ -"tuple of tuples (by default) or using the sequence factory previously\n" \ -"set in the tuplefactory attribute. Return None when no more data is\n" \ -"available.\n" +"fetchall() -> list of tuple\n\n" \ +"Return all the remaining rows of a query result set.\n\n" \ +"Rows are returned in the form of a list of tuples (by default) or using\n" \ +"the sequence factory previously set in the `row_factory` attribute.\n" \ +"Return `None` when no more data is available.\n" PyObject * psyco_curs_fetchall(cursorObject *self, PyObject *args) @@ -861,7 +861,7 @@ psyco_curs_fetchall(cursorObject *self, PyObject *args) /* callproc method - execute a stored procedure */ #define psyco_curs_callproc_doc \ -"callproc(procname, [parameters]) -> execute stored procedure" +"callproc(procname, parameters=None, async=0) -- Execute stored procedure." static PyObject * psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs) @@ -917,7 +917,7 @@ psyco_curs_callproc(cursorObject *self, PyObject *args, PyObject *kwargs) /* nextset method - return the next set of data (not supported) */ #define psyco_curs_nextset_doc \ -"nextset() -> skip to next set of data\n\n" \ +"nextset() -- Skip to next set of data.\n\n" \ "This method is not supported (PostgreSQL does not have multiple data \n" \ "sets) and will raise a NotSupportedError exception." @@ -936,7 +936,7 @@ psyco_curs_nextset(cursorObject *self, PyObject *args) /* setinputsizes - predefine memory areas for execute (does nothing) */ #define psyco_curs_setinputsizes_doc \ -"setinputsizes(sizes) -> set memory areas before execute\n\n" \ +"setinputsizes(sizes) -- Set memory areas before execute.\n\n" \ "This method currently does nothing but it is safe to call it." static PyObject * @@ -957,7 +957,7 @@ psyco_curs_setinputsizes(cursorObject *self, PyObject *args) /* setoutputsize - predefine memory areas for execute (does nothing) */ #define psyco_curs_setoutputsize_doc \ -"setoutputsize(size, [column]) -> set column buffer size\n\n" \ +"setoutputsize(size, column=None) -- Set column buffer size.\n\n" \ "This method currently does nothing but it is safe to call it." static PyObject * @@ -978,7 +978,7 @@ psyco_curs_setoutputsize(cursorObject *self, PyObject *args) /* scroll - scroll position in result list */ #define psyco_curs_scroll_doc \ -"scroll(value, mode='relative') -> scroll to new position according to mode" +"scroll(value, mode='relative') -- Scroll to new position according to mode." static PyObject * psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs) @@ -1043,7 +1043,7 @@ psyco_curs_scroll(cursorObject *self, PyObject *args, PyObject *kwargs) /* extension: copy_from - implements COPY FROM */ #define psyco_curs_copy_from_doc \ -"copy_from(file, table, sep='\\t', null='\\N') -> copy file to table." +"copy_from(file, table, sep='\\t', null='\\N') -- Copy table from file." static int _psyco_curs_has_read_check(PyObject* o, void* var) @@ -1104,7 +1104,7 @@ psyco_curs_copy_from(cursorObject *self, PyObject *args, PyObject *kwargs) } #define psyco_curs_copy_to_doc \ -"copy_to(file, table, sep='\\t', null='\\N') -> copy file to table." +"copy_to(file, table, sep='\\t', null='\\N') -- Copy table to file." static int _psyco_curs_has_write_check(PyObject* o, void* var) @@ -1163,7 +1163,7 @@ psyco_curs_copy_to(cursorObject *self, PyObject *args, PyObject *kwargs) /* extension: fileno - return the file descripor of the connection */ #define psyco_curs_fileno_doc \ -"fileno() -> return file descriptor associated to database connection" +"fileno() -> int -- Return file descriptor associated to database connection." static PyObject * psyco_curs_fileno(cursorObject *self, PyObject *args) @@ -1188,7 +1188,7 @@ psyco_curs_fileno(cursorObject *self, PyObject *args) /* extension: isready - return true if data from async execute is ready */ #define psyco_curs_isready_doc \ -"isready() -> return True if data is ready after an async query" +"isready() -> bool -- Return True if data is ready after an async query." static PyObject * psyco_curs_isready(cursorObject *self, PyObject *args) @@ -1296,17 +1296,26 @@ static struct PyMethodDef cursorObject_methods[] = { static struct PyMemberDef cursorObject_members[] = { /* DBAPI-2.0 basics */ - {"rowcount", T_LONG, OFFSETOF(rowcount), RO}, - {"arraysize", T_LONG, OFFSETOF(arraysize), 0}, - {"description", T_OBJECT, OFFSETOF(description), RO}, - {"lastrowid", T_LONG, OFFSETOF(lastoid), RO}, + {"rowcount", T_LONG, OFFSETOF(rowcount), RO, + "Number of rows read from the backend in the last command."}, + {"arraysize", T_LONG, OFFSETOF(arraysize), 0, + "Number of records `fetchmany()` must fetch if not explicitely " \ + "specified."}, + {"description", T_OBJECT, OFFSETOF(description), RO, + "Cursor description as defined in DBAPI-2.0."}, + {"lastrowid", T_LONG, OFFSETOF(lastoid), RO, + "The ``oid`` of the last row inserted by the cursor."}, /* DBAPI-2.0 extensions */ - {"rownumber", T_LONG, OFFSETOF(row), RO}, - {"connection", T_OBJECT, OFFSETOF(conn), RO}, + {"rownumber", T_LONG, OFFSETOF(row), RO, + "The current row position."}, + {"connection", T_OBJECT, OFFSETOF(conn), RO, + "The connection where the cursor comes from."}, #ifdef PSYCOPG_EXTENSIONS {"name", T_STRING, OFFSETOF(name), RO}, - {"statusmessage", T_OBJECT, OFFSETOF(pgstatus), RO}, - {"query", T_OBJECT, OFFSETOF(query), RO}, + {"statusmessage", T_OBJECT, OFFSETOF(pgstatus), RO, + "The return message of the last command."}, + {"query", T_OBJECT, OFFSETOF(query), RO, + "The last query text sent to the backend."}, {"row_factory", T_OBJECT, OFFSETOF(tuple_factory), 0}, {"tzinfo_factory", T_OBJECT, OFFSETOF(tzinfo_factory), 0}, {"typecaster", T_OBJECT, OFFSETOF(caster), RO}, diff --git a/psycopg/microprotocols.h b/psycopg/microprotocols.h index d6df2545..5501a7c6 100644 --- a/psycopg/microprotocols.h +++ b/psycopg/microprotocols.h @@ -55,6 +55,6 @@ extern PyObject *microprotocol_getquoted( extern PyObject * psyco_microprotocols_adapt(cursorObject *self, PyObject *args); #define psyco_microprotocols_adapt_doc \ - "psycopg.adapt(obj, protocol, alternate) -> adapt obj to given protocol" + "adapt(obj, protocol, alternate) -> object -- adapt obj to given protocol" #endif /* !defined(PSYCOPG_MICROPROTOCOLS_H) */ diff --git a/psycopg/microprotocols_proto.c b/psycopg/microprotocols_proto.c index a7934bbe..72c3a7eb 100644 --- a/psycopg/microprotocols_proto.c +++ b/psycopg/microprotocols_proto.c @@ -38,7 +38,7 @@ /* getquoted - return quoted representation for object */ #define psyco_isqlquote_getquoted_doc \ -"getquoted() -> return SQL-quoted representation of this object" +"getquoted() -- return SQL-quoted representation of this object" static PyObject * psyco_isqlquote_getquoted(isqlquoteObject *self, PyObject *args) @@ -52,7 +52,7 @@ psyco_isqlquote_getquoted(isqlquoteObject *self, PyObject *args) /* getbinary - return quoted representation for object */ #define psyco_isqlquote_getbinary_doc \ -"getbinary() -> return SQL-quoted binary representation of this object" +"getbinary() -- return SQL-quoted binary representation of this object" static PyObject * psyco_isqlquote_getbinary(isqlquoteObject *self, PyObject *args) @@ -66,7 +66,7 @@ psyco_isqlquote_getbinary(isqlquoteObject *self, PyObject *args) /* getbuffer - return quoted representation for object */ #define psyco_isqlquote_getbuffer_doc \ -"getbuffer() -> return this object" +"getbuffer() -- return this object" static PyObject * psyco_isqlquote_getbuffer(isqlquoteObject *self, PyObject *args) @@ -152,7 +152,9 @@ isqlquote_del(PyObject* self) /* object type */ #define isqlquoteType_doc \ -"Abstract ISQLQuote protocol" +"Abstract ISQLQuote protocol\n\n" \ +"An object conform to this protocol should expose a ``getquoted()`` method\n" \ +"returning the SQL representation of the object.\n\n" PyTypeObject isqlquoteType = { PyObject_HEAD_INIT(NULL) diff --git a/psycopg/psycopgmodule.c b/psycopg/psycopgmodule.c index cb2e71fb..eee3acbb 100644 --- a/psycopg/psycopgmodule.c +++ b/psycopg/psycopgmodule.c @@ -65,25 +65,25 @@ PyObject *decimalType = NULL; /** connect module-level function **/ #define psyco_connect_doc \ -"connect(dsn, ...) -> new connection object\n\n" \ +"connect(dsn, ...) -> new connection object -- Create a new database connection.\n\n" \ "This function supports two different but equivalent sets of arguments.\n" \ -"A single data source name or 'dsn' string can be used to specify the\n" \ +"A single data source name or ``dsn`` string can be used to specify the\n" \ "connection parameters, as follows::\n\n" \ " psycopg2.connect(\"dbname=xxx user=xxx ...\")\n\n" \ -"If 'dsn' is not provided it is possible to pass the parameters as\n" \ +"If ``dsn`` is not provided it is possible to pass the parameters as\n" \ "keyword arguments; e.g.::\n\n" \ " psycopg2.connect(database='xxx', user='xxx', ...)\n\n" \ "The full list of available parameters is:\n\n" \ -" - dbname -- database name (only in 'dsn')\n" \ -" - database -- database name (only as keyword argument)\n" \ -" - host -- host address (defaults to UNIX socket if not provided)\n" \ -" - port -- port number (defaults to 5432 if not provided)\n" \ -" - user -- user name used to authenticate\n" \ -" - password -- password used to authenticate\n" \ -" - sslmode -- SSL mode (see PostgreSQL documentation)\n\n" \ -"If the 'connection_factory' keyword argument is not provided this\n" \ -"function always return an instance of the 'psycopg2.connection' class.\n" \ -"Else the given sub-class of 'psycopg2.connection' will be used to\n" \ +"- ``dbname`` -- database name (only in 'dsn')\n" \ +"- ``database`` -- database name (only as keyword argument)\n" \ +"- ``host`` -- host address (defaults to UNIX socket if not provided)\n" \ +"- ``port`` -- port number (defaults to 5432 if not provided)\n" \ +"- ``user`` -- user name used to authenticate\n" \ +"- ``password`` -- password used to authenticate\n" \ +"- ``sslmode`` -- SSL mode (see PostgreSQL documentation)\n\n" \ +"If the ``connection_factory`` keyword argument is not provided this\n" \ +"function always return an instance of the ``connection`` class.\n" \ +"Else the given sub-class of ``connection`` will be used to\n" \ "instantiate the connection object.\n" static int @@ -102,17 +102,17 @@ _psyco_connect_fill_exc(connectionObject *conn) Py_INCREF(Error); conn->exc_Warning = Warning; Py_INCREF(Warning); - conn->exc_InterfaceError = Error; + conn->exc_InterfaceError = InterfaceError; Py_INCREF(InterfaceError); - conn->exc_DatabaseError = Error; + conn->exc_DatabaseError = DatabaseError; Py_INCREF(DatabaseError); - conn->exc_InternalError = Error; + conn->exc_InternalError = InternalError; Py_INCREF(InternalError); - conn->exc_ProgrammingError = Error; + conn->exc_ProgrammingError = ProgrammingError; Py_INCREF(ProgrammingError); - conn->exc_IntegrityError = Error; + conn->exc_IntegrityError = IntegrityError; Py_INCREF(IntegrityError); - conn->exc_DataError = Error; + conn->exc_DataError = DataError; Py_INCREF(DataError); conn->exc_NotSupportedError = NotSupportedError; Py_INCREF(NotSupportedError); @@ -194,7 +194,21 @@ psyco_connect(PyObject *self, PyObject *args, PyObject *keywds) /** type registration **/ #define psyco_register_type_doc \ -"register_type(obj) -> register obj with psycopg type system" +"register_type(obj) -> None -- register obj with psycopg type system\n\n" \ +":Parameters:\n" \ +" * `obj`: A type adapter created by `new_type()`" + +#define typecast_from_python_doc \ +"new_type(oids, name, adapter) -> new type object\n\n" \ +"Create a new binding object. The object can be used with the\n" \ +"`register_type()` function to bind PostgreSQL objects to python objects.\n\n" \ +":Parameters:\n" \ +" * `oids`: Tuple of ``oid`` of the PostgreSQL types to convert.\n" \ +" * `name`: Name for the new type\n" \ +" * `adapter`: Callable to perform type conversion.\n" \ +" It must have the signature ``fun(value, cur)`` where ``value`` is\n" \ +" the string representation returned by PostgreSQL (`None` if ``NULL``)\n" \ +" and ``cur`` is the cursor from which data are read." static PyObject * psyco_register_type(PyObject *self, PyObject *args) @@ -383,7 +397,7 @@ static PyMethodDef psycopgMethods[] = { {"register_type", (PyCFunction)psyco_register_type, METH_VARARGS, psyco_register_type_doc}, {"new_type", (PyCFunction)typecast_from_python, - METH_VARARGS|METH_KEYWORDS}, + METH_VARARGS|METH_KEYWORDS, typecast_from_python_doc}, {"AsIs", (PyCFunction)psyco_AsIs, METH_VARARGS, psyco_AsIs_doc}, diff --git a/scripts/ext2html.py b/scripts/ext2html.py new file mode 100755 index 00000000..488e97ff --- /dev/null +++ b/scripts/ext2html.py @@ -0,0 +1,169 @@ +#!/usr/bin/env python + +# Author: Daniele Varrazzo +# Contact: daniele dot varrazzo at gmail dot com +# Revision: $Revision$ +# Date: $Date$ +# Copyright: This module has been placed in the public domain. + +""" +A minimal front end to the Docutils Publisher, producing HTML. + +Output can refer to Epydoc-generated APIs through the iterpreted text role +"api". +""" + +import types +import sys + +# The url fragment where the api "index.html" resides w.r.t. the generated docs +api_root = "api/" + +try: + import locale + locale.setlocale(locale.LC_ALL, '') +except: + pass + +from docutils.core import publish_cmdline, default_description +from docutils.parsers.rst.roles import register_canonical_role +from docutils import nodes, utils + +# api references are searched for in these modules +api_modules = [ + 'psycopg2', + 'psycopg2._psycopg', + 'psycopg2.extensions', +] + +# name starting with a dot are looking as those objects attributes. +searched_objects = [ + # module_name, object_name + ('psycopg2.extensions', 'connection'), + ('psycopg2.extensions', 'cursor'), +] + +# import all the referenced modules +for modname in api_modules: + __import__(modname) + +class EpydocTarget: + """Representation of an element language.""" + def __init__(self, name, element): + self.name = name + + # The python object described + self.element = element + + # The base name of the page + self.page = None + + # The url fragment + self.fragment = None + + def get_url(self): + # is it a private element? + components = self.page.split('.') + if self.fragment: components.append(self.fragment) + + for component in components: + if component.startswith('_'): + private = True + break + else: + private = False + + ref = api_root + (private and "private/" or "public/") \ + + self.page + "-" + self.get_type() + ".html" + if self.fragment: + ref = ref + "#" + self.fragment + + return ref + + def get_type(self): + # detect the element type + if isinstance(self.element, types.TypeType): + return 'class' + elif isinstance(self.element, types.ModuleType): + return 'module' + else: + raise ValueError("Can't choose a type for '%s'." % self.name) + +def filter_par(name): + """Filter parenthesis away from a name.""" + if name.endswith(")"): + return name.split("(")[0] + else: + return name + +def get_element_target(name): + """Return the life, the death, the miracles about a package element.""" + + name = filter_par(name) + + if name.startswith('.'): + for modname, objname in searched_objects: + if hasattr(getattr(sys.modules[modname], objname), name[1:]): + name = objname + name + break + + # is the element a module? + if name in api_modules: + out = EpydocTarget(name, sys.modules[name]) + out.page = name + return out + + # look for the element in some module + for modname in api_modules: + element = getattr(sys.modules[modname], name, None) + if element is not None: + + # Check if it is a function defined in a module + if isinstance(element, + (int, types.FunctionType, types.BuiltinFunctionType)): + out = EpydocTarget(name, sys.modules[modname]) + out.page = modname + out.fragment = name + else: + out = EpydocTarget(name, element) + out.page = modname + '.' + name + + return out + + # maybe a qualified name? + if '.' in name: + out = get_element_target('.'.join(name.split('.')[:-1])) + if out is not None: + out.fragment = filter_par(name.split('.')[-1]) + return out + + raise ValueError("Can't find '%s' in any provided module." % name) + +def api_role(role, rawtext, text, lineno, inliner, + options={}, content=[]): + try: + target = get_element_target(text) + except Exception, exc: + msg = inliner.reporter.error(str(exc), line=lineno) + prb = inliner.problematic(rawtext, rawtext, msg) + return [prb], [msg] + + ref = target.get_url() + node2 = nodes.literal(rawtext, utils.unescape(text)) + node = nodes.reference(rawtext, '', node2, refuri=ref, + **options) + return [node], [] + + +register_canonical_role('api', api_role) + +# Register the 'api' role as canonical role +from docutils.parsers.rst import roles +roles.DEFAULT_INTERPRETED_ROLE = 'api' + + +description = ('Generates (X)HTML documents from standalone reStructuredText ' + 'sources with links to Epydoc API. ' + default_description) + + +publish_cmdline(writer_name='html', description=description) diff --git a/scripts/makedocs.py b/scripts/makedocs.py new file mode 100755 index 00000000..dcaa940a --- /dev/null +++ b/scripts/makedocs.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python +"""Build documentation and api.""" + +import os + +EPYDOC = "python c:/programmi/python23/scripts/epydoc.py" +PSYCOPG = "c:/programmi/python23/lib/site-packages/psycopg2" + +os.system("python ext2html.py ../doc/extensions.rst > ../doc/extensions.html") +os.system("%s " + "-o ../doc/api " + "--css ../doc/api-screen.css " + "--docformat restructuredtext " + "%s" + % (EPYDOC,PSYCOPG,))