API Documentation

pytmc.pragmas

This file contains the objects for taking in pytmc-parsed TMC files and generating Python-level configuration information.

class pytmc.pragmas.SingularChain(item_to_config)

Bases: object

A chain of data types, all with pytmc pragmas, representing a single piece of data that should be accessible via EPICS/ADS

Parameters:

item_to_config (dict) – Keys would be TwincatItem s such as Symbol, and values would be dictionary configurations from parsed pytmc pragmas.

item_to_config
Type:

dict

chain

The chain of items (i.e., item_to_config keys)

Type:

list

tcname

The full TwinCAT name of the item

Type:

str

pvname

The user-specified PV name

Type:

str

last

The last item, which determines the overall data type

Type:

list

data_type

The data type of the last item

Type:

DataType

config

The final configuration based on the full chain of configurations

Type:

dict

pytmc.pragmas.chains_from_symbol(symbol, *, pragma='pytmc', allow_no_pragma=False)

Build all SingularChain instances from a Symbol

pytmc.pragmas.dictify_config(raw_conf, array_index=None)

Make a raw config list into an easier-to-use dictionary

Example::
[{‘title’: ‘pv’, ‘tag’: ‘a’},

{‘title’: ‘io’, ‘tag’: ‘io_for_a’}, {‘title’: ‘field’, ‘tag’: {‘f_name’: ‘fieldname’, ‘f_set’: ‘value’}}, ]

Becomes:

{'pv': 'a',
 'io': 'io_for_a',
 'field': {'fieldname': 'value'}}
pytmc.pragmas.expand_configurations_from_chain(chain, *, pragma='pytmc', allow_no_pragma=False)

Generate all possible configuration combinations

For example, from a chain with two items:

[item1, item2]

The latter of which has a configuration that creates two PVs (specified by configuration dictionaries config1, config2), this function will return:

[
    [(item1, config1), (item2, config1)],
    [(item1, config1), (item2, config2)],
]

Special handling for arrays of complex types will unroll the array into individual elements. That is, arr : ARRAY [1..5] of ST_Structure will be unrolled into arr[1] through arr[5].

Returns:

Tuple of tuples. See description above.

Return type:

tuple

pytmc.pragmas.find_pytmc_symbols(tmc, allow_no_pragma=False)

Find all symbols in a tmc file that contain pragmas

pytmc.pragmas.get_array_suffix(config, array_index, *, default=':%.2d')

Return array index suffix based on the expand settings in the config.

pytmc.pragmas.get_pragma(item, *, name='pytmc')

Get all pragmas with a certain tag.

Parameters:
  • item (parser.SubItem, parser.Symbol, parser.Symbol subclass) – Representation of beckhoff variable or data structure

  • name (str, optional) – Accept tmc entries where the <Name> field equals the passed string

Yields:

str

Return type:

Generator[str, None, None]

pytmc.pragmas.has_pragma(item, *, name='pytmc')

Does item have a pragma titled name?

pytmc.pragmas.make_fake_symbol_from_data_type(data_type, symbol_pragma_text, *, name='$(SYMBOL)', pragma_name='pytmc', data_area_index=0, tmc=None, create_data_area_if_needed=True)

Create a _FakeSymbol from the given data type.

Parameters:
  • data_type (pytmc.parser.DataType) – The TMC data type.

  • symbol_pragma_text (str) – The pragma text to attach.

  • name (str, optional) – The symbol name.

  • pragma_name (str, optional) – The pragma name to use (defaults to “pytmc”).

  • data_area_index (int, optional) – The data area to pretend the symbol exists in.

pytmc.pragmas.normalize_config(config)

Parse and normalize pragma values into Python representations

The following keys will be interpreted: io, archive, update

Parameters:

config (dict) – The configuration

Returns:

A shallow-copy of config with parsed and normalized values

Return type:

dict

pytmc.pragmas.normalize_io(io)

Normalize an ‘io’ specifier in a pragma into either ‘input’ or ‘output’

Parameters:

io (str) – The I/O specifier from the pragma

Return type:

{‘input’, ‘output’}

Raises:

ValueError – If an invalid specifier is given

pytmc.pragmas.parse_archive_settings(archive, default={'frequency': 1, 'method': 'scan', 'seconds': 1})

Parse an ‘archive’ specifier in a pragma

Parameters:

archive (str) – The archive specifier from the pragma.

Returns:

