Ravenbrook / Projects / Perforce Defect Tracking Integration
Perforce Defect Tracking Integration Project
This document describes a Python extension that provides an interface to the TeamShare API, and specifically to the tTrack defect tracking system.
The purpose of this document is to make it possible for people to maintain the extension, and to use the Python interface.
The intended readership is anyone working on the p4dti project.
The interface defines one module, ttrack
(use
import ttrack
). There are two classes, representing tTrack
servers and records from the tTrack database. These classes don't have
names in Python: the only way to make a server object is to connect to a
server using ttrack.connect
, and the only way to make
record objects (at present) is to query the server.
The Python error object for errors generated by the TeamShare interface or by the TeamShare API. It is always associated with a message. For example:
try:
# do ttrack stuff
except ttrack.error, message:
print message
The ttrack
module can throw other exceptions, notably
KeyError
(when a field name is not found in a record).
A dictionary that maps the name of a table in the tTrack database
(minus the initial TS_
) to its table identifier (a small
integer). For example
ttrack.tables['CASES']
is the table identifier for the TS_CASES
table.
Attempts to connect to a TeamShare server on hostname (use the format
"host:8080
" to specify a non-default port number) with the
specified userid and password. If it succeeds, it returns a server
object representing the connection. If it fails, it raises a
ttrack.error
exception. For example:
server = ttrack.connect('joe', '', 'sandpiper')
Attempts to read the record from the specified table (which must be
one of the table identifiers specified in ttrack.table
)
with the specified record identifier. If it succeeds, it returns a
record object representing the record. If it fails, it raises a
ttrack.error
exception. For example, the call
record = server.read_record(ttrack.tables['CASES'], 17)
is roughly equivalent to the SQL query
SELECT * FROM TS_CASES WHERE TS_ID = 17
Executes an SQL query on the specified table (which must be one of the
table identifiers specified in ttrack.table
) of the form
SELECT * FROM table
(if where_clause
is the empty string), or
SELECT * FROM table WHERE where_clause
(otherwise). If it is successful, the records matching the query are
returned as list of record objects. If it fails, it raises a
ttrack.error
exception.
Remember to use the right field names in the where clause: the
returned record may contain a field called foo
, but the
database field is probably TS_FOO
. See [TeamShare
2000-01-20] for details of the TeamShare database.
Records present (part of) the Python dictionary interface. To look up a field in a record object, index the record object with the field name. For example:
# Get the title of case 17
record = server.read_record(ttrack.tables['CASES'], 17)
title = record['TITLE']
To update a field in a record object, assign to the index expression.
For example record['TITLE'] = 'Foo'
.
As for ordinary Python dictionaries, the has_key
method determines if a field is present in the record, and the
keys
method returns a list of names of fields in the
record.
To get all the cases which have changed in the last hour:
import ttrack, time
s = ttrack.connect('joe', '', 'sandpiper')
t = time.time() - 3600
q = 'TS_ID IN (SELECT TS_CASEID FROM TS_CHANGES WHERE TS_TIME>%d)' % t
cases = s.query(ttrack.tables['CASES'], q)
Python extension modules are described in [Lutz 1996, 14]. Additional details with respect to building Python extensions using Visual C++ on Windows are given in [Hammond 2000, 22].
The TeamShare interface to tTrack is described in [TeamShare 2000-01-19].
I have only built the extension under Windows NT and Windows 2000. I believe it should build and run anywhere that Python and the TeamShare API run.
TeamShare provide two versions of their library:
tsapi.lib
and TSApiWin32.dll
. I can build
extensions using the former but not using the latter. I guess that the
former is suitable for console applications and that latter for MFC
applications.
There are three places where I have used Windows-specific code. In
all cases the code is protected by #if defined(WIN32)
... #endif
.
The file ttrackpython.h
is a wrapper around
Python.h
that makes sure that the constant
_DEBUG
is not defined when Python.h
is
compiled. This is because Python.h
contains a pair of
#pragma
statements that indicate to Visual C++ which
library should be linked with (pythonnn.lib
or
pythonnn_d.lib
for debugging). The problem with
this is that Python extensions have to be linked with the same Python
library that the Python interpreter and all other extensions are linked
with. The Python distribution doesn't come with a debugging version of
Python or any of its extensions, so we'd have to build all of these
ourselves. It's better for us just to link with the release version of
the Python library regardless. This is explained in [Hammond 2000, 22].
Sockets on Windows need to be initialized. The TeamShare API
provides the function TSInitializeWinsock
to do this. I
call this from initttrack
in
ttrackmodule.cpp
.
Functions that are exported from a DLL need either to have the declarator
__declspec(dllexport)
or to be mentioned in a
/DLLEXPORT:foo
compiler option. We use the former method,
defining the macro TTRACK_EXPORTED
for this purpose. The
only exported function is inittrack
in
ttrackmodule.cpp
.
Reference count management is briefly introduced in [Lutz 1996, page 585], but there's a much better account in [van Rossum 1999-04-13, 1.10].
I've commented each use of Py_DECREF
with the new owner
of the object, or "Destroy" if the intention is to destroy the object.
Where a Py_DECREF
would be expected (because the object has
been passed to a new owner) but is not needed because the new owner does
not increment the reference count, I have added a note to say so. This
applied to objects passed to PyList_SetItem
and
PyTuple_SetItem
(I guess that these functions are optimized
for the case where a newly-created object is added to the structure).
See [van Rossum 1999-04-13,
1.10.2].
The API source calls new
, malloc
and
realloc
without checking the return code.
When an error occurs at the tTrack server, no information about
the error is recorded by the TeamShare API. For example, if you call
TSServer::ReadRecordListWithWhere
with bogus SQL for the
where clause then you don't get a SQL error back - you just get a
generic TS_ERROR
. This makes it very hard to debug
problems on the server side.
The TeamShare API sometimes sets an error code and an error message; most of the time it just sets an error code.
The TeamShare API documentation doesn't say anything about memory
management. For example, if you create a TSRecordList
object (say by calling TSServer::ReadRecordList) then
are the TSRecord
objects in that list deleted when the
TSRecordList
object is deleted? It appears not to be the
case: it looks like you have to call
TSRecordList::EmptyAndDestroyList
. It would be nice if
the documentation were more explicit about this issue.
[Hammond 2000] | "Python Programming on Win32"; Mark Hammond and Andy Robinson; OReilly; 2000-01; ISBN 1-56592-621-8. |
[Lutz 1996] | "Programming Python"; Mark Lutz; O'Reilly; 1996-10; ISBN 1-56592-197-6. |
[TeamShare 2000-01-19] | "TeamShare API"; TeamShare; 2000-01-19. |
[TeamShare 2000-01-20] | "TeamTrack Database Schema (Database Version: 21)"; TeamShare; 2000-01-20. |
[van Rossum 1999-04-13] | "Extending and Embedding the Python Interpreter (release 1.5.2)"; Guido van Rossum; 1999-04-13. |
2000-08-08 | GDR | Created |
Copyright © 2000 Ravenbrook Limited. This document is provided "as is", without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this document. You may make and distribute verbatim copies of this document provided that you do not charge a fee for this document or for its distribution.
$Id: //info.ravenbrook.com/project/p4dti/version/0.1/ttrack/ttrack.html#2 $
Ravenbrook / Projects / Perforce Defect Tracking Integration