Api Layer

Public Api for the PyCommence library, which provides a Python interface to the Commence database.

PyCommence Manager

class PyCommence(cmc_wrapper=<factory>, csrs=<factory>, conversations=<factory>)[source]

Main interface for interacting with a Commence database.

Manages database connections, cursors, and DDE conversations. Provides high-level methods for CRUD operations and cursor management. Wraps an instance of CommenceWrapper

Typical Usage:
>>> pyc = PyCommence.with_csr("Contacts", mode=CursorType.CATEGORY)
>>> pyc.create_row({"Name": "Alice"})
>>> for row in pyc.read_rows():
...     print(row)
cmc_wrapper: CommenceWrapper
csrs: dict[str, CursorAPI]
conversations: dict[ConversationTopic, ConversationAPI]
classmethod with_csr(csrname, mode=CursorType.CATEGORY)[source]

Create a new PyCommence instance with a cursor.

Parameters:
  • csrname (str) – Name of the category or view.

  • mode (CursorType) – Cursor type (default: CATEGORY).

Returns:

Instance with cursor initialised.

Return type:

PyCommence

set_csr(csrname, mode=CursorType.CATEGORY)[source]

Add or update a cursor by name and type.

Parameters:
  • csrname (str) – Name of the category or view.

  • mode (CursorType) – Cursor type (default: CATEGORY).

Returns:

Self for chaining.

Return type:

PyCommence

csr(csrname=None)[source]

Return a cursor by name, or the only cursor if only one is available.

Return type:

CursorAPI

refresh_csr(csr)[source]

Reset an existing cursor with same name, mode and filter_array

Return type:

Self

set_conversation(topic='ViewData')[source]

Add a DDE conversation by topic.

Parameters:

topic (ConversationTopic) – DDE topic name.

Returns:

Self for chaining.

Return type:

PyCommence

classmethod with_conversation(topic='ViewData')[source]

Create a PyCommence instance with a DDE conversation.

Parameters:

topic (ConversationTopic) – DDE topic name.

Returns:

Instance with conversation set.

Return type:

PyCommence

create_row(create_pkg, csrname=None)[source]

Add a new row to the database.

Parameters:
  • create_pkg (dict) – Field names and values for the new row.

  • csrname (str, optional) – Cursor name (or only available).

read_row(*, csrname=None, row_id=None, pk=None)[source]
Return type:

RowData

read_rows(csrname=None, pagination=None, filter_array=None, row_filter=None, fetch_ids=True)[source]

Generate rows from a cursor

Parameters:
  • csrname (str | None) – Name of cursor (optional if only one cursor is set)

  • pagination (Pagination | None) – Pagination object

  • filter_array (FilterArray | None) – FilterArray object (override cursor filter)

  • row_filter (Callable[[Generator[dict[str, str], None, None]], Generator[dict[str, str], None, None]] | None) – Filter generator

  • fetch_ids (bool) – default: True, disable for performance

Yields:

row_data – RowData more_available: MoreAvailable

Return type:

Generator[RowData | MoreAvailable, None, None]

update_row(update_pkg, row_id=None, pk=None, csrname=None)[source]

Update a row by id or pk

Parameters:
  • update_pkg (dict) – dict of field names and values to update

  • row_id (str | None) – row id (id or pk must be provided)

  • pk (str | None) – row pk (id or pk must be provided)

  • csrname (str | None) – cursor name (default = Self.get_csrname())

delete_row(row_id=None, pk=None, csrname=None)[source]

Delete a row by ID or primary key.

pycommence_context(csrname, mode=CursorType.CATEGORY)[source]

Context manager for PyCommence with a single cursor

Return type:

Generator[PyCommence, None, None]

pycommences_context(csrnames)[source]

Context manager for PyCommence with multiple cursors

Return type:

Generator[PyCommence, None, None]

Cursor

Cursor abstraction for Commence database.

Provides the CursorAPI class for high-level CRUD operations, filtering, and row navigation. Wraps CursorWrapper for direct COM access.

raise_for_id_or_pk(id, pk)[source]

Ensure at least one of id or pk is provided.

class CursorAPI(cursor_wrapper, mode=CursorType.CATEGORY, csrname='')[source]

High-level API for interacting with a Commence database cursor.

Wraps CursorWrapper and provides methods for CRUD operations, filtering, and row navigation.

Not to be created directly; use PyCommence to manage cursors.

cursor_wrapper

Underlying COM cursor wrapper.

Type:

CursorWrapper

mode

Cursor type (e.g., CATEGORY, VIEW).

Type:

CursorType

csrname

Name of the category or view.

Type:

str

property category: str

Commence Category name.

property column_count: int