With keys {‘seconds’, ‘frequency’, ‘method’} Where ‘method’ is one of: {‘scan’, ‘monitor’}

Return type:

dict

Raises:

ValueError – If an invalid pragma is supplied

pytmc.pragmas.parse_array_settings(pragma, dimensions)

Parse an ‘array’ specifier in a pragma, yielding array elements.

Parameters:
  • pragma (str) – The I/O specifier from the pragma.

  • dimensions (2-tuple) – Lower and upper-bound of the array corresponding to the pragma.

Yields:

element (int) – Integer element of selected array indices.

Raises:

ValueError – If an invalid pragma is supplied

pytmc.pragmas.parse_update_rate(update, default={'frequency': 1, 'method': 'poll', 'seconds': 1})

Parse an ‘update’ specifier in a pragma

Parameters:

update (str) – The update rate specifier from the pragma.

Returns:

With keys {‘seconds’, ‘frequency’, ‘method’} Where ‘method’ is one of: {‘poll’, ‘notify’}

Return type:

dict

Raises:

ValueError – If an invalid pragma is supplied

pytmc.pragmas.record_packages_from_symbol(symbol, *, pragma='pytmc', yield_exceptions=False, allow_no_pragma=False)

Create all record packages from a given Symbol

pytmc.pragmas.separate_configs_by_pv(config_lines)

Take in a pre-parsed pragma such as:

[{'title': 'pv', 'tag': 'a'},
 {'title': 'io', 'tag': 'io_for_a'},
 {'title': 'pv', 'tag': 'b'},
 {'title': 'io', 'tag': 'io_for_a'},
 ]

Which was generated from:

pv: a
io: io_for_a
pv: b
io: io_for_b

And yield the following:

('a', [{'title': 'io', 'tag': 'io_for_a'}])
('b', [{'title': 'io', 'tag': 'io_for_b'}])
pytmc.pragmas.split_field(string)

When applied to field line’s tag, break the string into its own dict

Parameters:

string (str) – This is the string to be broken into field name and field setting

Returns:

Keys are ‘f_name’ for the field name and ‘f_set’ for the corresponding setting.

Return type:

dict

pytmc.pragmas.split_pytmc_pragma(pragma_text)

Return dictionaries for each line. Derived from raw_config

Parameters:

raw_config (str) – completely unformatted string from configuration. Defaults to raw_config.

Returns:

This list contains a dictionary for each line broken up into two keys: ‘title’ and ‘tag’.

Return type:

list

pytmc.pragmas.squash_configs(*configs)

Take a list of configurations, and squash them into one dictionary

The key ‘pv’ will be a list of all PV segments found.

Later configurations override prior ones.

Parameters:

*configs (list of dict) – Configurations to squash. Original configs will not be modified.

pytmc.record

Record generation and templating

class pytmc.record.BinaryRecordPackage(ads_port, chain=None, origin=None)

Bases: TwincatTypeRecordPackage

Create a set of records for a binary Twincat Variable

class pytmc.record.EPICSRecord(pvname, record_type, direction, fields=None, template=None, autosave=None, aliases=None, archive_settings=None, package=None)

Bases: object

Representation of a single EPICS Record

render(sort=True)

Render the provided template

update_autosave_from_pragma(config)

Update autosave settings from a pragma configuration

To apply to either input or output records, pragma keys autosave_pass0 or autosave_pass1 can be used.

To only apply to input records, pragma keys autosave_input_pass0 autosave_input_pass1 can be used.

To only apply to output records, pragma keys autosave_output_pass0 autosave_output_pass1 can be used.

Parameters:

config (dict) – The pragma configuration dictionary

update_pini_for_autosave()

Set PINI=1 if VAL is autosaved at pass1.

This is a bandaid fix for unexplained behavior where the autosave pass1 does not send values to the PLC unless PINI=1.

This is intended to be called for output records.

class pytmc.record.EnumRecordPackage(*args, **kwargs)

Bases: TwincatTypeRecordPackage

Create a set of record for a ENUM Twincat Variable

class pytmc.record.FloatRecordPackage(ads_port, chain=None, origin=None)

Bases: TwincatTypeRecordPackage

Create a set of records for a floating point Twincat Variable

generate_input_record()

Generate the record to read values into to the IOC

Returns:

record – Description of input record

Return type:

EpicsRecord

generate_output_record()

Generate the record to write values back to the PLC

This will only be called if the io_direction is set to "output"

