What’s new in Version 4.0
Last update: 16.07.2025Key features introduced or improved in MI Scripting Toolkit for Python 4.0.
What’s new?
Subsets
Summary
- If your code does not use the
Table.subsetsproperty and the default subset in your tables contain all records, you should see no behavior changes. This is the most common scenario. - If your code sets the
Table.subsetsproperty to the default subset, then you should disable this assignment from your code, since it now occurs automatically. - If your code sets the
Table.subsetsproperty to a non-default subset, then you should clear theTable.subsetsproperty withtable_object.subsets.clear()before setting the non-default subset. - If your code sets the
Table.subsetsproperty to a set containing more than one subset and you perform any subsequent record fetching or search operations, these operations will raise aValueError. They would previously not consider all applied subsets, and so would return incorrect results.
Detailed description of changes
The Table.subsets property defines the applied subset or subsets for a particular table.
In previous releases, if the subsets argument was not provided to the Database.get_table() and
Database.get_table_by_guid() methods, they returned a Table object with an empty
subsets property, which meant that there was no active subset for that table. In this release,
calling those methods with an empty subsets argument now returns a Table object with the default
subset for that table activated. This causes the following changes in default behavior:
- Records are now added to the default subset automatically on import.
- All record fetching operations, table-specific searches and database criteria searches will only consider records in the default subset (see Searching and browsing for records for more details).
A new property default_subset has been added to the Table class, which always
contains the default subset as defined in the schema. This can be used to reactivate the default
subset with the code:
table.subsets.clear()
table.subsets.add(table.default_subset)
Adding additional subsets to the Table.subsets property is allowed, but a Table
in this state can only be used for creating new records. Any attempt to perform a retrieval of
records, for example by searching or calling Table.all_records(), will result in a
ValueError.
The method Exporter.run_exporter() previously performed some record filtering in rare situations. The
behavior has been simplified and now subset filtering is never performed.
Unchanged operations
The subset filtering of LinkFetcher.fetch_linked_records() is unchanged, and optionally
filters the results to include only records that are in the default subset of the target table. This
is controlled with the optional filter_subsets argument.
The following record fetching and data export operations are unchanged and do not perform any subset filtering:
Table.bulk_fetch()andRecordon-demand attribute value fetchingRecordon-demand link fetchingRecord.find_parent()andRecord.refresh_path()record fetching
Reverting to the previous behavior
The previous behavior can be retrieved by supplying subsets={} as an additional argument to
Database.get_table(), or by calling clear() on the Table.subsets property before
interacting with the Table object.
Searching and browsing for records
Summary
- All searches except
Database.search_for_records_by_text()now apply a subset filter when searching. If a table included in a search has multiple applied subsets, aValueErroris raised. - The
Table.search_for_records_where()list_of_criteriaparameter must now only contain criteria based on pseudo-attributes and attribute definitions from the table being searched. Otherwise aValueErroris raised. - The
Database.search_for_records_where()list_of_criteriaparameter must now only contain criteria based on pseudo-attributes and attribute definitions from at most one table within the database being searched. Otherwise aValueErroris raised. - Getting records based on the Granta MI tree is generally now subject to subset filtering. If a
table included in a record fetch operation has multiple applied subsets, a
ValueErroris raised.
Detailed description of changes
The behavior of subsets related to searching and fetching records has been standardized:
- The following table-specific search and record fetching methods only consider records in the
active subset (the subset defined in the
Table.subsetsproperty) by default. If there is more than one active subset, aValueErroris raised. This behavior can be modified with the newfilter_by_subsetandsubset_namearguments, see the API documentation for each method for details): - The following record fetching properties only consider records in the active subset. If there
is more than one active subset, a
ValueErroris raised:Table.children(can be modified by callingTable.refetch_children()first)Record.children(can be modified by callingRecord.refetch_children()first)Table.get_records_from_path()
- The following database-specific search methods search in the subset defined in the
Table.subsetsproperty. If this property contains multiple subsets, aValueErroris raised. This behavior cannot be overridden: - The
Database.search_for_records_by_text()search method does not apply any subset filtering. - The
Table.search_for_records_where()search method now only accepts a list of criteria that is a combination of pseudo-attributes and attributes from the table being searched over. If one or more criteria from a different table or database are provided, aValueErroris raised. - The
Database.search_for_records_where()search method now only accepts a list of criteria that is a combination of pseudo-attributes and attributes from at most one table. The following scenarios result in aValueError:- If criteria from multiple tables are provided.
- If one or more criteria from a different database are provided.
Searching with pseudo-attribute criteria
- Searching for pseudo-attributes in
Table.search_for_records_where()andDatabase.search_for_records_where()searches no longer return duplicate search results. - It is no longer required to manually add a
PartialTableReferenceto thePseudoAttributeDefinitionto restrict searches to a single table. This is handled automatically:Database.search_for_records_where()will return results from all tables in the database, andTable.search_for_records_where()will return results from the relevant table only.
Streamlined API enhancements and bug fixes
Enhancements
- The documentation describing the
Session.spawn_session()behavior has been clarified. Calling this method in a situation that would fail to return a foundation-layer session has been deprecated. - The
DATABASE_UNIT_SYSTEMconstant is now documented. This constant is now the only valid way to refer to the unit system for a particular database. Other names, such as “database units” were deprecated in a previous release and are no longer valid. - Added method
Table.refetch_children()to update the list of direct children of the table. - Added property
AttributeDefinition.history, describing the revision information of an attribute. - Added new class
RecordProperties, providing aPseudoAttributeDefinitionfor all supported pseudo-attributes. - Improved the
AttributeDefinition.search_criterion()andSearchCriteriondocumentation to describe how to perform exact searches on discrete attributes. Record.linkssmart links can include reverse direction links to the source table.- Added property
Record.data_revision_history, which returns aDataRevisionHistoryfor each attribute of the record. It contains information about the attribute data and its revision history. AddedTable.bulk_fetch_data_revision_history()andDataRevisionHistoryFetcherto populatedata_revision_historyin bulk. - Added new properties on
Recordfor pseudo-attributes.Record.pseudo_attributeshas been deprecated. - The property
Record.typenow uses the new enumerationRecordType. String inputs have been deprecated. - Datetime pseudo-attributes (
Record.created_on,Record.last_modified_on) now return timezone aware datetime objects. - The
parentproperty of records obtained viaRecord.all_children(),Record.children,Table.all_records(), andTable.childrenis now populated with the appropriate record from the hierarchy. - Added method
Record.move_to()to move existing records to a new location. - Renamed
Record.all_children()toRecord.get_descendants()to better match the behavior.Record.all_children()is now deprecated and will be removed in a future release. - Added property
AttributeTabular.column_types, containing the tabular column types for all tabular columns containing data.
Bug fixes
- Non-Scripting Toolkit names such as
DictandEnumare no longer importable fromGRANTA_MIScriptingToolkit.granta. - Attempting to use
Table.bulk_link_fetch()with a record link group that does not exist in theTableraises aValueError. - A record link group can now be completely cleared for a record by calling
Record.set_links()with an empty iterable for therecordsargument. - Setting
Record.typefor an existing record now raises aValueError.Record.typecan only be set when records are created. - When
short_nameis not provided on Record instantiation,Record.short_nameis no longer set to thenameargument value.Record.short_namecan now be None for new records, in which case the record tree name will default to the record name upon record creation on the server. - The
childrenproperty of records obtained viaRecord.all_children()andTable.all_records()no longer includes all descendants, and now only includes direct children. - Record types excluded via the arguments
include_foldersorinclude_genericsonRecord.all_children()andTable.all_records()are no longer incorrectly excluded in thechildrenproperty of resulting records. - Unit systems now correctly affect tabular attributes:
AttributeDefinitionTabular.column_unitsnow returns column units in the active unit system.- Search criteria on tabular columns are now defined in the active unit system.
- Units of rows added with
AttributeTabular.add_row()now default to the active unit system.
- Accessing a
AttributeDefinitionTabularorAttributeTabularobject linked to a hidden table no longer raises aKeyError. - Attempting to call
Exporter.get_parameters_required_for_exportfor an FEA exporter which contains functional meta-attributes no longer raises aKeyError.
Examples
Example notebooks are included in the MI Scripting Toolkit, this is included as part of the Granta MI Enterprise package on the Ansys Customer Portal. Contact your system administrator for more details.
Foundation API enhancements and bug fixes
TabularColumnDetail.databaseUnitis now correctly populated for linked columns.- Added property
TabularColumnDetail.identity, providing the internal identity of the tabular column.
Backwards incompatible API changes
Streamlined API
The changes described above in Subsets and Searching and browsing for records are breaking changes to the streamlined API. In addition:
Session.records_from_string()now defaults touse_strict_version=True.get_records_by_idsandget_record_by_idmethods onSession,Database, andTableclasses no longer accept theidentityargument. Usehistory_identityinstead.Table.paths_from(),Table.path_from(), andTable.get_records_from_path()no longer supportstrandTableinputs. UseNoneto use the table root as starting node. All three methods now raise aValueErrorif the record specified asstarting_nodeis not in the current table, and raise aTypeErrorif the argument value is not aRecordorNone.Record.colorno longer supportsstrinputs. OnlyRecordColorobjects are supported.AttributeFunctional.add_point()andAttributeFunctional.add_range()methods now raiseKeyErrorexceptions if a dictionary with incorrect keys is provided.File.load(),File.save(),Picture.load(), andPicture.save()no longer acceptfile_nameas an argument. Provide the full path including the file name to thepathargument. For file attributes, the name of the file is part of the attribute value and can be accessed viaAttributeFile.file_nameorFile.file_nameto build a full path.File.namehas been removed. UseFile.file_name.Picture.namehas been removed.FileandPictureno longer acceptnameorloadas arguments. Provide the full path to the file/picture (including the file name) to the keyword only argumentpath.File.descriptionnow only supportsstrinputs.- Attempting to import an empty
AttributeTabularis deprecated. Instead useRecord.clear_attributes()to delete the attribute value, or setAttributeValue.is_applicabletoFalseto mark the attribute as Not Applicable.
AsyncJobs
The AsyncJobQueue functionality has been moved to a new PyAnsys package called PyGranta JobQueue.
If you are using Granta MI 2024 R2 or later, you can use this package to import and export Excel
files and import text data into Granta MI. The package can be installed with
pip install ansys-grantami-jobqueue, and documentation can be accessed here. The differences
between the packages are minimal, and the PyGranta JobQueue API documentation includes a guide for
migrating code from Scripting Toolkit AsyncJobs to PyGranta JobQueue.
If you are using Granta MI 2024 R1 or earlier and require Job Queue functionality, you should continue to use Scripting Toolkit v3.3.
Known issues
-
If an attribute is exported with the
Table.bulk_fetchmethod withinclude_binary_data=False, subsequent values returned by theAttributePicture.mime_file_typeproperty will always returnimage/png, regardless of the actual image format. The header returned when accessing the URL is unaffected and should be used instead. -
In version-controlled tables,
DataRevisionHistoryobjects have an ambiguous meaning. Thehistory.last_modified_datefor the following attribute types is updated when the release state of the parent record is modified:- Date
- Hyperlink
- Integer
- Logical
- Range
- Short text
The
history.last_modified_datefor the following attribute types is not updated when the release state of the parent record is modified:- Discrete
- File
- Functional
- Long text
- Picture
- Point
- Tabular