Release notes¶
3.5.1¶
Minor improvements:
Further code optimizations have decreased NMR-STAR parsing time by nearly another 50%.
Saveframe and loop properties which were intended to be read only are now properly typed that way to make it clearer to end users by surfacing type warnings. Specifically
pynmrstar.Entry.frame_list,pynmrstar.Saveframe.tags,pynmrstar.Saveframe.loops, andpynmrstar.Loop.tags.
3.5.0¶
Major improvements:
The library now scans for whitespace in a fully unicode-aware manner. It warns when whitespace other than that officially allowed in the STAR specification is found (’ ‘, ‘\t’, ‘\r’, ‘\n’, ‘\v’) but it still parses it without issues. If raise_parse_warnings is set, an exception is thrown.
Minor improvements:
pynmrstar.Loop.categoryis now a property to be able to validate it when set. Previously, invalid loop categories (tag prefixes) could be provided.
Potentially breaking changes:
pynmrstar.definitions.WHITESPACE has been removed. This allowed users to set custom characters that they considered whitespace. This functionality was never encouraged. Instead, the standard STAR whitespace characters are considered official whitespace characters, but anything in Unicode considered whitespace is also handled properly.
3.4.0¶
Major improvements:
The C helper module has been reimplemented in Rust and other performance critical functions have also been moved to the Rust module. (Specifically, the Parsing logic and the loop string formatting logic.) Additional effort towards maximizing the performance of the Rust module has been made, leading to massive speedups in performance of common actions.
Parsing a file is now nearly twice as fast.
Rendering an Entry to a string is now nearly three times as fast.
This change is tested to be and understood to be fully backwards compatible, but due to the major nature of the change is getting a new minor version number.
3.3.6¶
Update pynmrstar.Entry.from_file(), pynmrstar.Saveframe.from_file(), pynmrstar.Loop.from_file(),
pynmrstar.Entry.write_to_file(), and pynmrstar.Saveframe.write_to_file()
to support Path objects in addition to strings for the file name.
3.3.5¶
No code changes, just repackaging to fix some build issues in previous releases. Dropping official support for Python3.7 but the code still runs without issue in Python3.7 environments.
3.3.4¶
Minor improvements:
Support creating
pynmrstar.Entry,pynmrstar.Saveframe, andpynmrstar.Loopobjects from string or from file while specifying a Schema object to be used rather than the default schema.
3.3.3¶
Minor improvements:
Preserve whatever capitalization was used when calling
pynmrstar.Loop.get_tags()withdict_result=Trueso that it is easy to index into the resulting dictionary.
Other changes:
Updates to the package metadata to tell PyPI that Python versions through 3.12 are supported.
Minor updates to the documentation.
Ended official support for end-of-life Python 3.6 and stopped building wheels for it. You should still be able to install on 3.6 if you are able to build cnmrstar from source. Alternatively, use version 3.3.2.
3.3.2¶
Minor improvements:
Fix a bug in
pynmrstar.Saveframe.categorywhich incorrectly modified the sf_category tag and value. Note that setting the category now creates a Sf_framecode tag if it wasn’t previously present, since there is no way to set the category of a saveframe otherwise.Fix a bug in
pynmrstar.Entry.remove_empty_saveframes()which failed to remove all saveframes when removing more than one saveframe.
3.3.1¶
Minor improvements:
The module now uses it’s own pynmrstar logger rather than the default (root) logger. This enables the end user of the library to have much better control over the log level and output of the logging, and avoids setting state on the root logger in a way that could conflict with calling code.
It is now possible to specify raise_parse_warnings when calling
pynmrstar.Entry.from_file(),pynmrstar.Entry.from_string(),pynmrstar.Saveframe.from_file(),pynmrstar.Saveframe.from_string(),pynmrstar.Loop.from_file(), andpynmrstar.Loop.from_string(). This will result in certain ignorable but technically wrong issues found when parsing to result in throwing of apynmrstar.exceptions.ParsingErrorrather than just a warning being logged. Use this if you want to ensure that you never silently parse invalid files.Some exceptions are displayed with less of a traceback when the traceback is not relevant to the exception.
3.3.0¶
pynmrstar.Loop.add_data() has been significantly improved. Adding data to a loop used to be somewhat
cumbersome, but the function has been updated to support adding data in two new ways which should be significantly
easier. For one, you can provide a list of dictionaries of tags to add. For example, adding
[{'name': 'Jeff', 'location': 'Connecticut'}, {'name': 'Chad', 'location': 'Madison'}] to a loop will add two new
rows, and set the values of name and location to the values provided. If there are other tags in the loop, they will
be assigned null values for the rows corresponding to the tags added.
An additional way to add data, is adding a dictionary of lists, as such (corresponds to the example above):
{'name': ['Jon', 'Connecticut'], 'location': ['Chad', 'Madison']}. This will also create two new rows in the loop
and assign the values provided.
For both of these, any tags present in the loop for which you do no provide values, or tags for which you provide fewer values than other tags, will have the remaining values filled in with null values.
See the function help/documentation (pynmrstar.Loop.add_data()) for more details. The original functionality
has been preserved for backwards compatibility, though the new functionality is expected to be easier to use and lead
to more readable code.
Other minor improvements:
When checking if a token found in a data block while parsing is in the reserved keywords, perform the check case-insensitively.
Fix a typo in an error message.
3.2.1¶
Minor improvements.
Changes:
Improved retry logic to better handle throttling on the server.
Fixed a bug in the retry logic which would return the wrong content type under certain circumstances.
Better detection of ReadTheDocs environment to determine if check for cnmrstar is needed.
3.2.0¶
Performance, performance, and packaging!
This release makes some relatively large under-the-hood changes to improve performance, as well as to set up the library for further performance improvements in the future. Attempts were made to avoid changes which could impact current code, but a few (unlikely to be an issue) breaking changes have been made.
PyNMR-STAR is now distributed in binary (wheel) form! This not only should speed up installation, but it will also allow us to more tightly integrate the c library in the future, leading to even faster code.
Changes:
Significant speed improvements all over the library:
Formatting an Entry object as a string is now up to four times faster under certain circumstances, but significantly faster under all circumstances.
Deleting saveframes from entries with a large number of saveframes is now significantly faster
pynmrstar.Entry,pynmrstar.Saveframe, andpynmrstar.Loopequality comparisons are much faster (and also more exacting - see the breaking changes).Iterating over saveframes in an entry, Loops in a saveframe, and rows in a loop is now roughly twice as fast
Added new
pynmrstar.Saveframe.remove_loop(),pynmrstar.Saveframe.remove_tag(), andpynmrstar.Loop.remove_tag()methods. All are capable of removing more than one loop/tag (respectively) at a time. Please use these rather than del saveframe[tag] constructions as it is less ambiguous as to whether a tag or loop will be removed for others reading your code.A bug which erroneously omitted loops when getting the string representation of a saveframe with no tags has been resolved. This shouldn’t have been triggered in practice, since
pynmrstar.Saveframeobjects, to be valid NMR-STAR, require at least two tags. (TheSf_framecodeandSf_categorytags.)
Potentially breaking changes:
Equality checks operate differently. Before,
pynmrstar.Entry,pynmrstar.Saveframe, andpynmrstar.Loopclasses, when compared using the __eq__ built-in, performed a “NMR-STAR-aware” comparison. This meant comparing tag names case insensitively, etc. This was very slow, and may have lead to confusing behavior in some circumstances. If you want to perform this type of comparison, usepynmrstar.Entry.compare(),pynmrstar.Saveframe.compare(), andpynmrstar.Loop.compare()and check if the list of differences is empty. __eq__ now checks if the objects have the same exact contents - including source, tag capitalization, etc. Previously the string representation of an entry would compare equal to the actual Entry object, for example.If you use
pynmrstar.utils.quote_value()(very unlikely) and you also modifypynmrstar.definitions.STR_CONVERSION_DICT(extraordinarily unlikely) then you must callpynmrstar.utils.quote_value.clear_cache()before performing any operations which render objects as NMR-STAR strings.pynmrstar.Saveframe.delete_tag()has been renamed topynmrstar.Saveframe.remove_tag().pynmrstar.Loop.delete_tag()has been renamed topynmrstar.Loop.remove_tag().pynmrstar.Loop.delete_data_by_tag_value()has been renamed topynmrstar.Loop.remove_data_by_tag_value().pynmrstar.Entry.delete_empty_saveframes()has been renamed topynmrstar.Entry.remove_empty_saveframes(). All of the original methods remain for now in a deprecated state. Please update them as they will be removed in the 4.0 release.pynmrstar.Entry.frame_list,pynmrstar.Saveframe.tags,pynmrstar.Saveframe.category,pynmrstar.Saveframe.loops, andpynmrstar.Loop.tagshave all been converted into properties. Of them, onlypynmrstar.Saveframe.categorycan be set - the others are read only. Please use the built in functions to modify these rather than manually modifying the returned lists. In version 4.0, modifying these directly will be impossible as they will become iterators, and all modification must be done through the provided methods. This will allow for more speed improvements in the library, as well as more robust sanity checks.
3.1.1¶
Changes:
Significant extra detail added to most error messages.
A new exception called
pynmrstar.exceptions.InvalidStateErroris thrown when trying to perform actions which cannot be completed because the current state of the objects cannot be properly mapped to NMR-STAR. When using the appropriate setters and getters rather than directly modifying object attributes, it is somewhat hard to create such invalid states. The exception inherits fromValueError(which is the exception that used to be thrown in these circumstances) so no code changes should be necessary to catch these exceptions.The parser now properly handles some ultra rare edge cases during loop parsing during which it previously either threw exceptions when it shouldn’t have, or failed to throw an exception when it should have.
Deprecated
pynmrstar.Loop.add_data_by_tag(). This was originally used internally when parsing an entry, but it is recommended to usepynmrstar.Loop.add_data()instead, orloop[['Number', 'Unit']] = [[1,2,3],['db', 'atm', 'bar']]style assignments. New methods to make tag assignment in a loop easier are also being considered.
Potentially breaking changes:
Saveframe tags no longer store the line number from which a tag was originally read. This was not always set anyway, since saveframes could also be created from scratch. This was also never advertised to calling code, so it’s very unlikely this change will affect you.
Long deprecated methods
pynmrstar.Loop.add_column(),pynmrstar.Loop.add_data_by_column(), andpynmrstar.Loop.get_columns()were removed. Also, the long deprecated root level reference toiter_entries()was removed, but the function is still available inpynmrstar.utils.
3.1.0¶
Changes:
PyNMRSTAR automatically retries fetching an entry from the BMR API using an exponential backoff if rate limited.
PyNMRSTAR now lists the package Requests as a requirement, which allows it to significantly speed up fetching entries from the database. It will still work if requests is not installed though, as in the case where you have checked out the code locally and don’t have requests installed - you just won’t get the enhanced performance.
Breaking changes:
The default value of
skip_empty_loopsof the methodspynmrstar.Entry.write_to_file()andpynmrstar.Saveframe.write_to_file()has been changed toTrueto write out empty loops. Technically according to the NMR-STAR format, empty loops should be omitted. In practice, many libraries fail to treat a missing tag as equivalent to a present but null tag, and would be confused by the fact that reading in a file and writing it back out again would cause these empty loops to go missing. You can still manually specifyskip_empty_loops=Trueto maintain the previous behavior.
3.0.9¶
Changes:
The library now tolerates keywords (
save_,stop_, etc.) that are not entirely lowercase which is technically allowed according to the STAR specification.Minor improvements to the c module
Breaking changes:
When calling
pynmrstar.Loop.filter()withignore_missing_tags=False, the Loop will now throw aKeyErrorrather than aValueError.
3.0.8¶
Changes:
Extra validation of tag names in saveframes and loops to ensure that users do not create tag names which contain whitespace or are the empty string.
pynmrstar.Saveframe.namehas been converted to a property from an attibute. This allows extra verification of the saveframe name, so that it can also be checked to ensure it does not contain whitespace or the empty string. This should generally not affect calling code.Updated code to use new api.bmrb.io domain when fetching entries
Potentially breaking change:
When the name of a saveframe is reassigned, if the tag
sf_framecode, is present, it is automatically updated. Also, if the tagsf_framecodeis assigned, then the saveframe name is updated.
3.0.7¶
Yanked due to a packaging error.
3.0.6¶
Changes:
If there is an issue with the number of data elements in a loop during parsing, raise a
pynmrstar.exceptions.ParsingErrorrather than theValueErrorthat would be raised normally.pynmrstar.Entry.write_to_file()had a default value ofTrueforskip_empty_tags- this value has been changed to a default ofFalseto match the default forpynmrstar.Saveframe.write_to_file().
3.0.5¶
Changes:
Add new
pynmrstar.exceptions.FormattingException, and throw it when formatting an entry with an empty string as a tag value with context information, rather than just allowing theValueErrorfrompynmrstar.utils.quote_value()to go uncaught. Note - This exception has since been renamed topynmrstar.exceptions.InvalidStateErrorpynmrstar.Entry.__str__()andpynmrstar.Saveframe.__str__()show empty loops to help development, butpynmrstar.Entry.format(),pynmrstar.Entry.write_to_file(),pynmrstar.Saveframe.format(), andpynmrstar.Saveframe.write_to_file()still do notUpdate to
pynmrstar.Entry.normalize()to ensure that all tags have the proper capitalization.Minor improvement in behavior of
pynmrstar.Loop.filter()to preserve the case of the existing tags if the filtered tags were the same but with different capitalization.
3.0.4¶
Changes:
Update packaging to mark that the 3.x branch is only for Python3.
3.0.2, 3.03¶
Changes:
Minor bug fixes to
pynmrstar.Entry.normalize()
3.0.1¶
Changes:
Added support for
skip_empty_tagsinpynmrstar.Entry.write_to_file()andpynmrstar.Saveframe.write_to_file(). Originally it was only available inpynmrstar.Entry.format()
3.0¶
3.0 has been a long time coming! There are some major improvements, specifically:
Type annotations for all functions and classes
Classes are broken out into their own files
More consistent method naming in a few places
A lot of minor improvements and cleanup
As much as possible, old method and functions have been preserved with
a DeprecationWarning to help you migrate to version 3. Using an editor like PyCharm will show where
your code using the PyNMR-STAR v2 library may be using deprecated methods/functions or have other
incompatibilities with version 3.
If you do not have the time to make the minor changes that may be
needed to start working with version 3, you can continue using the version 2 branch, which will no longer receive
updates, but will still have any major bugs fixed. To do that, either checkout the v2 branch
from GitHub, or if using PyPI, simply specify pynmrstar<=3 rather than pynmrstar when using
pip install or a requirements.txt file.
Breaking changes:
pynmrstar.Saveframe.get_tag()now returns a list of values rather than a single value. This is to be consistent withpynmrstar.Loop.get_tag()andpynmrstar.Entry.get_tag().Furthermore, calling
pynmrstar.Entry.get_tag()orpynmrstar.Saveframe.get_tag()will return all values for that tag within any children objects. (For example, you can get the values of loop tags within a loop in a specific saveframe by callingpynmrstar.Saveframe.get_tag()rather than first getting a reference to the Loop and thenpynmrstar.Loop.get_tag().)Global variables to control behavior have been removed, and definitions that under certain circumstances might be edited have been moved to the definitions submodule. Those previous module-level features have been preserved where possible:
pynmrstar.VERBOSEhas been replaced with setting the log level using the standard logging modulepynmrstar.RAISE_PARSE_WARNINGShas been moved to theraise_parse_warningsargument of the parse() function in the parser modulepynmrstar.SKIP_EMPTY_LOOPSis now the default behavior, but empty loops can be printed by specifyingskip_empty_loops=Falseas an argument topynmrstar.Entry.format(),pynmrstar.Entry.write_to_file(),pynmrstar.Saveframe.format(),pynmrstar.Saveframe.write_to_file(),pynmrstar.Loop.format()NMR-STAR 2.1 files are no longer supported. NMR-STAR 2.1 is no longer officially supported by the BMRB. Please refer to this resource if you still have 2.1 files you need to convert.
Other changes:
pynmrstar.Entry,pynmrstar.Saveframe, andpynmrstar.Loophave aformat()method to customize how the entry is formatted. Use this if you want to only show tags with values, hide comments, etc. Theskip_empty_tagsargument will only print tags with non-null values.pynmrstar.Entry.entry_idis now a property rather than a variable. When set, it will update theEntry_IDtags throughout the entry automaticallyThe
pynmrstar.Entry.normalize()method has been made more robust and fully featured than in v2.
2.6.5¶
Releases from this point forward will only fix bugs, no new features will be added on the 2.x branch. Please prepare to migrate your code to the 3.x branch once you are running in a Python3 environment.
Changes:
Fix a bug in
pynmrstar.Entry.normalize()which sorted loop and saveframe tags according to the default schema rather than provided schema.Added
DeprecationWarningto methods and functions that are removed in v3.x releases or will be removed in the future.Fix a bug in
pynmrstar.Loop.filter()triggered when a loop only has one tag.
2.6.4¶
Changes:
Fixed a bug in the c tokenizer which would incorrectly throw a parse exception if a file had a comment prior to the
data_ENTRY_IDtoken.Fixed a bug in
pynmrstar.Loop.add_data()that would replace the existing data rather than appending to it.
2.6.3¶
Changes:
Improvements to
pynmrstar.Entry.from_template()Added new
pynmrstar.Saveframe.emptyandpynmrstar.Loop.emptyproperties which will indicate if the saveframe or loop has any tag values set.Added option
default_valuestopynmrstar.Entry.from_template(),pynmrstar.Saveframe.from_template()andpynmrstar.Loop.from_template()classmethods which will set tags to the schema defined default value if present.Fix a bug in
pynmrstar.Entry.write_to_file()andpynmrstar.Saveframe.write_to_file()which would write an empty output file if an exception occurred during string formatting. Instead the output file is not touched if an error occurs.Updated built-in schema to 3.2.1.5
2.6.2¶
Changes:
Added
pynmrstar.utils.iter_entries()generator for retrieving all BMRB entries.Added
pynmrstar.Entry.from_template()methodOnly print saveframe descriptions once per category
Code linting
Breaking changes:
Converted
frame_dictandcategory_listmethods ofEntryclass into properties (pynmrstar.Entry.frame_dictandpynmrstar.Entry.category_list). You will need to remove the () from your code if you use those methods.