Returns:

record – Description of output record

Return type:

EpicsRecord

get_scale_offset()

Get the scale and offset for the analog record(s).

class pytmc.record.IntegerRecordPackage(ads_port, chain=None, origin=None)

Bases: TwincatTypeRecordPackage

Create a set of records for an integer Twincat Variable

class pytmc.record.RecordPackage(ads_port, chain=None, origin=None)

Bases: object

Base class to be inherited by all other RecordPackages

The subclass must implement the records property which returns the EPICSRecord objects which will be rendered from the package. Optionally, RecordPackage can have a configure method which does the necessary setup before the record can be configured.

static from_chain(*args, chain, **kwargs)

Select the proper subclass of TwincatRecordPackage from chain

property records

Generated EPICSRecord objects

render()
Returns:

Jinja rendered entry for the RecordPackage

Return type:

string

property valid

returns: Returns true if this record is fully specified and valid. :rtype: bool

class pytmc.record.StringRecordPackage(ads_port, chain=None, origin=None)

Bases: TwincatTypeRecordPackage

RecordPackage for broadcasting string values

generate_input_record()

Generate the record to read values into to the IOC

Returns:

record – Description of input record

Return type:

EpicsRecord

An auxiliary ‘lso’ link record to pass string PVs to the PLC.

generate_output_record()

Generate the record to write values back to the PLC

This will only be called if the io_direction is set to "output"

Returns:

record – Description of output record

Return type:

EpicsRecord

property nelm

Number of elements in record

property records

All records that will be created in the package

class pytmc.record.TwincatTypeRecordPackage(ads_port, chain=None, origin=None)

Bases: RecordPackage

The common parent for all RecordPackages for basic Twincat types

This main purpose of this class is to handle the parsing of the pragma chains that will be shared among all variable types. This includes setting the appropriate asyn port together and handling the “io” directionality. If you have a TmcChain but are not certain which class is appropriate use the from_chain() class constructor and the correct subclass will be chosen based on the given variable information.

In order to subclass:

  1. input_rtyp and output_rtyp need to be provided. These are the EPICS RTYPs that are necessary for input and output variables.

  2. If there are default values for fields, these can be provided in the field_defaults. Setting this on a subclass will only override fields in parent classes that are redundant. In other words, default_fields are inherited if not explicitly overwritten. Also note that these defaults are applied to both the input and output records.

  3. dtyp needs to be set to the appropriate value for the Twincat type.

  4. The generate_input_record() and generate_output_record() functions can be subclasses if further customisation is needed. This is not required.

property asyn_input_port_spec

Asyn input port specification (for INP field)

property asyn_output_port_spec

Asyn output port specification (for OUT field)

property asyn_update_options

Input record update options (TS_MS or POLL_RATE)

generate_input_record()

Generate the record to read values into to the IOC

Returns:

record – Description of input record

Return type:

EpicsRecord

generate_output_record()

Generate the record to write values back to the PLC

This will only be called if the io_direction is set to "output"

Returns:

record – Description of output record

Return type:

EpicsRecord

property io_direction

Determine the direction based on the io config lines

Returns:

direction – {‘input’, ‘output’}

Return type:

str

property records

All records that will be created in the package

class pytmc.record.WaveformRecordPackage(*args, **kwargs)

Bases: TwincatTypeRecordPackage

Create a set of records for a Twincat Array

property dtyp

Add field specifying DTYP without specifying array direction

The following is taken from the EPICS wiki: “This field specifies the device type for the record. Each record type has its own set of device support routines which are specified in devSup.ASCII. If a record type does not have any associated device support, DTYP and DSET are meaningless.”

property ftvl

Field type of value

generate_input_record()

Generate the record to read values into to the IOC

Returns:

record – Description of input record

Return type:

EpicsRecord

generate_output_record()

Generate the record to write values back to the PLC

This will only be called if the io_direction is set to "output"

Returns:

record – Description of output record

Return type:

EpicsRecord

property nelm

Number of elements in record

pytmc.record.generate_archive_settings(packages)

Generate an archive settings given a list of record packages

Parameters:

packages (list of record packages)

Yields:

str – One line from the archiver settings file

pytmc.record.make_autosave_defaults(input_pass0=None, input_pass1=None, output_pass0=None, output_pass1=None, exclude_defaults=False)

Create autosave defaults for a given record type.

