source: orange-bioinformatics/_bioinformatics/obiKEGG/entry/__init__.py @ 1734:91d14dd2cf0e

Revision 1734:91d14dd2cf0e, 4.5 KB checked in by Ales Erjavec <ales.erjavec@…>, 14 months ago (diff)

obiKEGG code style fixes.

Line 
1"""
2DBGET entry
3"""
4from __future__ import absolute_import
5
6__all__ = ["parser", "fields"]
7
8from collections import defaultdict
9
10from . import fields
11from .parser import DBGETEntryParser
12
13
14def entry_decorate(cls):
15    """
16    Decorate the DBEntry subclass with properties for accessing
17    the fields through the 'DBField._convert' interface
18
19    """
20    reserved_names_map = {"class": "class_", "def": "def_"}
21
22    def construct_one(name):
23        def get(self):
24            field = getattr(self, name, None)
25            if field is not None:
26                return field._convert()
27            else:
28                return None
29        return property(get, doc=name)
30
31    def construct_multiple(name):
32        def get(self):
33            field = getattr(self, name, None)
34            if field is not None:
35                return [f._convert() for f in field]
36            else:
37                return None
38        return property(get, doc=name)
39
40    for name, field in cls.FIELDS:
41        name_lower = name.lower()
42        if not hasattr(cls, name_lower):
43            if name in cls.MULTIPLE_FIELDS:
44                prop = construct_multiple(name)
45            else:
46                prop = construct_one(name)
47            setattr(cls, reserved_names_map.get(name_lower, name_lower), prop)
48
49    return cls
50
51
52class DBEntry(object):
53    """
54    A DBGET entry object.
55    """
56    FIELDS = [("ENTRY", fields.DBEntryField)]
57    MULTIPLE_FIELDS = []
58
59    def __init__(self, text=None):
60        self._sections = {}
61        if text is not None:
62            self.parse(text)
63
64    @property
65    def entry_key(self):
66        """ Primary entry key used for querying.
67        """
68        return self.entry.split(" ", 1)[0]
69
70    def parse(self, text):
71        parser = DBGETEntryParser()
72        gen = parser.parse_string(text)
73        field_constructors = dict(self.FIELDS)
74
75        current = None
76        current_subfield = None
77        entry_fields = []
78        for (event, title, text) in gen:
79            if event == DBGETEntryParser.SECTION_START:
80                if title in field_constructors:
81                    ftype = field_constructors[title]
82                else:
83                    ftype = fields.DBSimpleField
84                current = ftype(text)
85                if current.TITLE is None:
86                    current.TITLE = title
87            elif event == DBGETEntryParser.SECTION_END:
88                entry_fields.append(current)
89                current = None
90            elif event == DBGETEntryParser.SUBSECTION_START:
91                current_subfield = fields.DBSimpleField(text)
92                current_subfield.TITLE = title
93                if not isinstance(current, fields.DBFieldWithSubsections):
94                    # Upgrade simple fields to FieldWithSubsection
95                    new = fields.DBFieldWithSubsections(current.text)
96                    new.TITLE = current.TITLE
97                    current = new
98
99            elif event == DBGETEntryParser.SUBSECTION_END:
100                current.subsections.append(current_subfield)
101                current_subfield = None
102            elif event == DBGETEntryParser.TEXT:
103                if current_subfield is not None:
104                    current_subfield.text += text
105                elif current is not None:
106                    current.text += text
107            elif event == DBGETEntryParser.ENTRY_END:
108                break
109
110        self.fields = entry_fields
111        self._consolidate()
112
113    def _consolidate(self):
114        """
115        Update mapping to field entries.
116        """
117        registered_fields = dict(self.FIELDS)
118        multiple_fields = set(self.MULTIPLE_FIELDS)
119
120        for field in self.fields:
121            title = field.TITLE
122            if title not in registered_fields:
123                import warnings
124                warnings.warn("Nonregisterd field %r in %r" % \
125                              (title, type(self)))
126
127            if title in multiple_fields:
128                if not hasattr(self, title):
129                    setattr(self, title, [])
130                getattr(self, title).append(field)
131            else:
132                setattr(self, title, field)
133
134    def __str__(self):
135        return self.format()
136
137    def format(self, section_indent=12):
138        return "".join(f.format(section_indent)
139                       for f in self.fields)
140
141    def get(self, key, default=None):
142        raise NotImplementedError
143
144        f = getattr(self, key, None)
145        if f is not None:
146            if key in self.MULTIPLE_FIELDS:
147                return [f.text for f in f]
148            else:
149                return f.text
150        else:
151            return None
Note: See TracBrowser for help on using the repository browser.