<commit_before>from django.db import models
from django import forms
from django.core.exceptions import FieldError
from django.utils.text import capfirst
from philo.models.base import Entity
from philo.signals import entity_class_prepared

__all__ = ('AttributeField', 'RelationshipField')

class EntityProxyField(object):
	descriptor_class = None

	def __init__(self, *args, **kwargs):
		if self.descriptor_class is None:
			raise NotImplementedError('EntityProxyField subclasses must specify a descriptor_class.')
		self.verbose_name = kwargs.get('verbose_name', None)
		self.help_text = kwargs.get('help_text', None)

	def actually_contribute_to_class(self, sender, **kwargs):
		sender._entity_meta.add_proxy_field(self)
		setattr(sender, self.attname, self.descriptor_class(self))

	def contribute_to_class(self, cls, name):
		if issubclass(cls, Entity):
			self.name = name
			self.attname = name
			if self.verbose_name is None and name:
				self.verbose_name = name.replace('_', ' ')
			entity_class_prepared.connect(self.actually_contribute_to_class, sender=cls)
		else:
			raise FieldError('%s instances can only be declared on Entity subclasses.' % self.__class__.__name__)

	def formfield(self, *args, **kwargs):
		raise NotImplementedError('EntityProxyField subclasses must implement a formfield method.')

	def value_from_object(self, obj):
		return getattr(obj, self.attname)

class AttributeFieldDescriptor(object):
	def __init__(self, field):
		self.field = field

	def __get__(self, instance, owner):
		if instance:
			if self.field.key in instance._added_attribute_registry:
				return instance._added_attribute_registry[self.field.key]
			if self.field.key in instance._removed_attribute_registry:
				return None
			try:
				return instance.attributes[self.field.key]
			except KeyError:
				return None
		else:
			raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))

	def __set__(self, instance, value):
		if self.field.key in instance._removed_attribute_registry:
			instance._removed_attribute_registry.remove(self.field.key)
		instance._added_attribute_registry[self.field.key] = value

	def __delete__(self, instance):
		if self.field.key in instance._added_attribute_registry:
			del instance._added_attribute_registry[self.field.key]
		instance._removed_attribute_registry.append(self.field.key)

class AttributeField(EntityProxyField):
	descriptor_class = AttributeFieldDescriptor

	def __init__(self, key, field_template=None):
		super(AttributeField, self).__init__()
		self.key = key
		if field_template is None:
			field_template = models.CharField(max_length=255)
		self.field_template = field_template

	def formfield(self, **kwargs):
		defaults = {'required': False, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
		defaults.update(kwargs)
		return self.field_template.formfield(**defaults)

class RelationshipFieldDescriptor(object):
	def __init__(self, field):
		self.field = field

	def __get__(self, instance, owner):
		if instance:
			if self.field.key in instance._added_relationship_registry:
				return instance._added_relationship_registry[self.field.key]
			if self.field.key in instance._removed_relationship_registry:
				return None
			try:
				return instance.relationships[self.field.key]
			except KeyError:
				return None
		else:
			raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))

	def __set__(self, instance, value):
		if isinstance(value, (models.Model, type(None))):
			if self.field.key in instance._removed_relationship_registry:
				instance._removed_relationship_registry.remove(self.field.key)
			instance._added_relationship_registry[self.field.key] = value
		else:
			raise AttributeError('The \'%s\' attribute can only be set using existing Model objects.' % self.field.name)

	def __delete__(self, instance):
		if self.field.key in instance._added_relationship_registry:
			del instance._added_relationship_registry[self.field.key]
		instance._removed_relationship_registry.append(self.field.key)

class RelationshipField(EntityProxyField):
	descriptor_class = RelationshipFieldDescriptor

	def __init__(self, key, model, limit_choices_to=None):
		super(RelationshipField, self).__init__()
		self.key = key
		self.model = model
		if limit_choices_to is None:
			limit_choices_to = {}
		self.limit_choices_to = limit_choices_to

	def formfield(self, form_class=forms.ModelChoiceField, **kwargs):
		defaults = {'required': False, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
		defaults.update(kwargs)
		return form_class(self.model._default_manager.complex_filter(self.limit_choices_to), **defaults)

	def value_from_object(self, obj):
		relobj = super(RelationshipField, self).value_from_object(obj)
		return getattr(relobj, 'pk', None)<commit_msg>Explicit declaration of keys for AttributeFields and RelationshipFields is now unnecessary, as they will use the attribute name on the model class they were assigned to by default. This implements feature #20.<commit_after>from django.db import models
from django import forms
from django.core.exceptions import FieldError
from django.utils.text import capfirst
from philo.models.base import Entity
from philo.signals import entity_class_prepared

__all__ = ('AttributeField', 'RelationshipField')

class EntityProxyField(object):
	descriptor_class = None

	def __init__(self, *args, **kwargs):
		if self.descriptor_class is None:
			raise NotImplementedError('EntityProxyField subclasses must specify a descriptor_class.')
		self.verbose_name = kwargs.get('verbose_name', None)
		self.help_text = kwargs.get('help_text', None)

	def actually_contribute_to_class(self, sender, **kwargs):
		sender._entity_meta.add_proxy_field(self)
		setattr(sender, self.attname, self.descriptor_class(self))

	def contribute_to_class(self, cls, name):
		if issubclass(cls, Entity):
			self.name = name
			self.attname = name
			if self.verbose_name is None and name:
				self.verbose_name = name.replace('_', ' ')
			entity_class_prepared.connect(self.actually_contribute_to_class, sender=cls)
		else:
			raise FieldError('%s instances can only be declared on Entity subclasses.' % self.__class__.__name__)

	def formfield(self, *args, **kwargs):
		raise NotImplementedError('EntityProxyField subclasses must implement a formfield method.')

	def value_from_object(self, obj):
		return getattr(obj, self.attname)

class AttributeFieldDescriptor(object):
	def __init__(self, field):
		self.field = field

	def __get__(self, instance, owner):
		if instance:
			if self.field.key in instance._added_attribute_registry:
				return instance._added_attribute_registry[self.field.key]
			if self.field.key in instance._removed_attribute_registry:
				return None
			try:
				return instance.attributes[self.field.key]
			except KeyError:
				return None
		else:
			raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))

	def __set__(self, instance, value):
		if self.field.key in instance._removed_attribute_registry:
			instance._removed_attribute_registry.remove(self.field.key)
		instance._added_attribute_registry[self.field.key] = value

	def __delete__(self, instance):
		if self.field.key in instance._added_attribute_registry:
			del instance._added_attribute_registry[self.field.key]
		instance._removed_attribute_registry.append(self.field.key)