Parameters:
  • input_pass0 (List[str]) – Fields to save on the input record for pass 0 (pre-iocInit)

  • input_pass1 (List[str]) – Fields to save on the input record for pass 1 (post-iocInit)

  • output_pass0 (List[str]) – Fields to save on the output record for pass 0 (pre-iocInit)

  • output_pass1 (List[str]) – Fields to save on the output record for pass 1 (post-iocInit)

  • exclude_defaults (bool, optional) – Exclude the defaults normally used for all records.

Returns:

Dictionary of defaults with keys “input” and “output”, under which are keys “pass0” and “pass1”.

Return type:

dict

pytmc.record.sort_fields(unsorted, sort_lookup=None, last=True)

Sort the ordered dict according to the sort_scheme given at instantiation. Does NOT sort in place.

Parameters:
  • unsorted (OrderedDict) – An OrderedDict in need of sorting.

  • sort_lookup (Optional[dict]) – Requires a Dictionary, reverse lookup table for identifying sorting order. If left as None, default_settings.unified_ordered_field_list.unified_list is used.

  • last (Optional[bool]) – If True, place the alphabetized entries at the end, otherwise, place them at the start.

Return type:

OrderedDict

pytmc.parser

TMC, XTI, tsproj parsing utilities

class pytmc.parser.Action(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem, _POUMember

[TcPOU] Code declaration for actions.

class pytmc.parser.ArrayInfo(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] Array information for a DataType or Symbol

property level

ARRAY [] OF ARRAY [] level

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.Axis(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] A single NC axis

class pytmc.parser.AxisPara(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Axis Parameters

Has information on units, acceleration, deadband, etc.

class pytmc.parser.BaseType(element, *, filename, parent=None, name=None)

Bases: Type

[TMC] A reference to the data type of a symbol

class pytmc.parser.BitOffs(element, *, filename, parent=None, name=None)

Bases: _TmcItem

class pytmc.parser.BitSize(element, *, filename, parent=None, name=None)

Bases: _TmcItem

class pytmc.parser.BoundDataType(data_type, array_info=None, pointer=False, reference=False)

Bases: object

Binds a symbol or SubItem with array/pointer/etc information.

class pytmc.parser.Box(element, *, filename, parent=None, name=None)

Bases: _IoTreeItem

[XTI] A box / module

class pytmc.parser.BuiltinDataType(typename, *, length=1)

Bases: object

[TMC] A built-in data type such as STRING, INT, REAL, etc.

class pytmc.parser.Compile(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] A code entry in a nested/virtual PLC project

File to load is marked with ‘Include’ May be TcTTO, TcPOU, TcDUT, GVL, etc.

class pytmc.parser.DUT(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcDUT] Data unit type (DUT)

property declaration: str

The declaration code; i.e., the top portion in visual studio

get_source_code(*, close_block=True)

The full source code - declaration only in the case of a DUT

Return type:

str

class pytmc.parser.DataArea(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] Container that holds symbols

class pytmc.parser.DataType(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC or TSPROJ] A DataType with SubItems, likely representing a structure

property guid

Globally unique identifier for the data type.

Note

This is not available for all data types.

class pytmc.parser.DataTypes(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC or TSPROJ] Container of DataType

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.Declaration(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcDUT/TcPOU/TcGVL] Code declaration

class pytmc.parser.DefaultResolution(element, *, filename, parent=None, name=None)

Bases: Resolution

Library default version resolution.

class pytmc.parser.Device(element, *, filename, parent=None, name=None)

Bases: _IoTreeItem

[XTI] Top-level IO device container

class pytmc.parser.EncPara(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Encoder parameters

Includes such parameters as ScaleFactorNumerator, ScaleFactorDenominator, and so on.

class pytmc.parser.Encoder(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Encoder

Contains EncPara, Vars, Mappings, etc.

class pytmc.parser.Entry(element, *, filename, parent=None, name=None)

Bases: TwincatItem

Pdo Entry, containing name and type information.

property comment: str

The comment associated with the entry.

property entry_type: Type | None

The type of the entry.

class pytmc.parser.EnumInfo(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] Enum values, strings, and associated comments

class pytmc.parser.EnumerationTextList(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcDUT] An enumerated text list type

property declaration

The declaration code; i.e., the top portion in visual studio

get_source_code(*, close_block=True)

The full source code - declaration only in the case of an ENUM

Return type:

str

class pytmc.parser.EtherCAT(element, *, filename, parent=None, name=None)

Bases: TwincatItem

EtherCAT information for a given Box.

Contains SyncMan, Fmmu, DcMode, Pdo, etc.

class pytmc.parser.ExtendsType(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] A marker of inheritance / extension, found on DataType

property guid

Globally unique identifier for the data type.

Note

This is not available for all data types.

property namespace

Namespace of the data type.

property type_name

The type name, without a namespace.

class pytmc.parser.GVL(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcGVL] A Global Variable List

property declaration

The declaration code; i.e., the top portion in visual studio

get_source_code(*, close_block=True)

The full source code - declaration only in the case of a GVL

Return type:

str

class pytmc.parser.Get(element, *, filename, parent=None, name=None)

Bases: _POUPropertyMember

POU Property getter.

class pytmc.parser.Implementation(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcDUT/TcPOU] Code implementation

ST: list[ST]

Structured text code if it exists:

class pytmc.parser.Instance(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[tsproj] PLC Instance.

property task_pous: dict[int, tuple[str, Task]]

Index to Object ID.

class pytmc.parser.Io(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Top-level IO container, which has devices

class pytmc.parser.LibraryReference(element, *, filename, parent=None, name=None)

Bases: TwincatItem, _VersionItemMixin

Library reference.

Bases: TwincatItem

[XTI] Links between NC/PLC/IO

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.Method(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem, _POUMember

[TcPOU] Code declaration for function block methods.

class pytmc.parser.Module(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] A Module

Contains generated symbols, data areas, and miscellaneous properties.

property ads_port

The ADS port assigned to the Virtual PLC

class pytmc.parser.NC(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj or XTI] Top-level NC

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.Name(element, *, filename, parent=None, name=None)

Bases: _TmcItem

class pytmc.parser.Namespace(element, *, filename, parent=None, name=None)

Bases: TwincatItem

Type / library namespace information.

class pytmc.parser.OwnerA(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] For a Link between VarA and VarB, this is the parent of VarA

class pytmc.parser.OwnerB(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] For a Link between VarA and VarB, this is the parent of VarB

class pytmc.parser.POU(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[XTI] A Program Organization Unit

property actions: list[Action]

The action implementations (zero or more)

property call_blocks: dict

A dictionary of all implementation call blocks

property declaration: str

The declaration code; i.e., the top portion in visual studio

get_source_code(*, close_block=True)

The full source code - declaration, implementation, and actions

Return type:

str

property implementation: str

The implementation code; i.e., the bottom portion in visual studio

property methods: list[Method]

The method implementations (zero or more)

property program_name: str

The program name, determined from the declaration

property properties: list[Property]

The property implementations (zero or more)

property variables

A dictionary of variables defined in the POU

class pytmc.parser.Pdo(element, *, filename, parent=None, name=None)

Bases: TwincatItem

Process data objects, part of an EtherCAT block.

class pytmc.parser.PlaceholderReference(element, *, filename, parent=None, name=None)

Bases: TwincatItem, _VersionItemMixin

Library placeholder reference.

class pytmc.parser.PlaceholderResolution(element, *, filename, parent=None, name=None)

Bases: TwincatItem, _VersionItemMixin

Library placeholder resolution.

class pytmc.parser.Plc(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] A project which contains Plc, Io, Mappings, etc.

This can be an embedded Plc node in a TopLeveLProject or an external PLC project reference in a Plc node marked with “File” or “PrjFilePath” attributes.

These can be found under TcSmProject / TopLevelProject / Plc.

property ams_id

The AMS ID of the configured target

find(cls, *, recurse=True)

Find any descendents that are instances of cls.

Parameters:

cls (TwincatItem)

Return type:

Generator[TypeVar(T), None, None]

get_source_code()

Get the full source code, DUTs, GVLs, and then POUs

Return type:

str

property port

The ADS port for the project

post_init()

Hook for subclasses; called after __init__

property target_ip

A guess of the target IP, based on the AMS ID

class pytmc.parser.PlcProject(element, *, filename, parent=None, name=None)

Bases: TwincatItem

The top-level of an external .plcproj project -> PlcProject.

Found in the .plcproj file referenced via TcSmProject / TopLevelProject / Plc

class pytmc.parser.Property(element, *, filename, parent=None, name=None)

Bases: _TmcItem, _TwincatProjectSubItem, _POUMember

Two possibilities: [TcPOU] Code declaration for function block properties [TMC] A property containing a key/value pair

Examples of TMC properties:

ApplicationName (used for the ADS port)
ChangeDate
GeneratedCodeSize
GlobalDataSize
property key

The property key name

property value

The property value text

class pytmc.parser.RemoteConnections(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[StaticRoutes] Routes contained in the TwinCat configuration

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.Resolution(element, *, filename, parent=None, name=None)

Bases: TwincatItem

Library version resolution.

class pytmc.parser.ST(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TcDUT/TcPOU] Structured text

class pytmc.parser.Safety(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] A container for a safety PLC project (SafetyPlc)

class pytmc.parser.SafetyPlc(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] A safety PLC project

Found under TcSmProject / TopLevelProject / Safety.

class pytmc.parser.Set(element, *, filename, parent=None, name=None)

Bases: _POUPropertyMember

POU Property setter.

class pytmc.parser.SubItem(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] One element of a DataType

property bit_offset

The sub item offset, in bits

property bit_size

The sub item size, in bits

property qualified_type_name

The base type, including the namespace

property type

The base type

class pytmc.parser.Symbol(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] A basic Symbol type

This is dynamically subclassed into new classes for ease of implementation and searching. For example, a function block defined as FB_MotionStage will become Symbol_FB_MotionStage.

property base_type: BaseType

The reference used to determine the data type (BaseType)

property module: Module

The TMC Module containing the Symbol

property qualified_type_name: str

The base type name, including the namespace

property type_name: str

The base type name.

pytmc.parser.Symbol_DUT_MotionStage

alias of Symbol_ST_MotionStage

class pytmc.parser.Symbol_ST_MotionStage(element, *, filename, parent=None, name=None)

Bases: Symbol

[TMC] A customized Symbol, representing only ST_MotionStage

property motor_name

M1 of Main.M1

property nc_axis

The NC Axis associated with the ST_MotionStage

The Link for NcToPlc

That is, how the NC axis is connected to the ST_MotionStage

property program_name

Main of Main.M1

class pytmc.parser.System(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] Top-level system settings.

`TcSmProject/TopLevelProject/System`

class pytmc.parser.T_MaxString

Bases: BuiltinDataType

class pytmc.parser.Task(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] Task instance defined at the project-level (not per PLC).

TcSmProject/TopLevelProject/System/Tasks/Task

property array_index: int

Array index in SystemInfoVarList._TaskInfo.

property priority: int

Task priority which also defines the task index.

class pytmc.parser.Tasks(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] Task container.

TcSmProject/TopLevelProject/System/Tasks

post_init()

Hook for subclasses; called after __init__

priority_to_task: dict[int, Task]

Unique priority to task.

class pytmc.parser.TcModuleClass(element, *, filename, parent=None, name=None)

Bases: _TwincatProjectSubItem

[TMC] The top-level TMC file

create_data_area(module_index=0)

Create a fake DataArea in a given parsed TcModuleClass (tmc).

Some .tmc files (specifically for libraries) may not have a DataArea.

These areas are required to enumerate data types for summaries and documentation, due to how pytmc operates internally.

class pytmc.parser.TcSmItem(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Top-level container for XTI files

Visual Studio-level configuration changes the project layout significantly, with individual XTI files being created for axes, PLCs, etc. instead of updating the original tsproj file.

The additional, optional, level of indirection here can make walking the tree frustrating. So, we squash these TcSmItems - skipping over them in the hierarchy - and pushing its children into its parent.

The original container TcSmItem is accessible in those items through the .container attribute.

class pytmc.parser.TcSmProject(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] A top-level TwinCAT tsproj

The .tsproj root node.

Contains a “top_level_plc” which can contain one or more PLC projects.

property plcs: Generator[Plc, None, None]

The virtual PLC projects contained in this TcSmProject

The virtual PLC projects in a dictionary keyed by link name

property plcs_by_name: dict[str, Plc]

The virtual PLC projects in a dictionary keyed by name

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.TopLevelPlc(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[XTI] Top-level PLC, contains one or more projects

post_init()

Hook for subclasses; called after __init__

class pytmc.parser.TopLevelProject(element, *, filename, parent=None, name=None)

Bases: TwincatItem

[tsproj] A top-level project.

Contains Io, System, Motion, Safety, TopLevelPlc, etc. Found in .tsproj under TcSmProject.

property ams_id: str

The AMS ID of the configured target

property target_ip: str

A guess of the target IP, based on the AMS ID

property tasks: Tasks | None

Tasks defined in the project.

property top_level_plc: TopLevelPlc | None

The top-level PLC associated with the project.

This may contain one or more PLC projects.

class pytmc.parser.Type(element, *, filename, parent=None, name=None)

Bases: _TmcItem

[TMC] DataTypes/DataType/SubItem/Type

property guid: str

The referenced type name.

property qualified_type

The base type, including the namespace

property qualified_type_name

The base type, including the namespace

property type_name: str

The referenced type name.

pytmc.parser.case_insensitive_path(path)

Match a path in a case-insensitive manner, returning the actual filename as it exists on the host machine

Required on Linux to find files in a case-insensitive way. Not required on OSX/Windows, but platform checks are not done here.

Parameters:

path (pathlib.Path or str) – The case-insensitive path

Returns:

path – The case-corrected path

Return type:

pathlib.Path

Raises:

FileNotFoundError – When the file can’t be found

pytmc.parser.element_to_class_name(element, *, parent=None)

Determine the Python class name for an element

Parameters:
  • element (lxml.etree.Element)

  • parent (TwincatItem, optional) – The parent to assign to the new element.

Return type:

tuple[str, type[TwincatItem]]

Returns:

  • class_name (str)

  • base_class (class)

pytmc.parser.get_data_type_by_reference(ref, data_type_holders, *, fallback_to_builtin=True, array_info=None, reference=None, pointer=None)

Get a data type from the project, falling back to the tmc file.

pytmc.parser.parse(fn, *, parent=None)

Parse a given tsproj, xti, or tmc file.

Returns:

item

Return type:

TwincatItem

pytmc.parser.projects_from_solution(fn, *, exclude=None)

Find project filenames from a solution.

Parameters:
  • fn (str, pathlib.Path) – Solution filename

  • exclude (list or None) – Exclude certain extensions. Defaults to excluding .tcmproj

pytmc.parser.separate_by_classname(children)

Take in a list of TwincatItem, categorize each by their class name (based on XML tag), and return a dictionary keyed on that.

For example:

<a> <a> <b> <b>

Would become:

{'a': [<a>, <a>],
 'b': [<b>, <b>]
 }
Parameters:

children (list) – list of TwincatItem

Returns:

Categorized children

Return type:

dict

pytmc.parser.strip_namespace(tag)

Strip off {{namespace}} from: {{namespace}}tag

Return type:

str

pytmc.linter

class pytmc.linter.DbdFile(fn)

Bases: object

An expanded EPICS dbd file

Parameters:

fn (str or file) – dbd filename

filename

The dbd filename

Type:

str

parsed

pyPDB parsed dbd nodes

Type:

list

class pytmc.linter.LinterResults(args)

Bases: Results

Container for dbdlint results, with easier-to-access attributes

Extends pyPDB.dbdlint.Results

Each error or warning has dictionary keys:

{name, message, file, line, raw_message, format_args}
errors

List of errors found

Type:

list

warnings

List of warnings found

Type:

list

property success

returns: success – True if the linting process succeeded without errors :rtype: bool

pytmc.linter.lint_db(dbd, db, *, full=True, warn_ext_links=False, warn_bad_fields=True, warn_rec_append=False, warn_quoted=False, warn_varint=True, warn_spec_comm=True)

Lint a db (database) file using its database definition file (dbd) using pyPDB.

Parameters:
  • dbd (DbdFile or str) – The database definition file; filename or pre-loaded DbdFile

  • db (str) – The database filename or text

  • full (bool, optional) – Validate as a complete database

  • warn_quoted (bool, optional) – A node argument isn’t quoted

  • warn_varint (bool, optional) – A variable(varname) node which doesn’t specify a type, which defaults to ‘int’

  • warn_spec_comm (bool, optional) – Syntax error in special #: comment line

  • warn_ext_link (bool, optional) – A DB/CA link to a PV which is not defined. Add ‘#: external(“pv.FLD”)

  • warn_bad_field (bool, optional) – Unable to validate record instance field due to a previous error (missing recordtype).

  • warn_rec_append (bool, optional) – Not using Base >=3.15 style recordtype “*” when appending/overwriting record instances

Raises:

DBSyntaxError – When a syntax issue is discovered. Note that this exception contains file and line number information (attributes: fname, lineno, results)

Returns:

results

Return type:

LinterResults