Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1901 serge 1
#!/usr/bin/python
2
#
3
# Copyright (C) 2009 Chia-I Wu 
4
#
5
# Permission is hereby granted, free of charge, to any person obtaining a
6
# copy of this software and associated documentation files (the "Software"),
7
# to deal in the Software without restriction, including without limitation
8
# on the rights to use, copy, modify, merge, publish, distribute, sub
9
# license, and/or sell copies of the Software, and to permit persons to whom
10
# the Software is furnished to do so, subject to the following conditions:
11
#
12
# The above copyright notice and this permission notice (including the next
13
# paragraph) shall be included in all copies or substantial portions of the
14
# Software.
15
#
16
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.  IN NO EVENT SHALL
19
# IBM AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
22
# IN THE SOFTWARE.
23
"""
24
A parser for APIspec.
25
"""
26
 
27
class SpecError(Exception):
28
    """Error in the spec file."""
29
 
30
 
31
class Spec(object):
32
    """A Spec is an abstraction of the API spec."""
33
 
34
    def __init__(self, doc):
35
        self.doc = doc
36
 
37
        self.spec_node = doc.getRootElement()
38
        self.tmpl_nodes = {}
39
        self.api_nodes = {}
40
        self.impl_node = None
41
 
42
        # parse 
43
        node = self.spec_node.children
44
        while node:
45
            if node.type == "element":
46
                if node.name == "template":
47
                    self.tmpl_nodes[node.prop("name")] = node
48
                elif node.name == "api":
49
                    self.api_nodes[node.prop("name")] = node
50
                else:
51
                    raise SpecError("unexpected node %s in apispec" %
52
                            node.name)
53
            node = node.next
54
 
55
        # find an implementation
56
        for name, node in self.api_nodes.iteritems():
57
            if node.prop("implementation") == "true":
58
                self.impl_node = node
59
                break
60
        if not self.impl_node:
61
            raise SpecError("unable to find an implementation")
62
 
63
    def get_impl(self):
64
        """Return the implementation."""
65
        return API(self, self.impl_node)
66
 
67
    def get_api(self, name):
68
        """Return an API."""
69
        return API(self, self.api_nodes[name])
70
 
71
 
72
class API(object):
73
    """An API consists of categories and functions."""
74
 
75
    def __init__(self, spec, api_node):
76
        self.name = api_node.prop("name")
77
        self.is_impl = (api_node.prop("implementation") == "true")
78
 
79
        self.categories = []
80
        self.functions = []
81
 
82
        # parse 
83
        func_nodes = []
84
        node = api_node.children
85
        while node:
86
            if node.type == "element":
87
                if node.name == "category":
88
                    cat = node.prop("name")
89
                    self.categories.append(cat)
90
                elif node.name == "function":
91
                    func_nodes.append(node)
92
                else:
93
                    raise SpecError("unexpected node %s in api" % node.name)
94
            node = node.next
95
 
96
        # realize functions
97
        for func_node in func_nodes:
98
            tmpl_node = spec.tmpl_nodes[func_node.prop("template")]
99
            try:
100
                func = Function(tmpl_node, func_node, self.is_impl,
101
                                self.categories)
102
            except SpecError, e:
103
                func_name = func_node.prop("name")
104
                raise SpecError("failed to parse %s: %s" % (func_name, e))
105
            self.functions.append(func)
106
 
107
    def match(self, func, conversions={}):
108
        """Find a matching function in the API."""
109
        match = None
110
        need_conv = False
111
        for f in self.functions:
112
            matched, conv = f.match(func, conversions)
113
            if matched:
114
                match = f
115
                need_conv = conv
116
                # exact match
117
                if not need_conv:
118
                    break
119
        return (match, need_conv)
120
 
121
 
122
class Function(object):
123
    """Parse and realize a