summaryrefslogtreecommitdiffstats
path: root/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py
diff options
context:
space:
mode:
Diffstat (limited to 'azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py')
-rw-r--r--azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py119
1 files changed, 119 insertions, 0 deletions
diff --git a/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py
new file mode 100644
index 0000000..57b4d50
--- /dev/null
+++ b/azure/aria/aria-extension-cloudify/src/aria/aria/parser/reading/locator.py
@@ -0,0 +1,119 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from ...utils.console import puts, Colored, indent
+
+
+# We are inheriting the primitive types in order to add the ability to set
+# an attribute (_locator) on them.
+
+class LocatableString(unicode):
+ pass
+
+
+class LocatableInt(int):
+ pass
+
+
+class LocatableFloat(float):
+ pass
+
+
+def wrap(value):
+ if isinstance(value, basestring):
+ return True, LocatableString(value)
+ elif isinstance(value, int) and \
+ not isinstance(value, bool): # Note: bool counts as int in Python!
+ return True, LocatableInt(value)
+ elif isinstance(value, float):
+ return True, LocatableFloat(value)
+ return False, value
+
+
+class Locator(object):
+ """
+ Stores location information (line and column numbers) for agnostic raw data.
+ """
+ def __init__(self, location, line, column, children=None):
+ self.location = location
+ self.line = line
+ self.column = column
+ self.children = children
+
+ def get_child(self, *names):
+ if (not names) or (not isinstance(self.children, dict)):
+ return self
+ name = names[0]
+ if name not in self.children:
+ return self
+ child = self.children[name]
+ return child.get_child(names[1:])
+
+ def link(self, raw, path=None):
+ if hasattr(raw, '_locator'):
+ # This can happen when we use anchors
+ return
+
+ try:
+ setattr(raw, '_locator', self)
+ except AttributeError:
+ return
+
+ if isinstance(raw, list):
+ for i, raw_element in enumerate(raw):
+ wrapped, raw_element = wrap(raw_element)
+ if wrapped:
+ raw[i] = raw_element
+ child_path = '%s.%d' % (path, i) if path else str(i)
+ try:
+ self.children[i].link(raw_element, child_path)
+ except KeyError:
+ raise ValueError('location map does not match agnostic raw data: %s' %
+ child_path)
+ elif isinstance(raw, dict):
+ for k, raw_element in raw.iteritems():
+ wrapped, raw_element = wrap(raw_element)
+ if wrapped:
+ raw[k] = raw_element
+ child_path = '%s.%s' % (path, k) if path else k
+ try:
+ self.children[k].link(raw_element, child_path)
+ except KeyError:
+ raise ValueError('location map does not match agnostic raw data: %s' %
+ child_path)
+
+ def merge(self, locator):
+ if isinstance(self.children, dict) and isinstance(locator.children, dict):
+ for k, loc in locator.children.iteritems():
+ if k in self.children:
+ self.children[k].merge(loc)
+ else:
+ self.children[k] = loc
+
+ def dump(self, key=None):
+ if key:
+ puts('%s "%s":%d:%d' %
+ (Colored.red(key), Colored.blue(self.location), self.line, self.column))
+ else:
+ puts('"%s":%d:%d' % (Colored.blue(self.location), self.line, self.column))
+ if isinstance(self.children, list):
+ with indent(2):
+ for loc in self.children:
+ loc.dump()
+ elif isinstance(self.children, dict):
+ with indent(2):
+ for k, loc in self.children.iteritems():
+ loc.dump(k)
+
+ def __str__(self):
+ # Should be in same format as Issue.locator_as_str
+ return '"%s":%d:%d' % (self.location, self.line, self.column)