Skip to content

Commit eb97b7f

Browse files
authored
Merge pull request #290 from mpsonntag/order
Sort and order
2 parents 91b0fef + aaa5586 commit eb97b7f

File tree

8 files changed

+492
-7
lines changed

8 files changed

+492
-7
lines changed

CHANGELOG.md

Lines changed: 236 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,236 @@
1+
# Changelog
2+
3+
Used to document all changes from previous releases and collect changes
4+
until the next release.
5+
6+
# Version 1.4.0
7+
## Breaking changes
8+
9+
The switch from odML version 1.3 to 1.4 contains many cool updates which should make work more comfortable, but also includes some breaking changes.
10+
11+
### Update of the odML file format version
12+
- The odML format version number in odML files has changed from "1" to "1.1".
13+
14+
### Changes in odML classes
15+
- The odML class hierarchy has been flattened:
16+
- removing `base._baseobj` class, leaving `BaseObject` as the root odML class.
17+
- removing `doc.Document` class, leaving `BaseDocument` as the only odML Document class.
18+
- removing `section.Section` class, leaving `BaseSection` as the only odML Section class.
19+
- removing `property.Property` class leaving `BaseProperty` as the only odML Property class.
20+
- `baseobject` and `sectionable` are renamed to `BaseObject` and `Sectionable` respectively.
21+
- `base.SafeList` and `base.SmartList` have been merged, `base.SafeList` has been removed.
22+
- `base.SmartList` can now only contain Sections or Properties. See #272.
23+
- The `reorder` method is moved from the `base` to the `Section` class. See #267.
24+
25+
### Changes in Value handling:
26+
- The `Value` class has been removed.
27+
- `Property.value` now always holds a list of uniform values. `Property.value` always
28+
returns a copy of the actual value list. See #227.
29+
- Values can only be changed directly via the `__setitem__` method of a `Property`
30+
- `Value` attributes `uncertainty`, `unit`, `dtype` and `reference` have been moved to
31+
`Property` and now apply to all values of the `Property.value` list.
32+
- The `Value` attributes `filename`, `encoder` and `checksum` have been removed.
33+
34+
### DType changes:
35+
- The `binary` dtype has been removed. Providing binary content via odML files is
36+
discouraged in favor of providing a reference to the origin files using the `URL`
37+
dtype instead.
38+
39+
### Mapping
40+
- Any `mapping` functionality has been removed.
41+
42+
### Minor breaking changes
43+
- `XMLReader.fromFile()` and `.fromString()` have been renamed to `.from_file()` and `.from_string()` respectively.
44+
45+
46+
## Features and changes
47+
48+
### Required odML entity attributes handling
49+
- Required attributes of odML entities in `odml.format` where changed: `Section.name`,
50+
`Section.type` and `Property.name` are the only attributes set to be required for
51+
their respective odML entities. See #240.
52+
- `Section.name` and `Property.name` can now be `None` on init. If this is the case, the
53+
entities' `id` value is used as `name` value.
54+
- Hardcoded checks for existing `name` attributes in the XML Parser are removed. Only
55+
attributes set as required in `format` are now used to check for missing required odML
56+
entity attributes. See #241.
57+
- The `name` attribute of a `Section` or a `Property` can now only be rewritten if there
58+
is no sibling with the same name on the same hierarchical level. See #283.
59+
60+
### Addition of the 'id' attribute
61+
- `Document`, `Section` and `Property` now have an `id` attribute to uniquely identify any
62+
entity. If no valid id is provided when an entity is initialized, an id is
63+
automatically generated and assigned.
64+
- Adding the `new_id()` method to `Document`, `Section` and `Property` which generates
65+
and sets a new valid id for any entity. See #262.
66+
67+
### Changes in DType handling
68+
- Setting a dtype now also supports odML style tuple types. See #254.
69+
- DTypes now always return the defined default values if a value is `None` or `""`.
70+
- Any boolean dtype value other than `"false", "f", 0, False, "true", "t", 1` or `True`
71+
will now raise a `ValueError`. See #224
72+
73+
### 'base.Sectionable' (Document and Section) changes
74+
- Adds a `base.Sectionable.extend` method for child Sections and Properties. See #237.
75+
- Refactors the `base.Sectionable.insert` and `.append` methods. Only proper
76+
`BaseSections` with a unique name can be added to the Section child list of a
77+
`Sectionable`.
78+
- Appending multiple Sections or Properties has been removed from the `append` method to
79+
mirror Property `append` functionality and since `extend` now serves this need.
80+
81+
### 'Section' and 'Property' merge
82+
- `Property` now provides a `merge` method to merge two properties. This will sync all but
83+
the dependency and dependencyValue attributes. ValueErrors are raised, if information
84+
is set in both properties but are in conflict. See #221.
85+
- Adds a `Section.merge_check()` method which validates whether a Section including all
86+
its sub-sections and sub-properties can properly be merged. A `ValueError` is raised
87+
if any potential merge problem arises. This is necessary since a recursive Section
88+
merge cannot be easily rolled back once begun.
89+
- A Section merge imports `reference` and `definition` from the "source" Section if they
90+
were `None` in the "destination" Section. See #273.
91+
- Adds a `strict` flag to any `merge` method. Now all `Section` and `Property` attribute
92+
checks during a merge will only be done, if `strict=True`. On `strict=False` a
93+
`Section` or `Property` attribute will only be replaced with the "source" value, if
94+
the "destination" value is `None`. Otherwise the "destination" value will be kept and
95+
the "source" value lost. See #270.
96+
97+
### Changes of 'Section' and 'Property' clone
98+
- When a `Section` or a `Property` is cloned, a new id is set for the clone and of any
99+
cloned children. See #259.
100+
101+
### 'Document' changes
102+
- Tuples of Sections can now no longer be used with `Document.append` since
103+
`Document.extend` should be used to add multiple new Sections to a Document.
104+
105+
### 'Section' changes
106+
- Adds a `Section.extend` method.
107+
108+
### 'Property' changes
109+
- `Property` has the new attribute `value_origin` which may contain the origin of the
110+
property's value e.g. a filename.
111+
- `Property` init now supports setting all attributes as well as its parent.
112+
- `Property` now provides `append`, `extend` and `remove` methods to change the actual
113+
value list. This approach is required to ensure DType checks when adding new values
114+
to an existing list. See #223.
115+
- Only valid dtypes can now be set on `Property` init. See #253.
116+
117+
### Terminology changes
118+
- The default odML terminology repository is set to `http://portal.g-node.org/odml/terminologies/v1.1/terminologies.xml`.
119+
120+
### Changes in Tools and IO
121+
- The `XMLParser` can now be run in warning mode: any errors encountered during parsing
122+
will just print a warning, but will not stop and exit during the parsing process.
123+
- An odML document can now only be saved, if the validation does not show any errors.
124+
Saving an invalid document will stop the process before saving and print all
125+
encountered errors.
126+
- All parsers are now more relaxed when encountering unsupported or missing tags and only
127+
print warnings instead of ending with an exception. Warnings are collected and can be
128+
accessed via the parser object.
129+
- When trying to open a file with any of the odML parsers, the document format version
130+
number is checked. If the version number does not match the supported one, file
131+
loading will fail with an exception.
132+
133+
## New tools
134+
- Added the `tools.RDFWriter` and `toosl.RDFReader` classes, which enable the export of
135+
odML documents to RDF and also provides the used ontology OWL file at `doc/odml_terminology/`.
136+
- Added the `tools.ODMLWriter` and `tools.ODMLReader` classes which serve as an easy
137+
entry point to saving and loading for all the supported file formats `XML`, `YAML`,
138+
`JSON` and `RDF`.
139+
- Added the `tools.DictWriter` and `tools.DictReader` classes which convert Python
140+
dictionary data to odML data and vice versa, which in turn is required for both YAML
141+
and JSON format loading and saving.
142+
- Removed the `tools.jsonparser` file which is no longer required due to the classes in
143+
`tools.odmlparser` and `tools.dict_parser`.
144+
- Added the `tools.FormatConverter` class which enables batch conversion of one odML
145+
format into another.
146+
- Added the `tools.VersionConverter` class which enables conversion of pre-v1.4 odML files
147+
into valid v1.4 odML.
148+
- The `VersionConverter` converts `XML`, `JSON` and `YAML` based odML files of odML file
149+
version 1.0 to odML file version 1.1.
150+
- Only attributes supported by `Document`, `Section` and `Property` are exported. Any
151+
non supported attribute will produce a warning message, the content will be
152+
discarded.
153+
- The value content is moved from a `Value` object to its parent `Property` value list.
154+
- The first encountered `unit` or `uncertainty` of values of a `Property` will be moved
155+
to its parent `Property`. Any differing subsequent `unit` or `uncertainty` of
156+
values of the same `Property` will produce a warning message, the content will be
157+
discarded.
158+
- The first `filename` attribute content of a `Value` is moved to the `value_origin`
159+
attribute of its parent `Property`.
160+
- Any g-node terminology URL in `repository` or `link` is updated from v1.0 to their
161+
v1.1 counterparts if available.
162+
- A `VersionConverter` object provides a `.conversion_log` list attribute to access all
163+
info and warning messages after a conversion has taken place. See #234.
164+
165+
## Fixes
166+
- Various installation issues have been resolved for Linux and MacOS.
167+
- `False` as well as `F` are now properly converted to bool values in both
168+
Python 2 and 3. See #222.
169+
- Fixes saving datetime related values to JSON. See #248.
170+
- odML style custom tuples can now properly be saved using the `XMLParser`.
171+
- `Document` now properly uses the dtypes date setter on init. See #249.
172+
- Fixes load errors on Empty and `None` boolean and datetime related values. See #245.
173+
- Excludes `id` when comparing odML entities for equality. See #260.
174+
- When a `Property` is cloned, the parent of the clone is now properly set to `None`.
175+
- Avoids an `AttributeError` on `get_path()` when a `Property` has no parent. See #256.
176+
- Avoids an `AttributeError` on `get_merged_equivalent()` when a `Property`
177+
has no parent. See #257.
178+
- Avoids an error on `Property.append()`, if the dtype was not set. See #266.
179+
- Makes sure that `Property.append()` exits on empty values but accepts `0` and `False`.
180+
- Sets `Property.uncertainty` to `None` if an empty string is passed to it.
181+
- Changes the `Property.__init__` set attributes order: In the previous set attribute
182+
order, the repository attribute was overwritten with `None` by the `super.__init__`
183+
after it had been set.
184+
- Fixes set `Property.parent = None` bugs in `remove()` and `insert()` methods.
185+
- Consistently use relative imports to address circular imports and remove code that
186+
circumvents previous circular import errors in the `ODMLParser` class. See #199.
187+
- Consistently uses `BaseSection` or `BaseDocument` for isinstance checks throughout
188+
`base` instead of a mixture of `BaseSection` and `Section`.
189+
190+
191+
# Version 1.3.4
192+
193+
## Fixes
194+
- Potential installation issues due to import from `info.py`.
195+
196+
197+
# Version 1.3.3
198+
## Features
199+
200+
- Terminology caching and loading update.
201+
- Terminology section access and type listing functions.
202+
- Define and use common format version number for all parsers.
203+
- Supported format version check: When trying to open a file with any of the odml parsers,
204+
first the document format version number is checked. If the found version number does
205+
not match the supported one, file loading will fail an exception, since this is the
206+
oldest format version. If anyone tries to open a newer format, they should first
207+
update their odML package and not use this one.
208+
- Document saving: An odML document can now only be saved, if the validation does not show
209+
any errors. Saving an invalid document will exit while printing all encountered
210+
errors.
211+
- Parser: All parsers are now more relaxed when encountering unsupported tags or missing
212+
tags and only print warnings instead of ending with an exception. Warnings are
213+
collected and can be accessed via the parser object (required for display in
214+
[odml-ui](https://github.com/G-Node/odml-ui) to avoid potential loss of information).
215+
- Package and format information added or updated: `Version`, `Format version`, `Contact`,
216+
`Homepage`, `Author`, PyPI `Classifiers`, `Copyright`.
217+
- Removes the license text from `setup.py`. The license text interfered with the PyPI
218+
process in a way, that the description was not displayed on PyPI.
219+
- Removes the image folder from the project, since they are exclusively used in the
220+
outsourced [odml-ui](https://github.com/G-Node/odml-ui) project.
221+
222+
## Fixes
223+
- Fixes a bug that prohibits the parsing of `json` or `yaml` files; #191.
224+
- Fixes a bug that fails parsing of `json` or `yaml` files when `Section.repository`, `Section.link` or `Section.include` are present; #194.
225+
226+
227+
# Version 1.3.2
228+
- Expose load, save, and display functions to top level module
229+
- These functions accept a `backend` argument that specifies the parser or writer.
230+
Can be one of `XML`, `JSON`, or `YAML`.
231+
232+
233+
# Version 1.3.1
234+
- move ui to a separate repository https://github.com/g-node/odml-ui
235+
- python3 compatibility
236+
- add json and yaml storage backends

README.rst

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -94,10 +94,11 @@ To install the Python-odML library, enter the corresponding directory and run::
9494
**Note** The master branch is our current development branch, not all features might be
9595
working as expected. Use the release tags instead.
9696

97-
Documentation
98-
-------------
97+
odML Project page
98+
-----------------
9999

100-
`Documentation <https://g-node.github.io/python-odml>`_
100+
More information about the project including related projects as well as tutorials and
101+
examples can be found at our `odML project page <https://g-node.github.io/python-odml>`_
101102

102103
Bugs & Questions
103104
----------------

doc/conf.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -69,9 +69,9 @@ def __new__(meta, name, bases, clsdict):
6969
# built documents.
7070
#
7171
# The short X.Y version.
72-
version = '0.1'
72+
version = '1.4'
7373
# The full version, including alpha/beta/rc tags.
74-
release = '0.1'
74+
release = '1.4.0'
7575

7676
# The language for content autogenerated by Sphinx. Refer to documentation
7777
# for a list of supported languages.
@@ -115,7 +115,7 @@ def __new__(meta, name, bases, clsdict):
115115

116116
# The theme to use for HTML and HTML Help pages. Major themes that come with
117117
# Sphinx are currently 'default' and 'sphinxdoc'.
118-
html_theme = 'default'
118+
html_theme = 'sphinxdoc'
119119

120120
# Theme options are theme-specific and customize the look and feel of a theme
121121
# further. For a list of options available for each theme, see the

odml/base.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,28 @@ def __contains__(self, key):
131131
if (hasattr(obj, "name") and obj.name == key) or key == obj:
132132
return True
133133

134+
def __eq__(self, obj):
135+
"""
136+
SmartList attributes of 'sections' and 'properties' are
137+
handled specially: We want to make sure that the lists'
138+
objects are properly compared without changing the order
139+
of the individual lists.
140+
"""
141+
# This special case was introduced only due to the fact
142+
# that RDF files will be loaded with randomized list
143+
# order. With any other file format the list order
144+
# remains unchanged.
145+
if sorted(self, key=lambda x: x.name) != sorted(obj, key=lambda x: x.name):
146+
return False
147+
148+
return True
149+
150+
def __ne__(self, obj):
151+
"""
152+
Use the __eq__ function to determine if both objects are equal
153+
"""
154+
return not self == obj
155+
134156
def index(self, obj):
135157
"""
136158
Find obj in list
@@ -158,6 +180,13 @@ def append(self, *obj_tuple):
158180

159181
super(SmartList, self).append(obj)
160182

183+
def sort(self, key=lambda x: x.name, reverse=False):
184+
"""
185+
If not otherwise defined, sort by the *name* attribute
186+
of the lists *_content_type* object.
187+
"""
188+
super(SmartList, self).sort(key=key, reverse=reverse)
189+
161190

162191
@allow_inherit_docstring
163192
class Sectionable(BaseObject):

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
with open('README.rst') as f:
2828
description_text = f.read()
2929

30-
install_req = ["lxml", "pyyaml", "rdflib"]
30+
install_req = ["lxml", "pyyaml==3.12", "rdflib"]
3131

3232
if sys.version_info < (3, 4):
3333
install_req += ["enum34"]

0 commit comments

Comments
 (0)