class AttributeField(EntityProxyField):
	descriptor_class = AttributeFieldDescriptor

	def __init__(self, field_template=None, key=None, **kwargs):
		super(AttributeField, self).__init__(**kwargs)
		self.key = key
		if field_template is None:
			field_template = models.CharField(max_length=255)
		self.field_template = field_template

	def contribute_to_class(self, cls, name):
		super(AttributeField, self).contribute_to_class(cls, name)
		if self.key is None:
			self.key = name

	def formfield(self, **kwargs):
		defaults = {'required': False, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
		defaults.update(kwargs)
		return self.field_template.formfield(**defaults)

class RelationshipFieldDescriptor(object):
	def __init__(self, field):
		self.field = field

	def __get__(self, instance, owner):
		if instance:
			if self.field.key in instance._added_relationship_registry:
				return instance._added_relationship_registry[self.field.key]
			if self.field.key in instance._removed_relationship_registry:
				return None
			try:
				return instance.relationships[self.field.key]
			except KeyError:
				return None
		else:
			raise AttributeError('The \'%s\' attribute can only be accessed from %s instances.' % (self.field.name, owner.__name__))

	def __set__(self, instance, value):
		if isinstance(value, (models.Model, type(None))):
			if self.field.key in instance._removed_relationship_registry:
				instance._removed_relationship_registry.remove(self.field.key)
			instance._added_relationship_registry[self.field.key] = value
		else:
			raise AttributeError('The \'%s\' attribute can only be set using existing Model objects.' % self.field.name)

	def __delete__(self, instance):
		if self.field.key in instance._added_relationship_registry:
			del instance._added_relationship_registry[self.field.key]
		instance._removed_relationship_registry.append(self.field.key)

class RelationshipField(EntityProxyField):
	descriptor_class = RelationshipFieldDescriptor

	def __init__(self, model, limit_choices_to=None, key=None, **kwargs):
		super(RelationshipField, self).__init__(**kwargs)
		self.key = key
		self.model = model
		if limit_choices_to is None:
			limit_choices_to = {}
		self.limit_choices_to = limit_choices_to

	def contribute_to_class(self, cls, name):
		super(RelationshipField, self).contribute_to_class(cls, name)
		if self.key is None:
			self.key = name

	def formfield(self, form_class=forms.ModelChoiceField, **kwargs):
		defaults = {'required': False, 'label': capfirst(self.verbose_name), 'help_text': self.help_text}
		defaults.update(kwargs)
		return form_class(self.model._default_manager.complex_filter(self.limit_choices_to), **defaults)

	def value_from_object(self, obj):
		relobj = super(RelationshipField, self).value_from_object(obj)
		return getattr(relobj, 'pk', None)<|endoftext|>


<commit_before>#!/usr/bin/python
# $Id: $
"""
Define configuration for RDFDatabank testing

$Rev: $
"""

class RDFDatabankConfig:

    granary_uri_root="http://dataflow-jenkins.bodleian.ox.ac.uk"

    # Access via IP address
    #endpointhost="databank.ora.ox.ac.uk"
    #Access to local dev VM
    endpointhost="dataflow-jenkins.bodleian.ox.ac.uk"

    # Access credentials for testing
    endpointpath="/sandbox/"

    # Access credentials for testing from local dev VM as user
    endpointuser="sandbox_user"
    endpointpass="sandbox"

    # Access credentials for testing from local dev VM as admin
    endpointadminuser="admin"
    endpointadminpass="test"

    # Later, may define methods to override these defaults, e.g. from a configuration file

# End.
<commit_msg>Changed the host for jenkins as pylons runs under port 5000 in Jenkins<commit_after>#!/usr/bin/python
# $Id: $
"""
Define configuration for RDFDatabank testing

$Rev: $
"""

class RDFDatabankConfig:

    granary_uri_root="http://dataflow-jenkins.bodleian.ox.ac.uk"

    # Access via IP address
    #endpointhost="databank.ora.ox.ac.uk"
    #Access to local dev VM
    endpointhost="localhost:5000"

    # Access credentials for testing
    endpointpath="/sandbox/"

    # Access credentials for testing from local dev VM as user
    endpointuser="sandbox_user"
    endpointpass="sandbox"

    # Access credentials for testing from local dev VM as admin
    endpointadminuser="admin"
    endpointadminpass="test"

    # Later, may define methods to override these defaults, e.g. from a configuration file

# End.
<|endoftext|>


<commit_before>#
# file: estd.py
#
# author: Copyright (C) 2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
#
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
# distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

import gdb
import gdb.printing

########################################################################################################################
# GenericIntrusiveListIterator class
########################################################################################################################

class GenericIntrusiveListIterator:
	'Generic iterator for intrusive list'

	def __init__(self, begin, end, nodeValidator, nodePointer, u):
		self.end = end
		self.nodeValidator = nodeValidator
		self.u = u
		sizeType = gdb.lookup_type('size_t')
		self.offset = gdb.parse_and_eval('static_cast<%s>(0)->*%s' % (u.pointer(), nodePointer)).address.cast(sizeType)
		self.index = 0
		self.iterator = begin

	def __iter__(self):
		return self

	def __next__(self):
		if self.iterator == self.end:
			raise StopIteration
		if self.nodeValidator(self.iterator.dereference()) == False:
			raise StopIteration
		index = self.index
		sizeType = gdb.lookup_type('size_t')
		pointer = (self.iterator.cast(sizeType) - self.offset).cast(self.u.pointer())
		element = pointer.dereference()
		self.index += 1
		self.iterator = self.iterator['nextNode_']
		return ('[%d]' % index, element)

########################################################################################################################
# ContiguousRange class
########################################################################################################################

class ContiguousRange:
	'Print estd::ContiguousRange'

	class Iterator:
		'Iterate over estd::ContiguousRange'

		def __init__(self, begin, end):
			self.end = end
			self.index = 0
			self.iterator = begin

		def __iter__(self):
			return self

		def __next__(self):
			if self.iterator == self.end:
				raise StopIteration
			index = self.index
			element = self.iterator.dereference()
			self.index += 1
			self.iterator += 1
			return ('[%d]' % index, element)

	def __init__(self, value):
		self.value = value

	def children(self):
		if self.getLength() == 0:
			return iter([])
		return self.Iterator(self.value['begin_'], self.value['end_'])

	def display_hint(self):
		return 'array'

	def getLength(self):
		begin = self.value['begin_']
		end = self.value['end_']
		# value of "begin" must be less than or equal to "end"
		if begin > end :
			return 0
		sizeType = gdb.lookup_type('size_t')
		rawLength = end.cast(sizeType) - begin.cast(sizeType)
		# raw difference between values of "begin" and "end" must be a multiple of element size
		if rawLength % begin.type.target().sizeof != 0:
			return 0
		return end - begin

	def to_string(self):
		return ('estd::ContiguousRange of length %d' % self.getLength())

########################################################################################################################
# IntrusiveList class
########################################################################################################################

class IntrusiveList:
	'Print estd::IntrusiveList'

	class Iterator(GenericIntrusiveListIterator):
		'Iterate over estd::IntrusiveList'

		def __init__(self, begin, end, nodePointer, u):
			super().__init__(begin, end, IntrusiveList.isNodeValid, nodePointer, u)

	def __init__(self, value, name = 'estd::IntrusiveList'):
		self.value = value
		self.name = name

	def children(self):
		rootNode = self.value['intrusiveListBase_']['rootNode_']
		if IntrusiveList.isNodeValid(rootNode) == False:
			return iter([])
		return self.Iterator(rootNode['nextNode_'], rootNode.address, self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

	def display_hint(self):
		# https://bugs.eclipse.org/bugs/show_bug.cgi?id=512795
		return 'array'

	@staticmethod
	def isNodeValid(node):
		nextNode = node['nextNode_']
		sizeType = gdb.lookup_type('size_t')
		# value of "next" pointer must be  properly aligned
		if nextNode.cast(sizeType) % nextNode.type.sizeof != 0:
			return False
		previousNode_ = node['previousNode_']
		# value of "previous" pointer must be  properly aligned
		if previousNode_.cast(sizeType) % previousNode_.type.sizeof != 0:
			return False
		# "previous" link of next node must point to this node
		if nextNode['previousNode_'] != node.address:
			return False
		# "next" link of previous node must point to this node
		if previousNode_['nextNode_'] != node.address:
			return False
		return True

	def isValid(self):
		return IntrusiveList.isNodeValid(self.value['intrusiveListBase_']['rootNode_'])

	def to_string(self):
		return self.name

########################################################################################################################
# IntrusiveListIterator class
########################################################################################################################

class IntrusiveListIterator(IntrusiveList):
	'Print estd::IntrusiveListIterator'

	def __init__(self, value):
		super().__init__(value, 'estd::IntrusiveListIterator')

	def children(self):
		node = self.value['node_'];
		if node == 0:
			return iter([])
		return self.Iterator(node, node['nextNode_'], self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

########################################################################################################################
# SortedIntrusiveList class
########################################################################################################################

class SortedIntrusiveList(IntrusiveList):
	'Print estd::SortedIntrusiveList'

	def __init__(self, value, name = 'estd::SortedIntrusiveList'):
		super().__init__(value['implementation_']['intrusiveList'], name)

########################################################################################################################
# IntrusiveForwardList class
########################################################################################################################

class IntrusiveForwardList:
	'Print estd::IntrusiveForwardList'

	class Iterator(GenericIntrusiveListIterator):
		'Iterate over estd::IntrusiveForwardList'

		def __init__(self, begin, end, nodePointer, u):
			super().__init__(begin, end, IntrusiveForwardList.isNodeValid, nodePointer, u)

	def __init__(self, value, name = 'estd::IntrusiveForwardList'):
		self.value = value
		self.name = name

	def children(self):
		rootNode = self.value['intrusiveForwardListBase_']['rootNode_']
		if IntrusiveForwardList.isNodeValid(rootNode) == False:
			return iter([])
		return self.Iterator(rootNode['nextNode_'], 0, self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

	def display_hint(self):
		# https://bugs.eclipse.org/bugs/show_bug.cgi?id=512795
		return 'array'

	@staticmethod
	def isNodeValid(node):
		nextNode = node['nextNode_']
		sizeType = gdb.lookup_type('size_t')
		# value of "next" pointer must be  properly aligned
		if nextNode.cast(sizeType) % nextNode.type.sizeof != 0:
			return False
		return True

	def to_string(self):
		return self.name

########################################################################################################################
# IntrusiveForwardListIterator class
########################################################################################################################

class IntrusiveForwardListIterator(IntrusiveForwardList):
	'Print estd::IntrusiveForwardListIterator'

	def __init__(self, value):
		super().__init__(value, 'estd::IntrusiveForwardListIterator')

	def children(self):
		node = self.value['node_'];
		if node == 0:
			return iter([])
		return self.Iterator(node, node['nextNode_'], self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

########################################################################################################################
# SortedIntrusiveForwardList class
########################################################################################################################

class SortedIntrusiveForwardList(IntrusiveForwardList):
	'Print estd::SortedIntrusiveForwardList'

	def __init__(self, value):
		super().__init__(value['implementation_']['intrusiveForwardList'], 'estd::SortedIntrusiveForwardList')

########################################################################################################################
# registerPrettyPrinters()
########################################################################################################################

def registerPrettyPrinters(obj):
	'Register pretty-printers for estd'

	prettyPrinters = gdb.printing.RegexpCollectionPrettyPrinter('estd')
	prettyPrinters.add_printer('estd::ContiguousRange', '^estd::ContiguousRange<.*>$', ContiguousRange)
	prettyPrinters.add_printer('estd::IntrusiveForwardListIterator', '^estd::IntrusiveForwardListIterator<.*>$',
			IntrusiveForwardListIterator)
	prettyPrinters.add_printer('estd::IntrusiveForwardList', '^estd::IntrusiveForwardList<.*>$', IntrusiveForwardList)
	prettyPrinters.add_printer('estd::IntrusiveListIterator', '^estd::IntrusiveListIterator<.*>$',
			IntrusiveListIterator)
	prettyPrinters.add_printer('estd::IntrusiveList', '^estd::IntrusiveList<.*>$', IntrusiveList)
	prettyPrinters.add_printer('estd::SortedIntrusiveForwardList', '^estd::SortedIntrusiveForwardList<.*>$',
			SortedIntrusiveForwardList)
	prettyPrinters.add_printer('estd::SortedIntrusiveList', '^estd::SortedIntrusiveList<.*>$', SortedIntrusiveList)
	gdb.printing.register_pretty_printer(obj, prettyPrinters)
<commit_msg>Fix whitespace in estd.py<commit_after>#
# file: estd.py
#
# author: Copyright (C) 2017 Kamil Szczygiel http://www.distortec.com http://www.freddiechopin.info
#
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
# distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/.
#

import gdb
import gdb.printing

########################################################################################################################
# GenericIntrusiveListIterator class
########################################################################################################################

class GenericIntrusiveListIterator:
	'Generic iterator for intrusive list'

	def __init__(self, begin, end, nodeValidator, nodePointer, u):
		self.end = end
		self.nodeValidator = nodeValidator
		self.u = u
		sizeType = gdb.lookup_type('size_t')
		self.offset = gdb.parse_and_eval('static_cast<%s>(0)->*%s' % (u.pointer(), nodePointer)).address.cast(sizeType)
		self.index = 0
		self.iterator = begin

	def __iter__(self):
		return self

	def __next__(self):
		if self.iterator == self.end:
			raise StopIteration
		if self.nodeValidator(self.iterator.dereference()) == False:
			raise StopIteration
		index = self.index
		sizeType = gdb.lookup_type('size_t')
		pointer = (self.iterator.cast(sizeType) - self.offset).cast(self.u.pointer())
		element = pointer.dereference()
		self.index += 1
		self.iterator = self.iterator['nextNode_']
		return ('[%d]' % index, element)

########################################################################################################################
# ContiguousRange class
########################################################################################################################

class ContiguousRange:
	'Print estd::ContiguousRange'

	class Iterator:
		'Iterate over estd::ContiguousRange'

		def __init__(self, begin, end):
			self.end = end
			self.index = 0
			self.iterator = begin

		def __iter__(self):
			return self

		def __next__(self):
			if self.iterator == self.end:
				raise StopIteration
			index = self.index
			element = self.iterator.dereference()
			self.index += 1
			self.iterator += 1
			return ('[%d]' % index, element)

	def __init__(self, value):
		self.value = value

	def children(self):
		if self.getLength() == 0:
			return iter([])
		return self.Iterator(self.value['begin_'], self.value['end_'])

	def display_hint(self):
		return 'array'

	def getLength(self):
		begin = self.value['begin_']
		end = self.value['end_']
		# value of "begin" must be less than or equal to "end"
		if begin > end:
			return 0
		sizeType = gdb.lookup_type('size_t')
		rawLength = end.cast(sizeType) - begin.cast(sizeType)
		# raw difference between values of "begin" and "end" must be a multiple of element size
		if rawLength % begin.type.target().sizeof != 0:
			return 0
		return end - begin

	def to_string(self):
		return ('estd::ContiguousRange of length %d' % self.getLength())

########################################################################################################################
# IntrusiveList class
########################################################################################################################

class IntrusiveList:
	'Print estd::IntrusiveList'

	class Iterator(GenericIntrusiveListIterator):
		'Iterate over estd::IntrusiveList'

		def __init__(self, begin, end, nodePointer, u):
			super().__init__(begin, end, IntrusiveList.isNodeValid, nodePointer, u)

	def __init__(self, value, name = 'estd::IntrusiveList'):
		self.value = value
		self.name = name

	def children(self):
		rootNode = self.value['intrusiveListBase_']['rootNode_']
		if IntrusiveList.isNodeValid(rootNode) == False:
			return iter([])
		return self.Iterator(rootNode['nextNode_'], rootNode.address, self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

	def display_hint(self):
		# https://bugs.eclipse.org/bugs/show_bug.cgi?id=512795
		return 'array'

	@staticmethod
	def isNodeValid(node):
		nextNode = node['nextNode_']
		sizeType = gdb.lookup_type('size_t')
		# value of "next" pointer must be  properly aligned
		if nextNode.cast(sizeType) % nextNode.type.sizeof != 0:
			return False
		previousNode_ = node['previousNode_']
		# value of "previous" pointer must be  properly aligned
		if previousNode_.cast(sizeType) % previousNode_.type.sizeof != 0:
			return False
		# "previous" link of next node must point to this node
		if nextNode['previousNode_'] != node.address:
			return False
		# "next" link of previous node must point to this node
		if previousNode_['nextNode_'] != node.address:
			return False
		return True

	def isValid(self):
		return IntrusiveList.isNodeValid(self.value['intrusiveListBase_']['rootNode_'])

	def to_string(self):
		return self.name

########################################################################################################################
# IntrusiveListIterator class
########################################################################################################################

class IntrusiveListIterator(IntrusiveList):
	'Print estd::IntrusiveListIterator'

	def __init__(self, value):
		super().__init__(value, 'estd::IntrusiveListIterator')

	def children(self):
		node = self.value['node_'];
		if node == 0:
			return iter([])
		return self.Iterator(node, node['nextNode_'], self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

########################################################################################################################
# SortedIntrusiveList class
########################################################################################################################

class SortedIntrusiveList(IntrusiveList):
	'Print estd::SortedIntrusiveList'

	def __init__(self, value, name = 'estd::SortedIntrusiveList'):
		super().__init__(value['implementation_']['intrusiveList'], name)

########################################################################################################################
# IntrusiveForwardList class
########################################################################################################################

class IntrusiveForwardList:
	'Print estd::IntrusiveForwardList'

	class Iterator(GenericIntrusiveListIterator):
		'Iterate over estd::IntrusiveForwardList'

		def __init__(self, begin, end, nodePointer, u):
			super().__init__(begin, end, IntrusiveForwardList.isNodeValid, nodePointer, u)

	def __init__(self, value, name = 'estd::IntrusiveForwardList'):
		self.value = value
		self.name = name

	def children(self):
		rootNode = self.value['intrusiveForwardListBase_']['rootNode_']
		if IntrusiveForwardList.isNodeValid(rootNode) == False:
			return iter([])
		return self.Iterator(rootNode['nextNode_'], 0, self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

	def display_hint(self):
		# https://bugs.eclipse.org/bugs/show_bug.cgi?id=512795
		return 'array'

	@staticmethod
	def isNodeValid(node):
		nextNode = node['nextNode_']
		sizeType = gdb.lookup_type('size_t')
		# value of "next" pointer must be  properly aligned
		if nextNode.cast(sizeType) % nextNode.type.sizeof != 0:
			return False
		return True

	def to_string(self):
		return self.name

########################################################################################################################
# IntrusiveForwardListIterator class
########################################################################################################################

class IntrusiveForwardListIterator(IntrusiveForwardList):
	'Print estd::IntrusiveForwardListIterator'

	def __init__(self, value):
		super().__init__(value, 'estd::IntrusiveForwardListIterator')

	def children(self):
		node = self.value['node_'];
		if node == 0:
			return iter([])
		return self.Iterator(node, node['nextNode_'], self.value.type.template_argument(1),
				self.value.type.template_argument(2).strip_typedefs())

########################################################################################################################
# SortedIntrusiveForwardList class
########################################################################################################################

class SortedIntrusiveForwardList(IntrusiveForwardList):
	'Print estd::SortedIntrusiveForwardList'

	def __init__(self, value):
		super().__init__(value['implementation_']['intrusiveForwardList'], 'estd::SortedIntrusiveForwardList')

########################################################################################################################
# registerPrettyPrinters()
########################################################################################################################

def registerPrettyPrinters(obj):
	'Register pretty-printers for estd'

	prettyPrinters = gdb.printing.RegexpCollectionPrettyPrinter('estd')
	prettyPrinters.add_printer('estd::ContiguousRange', '^estd::ContiguousRange<.*>$', ContiguousRange)
	prettyPrinters.add_printer('estd::IntrusiveForwardListIterator', '^estd::IntrusiveForwardListIterator<.*>$',
			IntrusiveForwardListIterator)
	prettyPrinters.add_printer('estd::IntrusiveForwardList', '^estd::IntrusiveForwardList<.*>$', IntrusiveForwardList)
	prettyPrinters.add_printer('estd::IntrusiveListIterator', '^estd::IntrusiveListIterator<.*>$',
			IntrusiveListIterator)
	prettyPrinters.add_printer('estd::IntrusiveList', '^estd::IntrusiveList<.*>$', IntrusiveList)
	prettyPrinters.add_printer('estd::SortedIntrusiveForwardList', '^estd::SortedIntrusiveForwardList<.*>$',
			SortedIntrusiveForwardList)
	prettyPrinters.add_printer('estd::SortedIntrusiveList', '^estd::SortedIntrusiveList<.*>$', SortedIntrusiveList)
	gdb.printing.register_pretty_printer(obj, prettyPrinters)
<|endoftext|>


<commit_before># Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import logging
import os
from base import Updater
from influxdb import InfluxDBClient

class InfluxdbUpdater(Updater):
    """
    Updates a database
    """

    def use_store(self):
        """
        Opens a database to save data
        """

        self.db = InfluxDBClient(
            self.settings.get('host', 'localhost'),
            self.settings.get('port', 8086),
            self.settings.get('user', 'root'),
            self.settings.get('password', 'root'),
            self.settings.get('database', 'mcp'),
            )
        return self.db

    def reset_store(self):
        """
        Opens a database for points
        """

        logging.info('Resetting InfluxDB database')

        self.db = InfluxDBClient(
            self.settings.get('host', 'localhost'),
            self.settings.get('port', 8086),
            self.settings.get('user', 'root'),
            self.settings.get('password', 'root'),
            self.settings.get('database', 'mcp'),
            )
        self.db.drop_database(self.settings.get('database', 'mcp'))
        self.db.create_database(self.settings.get('database', 'mcp'))
        return self.db

    def update_summary_usage(self, items=[], region='dd-eu'):
        """
        Updates summary usage records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

        for item in items:

            if len(item[1]) < 1:
                continue

            measurement = {
                    "measurement": 'Summary usage',
                    "tags": {
                        "region": region,
                        "location": item[1],
                    },
                    "time": item[0],
                    "fields": {
                        "CPU Hours": int(item[2]),
                        "High Performance CPU Hours": int(item[3]),
                        "RAM Hours": int(item[4]),
                        "Storage Hours": int(item[5]),
                        "High Performance Storage Hours": int(item[6]),
                        "Economy Storage Hours": int(item[7]),
                        "Bandwidth In": int(item[8]),
                        "Bandwidth Out": int(item[9]),
                        "Sub-Admin Hours": float(item[10]),
                        "Network Hours": float(item[11]),
                        "Essentials Network Domain Hours": int(item[12]),
                        "Advanced Network Domain Hours": int(item[13]),
                        "VLAN Hours": int(item[14]),
                        "Public IP Hours": int(item[15]),
                        "Cloud Files Account Hours": float(item[16]),
                        "Cloud Files (GB Days)": int(item[17]),
                        "Software Units": int(item[18]),
                        "Essentials Client Days": int(item[19]),
                        "Advanced Client Days": int(item[20]),
                        "Enterprise Client Days": int(item[21]),
                        "Essentials Backups (GB)": int(item[22]),
                        "Advanced Backups (GB)": int(item[23]),
                        "Enterprise Backups (GB)": int(item[24]),
                        "Essentials Monitoring Hours": int(item[25]),
                        "Advanced Monitoring Hours": int(item[26]),
                    }
                }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Error as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

    def update_detailed_usage(self, items=[], region='dd-eu'):
        """
        Updates detailed usage records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        Note that headers can change dynamically, so it is important to map
        them appropriately.

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

# ['Name', 'UUID', 'Type', 'Location', 'Private IP Address', 'Status', '"user: EUITAAS_Tag"', '"user: Platform Owner"', '"user: Test_Agenda"', 'Start Time', 'End Time', 'Duration (Hours)', 'CPU Type', 'CPU Count', 'RAM (GB)', 'Storage (GB)', 'High Performance Storage (GB)', 'Economy Storage (GB)', 'CPU Hours', 'High Performance CPU Hours', 'RAM Hours', 'Storage Hours', 'High Performance Storage Hours', 'Economy Storage Hours', 'Bandwidth-In (GB)', 'Bandwidth-Out (GB)', 'Subadmin Hours', 'Network Hours', 'Essentials Network Domain Hours', 'Advanced Network Domain Hours', 'VLAN Hours', 'Public IP Hours', 'Cloud Files Account Hours', 'Cloud Storage (GB)']

        for item in items:

            if len(item[2]) < 1:  # no type (e.g., total line)
                continue

            if item[ headers.index('CPU Count') ] > '0':  # with CPU
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                            "region": region,
                            "location": item[3],
                            "private_ip": item[4],
                            "status": item[5],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                            "CPU": int(item[ headers.index('CPU Count') ]),
                            "RAM": int(item[ headers.index('RAM (GB)') ]),
                            "Storage": int(item[ headers.index('Storage (GB)') ]),
                            "HP Storage": int(item[ headers.index('High Performance Storage (GB)') ]),
                            "Eco Storage": int(item[ headers.index('Economy Storage (GB)') ]),
                        }
                    }

            elif len(item[3]) > 0: # at some location
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                            "region": region,
                            "location": item[3],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                        }
                    }

            else: # global
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                        }
                    }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Error as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

    def update_audit_log(self, items=[], region='dd-eu'):
        """
        Updates audit log records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

        for item in items:

            measurement = {
                    "measurement": 'Audit log',
                    "tags": {
                        "region": region,
                        "caller": item[2].lower().replace('.', ' '),
                        "department": item[3],
                        "custom-1": item[4],
                        "custom-2": item[5],
                        "type": item[6],
                        "name": item[7],
                        "action": item[8],
                        "details": item[9],
                        "status": item[10],
                    },
                    "time": item[1],
                    "fields": {
                        "API Call": 1,
                    }
                }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Error as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

<commit_msg>workaround run-time error on unicode decoding<commit_after># Licensed to the Apache Software Foundation (ASF) under one or more
# contributor license agreements.  See the NOTICE file distributed with
# this work for additional information regarding copyright ownership.
# The ASF licenses this file to You 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.

import logging
import os
from base import Updater
from influxdb import InfluxDBClient

class InfluxdbUpdater(Updater):
    """
    Updates a database
    """

    def use_store(self):
        """
        Opens a database to save data
        """

        self.db = InfluxDBClient(
            self.settings.get('host', 'localhost'),
            self.settings.get('port', 8086),
            self.settings.get('user', 'root'),
            self.settings.get('password', 'root'),
            self.settings.get('database', 'mcp'),
            )
        return self.db

    def reset_store(self):
        """
        Opens a database for points
        """

        logging.info('Resetting InfluxDB database')

        self.db = InfluxDBClient(
            self.settings.get('host', 'localhost'),
            self.settings.get('port', 8086),
            self.settings.get('user', 'root'),
            self.settings.get('password', 'root'),
            self.settings.get('database', 'mcp'),
            )
        self.db.drop_database(self.settings.get('database', 'mcp'))
        self.db.create_database(self.settings.get('database', 'mcp'))
        return self.db

    def update_summary_usage(self, items=[], region='dd-eu'):
        """
        Updates summary usage records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

        for item in items:

            if len(item[1]) < 1:
                continue

            measurement = {
                    "measurement": 'Summary usage',
                    "tags": {
                        "region": region,
                        "location": item[1],
                    },
                    "time": item[0],
                    "fields": {
                        "CPU Hours": int(item[2]),
                        "High Performance CPU Hours": int(item[3]),
                        "RAM Hours": int(item[4]),
                        "Storage Hours": int(item[5]),
                        "High Performance Storage Hours": int(item[6]),
                        "Economy Storage Hours": int(item[7]),
                        "Bandwidth In": int(item[8]),
                        "Bandwidth Out": int(item[9]),
                        "Sub-Admin Hours": float(item[10]),
                        "Network Hours": float(item[11]),
                        "Essentials Network Domain Hours": int(item[12]),
                        "Advanced Network Domain Hours": int(item[13]),
                        "VLAN Hours": int(item[14]),
                        "Public IP Hours": int(item[15]),
                        "Cloud Files Account Hours": float(item[16]),
                        "Cloud Files (GB Days)": int(item[17]),
                        "Software Units": int(item[18]),
                        "Essentials Client Days": int(item[19]),
                        "Advanced Client Days": int(item[20]),
                        "Enterprise Client Days": int(item[21]),
                        "Essentials Backups (GB)": int(item[22]),
                        "Advanced Backups (GB)": int(item[23]),
                        "Enterprise Backups (GB)": int(item[24]),
                        "Essentials Monitoring Hours": int(item[25]),
                        "Advanced Monitoring Hours": int(item[26]),
                    }
                }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Error as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

    def update_detailed_usage(self, items=[], region='dd-eu'):
        """
        Updates detailed usage records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        Note that headers can change dynamically, so it is important to map
        them appropriately.

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

# ['Name', 'UUID', 'Type', 'Location', 'Private IP Address', 'Status', '"user: EUITAAS_Tag"', '"user: Platform Owner"', '"user: Test_Agenda"', 'Start Time', 'End Time', 'Duration (Hours)', 'CPU Type', 'CPU Count', 'RAM (GB)', 'Storage (GB)', 'High Performance Storage (GB)', 'Economy Storage (GB)', 'CPU Hours', 'High Performance CPU Hours', 'RAM Hours', 'Storage Hours', 'High Performance Storage Hours', 'Economy Storage Hours', 'Bandwidth-In (GB)', 'Bandwidth-Out (GB)', 'Subadmin Hours', 'Network Hours', 'Essentials Network Domain Hours', 'Advanced Network Domain Hours', 'VLAN Hours', 'Public IP Hours', 'Cloud Files Account Hours', 'Cloud Storage (GB)']

        for item in items:

            if len(item[2]) < 1:  # no type (e.g., total line)
                continue

            if item[ headers.index('CPU Count') ] > '0':  # with CPU
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                            "region": region,
                            "location": item[3],
                            "private_ip": item[4],
                            "status": item[5],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                            "CPU": int(item[ headers.index('CPU Count') ]),
                            "RAM": int(item[ headers.index('RAM (GB)') ]),
                            "Storage": int(item[ headers.index('Storage (GB)') ]),
                            "HP Storage": int(item[ headers.index('High Performance Storage (GB)') ]),
                            "Eco Storage": int(item[ headers.index('Economy Storage (GB)') ]),
                        }
                    }

            elif len(item[3]) > 0: # at some location
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                            "region": region,
                            "location": item[3],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                        }
                    }

            else: # global
                measurement = {
                        "measurement": item[2],
                        "tags": {
                            "name": item[0],
                            "UUID": item[1],
                        },
                        "time": item[ headers.index('End Time') ],
                        "fields": {
                            "duration": float(item[ headers.index('Duration (Hours)') ]),
                        }
                    }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Error as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

    def update_audit_log(self, items=[], region='dd-eu'):
        """
        Updates audit log records

        :param items: new items to push to the database
        :type items: ``list`` of ``list``

        :param region: source of the information, e.g., 'dd-eu' or other region
        :type region: ``str``

        """

        measurements = []

        if len(items) > 0:
            headers = items.pop(0)
            logging.debug("- headers: {}".format(headers))

        for item in items:

            measurement = {
                    "measurement": 'Audit log',
                    "tags": {
                        "region": region,
                        "caller": item[2].lower().replace('.', ' '),
                        "department": item[3],
                        "custom-1": item[4],
                        "custom-2": item[5],
                        "type": item[6],
                        "name": item[7],
                        "action": item[8],
                        "details": item[9],
                        "status": item[10],
                    },
                    "time": item[1],
                    "fields": {
                        "API Call": 1,
                    }
                }

#            print measurement

            measurements.append(measurement)

        try:
            self.db.write_points(measurements)

            logging.info("- stored {} measurements for {} in influxdb".format(
                len(measurements), region))

        except Exception as feedback:
            logging.warning('- unable to update influxdb')
            logging.warning(str(feedback))

<|endoftext|>


<commit_before>#
# Copyright (c) 2017 Linaro
# Copyright (c) 2017 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#

from collections import defaultdict

# globals
phandles = {}
aliases = defaultdict(list)
chosen = {}
reduced = {}
defs = {}
bindings = {}
bus_bindings = {}
binding_compats = []
old_alias_names = False

regs_config = {
    'zephyr,sram'  : 'DT_SRAM',
    'zephyr,ccm'   : 'DT_CCM'
}

name_config = {
    'zephyr,console'     : 'DT_UART_CONSOLE_ON_DEV_NAME',
    'zephyr,shell-uart'  : 'DT_UART_SHELL_ON_DEV_NAME',
    'zephyr,bt-uart'     : 'DT_BT_UART_ON_DEV_NAME',
    'zephyr,uart-pipe'   : 'DT_UART_PIPE_ON_DEV_NAME',
    'zephyr,bt-mon-uart' : 'DT_BT_MONITOR_ON_DEV_NAME',
    'zephyr,uart-mcumgr' : 'DT_UART_MCUMGR_ON_DEV_NAME'
}

def str_to_label(s):
    # Change ,-@/ to _ and uppercase
    return s.replace('-', '_') \
            .replace(',', '_') \
            .replace('@', '_') \
            .replace('/', '_') \
            .upper()

def all_compats(node):
    # Returns a set() of all 'compatible' strings that appear at or below
    # 'node', skipping disabled nodes

    if node['props'].get('status') == 'disabled':
        return set()

    compats = set()

    if 'compatible' in node['props']:
        val = node['props']['compatible']
        if isinstance(val, list):
            compats.update(val)
        else:
            compats.add(val)

    for child_node in node['children'].values():
        compats.update(all_compats(child_node))

    return compats

def create_aliases(root):
    if 'aliases' in root['children']:
        for name, node_path in root['children']['aliases']['props'].items():
            aliases[node_path].append(name)

    # Treat alternate names as aliases
    for node_path, node in reduced.items():
        if 'alt_name' in node:
            aliases[node_path].append(node['alt_name'])

def get_compat(node_path):
    # Returns the value of the 'compatible' property for the node at
    # 'node_path'. Also checks the node's parent.
    #
    # Returns None if neither the node nor its parent has a 'compatible'
    # property.

    compat = reduced[node_path]['props'].get('compatible') or \
             reduced[get_parent_path(node_path)]['props'].get('compatible')

    if isinstance(compat, list):
        return compat[0]

    return compat

def create_chosen(root):
    if 'chosen' in root['children']:
        chosen.update(root['children']['chosen']['props'])

def create_phandles(root, name):
    if root['props'].get('status') == 'disabled':
        return

    if 'phandle' in root['props']:
        phandles[root['props']['phandle']] = name

    if name != '/':
        name += '/'

    for child_name, child_node in root['children'].items():
        create_phandles(child_node, name + child_name)

def insert_defs(node_path, new_defs, new_aliases):

    for key in new_defs:
        if key.startswith('DT_COMPAT_'):
            node_path = 'compatibles'

    remove = [k for k in new_aliases if k in new_defs]
    for k in remove: del new_aliases[k]

    if node_path in defs:
        remove = [k for k in new_aliases if k in defs[node_path]]
        for k in remove: del new_aliases[k]
        if 'aliases' in defs[node_path]:
            defs[node_path]['aliases'].update(new_aliases)
        else:
            defs[node_path]['aliases'] = new_aliases

        defs[node_path].update(new_defs)
    else:
        new_defs['aliases'] = new_aliases
        defs[node_path] = new_defs

# Dictionary where all keys default to 0. Used by create_reduced().
last_used_id = defaultdict(int)

def create_reduced(node, path):
    # Compress nodes list to nodes w/ paths, add interrupt parent

    if node['props'].get('status') == 'disabled':
        return

    reduced[path] = node.copy()
    reduced[path].pop('children', None)

    # Assign an instance ID for each compat
    compat = node['props'].get('compatible')
    if compat:
        if type(compat) is not list:
            compat = [compat]

        reduced[path]['instance_id'] = {}
        for comp in compat:
            reduced[path]['instance_id'][comp] = last_used_id[comp]
            last_used_id[comp] += 1

    # Flatten 'prop = <1 2>, <3 4>' (which turns into nested lists) to
    # 'prop = <1 2 3 4>'
    for val in node['props'].values():
        if isinstance(val, list) and isinstance(val[0], list):
            # In-place modification
            val[:] = [item for sublist in val for item in sublist]

    if node['children']:
        if path != '/':
            path += '/'

        for child_name, child_node in sorted(node['children'].items()):
            create_reduced(child_node, path + child_name)

def get_node_label(node_path):
    node_compat = get_compat(node_path)
    def_label = str_to_label(node_compat)
    if '@' in node_path:
        # See if we have number we can convert
        try:
            unit_addr = int(node_path.split('@')[-1], 16)
            (nr_addr_cells, nr_size_cells) = get_addr_size_cells(node_path)
            unit_addr += translate_addr(unit_addr, node_path,
                         nr_addr_cells, nr_size_cells)
            unit_addr = "%x" % unit_addr
        except:
            unit_addr = node_path.split('@')[-1]
        def_label += '_' + str_to_label(unit_addr)
    else:
        def_label += '_' + str_to_label(node_path.split('/')[-1])
    return def_label

def get_parent_path(node_path):
    # Turns /foo/bar into /foo

    return '/'.join(node_path.split('/')[:-1]) or '/'

def find_parent_prop(node_path, prop):
    parent_path = get_parent_path(node_path)

    if prop not in reduced[parent_path]['props']:
        raise Exception("Parent of node " + node_path +
                        " has no " + prop + " property")

    return reduced[parent_path]['props'][prop]

# Get the #{address,size}-cells for a given node
def get_addr_size_cells(node_path):
    parent_addr = get_parent_path(node_path)

    # The DT spec says that if #address-cells is missing default to 2
    # if #size-cells is missing default to 1
    nr_addr = reduced[parent_addr]['props'].get('#address-cells', 2)
    nr_size = reduced[parent_addr]['props'].get('#size-cells', 1)

    return (nr_addr, nr_size)

def translate_addr(addr, node_path, nr_addr_cells, nr_size_cells):
    parent_path = get_parent_path(node_path)

    ranges = reduced[parent_path]['props'].get('ranges')
    if not ranges:
        return 0

    if isinstance(ranges, list):
        ranges = ranges.copy()  # Modified in-place below
    else:
        # Empty value ('ranges;'), meaning the parent and child address spaces
        # are the same
        ranges = []

    nr_p_addr_cells, nr_p_size_cells = get_addr_size_cells(parent_path)

    range_offset = 0
    while ranges:
        child_bus_addr = 0
        parent_bus_addr = 0
        range_len = 0
        for x in range(nr_addr_cells):
            val = ranges.pop(0) << (32 * (nr_addr_cells - x - 1))
            child_bus_addr += val
        for x in range(nr_p_addr_cells):
            val = ranges.pop(0) << (32 * (nr_p_addr_cells - x - 1))
            parent_bus_addr += val
        for x in range(nr_size_cells):
            range_len += ranges.pop(0) << (32 * (nr_size_cells - x - 1))
        # if we are outside of the range we don't need to translate
        if child_bus_addr <= addr <= (child_bus_addr + range_len):
            range_offset = parent_bus_addr - child_bus_addr
            break

    parent_range_offset = translate_addr(addr + range_offset,
            parent_path, nr_p_addr_cells, nr_p_size_cells)
    range_offset += parent_range_offset

    return range_offset

def enable_old_alias_names(enable):
    global old_alias_names
    old_alias_names = enable

def add_compat_alias(node_path, label_postfix, label, prop_aliases):
    if 'instance_id' in reduced[node_path]:
        instance = reduced[node_path]['instance_id']
        for k in instance:
            i = instance[k]
            b = 'DT_' + str_to_label(k) + '_' + str(i) + '_' + label_postfix
            prop_aliases[b] = label

def add_prop_aliases(node_path,
                     alias_label_function, prop_label, prop_aliases):
    node_compat = get_compat(node_path)
    new_alias_prefix = 'DT_' + str_to_label(node_compat)

    for alias in aliases[node_path]:
        old_alias_label = alias_label_function(alias)
        new_alias_label = new_alias_prefix + '_' + old_alias_label

        if new_alias_label != prop_label:
            prop_aliases[new_alias_label] = prop_label
        if old_alias_names and old_alias_label != prop_label:
            prop_aliases[old_alias_label] = prop_label

def get_binding(node_path):
    compat = get_compat(node_path)

    # For just look for the binding in the main dict
    # if we find it here, return it, otherwise it best
    # be in the bus specific dict
    if compat in bindings:
        return bindings[compat]

    parent_path = get_parent_path(node_path)
    parent_compat = get_compat(parent_path)

    parent_binding = bindings[parent_compat]

    bus = parent_binding['child']['bus']
    binding = bus_bindings[bus][compat]

    return binding

def get_binding_compats():
    return binding_compats

def build_cell_array(prop_array):
    index = 0
    ret_array = []

    while index < len(prop_array):
        handle = prop_array[index]

        if handle in {0, -1}:
            ret_array.append([])
            index += 1
        else:
            # get controller node (referenced via phandle)
            cell_parent = phandles[handle]

            for prop in reduced[cell_parent]['props']:
                if prop[0] == '#' and '-cells' in prop:
                    num_cells = reduced[cell_parent]['props'][prop]
                    break

            ret_array.append(prop_array[index:index+num_cells+1])

            index += num_cells + 1

    return ret_array

def extract_controller(node_path, prop, prop_values, index,
                       def_label, generic, handle_single=False):

    prop_def = {}
    prop_alias = {}

    prop_array = build_cell_array(prop_values)
    if handle_single:
        prop_array = [prop_array[index]]

    for i, elem in enumerate(prop_array):
        num_cells = len(elem)

        # if the entry is empty, skip
        if num_cells == 0:
            continue

        cell_parent = phandles[elem[0]]
        l_cell = reduced[cell_parent]['props'].get('label')

        if l_cell is None:
            continue

        l_base = def_label.split('/')

        # Check is defined should be indexed (_0, _1)
        if handle_single or i == 0 and len(prop_array) == 1:
            # 0 or 1 element in prop_values
            l_idx = []
        else:
            l_idx = [str(i)]

        # Check node generation requirements
        try:
            generation = get_binding(node_path)['properties'
                    ][prop]['generation']
        except:
            generation = ''

        if 'use-prop-name' in generation:
            l_cellname = str_to_label(prop + '_' + 'controller')
        else:
            l_cellname = str_to_label(generic + '_' + 'controller')

        label = l_base + [l_cellname] + l_idx

        add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
        prop_def['_'.join(label)] = "\"" + l_cell + "\""

        #generate defs also if node is referenced as an alias in dts
        if node_path in aliases:
            add_prop_aliases(
                node_path,
                lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
                '_'.join(label),
                prop_alias)

        insert_defs(node_path, prop_def, prop_alias)

def extract_cells(node_path, prop, prop_values, names, index,
                  def_label, generic, handle_single=False):

    prop_array = build_cell_array(prop_values)
    if handle_single:
        prop_array = [prop_array[index]]

    for i, elem in enumerate(prop_array):
        num_cells = len(elem)

        # if the entry is empty, skip
        if num_cells == 0:
            continue

        cell_parent = phandles[elem[0]]

        try:
            cell_yaml = get_binding(cell_parent)
        except:
            raise Exception(
                "Could not find yaml description for " +
                    reduced[cell_parent]['name'])

        try:
            name = names.pop(0).upper()
        except:
            name = ''

        # Get number of cells per element of current property
        for props in reduced[cell_parent]['props']:
            if props[0] == '#' and '-cells' in props:
                if props in cell_yaml:
                    cell_yaml_names = props
                else:
                    cell_yaml_names = '#cells'
        try:
            generation = get_binding(node_path)['properties'][prop
                    ]['generation']
        except:
            generation = ''

        if 'use-prop-name' in generation:
            l_cell = [str_to_label(str(prop))]
        else:
            l_cell = [str_to_label(str(generic))]

        l_base = def_label.split('/')
        # Check if #define should be indexed (_0, _1, ...)
        if handle_single or i == 0 and len(prop_array) == 1:
            # Less than 2 elements in prop_values
            # Indexing is not needed
            l_idx = []
        else:
            l_idx = [str(i)]

        prop_def = {}
        prop_alias = {}

        # Generate label for each field of the property element
        for j in range(num_cells-1):
            l_cellname = [str(cell_yaml[cell_yaml_names][j]).upper()]
            if l_cell == l_cellname:
                label = l_base + l_cell + l_idx
            else:
                label = l_base + l_cell + l_cellname + l_idx
            label_name = l_base + [name] + l_cellname
            add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
            prop_def['_'.join(label)] = elem[j+1]
            if name:
                prop_alias['_'.join(label_name)] = '_'.join(label)

            # generate defs for node aliases
            if node_path in aliases:
                add_prop_aliases(
                    node_path,
                    lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
                    '_'.join(label),
                    prop_alias)

            insert_defs(node_path, prop_def, prop_alias)
<commit_msg>scripts/dts: Remove dead 'aliases' check in insert_defs()<commit_after>#
# Copyright (c) 2017 Linaro
# Copyright (c) 2017 Bobby Noelte
#
# SPDX-License-Identifier: Apache-2.0
#

from collections import defaultdict

# globals
phandles = {}
aliases = defaultdict(list)
chosen = {}
reduced = {}
defs = {}
bindings = {}
bus_bindings = {}
binding_compats = []
old_alias_names = False

regs_config = {
    'zephyr,sram'  : 'DT_SRAM',
    'zephyr,ccm'   : 'DT_CCM'
}

name_config = {
    'zephyr,console'     : 'DT_UART_CONSOLE_ON_DEV_NAME',
    'zephyr,shell-uart'  : 'DT_UART_SHELL_ON_DEV_NAME',
    'zephyr,bt-uart'     : 'DT_BT_UART_ON_DEV_NAME',
    'zephyr,uart-pipe'   : 'DT_UART_PIPE_ON_DEV_NAME',
    'zephyr,bt-mon-uart' : 'DT_BT_MONITOR_ON_DEV_NAME',
    'zephyr,uart-mcumgr' : 'DT_UART_MCUMGR_ON_DEV_NAME'
}

def str_to_label(s):
    # Change ,-@/ to _ and uppercase
    return s.replace('-', '_') \
            .replace(',', '_') \
            .replace('@', '_') \
            .replace('/', '_') \
            .upper()

def all_compats(node):
    # Returns a set() of all 'compatible' strings that appear at or below
    # 'node', skipping disabled nodes

    if node['props'].get('status') == 'disabled':
        return set()

    compats = set()

    if 'compatible' in node['props']:
        val = node['props']['compatible']
        if isinstance(val, list):
            compats.update(val)
        else:
            compats.add(val)

    for child_node in node['children'].values():
        compats.update(all_compats(child_node))

    return compats

def create_aliases(root):
    if 'aliases' in root['children']:
        for name, node_path in root['children']['aliases']['props'].items():
            aliases[node_path].append(name)

    # Treat alternate names as aliases
    for node_path, node in reduced.items():
        if 'alt_name' in node:
            aliases[node_path].append(node['alt_name'])

def get_compat(node_path):
    # Returns the value of the 'compatible' property for the node at
    # 'node_path'. Also checks the node's parent.
    #
    # Returns None if neither the node nor its parent has a 'compatible'
    # property.

    compat = reduced[node_path]['props'].get('compatible') or \
             reduced[get_parent_path(node_path)]['props'].get('compatible')

    if isinstance(compat, list):
        return compat[0]

    return compat

def create_chosen(root):
    if 'chosen' in root['children']:
        chosen.update(root['children']['chosen']['props'])

def create_phandles(root, name):
    if root['props'].get('status') == 'disabled':
        return

    if 'phandle' in root['props']:
        phandles[root['props']['phandle']] = name

    if name != '/':
        name += '/'

    for child_name, child_node in root['children'].items():
        create_phandles(child_node, name + child_name)

def insert_defs(node_path, new_defs, new_aliases):
    for key in new_defs:
        if key.startswith('DT_COMPAT_'):
            node_path = 'compatibles'

    remove = [k for k in new_aliases if k in new_defs]
    for k in remove: del new_aliases[k]

    if node_path in defs:
        remove = [k for k in new_aliases if k in defs[node_path]]
        for k in remove: del new_aliases[k]
        defs[node_path]['aliases'].update(new_aliases)
        defs[node_path].update(new_defs)
    else:
        new_defs['aliases'] = new_aliases
        defs[node_path] = new_defs

# Dictionary where all keys default to 0. Used by create_reduced().
last_used_id = defaultdict(int)

def create_reduced(node, path):
    # Compress nodes list to nodes w/ paths, add interrupt parent

    if node['props'].get('status') == 'disabled':
        return

    reduced[path] = node.copy()
    reduced[path].pop('children', None)

    # Assign an instance ID for each compat
    compat = node['props'].get('compatible')
    if compat:
        if type(compat) is not list:
            compat = [compat]

        reduced[path]['instance_id'] = {}
        for comp in compat:
            reduced[path]['instance_id'][comp] = last_used_id[comp]
            last_used_id[comp] += 1

    # Flatten 'prop = <1 2>, <3 4>' (which turns into nested lists) to
    # 'prop = <1 2 3 4>'
    for val in node['props'].values():
        if isinstance(val, list) and isinstance(val[0], list):
            # In-place modification
            val[:] = [item for sublist in val for item in sublist]

    if node['children']:
        if path != '/':
            path += '/'

        for child_name, child_node in sorted(node['children'].items()):
            create_reduced(child_node, path + child_name)

def get_node_label(node_path):
    node_compat = get_compat(node_path)
    def_label = str_to_label(node_compat)
    if '@' in node_path:
        # See if we have number we can convert
        try:
            unit_addr = int(node_path.split('@')[-1], 16)
            (nr_addr_cells, nr_size_cells) = get_addr_size_cells(node_path)
            unit_addr += translate_addr(unit_addr, node_path,
                         nr_addr_cells, nr_size_cells)
            unit_addr = "%x" % unit_addr
        except:
            unit_addr = node_path.split('@')[-1]
        def_label += '_' + str_to_label(unit_addr)
    else:
        def_label += '_' + str_to_label(node_path.split('/')[-1])
    return def_label

def get_parent_path(node_path):
    # Turns /foo/bar into /foo

    return '/'.join(node_path.split('/')[:-1]) or '/'

def find_parent_prop(node_path, prop):
    parent_path = get_parent_path(node_path)

    if prop not in reduced[parent_path]['props']:
        raise Exception("Parent of node " + node_path +
                        " has no " + prop + " property")

    return reduced[parent_path]['props'][prop]

# Get the #{address,size}-cells for a given node
def get_addr_size_cells(node_path):
    parent_addr = get_parent_path(node_path)

    # The DT spec says that if #address-cells is missing default to 2
    # if #size-cells is missing default to 1
    nr_addr = reduced[parent_addr]['props'].get('#address-cells', 2)
    nr_size = reduced[parent_addr]['props'].get('#size-cells', 1)

    return (nr_addr, nr_size)

def translate_addr(addr, node_path, nr_addr_cells, nr_size_cells):
    parent_path = get_parent_path(node_path)

    ranges = reduced[parent_path]['props'].get('ranges')
    if not ranges:
        return 0

    if isinstance(ranges, list):
        ranges = ranges.copy()  # Modified in-place below
    else:
        # Empty value ('ranges;'), meaning the parent and child address spaces
        # are the same
        ranges = []

    nr_p_addr_cells, nr_p_size_cells = get_addr_size_cells(parent_path)

    range_offset = 0
    while ranges:
        child_bus_addr = 0
        parent_bus_addr = 0
        range_len = 0
        for x in range(nr_addr_cells):
            val = ranges.pop(0) << (32 * (nr_addr_cells - x - 1))
            child_bus_addr += val
        for x in range(nr_p_addr_cells):
            val = ranges.pop(0) << (32 * (nr_p_addr_cells - x - 1))
            parent_bus_addr += val
        for x in range(nr_size_cells):
            range_len += ranges.pop(0) << (32 * (nr_size_cells - x - 1))
        # if we are outside of the range we don't need to translate
        if child_bus_addr <= addr <= (child_bus_addr + range_len):
            range_offset = parent_bus_addr - child_bus_addr
            break

    parent_range_offset = translate_addr(addr + range_offset,
            parent_path, nr_p_addr_cells, nr_p_size_cells)
    range_offset += parent_range_offset

    return range_offset

def enable_old_alias_names(enable):
    global old_alias_names
    old_alias_names = enable

def add_compat_alias(node_path, label_postfix, label, prop_aliases):
    if 'instance_id' in reduced[node_path]:
        instance = reduced[node_path]['instance_id']
        for k in instance:
            i = instance[k]
            b = 'DT_' + str_to_label(k) + '_' + str(i) + '_' + label_postfix
            prop_aliases[b] = label

def add_prop_aliases(node_path,
                     alias_label_function, prop_label, prop_aliases):
    node_compat = get_compat(node_path)
    new_alias_prefix = 'DT_' + str_to_label(node_compat)

    for alias in aliases[node_path]:
        old_alias_label = alias_label_function(alias)
        new_alias_label = new_alias_prefix + '_' + old_alias_label

        if new_alias_label != prop_label:
            prop_aliases[new_alias_label] = prop_label
        if old_alias_names and old_alias_label != prop_label:
            prop_aliases[old_alias_label] = prop_label

def get_binding(node_path):
    compat = get_compat(node_path)

    # For just look for the binding in the main dict
    # if we find it here, return it, otherwise it best
    # be in the bus specific dict
    if compat in bindings:
        return bindings[compat]

    parent_path = get_parent_path(node_path)
    parent_compat = get_compat(parent_path)

    parent_binding = bindings[parent_compat]

    bus = parent_binding['child']['bus']
    binding = bus_bindings[bus][compat]

    return binding

def get_binding_compats():
    return binding_compats

def build_cell_array(prop_array):
    index = 0
    ret_array = []

    while index < len(prop_array):
        handle = prop_array[index]

        if handle in {0, -1}:
            ret_array.append([])
            index += 1
        else:
            # get controller node (referenced via phandle)
            cell_parent = phandles[handle]

            for prop in reduced[cell_parent]['props']:
                if prop[0] == '#' and '-cells' in prop:
                    num_cells = reduced[cell_parent]['props'][prop]
                    break

            ret_array.append(prop_array[index:index+num_cells+1])

            index += num_cells + 1

    return ret_array

def extract_controller(node_path, prop, prop_values, index,
                       def_label, generic, handle_single=False):

    prop_def = {}
    prop_alias = {}

    prop_array = build_cell_array(prop_values)
    if handle_single:
        prop_array = [prop_array[index]]

    for i, elem in enumerate(prop_array):
        num_cells = len(elem)

        # if the entry is empty, skip
        if num_cells == 0:
            continue

        cell_parent = phandles[elem[0]]
        l_cell = reduced[cell_parent]['props'].get('label')

        if l_cell is None:
            continue

        l_base = def_label.split('/')

        # Check is defined should be indexed (_0, _1)
        if handle_single or i == 0 and len(prop_array) == 1:
            # 0 or 1 element in prop_values
            l_idx = []
        else:
            l_idx = [str(i)]

        # Check node generation requirements
        try:
            generation = get_binding(node_path)['properties'
                    ][prop]['generation']
        except:
            generation = ''

        if 'use-prop-name' in generation:
            l_cellname = str_to_label(prop + '_' + 'controller')
        else:
            l_cellname = str_to_label(generic + '_' + 'controller')

        label = l_base + [l_cellname] + l_idx

        add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
        prop_def['_'.join(label)] = "\"" + l_cell + "\""

        #generate defs also if node is referenced as an alias in dts
        if node_path in aliases:
            add_prop_aliases(
                node_path,
                lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
                '_'.join(label),
                prop_alias)

        insert_defs(node_path, prop_def, prop_alias)

def extract_cells(node_path, prop, prop_values, names, index,
                  def_label, generic, handle_single=False):

    prop_array = build_cell_array(prop_values)
    if handle_single:
        prop_array = [prop_array[index]]

    for i, elem in enumerate(prop_array):
        num_cells = len(elem)

        # if the entry is empty, skip
        if num_cells == 0:
            continue

        cell_parent = phandles[elem[0]]

        try:
            cell_yaml = get_binding(cell_parent)
        except:
            raise Exception(
                "Could not find yaml description for " +
                    reduced[cell_parent]['name'])

        try:
            name = names.pop(0).upper()
        except:
            name = ''

        # Get number of cells per element of current property
        for props in reduced[cell_parent]['props']:
            if props[0] == '#' and '-cells' in props:
                if props in cell_yaml:
                    cell_yaml_names = props
                else:
                    cell_yaml_names = '#cells'
        try:
            generation = get_binding(node_path)['properties'][prop
                    ]['generation']
        except:
            generation = ''

        if 'use-prop-name' in generation:
            l_cell = [str_to_label(str(prop))]
        else:
            l_cell = [str_to_label(str(generic))]

        l_base = def_label.split('/')
        # Check if #define should be indexed (_0, _1, ...)
        if handle_single or i == 0 and len(prop_array) == 1:
            # Less than 2 elements in prop_values
            # Indexing is not needed
            l_idx = []
        else:
            l_idx = [str(i)]

        prop_def = {}
        prop_alias = {}

        # Generate label for each field of the property element
        for j in range(num_cells-1):
            l_cellname = [str(cell_yaml[cell_yaml_names][j]).upper()]
            if l_cell == l_cellname:
                label = l_base + l_cell + l_idx
            else:
                label = l_base + l_cell + l_cellname + l_idx
            label_name = l_base + [name] + l_cellname
            add_compat_alias(node_path, '_'.join(label[1:]), '_'.join(label), prop_alias)
            prop_def['_'.join(label)] = elem[j+1]
            if name:
                prop_alias['_'.join(label_name)] = '_'.join(label)

            # generate defs for node aliases
            if node_path in aliases:
                add_prop_aliases(
                    node_path,
                    lambda alias: '_'.join([str_to_label(alias)] + label[1:]),
                    '_'.join(label),
                    prop_alias)

            insert_defs(node_path, prop_def, prop_alias)
<|endoftext|>