Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
24 commits
Select commit Hold shift + click to select a range
6540665
[document] Fix date get
mpsonntag Apr 4, 2018
60dadf3
[document] Fix date set
mpsonntag Apr 4, 2018
9bea28a
[test/doc] Add date test
mpsonntag Apr 4, 2018
1d694c0
[document] Set simple attributes None on ''
mpsonntag Apr 4, 2018
c5f154e
[test/doc] Add simple attribute tests
mpsonntag Apr 4, 2018
43dd4dd
[test/doc] Add terminology_equivalient test
mpsonntag Apr 11, 2018
d3f1b2a
[sec/prop] odmlui _parent quickfix
mpsonntag Apr 12, 2018
6ab40b9
[base/sectionable] Refactor insert
mpsonntag Apr 13, 2018
0d2f7e5
[test/doc] Add insert test
mpsonntag Apr 13, 2018
22db390
[test] Remove outdated document test files
mpsonntag Apr 13, 2018
873f40c
[base/sectionable] Add extend method
mpsonntag Apr 13, 2018
7e9ab65
[test/doc] Add extend test
mpsonntag Apr 13, 2018
9699331
[base/sectionable] Refactor append method
mpsonntag Apr 13, 2018
2aa1905
[test/doc] Add append test
mpsonntag Apr 13, 2018
ae936bd
[base/sectionable] Consistently use 'Base' classes
mpsonntag Apr 13, 2018
2e364c7
[base] Code cleanup
mpsonntag Apr 13, 2018
0da16a8
[README] Update introduction
mpsonntag Apr 13, 2018
23b79aa
[test/document int] Add file
mpsonntag Apr 13, 2018
4bd5efb
[test/document int] Add save_load method
mpsonntag Apr 13, 2018
8a54b78
[test/document int] Add id test
mpsonntag Apr 13, 2018
9f83048
[test/document int] Add simple attributes test
mpsonntag Apr 13, 2018
7a63199
[test/document int] Add section test
mpsonntag Apr 13, 2018
591deaa
[document] Code cleanup
mpsonntag Apr 13, 2018
b4fedcd
[test/doc] Fix windows urllib local file loading
mpsonntag Apr 13, 2018
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 12 additions & 9 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,17 @@
.. image:: https://coveralls.io/repos/github/G-Node/python-odml/badge.svg?branch=master
:target: https://coveralls.io/github/G-Node/python-odml?branch=master

odML libraries and editor
=========================
odML (Open metaData Markup Language) core library
=================================================

The Python-odML library (including the odML-Editor) is available on
`GitHub <https://github.com/G-Node/python-odml>`_. If you are not familiar with
the version control system **git**, but still want to use it, have a look at
the documentation available on the `git-scm website <https://git-scm.com/>`_.
The open metadata Markup Language is a file based format (XML, JSON, YAML) for storing
metadata in an organised human- and machine-readable way. odML is an initiative to define
and establish an open, flexible, and easy-to-use format to transport metadata.

The Python-odML library can be easily installed via :code:`pip`. The source code is freely
available on `GitHub <https://github.com/G-Node/python-odml>`_. If you are not familiar
with the version control system **git**, but still want to use it, have a look at the
documentation available on the `git-scm website <https://git-scm.com/>`_.

Dependencies
------------
Expand Down Expand Up @@ -85,6 +89,5 @@ Bugs & Questions
Should you find a behaviour that is likely a bug, please file a bug report at
`the github bug tracker <https://github.com/G-Node/python-odml/issues>`_.

If you have questions regarding the use of the library or the editor, feel free to
join the `#gnode <http://webchat.freenode.net?channels=%23gnode>`_ IRC channel
on freenode.
If you have questions regarding the use of the library, feel free to join the
`#gnode <http://webchat.freenode.net?channels=%23gnode>`_ IRC channel on freenode.
99 changes: 62 additions & 37 deletions odml/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
"""
Collects common base functionality
"""

import collections
import posixpath

from . import terminology
from .tools.doc_inherit import inherit_docstring, allow_inherit_docstring
from .tools.doc_inherit import allow_inherit_docstring


class _baseobj(object):
Expand Down Expand Up @@ -169,20 +169,20 @@ def append(self, *obj_tuple):
@allow_inherit_docstring
class sectionable(baseobject):
def __init__(self):
from odml.section import Section
self._sections = SmartList(Section)
from odml.section import BaseSection
self._sections = SmartList(BaseSection)
self._repository = None

@property
def document(self):
"""
Returns the parent-most node (if its a document instance) or None
"""
from odml.doc import BaseDocument
p = self
while p.parent:
p = p.parent
import odml.doc as doc
if isinstance(p, doc.Document):
if isinstance(p, BaseDocument):
return p

@property
Expand All @@ -192,29 +192,57 @@ def sections(self):

def insert(self, position, section):
"""
Adds the section to the section-list and makes this document the
section’s parent.
Insert a Section at the child-list position. A ValueError will be raised,
if a Section with the same name already exists in the child-list.

Currently just appends the section and does not insert at the
specified *position*
:param position: index at which the object should be inserted.
:param section: odML Section object.
"""
self._sections.append(section)
section._parent = self
from odml.section import BaseSection
if isinstance(section, BaseSection):
if section.name in self._sections:
raise ValueError("Section with name '%s' already exists." % section.name)

def append(self, *vsection_tuple):
self._sections.insert(position, section)
section._parent = self
else:
raise ValueError("Can only insert objects of type Section.")

