From f26dde45c9f424056d91e3b35d5200e615e7caa9 Mon Sep 17 00:00:00 2001 From: Damon Bohls Date: Tue, 20 Feb 2018 14:27:35 -0600 Subject: [PATCH 1/2] docs(DB): Add a few docs for database. Document database/database.py and database/_collection.py. --- docs/api_reference/database.rst | 2 + docs/api_reference/database/collection.rst | 7 ++ docs/api_reference/database/database.rst | 7 ++ docs/conf.py | 2 +- docs/examples/dynamic_database_creation.rst | 4 + nixnet/_session/base.py | 5 +- nixnet/database/_collection.py | 28 +++++++ nixnet/database/database.py | 82 ++++++++++++++++++- .../can_dynamic_database_creation.py | 1 + .../lin_dynamic_database_creation.py | 1 + 10 files changed, 135 insertions(+), 4 deletions(-) create mode 100644 docs/api_reference/database/collection.rst create mode 100644 docs/api_reference/database/database.rst diff --git a/docs/api_reference/database.rst b/docs/api_reference/database.rst index bc4cf2c..652fe84 100644 --- a/docs/api_reference/database.rst +++ b/docs/api_reference/database.rst @@ -6,8 +6,10 @@ nixnet.database :caption: API Reference: database/cluster + database/database database/ecu database/frame database/signal + database/collection database/dbc_attributes database/dbc_signal_value_table diff --git a/docs/api_reference/database/collection.rst b/docs/api_reference/database/collection.rst new file mode 100644 index 0000000..cb693f4 --- /dev/null +++ b/docs/api_reference/database/collection.rst @@ -0,0 +1,7 @@ +nixnet.database.collection +========================== + +.. automodule:: nixnet.database._collection + :members: + :inherited-members: + :show-inheritance: diff --git a/docs/api_reference/database/database.rst b/docs/api_reference/database/database.rst new file mode 100644 index 0000000..5c90a22 --- /dev/null +++ b/docs/api_reference/database/database.rst @@ -0,0 +1,7 @@ +nixnet.database.database +======================== + +.. automodule:: nixnet.database.database + :members: + :inherited-members: + :show-inheritance: diff --git a/docs/conf.py b/docs/conf.py index 6d0970a..595e11d 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -50,7 +50,7 @@ # General information about the project. project = u'nixnet' -copyright = u'2017, National Instruments' +copyright = u'2018, National Instruments' author = u'National Instruments' # The version info for the project you're documenting, acts as replacement for diff --git a/docs/examples/dynamic_database_creation.rst b/docs/examples/dynamic_database_creation.rst index d3fd2f5..9920746 100644 --- a/docs/examples/dynamic_database_creation.rst +++ b/docs/examples/dynamic_database_creation.rst @@ -7,11 +7,15 @@ used in a :any:`nixnet.session.SignalOutSinglePointSession` and :any:`nixnet.session.SignalInSinglePointSession` to write and then read a pair of signals. +.. _can_dynamic_database_creation_label: + CAN Dynamic Database Creation ----------------------------- .. literalinclude:: ../../nixnet_examples/can_dynamic_database_creation.py +.. _lin_dynamic_database_creation_label: + LIN Dynamic Database Creation ----------------------------- diff --git a/nixnet/_session/base.py b/nixnet/_session/base.py index 7a6b431..7673cee 100644 --- a/nixnet/_session/base.py +++ b/nixnet/_session/base.py @@ -353,8 +353,9 @@ def change_lin_schedule(self, sched_index): Args: sched_index(int): Index to the schedule table that the LIN master executes. - The schedule tables are sorted the way they are returned from the database - with the `nixnet.database._cluster.Cluster.lin_schedules` property. + The schedule tables are sorted the way they are returned from the + database with the `nixnet.database._cluster.Cluster.lin_schedules` + property. """ _funcs.nx_write_state(self._handle, constants.WriteState.LIN_SCHEDULE_CHANGE, _ctypedefs.u32(sched_index)) diff --git a/nixnet/database/_collection.py b/nixnet/database/_collection.py index ad85110..9e5158e 100644 --- a/nixnet/database/_collection.py +++ b/nixnet/database/_collection.py @@ -13,6 +13,7 @@ class DbCollection(collections.Mapping): + """Collection of Database objects.""" def __init__(self, handle, db_type, prop_id, factory): # type: (int, constants.ObjectClass, int, typing.Any) -> None @@ -48,6 +49,13 @@ def __iter__(self): return self.keys() def __getitem__(self, index): + """Return the database object. + + Args: + Name of database object + Returns: + index(str): Name of database object. + """ if isinstance(index, six.string_types): ref = _funcs.nxdb_find_object(self._handle, self._type, index) return self._factory(ref) @@ -59,18 +67,38 @@ def __delitem__(self, index): _funcs.nxdb_delete_object(ref) def keys(self): + """Return database object names in the collection. + + Yields: + An iterator to database object names in the collection. + """ for child in self._get_children(): yield child.name def values(self): + """Return database objects in the collection. + + Yields: + An iterator to database objects in the collection. + """ return self._get_children() def items(self): + """Return all database object names and objects in the collection. + + Yields: + An iterator to tuple pairs of database object names and objects in the collection + """ for child in self._get_children(): yield child.name, child def add(self, name): # type: (typing.Text) -> typing.Any + """Add a new database object to the collection. + + Args: + name(str): Name of the new database object. + """ ref = _funcs.nxdb_create_object(self._handle, self._type, name) return self._factory(ref) diff --git a/nixnet/database/database.py b/nixnet/database/database.py index 4302b4b..a31014d 100644 --- a/nixnet/database/database.py +++ b/nixnet/database/database.py @@ -16,7 +16,18 @@ class Database(object): - + """Opens a database file. + + When an already open database is opened, + this class grants access to the same database and increases an internal reference counter. + A multiple referenced (open) database must be closed as many times as it has been opened. + Until it is completely closed, the access to this database remains granted, + and the database uses computer resources (memory and handles). + For more information, refer to :any:`Database.close`. + + Args: + database_name(str): The database alias or file pathname to open. + """ def __init__(self, database_name): # type: (typing.Text) -> None self._handle = None # To satisfy `__del__` in case nxdb_open_database throws @@ -57,6 +68,37 @@ def __repr__(self): return '{}(handle={})'.format(type(self).__name__, self._handle) def close(self, close_all_refs=False): + # type: (bool) -> None + """Closes the database. + + For the case that different threads of an application are using the same database, + :any:`Database` and :any:`Database.close` + maintain a reference counter indicating how many times the database is open. + Every thread can open the database, work with it, + and close the database independently using ``close_all_refs`` set to ``False``. + Only the last call to :any:`Database.close` actually closes access to the database. + + .. note:: ``Database.__exit__`` calls :any:`Database.close` with ``close_all_refs`` set to ``False``. + See examples of this in :ref:`can_dynamic_database_creation_label` + and :ref:`lin_dynamic_database_creation_label`. + + Another option is that only one thread executes :any:`Database.close` once, + using ``close_all_refs`` set to ``True``, which closes access for all other threads. + This may be convenient when, for example, + the main program needs to stop all running threads + and be sure the database is closed properly, + even if some threads could not execute :any:`Database.close`. + + Args: + close_all_refs(bool): Indicates that a database open multiple times + (refer to :any:`Database`) should be closed completely + (``close_all_refs`` is ``True``), + or just the reference counter should be decremented + (``close_all_refs`` is ``False``), + and the database remains open. + When the database is closed completely, + all references to objects in this database become invalid. + """ if self._handle is None: warnings.warn( 'Attempting to close NI-XNET system but system was already ' @@ -69,20 +111,58 @@ def close(self, close_all_refs=False): def save(self, db_filepath=""): # type: (typing.Text) -> None + """Saves the open database to a FIBEX 3.1.0 file. + + The file extension must be .xml. If the target file exists, it is overwritten. + + XNET saves to the FIBEX file only features that XNET sessions use to communicate on the network. + If the original file was created using non-XNET software, + the target file may be missing details from the original file. + For example, NI-XNET supports only linear scaling. + If the original FIBEX file used a rational equation that cannot be expressed as a linear scaling, + XNET converts this to a linear scaling with factor 1.0 and offset 0.0. + + If ``db_filepath`` is empty, the file is saved to the same FIBEX file specified when opened. + If opened as a file path, it uses that file path. + If opened as an alias, it uses the file path registered for that alias. + + Saving a database is not supported under Real-Time (RT), + but you can deploy and use a database saved on Windows on a Real-Time (RT) target (refer to `Database.deploy`). + + Args: + db_filepath(str): Contains the pathname to the database file or is + empty (saves to the original filepath). + """ _funcs.nxdb_save_database(self._handle, db_filepath) @property def name(self): + # type: () -> typing.Text return _props.get_database_name(self._handle) @property def clusters(self): + # type: () -> _collection.DbCollection + """:any:`DbCollection`: Returns a collection of :any:`Cluster` objects in this database. + + A cluster is assigned to a database when the cluster object is created. + You cannot change this assignment afterwards. + + FIBEX and AUTOSAR files can contain any number of clusters, + and each cluster uses a unique name. + + For CANdb (.dbc), LDF (.ldf), or NI-CAN (.ncd) files, + the file contains only one cluster, and no cluster name is stored in the file. + For these database formats, NI-XNET uses the name Cluster for the single cluster. + """ return self._clusters @property def show_invalid_from_open(self): + # type: () -> bool return _props.get_database_show_invalid_from_open(self._handle) @show_invalid_from_open.setter def show_invalid_from_open(self, value): + # type: (bool) -> None _props.set_database_show_invalid_from_open(self._handle, value) diff --git a/nixnet_examples/can_dynamic_database_creation.py b/nixnet_examples/can_dynamic_database_creation.py index 869f213..7b3053e 100644 --- a/nixnet_examples/can_dynamic_database_creation.py +++ b/nixnet_examples/can_dynamic_database_creation.py @@ -22,6 +22,7 @@ def main(): input_interface = 'CAN2' # Open the default in-memory database. + # Database.close will be called by Database.__exit__ when exiting the 'with' block. with database.Database(database_name) as db: # Add a CAN cluster, a frame, and two signals to the database. diff --git a/nixnet_examples/lin_dynamic_database_creation.py b/nixnet_examples/lin_dynamic_database_creation.py index 37fe2a5..c811c69 100644 --- a/nixnet_examples/lin_dynamic_database_creation.py +++ b/nixnet_examples/lin_dynamic_database_creation.py @@ -26,6 +26,7 @@ def main(): input_interface = 'LIN2' # Open the default in-memory database. + # Database.close will be called by Database.__exit__ when exiting the 'with' block. with database.Database(database_name) as db: # Add a LIN cluster, a frame, and two signals to the database. From fad6e51fe563c18172359378e5b1f8965e18ceba Mon Sep 17 00:00:00 2001 From: Damon Bohls Date: Wed, 21 Feb 2018 19:48:39 -0600 Subject: [PATCH 2/2] docs: Update copyright info. Copyright year(s) should now be 2017-2018. Update conf.py so that Sphinx generates doc copyrights that end with the current year. --- LICENSE | 2 +- docs/conf.py | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/LICENSE b/LICENSE index 47dff57..999c432 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2017, National Instruments Corp. +Copyright (c) 2017-2018, National Instruments Corp. Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/docs/conf.py b/docs/conf.py index 595e11d..82d7449 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -16,6 +16,7 @@ # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. # +from datetime import datetime import os import re import sys @@ -50,8 +51,8 @@ # General information about the project. project = u'nixnet' -copyright = u'2018, National Instruments' author = u'National Instruments' +copyright = u'2017-{}, {}'.format(datetime.now().year, author) # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the