vFW and vDNS support added to azure-plugin
[multicloud/azure.git] / azure / aria / aria-extension-cloudify / src / aria / aria / parser / reading / locator.py
1 # Licensed under the Apache License, Version 2.0 (the "License");
2 # you may not use this file except in compliance with the License.
3 # You may obtain a copy of the License at
4 #
5 # http://www.apache.org/licenses/LICENSE-2.0
6 #
7 # Unless required by applicable law or agreed to in writing, software
8 # distributed under the License is distributed on an "AS IS" BASIS,
9 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10 # See the License for the specific language governing permissions and
11 # limitations under the License.
12
13 from ...utils.console import puts, Colored, indent
14
15
16 # We are inheriting the primitive types in order to add the ability to set
17 # an attribute (_locator) on them.
18
19 class LocatableString(unicode):
20     pass
21
22
23 class LocatableInt(int):
24     pass
25
26
27 class LocatableFloat(float):
28     pass
29
30
31 def wrap(value):
32     if isinstance(value, basestring):
33         return True, LocatableString(value)
34     elif isinstance(value, int) and \
35             not isinstance(value, bool):  # Note: bool counts as int in Python!
36         return True, LocatableInt(value)
37     elif isinstance(value, float):
38         return True, LocatableFloat(value)
39     return False, value
40
41
42 class Locator(object):
43     """
44     Stores location information (line and column numbers) for agnostic raw data.
45     """
46     def __init__(self, location, line, column, children=None):
47         self.location = location
48         self.line = line
49         self.column = column
50         self.children = children
51
52     def get_child(self, *names):
53         if (not names) or (not isinstance(self.children, dict)):
54             return self
55         name = names[0]
56         if name not in self.children:
57             return self
58         child = self.children[name]
59         return child.get_child(names[1:])
60
61     def link(self, raw, path=None):
62         if hasattr(raw, '_locator'):
63             # This can happen when we use anchors
64             return
65
66         try:
67             setattr(raw, '_locator', self)
68         except AttributeError:
69             return
70
71         if isinstance(raw, list):
72             for i, raw_element in enumerate(raw):
73                 wrapped, raw_element = wrap(raw_element)
74                 if wrapped:
75                     raw[i] = raw_element
76                 child_path = '%s.%d' % (path, i) if path else str(i)
77                 try:
78                     self.children[i].link(raw_element, child_path)
79                 except KeyError:
80                     raise ValueError('location map does not match agnostic raw data: %s' %
81                                      child_path)
82         elif isinstance(raw, dict):
83             for k, raw_element in raw.iteritems():
84                 wrapped, raw_element = wrap(raw_element)
85                 if wrapped:
86                     raw[k] = raw_element
87                 child_path = '%s.%s' % (path, k) if path else k
88                 try:
89                     self.children[k].link(raw_element, child_path)
90                 except KeyError:
91                     raise ValueError('location map does not match agnostic raw data: %s' %
92                                      child_path)
93
94     def merge(self, locator):
95         if isinstance(self.children, dict) and isinstance(locator.children, dict):
96             for k, loc in locator.children.iteritems():
97                 if k in self.children:
98                     self.children[k].merge(loc)
99                 else:
100                     self.children[k] = loc
101
102     def dump(self, key=None):
103         if key:
104             puts('%s "%s":%d:%d' %
105                  (Colored.red(key), Colored.blue(self.location), self.line, self.column))
106         else:
107             puts('"%s":%d:%d' % (Colored.blue(self.location), self.line, self.column))
108         if isinstance(self.children, list):
109             with indent(2):
110                 for loc in self.children:
111                     loc.dump()
112         elif isinstance(self.children, dict):
113             with indent(2):
114                 for k, loc in self.children.iteritems():
115                     loc.dump(k)
116
117     def __str__(self):
118         # Should be in same format as Issue.locator_as_str
119         return '"%s":%d:%d' % (self.location, self.line, self.column)