def append(self, section):
"""
Adds the section to the section-list and makes this document the
section’s parent.
Method appends a single Section to the section child-lists of the current Object.

:param section: odML Section object.
"""
from odml.section import BaseSection
from odml.doc import BaseDocument
for vsection in vsection_tuple:
if (not isinstance(vsection, BaseSection)) & \
isinstance(self, BaseDocument):
raise KeyError("Object " + str(vsection) +
" is not a Section.")
self._sections.append(vsection)
vsection._parent = self
if isinstance(section, BaseSection):
self._sections.append(section)
section._parent = self
elif isinstance(section, collections.Iterable) and not isinstance(section, str):
raise ValueError("Use extend to add a list of Sections.")
else:
raise ValueError("Can only append objects of type Section.")

def extend(self, sec_list):
"""
Method adds Sections to the section child-list of the current object.

:param sec_list: Iterable containing odML Section entries.
"""
from odml.section import BaseSection
if not isinstance(sec_list, collections.Iterable):
raise TypeError("'%s' object is not iterable" % type(sec_list).__name__)

# Make sure only Sections with unique names will be added.
for sec in sec_list:
if not isinstance(sec, BaseSection):
raise ValueError("Can only extend objects of type Section.")

elif isinstance(sec, BaseSection) and sec.name in self._sections:
raise KeyError("Section with name '%s' already exists." % sec.name)

for sec in sec_list:
self.append(sec)

def remove(self, section):
""" Removes the specified child-section """
Expand Down Expand Up @@ -254,7 +282,7 @@ def itersections(self, recursive=True, yield_self=False,
if self == self.document and ((max_depth is None) or (max_depth > 0)):
for sec in self.sections:
stack.append((sec, 1)) # (<section>, <level in a tree>)
elif not self == self.document:
elif self != self.document:
stack.append((self, 0)) # (<section>, <level in a tree>)

while len(stack) > 0:
Expand Down Expand Up @@ -319,12 +347,11 @@ def contains(self, obj):
if obj.name == i.name and obj.type == i.type:
return i

# FIXME type arguments renamed to dtype?
def _matches(self, obj, key=None, type=None, include_subtype=False):
def _matches(self, obj, key=None, otype=None, include_subtype=False):
"""
Find out
* if the *key* matches obj.name (if key is not None)
* or if *type* matches obj.type (if type is not None)
* or if *otype* matches obj.type (if type is not None)
* if type does not match exactly, test for subtype.
(e.g.stimulus/white_noise)
comparisons are case-insensitive, however both key and type
Expand All @@ -333,18 +360,16 @@ def _matches(self, obj, key=None, type=None, include_subtype=False):
name_match = (key is None or (
key is not None and hasattr(obj, "name") and obj.name == key))

exact_type_match = (type is None or (type is not None and
hasattr(obj, "type") and
obj.type.lower() == type))
exact_type_match = (otype is None or (otype is not None and
hasattr(obj, "type") and
obj.type.lower() == otype))

if not include_subtype:
return name_match and exact_type_match

subtype_match = type is None or (type is not None and
hasattr(obj, "type") and
type in obj.type
.lower().split('/')[:-1])
# TODO : Break the above line more elegantly
subtype_match = (otype is None or
(otype is not None and hasattr(obj, "type") and
otype in obj.type.lower().split('/')[:-1]))

return name_match and (exact_type_match or subtype_match)

Expand Down Expand Up @@ -539,10 +564,10 @@ def clone(self, children=True):
Clone this object recursively allowing to copy it independently
to another document
"""
from odml.section import Section
from odml.section import BaseSection
obj = super(sectionable, self).clone(children)
obj._parent = None
obj._sections = SmartList(Section)
obj._sections = SmartList(BaseSection)
if children:
for s in self._sections:
obj.append(s.clone())
Expand Down
16 changes: 12 additions & 4 deletions odml/doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ class Document(base._baseobj):
@allow_inherit_docstring
class BaseDocument(base.sectionable, Document):
"""
A represenation of an odML document in memory.
A representation of an odML document in memory.
Its odml attributes are: *author*, *date*, *version* and *repository*.
A Document behaves very much like a section, except that it cannot hold
properties.
Expand Down Expand Up @@ -69,6 +69,8 @@ def author(self):

@author.setter
def author(self, new_value):
if new_value == "":
new_value = None
self._author = new_value

@property
Expand All @@ -81,18 +83,24 @@ def version(self):

@version.setter
def version(self, new_value):
if new_value == "":
new_value = None
self._version = new_value

@property
def date(self):
"""
The date the document was created.
"""
return dtypes.set(self._date, "date")
return self._date

@date.setter
def date(self, new_value):
self._date = dtypes.get(new_value, "date")
if not new_value:
new_value = None
else:
new_value = dtypes.date_set(new_value)
self._date = new_value

@property
def parent(self):
Expand Down Expand Up @@ -125,4 +133,4 @@ def get_terminology_equivalent(self):
if self.repository is None:
return None
term = terminology.load(self.repository)
return term
return term
3 changes: 2 additions & 1 deletion odml/property.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ def __init__(self, name, value=None, parent=None, unit=None,
except ValueError as e:
print(e)
self._id = str(uuid.uuid4())

self._parent = None
self._name = name
self._value_origin = value_origin
self._unit = unit
Expand All @@ -79,7 +81,6 @@ def __init__(self, name, value=None, parent=None, unit=None,
self._value = []
self.value = value

self._parent = None
self.parent = parent

@property
Expand Down
2 changes: 1 addition & 1 deletion odml/section.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def __init__(self, name, type=None, parent=None,
print(e)
self._id = str(uuid.uuid4())

self._parent = None
self._name = name
self._definition = definition
self._reference = reference
Expand All @@ -55,7 +56,6 @@ def __init__(self, name, type=None, parent=None,

# this may fire a change event, so have the section setup then
self.type = type
self._parent = None
self.parent = parent

def __repr__(self):
Expand Down
Loading