Number of columns in the Cursor.

property row_count: int

Number of rows in the Cursor.

property shared: bool

True if the database is enrolled in a workgroup.

property pk_label: str

Column 0 label.

pk_filter(pk, condition=ConditionType.EQUAL)[source]

Create a filter for the given primary key.

Return type:

FieldFilter

pk_exists(pk)[source]

Check if primary key exists in the Cursor.

Parameters:

pk (str) – Primary key value to check.

Returns:

True if the primary key exists, else False.

Return type:

bool

pk_to_id(pk)[source]

Convert primary key to row ID.

Parameters:

pk (str) – Primary key value.

Returns:

Row ID corresponding to the primary key.

Return type:

str

Raises:
pk_to_row_ids(pk)[source]

Get all row IDs matching a primary key. (Commence allows duplicate entries, disambiguation not yet implemented in PyCommence)

Parameters:

pk (str) – Primary key value.

Returns:

List of row IDs.

Return type:

list[str]

row_id_to_pk(row_id)[source]

Convert row ID to primary key.

Return type:

str

create_row(create_pkg)[source]

Add a new row to the database.

Parameters:

create_pkg (dict) – Field names and values for the new row (must contain primary_key).

Raises:
  • ValueError – If primary key is not provided in create_pkg.

  • PyCommenceExistsError – If primary key already exists.

Return type:

None

read_row(row_id)[source]

Retrieve a single row by row ID.

Parameters:

row_id (str) – Row ID.

Returns:

Object containing row information and data.

Return type:

RowData

read_rows(pagination=None, filter_array=None, row_filter=None)[source]
Return type:

Generator[dict[str, str] | MoreAvailable, None, None]

read_rows2(pagination=None, filter_array=None, row_filter=None, fetch_ids=False)[source]
Return type:

Generator[RowData | MoreAvailable, None, None]

update_row(update_pkg, *, id=None, pk=None)[source]
delete_row(id=None, pk=None)[source]
Return type:

None

add_category_to_dict(row)[source]
filter_by_array(filter_array)[source]
Return type:

Self

temporary_offset(offset)[source]

Temporarily offset the cursor.

temporary_filter(fil_array)[source]

Temporarily filter by FilterArray object.

Parameters:

fil_array (FilterArray) – FilterArray object

clear_filter(slot=1)[source]
Return type:

None

clear_all_filters()[source]

Clear all filters.

Return type:

None

Add a related column to the cursor.

Return type:

Self

Filters

class ConditionType(*values)[source]
EQUAL = 'Equal To'
CONTAIN = 'Contains'
AFTER = 'After'
BETWEEN = 'Is Between'
BEFORE = 'Before'
NOT_EQUAL = 'Not Equal To'
NOT_CONTAIN = "Doesn't Contain"
ON = 'On'
NOT = 'No'
pydantic model CmcFilter[source]
Fields:
field kind: FilterKind [Required]
field column: str [Required]
field value: str = ''
field not_flag: NotFlagType = ''
field condition: ConditionType = 'Equal To'
view_filter_str(slot=1)[source]
pydantic model FieldFilter[source]

Cursor Filter.

Fields:
field kind: Literal['F'] = 'F'
to_array()[source]

Convert to FilterArray.

Return type:

FilterArray

pydantic model ConnectedItemFilter[source]
Fields:
field kind: Literal['CTI'] = 'CTI'
field connection_category: str [Required]
pydantic model ConnectedFieldFilter[source]
Fields:
field kind: Literal['CTCF'] = 'CTCF'
field connected_column: str [Required]
classmethod from_fil(field_fil, connection)[source]
pydantic model ConnectedItemConnectedItemFilter[source]
Fields:
field kind: Literal['CTCTI'] = 'CTCTI'
field connection_column_2: str [Required]
field connection_category_2: str [Required]
class SortOrder(*values)[source]
ASC = 'Ascending'
DESC = 'Descending'
class Sort(column, order)[source]
column: str

Alias for field number 0

order: SortOrder

Alias for field number 1

class Sorts(iterable=(), /)[source]
pydantic model FilterArray[source]

Array of Cursor Filters.

Fields:
Validators:
field filters: dict[int, CmcFilter] [Optional]
Validated by:
field sorts: list[Sort] [Optional]
Validated by:
field logics: list[Logic] [Optional]
Validated by:
validator val_logics  »  all fields[source]
classmethod from_filters(*filters, sorts=None, logics=None)[source]
property sorts_txt
property view_sort_text
property sort_logics_text
property filter_strs
update(pkg)[source]
add_filter(cmc_filter, logic='And')[source]
add_filters(*filters)[source]
field_fil_to_confil(field_fil, connection)[source]

Types

class RowInfo(category, id)[source]
category: str

Alias for field number 0

id: str

Alias for field number 1

class RowData(row_info, data)[source]
row_info: RowInfo

Alias for field number 0

data: dict[str, str]

Alias for field number 1

classmethod from_data(category, row_id, data)[source]

Create a RowData instance from category, row_id, and data.

Return type:

RowData

class NoneFoundHandler(*values)[source]
ignore = 'IGNORE'
error = 'ERROR'
class SeekBookmark(*values)[source]

Starting point for cursor seek operations.

BEGINNING = 0
CURRENT = 1
END = 2
class Connection1(name, from_table, to_table)[source]
name: str
from_table: str
to_table: str
class Connection(name, category, column)[source]
name: str
category: str
column: str
to_cmc_date(datecheck)[source]
get_cmc_date(v)[source]

Use CMC Cannonical flag

Return type:

date | None

get_cmc_time(time_str)[source]

Use CMC Cannonical flag

class CursorType(*values)[source]

Commence Cursor Types to view based on category, view, or preferences.

CATEGORY = 0
VIEW = 1
PILOT_ADDRESS = 2
PILOT_MEMO = 3
PILOT_TODO = 5
PILOT_APPOINT = 6
OUTLOOK_ADDRESS = 7
OUTLOOK_APPOINT = 8
OUTLOOK_EMAIL_LOG = 9
OUTLOOK_TASK = 10
LETTER_MERGE = 11
class Bookmark(*values)[source]

Starting point for cursor seek operations.

BEGINNING = 0
CURRENT = 1
END = 2
class OptionFlag(*values)[source]

Flags for get_record and get_value methods.

NONE = 0
FIELD_NAME = 1
ALL = 2
SHARED = 4
PILOT = 8
CANONICAL = 16
INTERNET = 32
class OptionFlagInt(*values)[source]

Flags for get_record and get_value methods.

NONE = 0
FIELD_NAME = 1
ALL = 2
SHARED = 4
PILOT = 8
CANONICAL = 16
INTERNET = 32
class CmcFieldType(*values)[source]
TEXT = 0
NUMBER = 1
DATE = 2
TELEPHONE = 3
CHECKBOX = 7
NAME = 11
DATAFILE = 12
IMAGE = 13
TIME = 14
EXCEL_CELL = 15
CALCULATION = 20
SEQUENCE = 21
SELECTION = 22
EMAIL = 23
URL = 24
class CmcFieldDataType(*values)[source]
TEXT = <class 'str'>
NUMBER = <class 'decimal.Decimal'>
DATE()

Return date object with same year, month and day.

TELEPHONE = <class 'str'>
CHECKBOX = <class 'bool'>
NAME = <class 'str'>
DATAFILE = <class 'pathlib._local.Path'>
IMAGE = <class 'pathlib._local.Path'>
TIME()

Return time object with same time but with tzinfo=None.

EXCEL_CELL = <class 'str'>
CALCULATION = <class 'str'>
SEQUENCE = <class 'int'>
SELECTION = <class 'str'>
EMAIL = <class 'str'>
URL(url) = <class 'pydantic.networks.HttpUrl'>
class CmcFieldDefinition(type, combobox, shared, mandatory, recurring, max_chars, default_string='')[source]
type: CmcFieldType
combobox: bool
shared: bool
mandatory: bool
recurring: bool
max_chars: int
default_string: str = ''
classmethod from_field_info(field_info)[source]
class MoreAvailable(n_more)[source]
n_more: int
class Pagination(offset=0, limit=0)[source]
offset: int = 0
limit: int = 0
next_page()[source]
prev_page()[source]

Exceptions

exception CmcError(msg='')[source]
exception PyCommenceError[source]
exception PyCommenceExistsError[source]
exception PyCommenceNotFoundError[source]
exception PyCommenceMaxExceededError[source]
exception PyCommenceServerError[source]
class Handle(*values)[source]
IGNORE = 'ignore'
RAISE = 'raise'
UPDATE = 'update'
REPLACE = 'replace'
ALL = 'all'
class HasRowCount(*args, **kwargs)[source]
property row_count: int
raise_for_one(res)[source]

Resolvers

class HasCursors(*args, **kwargs)[source]
csrs: dict[str, CursorAPI]
get_csrname(self, csrname=None)[source]
resolve_csrname(func)[source]

Decorator to get csrname from first positional argument or kwargs[‘csrname’], or else the only cursor available, or else raise ValueError

resolve_row_id(func)[source]

Decorator to get row_id from kwargs, or else get pk and cursornames from kwargs, and use self.cursor’s pk_to_id method.