<commit_before># Copyright (c) 2016 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from PyQt5.QtCore import QObject, QVariant, pyqtProperty, pyqtSlot, pyqtSignal
from PyQt5.QtQml import QQmlPropertyMap

from UM.Logger import Logger
from UM.Settings.SettingFunction import SettingFunction

import UM.Settings

##  This class provides the value and change notifications for the properties of a single setting
#
#   Since setting values and other properties are provided by a stack, we need some way to
#   query the stack from QML to provide us with those values. This class takes care of that.
#
#   This class provides the property values through QObject dynamic properties so that they
#   are available from QML.
class SettingPropertyProvider(QObject):
    def __init__(self, parent = None, *args, **kwargs):
        super().__init__(parent = parent, *args, **kwargs)

        self._property_map = None

        self._stack_id = ""
        self._stack = None
        self._key = ""
        self._relations = set()
        self._watched_properties = []
        self._store_index = 0
        self._value_used = None
        self._stack_levels = []
        self._remove_unused_value = True
        self._validator = None

    ##  Set the containerStackId property.
    def setContainerStackId(self, stack_id):
        if stack_id == self._stack_id:
            return # No change.

        self._stack_id = stack_id

        if self._stack:
            self._stack.propertiesChanged.disconnect(self._onPropertiesChanged)
            self._stack.containersChanged.disconnect(self._update)

        if self._stack_id:
            if self._stack_id == "global":
                self._stack = UM.Application.getInstance().getGlobalContainerStack()
            else:
                stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = self._stack_id)
                if stacks:
                    self._stack = stacks[0]

            if self._stack:
                self._stack.propertiesChanged.connect(self._onPropertiesChanged)
                self._stack.containersChanged.connect(self._update)
        else:
            self._stack = None
        self._validator = None
        self._update()
        self.containerStackIdChanged.emit()

    ##  Emitted when the containerStackId property changes.
    containerStackIdChanged = pyqtSignal()
    ##  The ID of the container stack we should query for property values.
    @pyqtProperty(str, fset = setContainerStackId, notify = containerStackIdChanged)
    def containerStackId(self):
        return self._stack_id

    removeUnusedValueChanged = pyqtSignal()

    def setRemoveUnusedValue(self, remove_unused_value):
        self._remove_unused_value = remove_unused_value
        self.removeUnusedValueChanged.emit()

    @pyqtProperty(bool, fset = setRemoveUnusedValue, notify = removeUnusedValueChanged)
    def removeUnusedValue(self):
        return self._remove_unused_value

    ##  Set the watchedProperties property.
    def setWatchedProperties(self, properties):
        if properties != self._watched_properties:
            self._watched_properties = properties
            self._update()
            self.watchedPropertiesChanged.emit()

    ##  Emitted when the watchedProperties property changes.
    watchedPropertiesChanged = pyqtSignal()
    ##  A list of property names that should be watched for changes.
    @pyqtProperty("QVariantList", fset = setWatchedProperties, notify = watchedPropertiesChanged)
    def watchedProperties(self):
        return self._watched_properties

    ##  Set the key property.
    def setKey(self, key):
        if key != self._key:
            self._key = key
            self._validator = None
            self._update()
            self.keyChanged.emit()

    ##  Emitted when the key property changes.
    keyChanged = pyqtSignal()
    ##  The key of the setting that we should provide property values for.
    @pyqtProperty(str, fset = setKey, notify = keyChanged)
    def key(self):
        return self._key

    propertiesChanged = pyqtSignal()
    @pyqtProperty(QQmlPropertyMap, notify = propertiesChanged)
    def properties(self):
        return self._property_map

    @pyqtSlot()
    def forcePropertiesChanged(self):
        for watched_property in self._watched_properties:
            self._onPropertyChanged(self._key, watched_property)

    def setStoreIndex(self, index):
        if index != self._store_index:
            self._store_index = index
            self.storeIndexChanged.emit()

    storeIndexChanged = pyqtSignal()
    @pyqtProperty(int, fset = setStoreIndex, notify = storeIndexChanged)
    def storeIndex(self):
        return self._store_index

    stackLevelChanged = pyqtSignal()

    ##  At what levels in the stack does the value(s) for this setting occur?
    @pyqtProperty("QVariantList", notify = stackLevelChanged)
    def stackLevels(self):
        if not self._stack:
            return -1
        return self._stack_levels

    ##  Set the value of a property.
    #
    #   \param stack_index At which level in the stack should this property be set?
    #   \param property_name The name of the property to set.
    #   \param property_value The value of the property to set.
    @pyqtSlot(str, "QVariant")
    def setPropertyValue(self, property_name, property_value):
        if not self._stack or not self._key:
            return

        if property_name not in self._watched_properties:
            Logger.log("w", "Tried to set a property that is not being watched")
            return

        container = self._stack.getContainer(self._store_index)
        if isinstance(container, UM.Settings.DefinitionContainer):
            return

        # In some cases we clean some stuff and the result is as when nothing as been changed manually.
        if property_name == "value" and self._remove_unused_value:
            for index in self._stack_levels:
                if index > self._store_index:
                    old_value = self.getPropertyValue(property_name, index)

                    key_state = str(self._stack.getContainer(self._store_index).getProperty(self._key, "state"))
                    # sometimes: old value is int, property_value is float
                    # (and the container is not removed, so the revert button appears)
                    if str(old_value) == str(property_value) and key_state != "InstanceState.Calculated":
                        # If we change the setting so that it would be the same as a deeper setting, we can just remove
                        # the value. Note that we only do this when this is not caused by the calculated state
                        # In this case the setting does need to be set, as it needs to be stored in the user settings.
                        self.removeFromContainer(self._store_index)
                        return
                    else:  # First value that we encountered was different, stop looking & continue as normal.
                        break

        # _remove_unused_value is used when the stack value differs from the effective value
        # i.e. there is a resolve function
        if self._property_map.value(property_name) == property_value and self._remove_unused_value:
            return

        container.setProperty(self._key, property_name, property_value)

    ##  Manually request the value of a property.
    #   The most notable difference with the properties is that you have more control over at what point in the stack
    #   you want the setting to be retrieved (instead of always taking the top one)
    #   \param property_name The name of the property to get the value from.
    #   \param stack_level the index of the container to get the value from.
    @pyqtSlot(str, int, result = "QVariant")
    def getPropertyValue(self, property_name, stack_level):
        try:
            # Because we continue to count if there are multiple linked stacks, we need to check what stack is targeted
            current_stack = self._stack
            while current_stack:
                num_containers = len(current_stack.getContainers())
                if stack_level >= num_containers:
                    stack_level -= num_containers
                    current_stack = self._stack.getNextStack()
                else:
                    break  # Found the right stack

            if not current_stack:
                Logger.log("w", "Could not find the right stack for setting %s at stack level %d while trying to get property %s", self._key, stack_level, property_name)
                return None

            value = current_stack.getContainers()[stack_level].getProperty(self._key, property_name)
        except IndexError:  # Requested stack level does not exist
            Logger.log("w", "Tried to get property of type %s from %s but it did not exist on requested index %d", property_name, self._key, stack_level)
            return None
        return value

    @pyqtSlot(int)
    def removeFromContainer(self, index):
        current_stack = self._stack
        while current_stack:
            num_containers = len(current_stack.getContainers())
            if index >= num_containers:
                index -= num_containers
                current_stack = self._stack.getNextStack()
            else:
                break  # Found the right stack

        if not current_stack:
            Logger.log("w", "Unable to remove instance from container because the right stack at stack level %d could not be found", stack_level)
            return

        container = current_stack.getContainer(index)
        if not container or not isinstance(container, UM.Settings.InstanceContainer):
            Logger.log("w", "Unable to remove instance from container as it was either not found or not an instance container")
            return

        container.removeInstance(self._key)

    isValueUsedChanged = pyqtSignal()
    @pyqtProperty(bool, notify = isValueUsedChanged)
    def isValueUsed(self):
        if self._value_used is not None:
            return self._value_used
        if not self._stack:
            return False
        definition = self._stack.getSettingDefinition(self._key)
        if not definition:
            return False

        relation_count = 0
        value_used_count = 0
        for key in self._relations:
            # If the setting is not a descendant of this setting, ignore it.
            if not definition.isDescendant(key):
                continue

            relation_count += 1

            if self._stack.getProperty(key, "state") != UM.Settings.InstanceState.User:
                value_used_count += 1

            # If the setting has a formula the value is still used.
            if isinstance(self._stack.getRawProperty(key, "value"), SettingFunction):
                value_used_count += 1

        self._value_used = relation_count == 0 or (relation_count > 0 and value_used_count != 0)
        return self._value_used

    # protected:

    def _onPropertiesChanged(self, key, property_names):
        if key != self._key:
            if key in self._relations:
                self._value_used = None
                self.isValueUsedChanged.emit()
            return

        for property_name in property_names:
            if property_name not in self._watched_properties:
                continue

            self._property_map.insert(property_name, self._getPropertyValue(property_name))

        self._updateStackLevels()

    def _update(self, container = None):
        if not self._stack or not self._watched_properties or not self._key:
            return

        self._updateStackLevels()
        relations = self._stack.getProperty(self._key, "relations")
        if relations:  # If the setting doesn't have the property relations, None is returned
            for relation in filter(lambda r: r.type == UM.Settings.SettingRelation.RelationType.RequiredByTarget and r.role == "value", relations):
                self._relations.add(relation.target.key)

        self._property_map = QQmlPropertyMap(self)

        for property_name in self._watched_properties:
            self._property_map.insert(property_name, self._getPropertyValue(property_name))

        self.propertiesChanged.emit()

        # Force update of value_used
        self._value_used = None
        self.isValueUsedChanged.emit()

    def _updateStackLevels(self):
        levels = []
        # Start looking at the stack this provider is attached to.
        current_stack = self._stack
        index = 0
        while current_stack:
            for container in current_stack.getContainers():
                try:
                    if container.getProperty(self._key, "value") is not None:
                        levels.append(index)
                except AttributeError:
                    pass
                index += 1
            # If there is a next stack, check that one as well.
            current_stack = current_stack.getNextStack()
        if levels != self._stack_levels:
            self._stack_levels = levels
            self.stackLevelChanged.emit()

    def _getPropertyValue(self, property_name):
        property_value = self._stack.getProperty(self._key, property_name)
        if isinstance(property_value, UM.Settings.SettingFunction):
            property_value = property_value(self._stack)

        if property_name == "value":
            property_value = UM.Settings.SettingDefinition.settingValueToString(
                self._stack.getProperty(self._key, "type"), property_value)
        elif property_name == "validationState":
            # Setting is not validated. This can happen if there is only a setting definition.
            # We do need to validate it, because a setting defintions value can be set by a function, which could
            # be an invalid setting.
            if property_value is None:
                if not self._validator:
                    definition = self._stack.getSettingDefinition(self._key)
                    validator_type = UM.Settings.SettingDefinition.getValidatorForType(definition.type)
                    if validator_type:
                        self._validator = validator_type(self._key)
                if self._validator:
                    property_value = self._validator(self._stack)
        return str(property_value)
<commit_msg>Fix forcePropertiesChanged call<commit_after># Copyright (c) 2016 Ultimaker B.V.
# Uranium is released under the terms of the AGPLv3 or higher.

from PyQt5.QtCore import QObject, QVariant, pyqtProperty, pyqtSlot, pyqtSignal
from PyQt5.QtQml import QQmlPropertyMap

from UM.Logger import Logger
from UM.Settings.SettingFunction import SettingFunction

import UM.Settings

##  This class provides the value and change notifications for the properties of a single setting
#
#   Since setting values and other properties are provided by a stack, we need some way to
#   query the stack from QML to provide us with those values. This class takes care of that.
#
#   This class provides the property values through QObject dynamic properties so that they
#   are available from QML.
class SettingPropertyProvider(QObject):
    def __init__(self, parent = None, *args, **kwargs):
        super().__init__(parent = parent, *args, **kwargs)

        self._property_map = None

        self._stack_id = ""
        self._stack = None
        self._key = ""
        self._relations = set()
        self._watched_properties = []
        self._store_index = 0
        self._value_used = None
        self._stack_levels = []
        self._remove_unused_value = True
        self._validator = None

    ##  Set the containerStackId property.
    def setContainerStackId(self, stack_id):
        if stack_id == self._stack_id:
            return # No change.

        self._stack_id = stack_id

        if self._stack:
            self._stack.propertiesChanged.disconnect(self._onPropertiesChanged)
            self._stack.containersChanged.disconnect(self._update)

        if self._stack_id:
            if self._stack_id == "global":
                self._stack = UM.Application.getInstance().getGlobalContainerStack()
            else:
                stacks = UM.Settings.ContainerRegistry.getInstance().findContainerStacks(id = self._stack_id)
                if stacks:
                    self._stack = stacks[0]

            if self._stack:
                self._stack.propertiesChanged.connect(self._onPropertiesChanged)
                self._stack.containersChanged.connect(self._update)
        else:
            self._stack = None
        self._validator = None
        self._update()
        self.containerStackIdChanged.emit()

    ##  Emitted when the containerStackId property changes.
    containerStackIdChanged = pyqtSignal()
    ##  The ID of the container stack we should query for property values.
    @pyqtProperty(str, fset = setContainerStackId, notify = containerStackIdChanged)
    def containerStackId(self):
        return self._stack_id

    removeUnusedValueChanged = pyqtSignal()

    def setRemoveUnusedValue(self, remove_unused_value):
        self._remove_unused_value = remove_unused_value
        self.removeUnusedValueChanged.emit()

    @pyqtProperty(bool, fset = setRemoveUnusedValue, notify = removeUnusedValueChanged)
    def removeUnusedValue(self):
        return self._remove_unused_value

    ##  Set the watchedProperties property.
    def setWatchedProperties(self, properties):
        if properties != self._watched_properties:
            self._watched_properties = properties
            self._update()
            self.watchedPropertiesChanged.emit()

    ##  Emitted when the watchedProperties property changes.
    watchedPropertiesChanged = pyqtSignal()
    ##  A list of property names that should be watched for changes.
    @pyqtProperty("QVariantList", fset = setWatchedProperties, notify = watchedPropertiesChanged)
    def watchedProperties(self):
        return self._watched_properties

    ##  Set the key property.
    def setKey(self, key):
        if key != self._key:
            self._key = key
            self._validator = None
            self._update()
            self.keyChanged.emit()

    ##  Emitted when the key property changes.
    keyChanged = pyqtSignal()
    ##  The key of the setting that we should provide property values for.
    @pyqtProperty(str, fset = setKey, notify = keyChanged)
    def key(self):
        return self._key

    propertiesChanged = pyqtSignal()
    @pyqtProperty(QQmlPropertyMap, notify = propertiesChanged)
    def properties(self):
        return self._property_map

    @pyqtSlot()
    def forcePropertiesChanged(self):
        self._onPropertiesChanged(self._key, self._watched_properties)

    def setStoreIndex(self, index):
        if index != self._store_index:
            self._store_index = index
            self.storeIndexChanged.emit()

    storeIndexChanged = pyqtSignal()
    @pyqtProperty(int, fset = setStoreIndex, notify = storeIndexChanged)
    def storeIndex(self):
        return self._store_index

    stackLevelChanged = pyqtSignal()

    ##  At what levels in the stack does the value(s) for this setting occur?
    @pyqtProperty("QVariantList", notify = stackLevelChanged)
    def stackLevels(self):
        if not self._stack:
            return -1
        return self._stack_levels

    ##  Set the value of a property.
    #
    #   \param stack_index At which level in the stack should this property be set?
    #   \param property_name The name of the property to set.
    #   \param property_value The value of the property to set.
    @pyqtSlot(str, "QVariant")
    def setPropertyValue(self, property_name, property_value):
        if not self._stack or not self._key:
            return

        if property_name not in self._watched_properties:
            Logger.log("w", "Tried to set a property that is not being watched")
            return

        container = self._stack.getContainer(self._store_index)
        if isinstance(container, UM.Settings.DefinitionContainer):
            return

        # In some cases we clean some stuff and the result is as when nothing as been changed manually.
        if property_name == "value" and self._remove_unused_value:
            for index in self._stack_levels:
                if index > self._store_index:
                    old_value = self.getPropertyValue(property_name, index)

                    key_state = str(self._stack.getContainer(self._store_index).getProperty(self._key, "state"))
                    # sometimes: old value is int, property_value is float
                    # (and the container is not removed, so the revert button appears)
                    if str(old_value) == str(property_value) and key_state != "InstanceState.Calculated":
                        # If we change the setting so that it would be the same as a deeper setting, we can just remove
                        # the value. Note that we only do this when this is not caused by the calculated state
                        # In this case the setting does need to be set, as it needs to be stored in the user settings.
                        self.removeFromContainer(self._store_index)
                        return
                    else:  # First value that we encountered was different, stop looking & continue as normal.
                        break

        # _remove_unused_value is used when the stack value differs from the effective value
        # i.e. there is a resolve function
        if self._property_map.value(property_name) == property_value and self._remove_unused_value:
            return

        container.setProperty(self._key, property_name, property_value)

    ##  Manually request the value of a property.
    #   The most notable difference with the properties is that you have more control over at what point in the stack
    #   you want the setting to be retrieved (instead of always taking the top one)
    #   \param property_name The name of the property to get the value from.
    #   \param stack_level the index of the container to get the value from.
    @pyqtSlot(str, int, result = "QVariant")
    def getPropertyValue(self, property_name, stack_level):
        try:
            # Because we continue to count if there are multiple linked stacks, we need to check what stack is targeted
            current_stack = self._stack
            while current_stack:
                num_containers = len(current_stack.getContainers())
                if stack_level >= num_containers:
                    stack_level -= num_containers
                    current_stack = self._stack.getNextStack()
                else:
                    break  # Found the right stack

            if not current_stack:
                Logger.log("w", "Could not find the right stack for setting %s at stack level %d while trying to get property %s", self._key, stack_level, property_name)
                return None

            value = current_stack.getContainers()[stack_level].getProperty(self._key, property_name)
        except IndexError:  # Requested stack level does not exist
            Logger.log("w", "Tried to get property of type %s from %s but it did not exist on requested index %d", property_name, self._key, stack_level)
            return None
        return value

    @pyqtSlot(int)
    def removeFromContainer(self, index):
        current_stack = self._stack
        while current_stack:
            num_containers = len(current_stack.getContainers())
            if index >= num_containers:
                index -= num_containers
                current_stack = self._stack.getNextStack()
            else:
                break  # Found the right stack

        if not current_stack:
            Logger.log("w", "Unable to remove instance from container because the right stack at stack level %d could not be found", stack_level)
            return

        container = current_stack.getContainer(index)
        if not container or not isinstance(container, UM.Settings.InstanceContainer):
            Logger.log("w", "Unable to remove instance from container as it was either not found or not an instance container")
            return

        container.removeInstance(self._key)

    isValueUsedChanged = pyqtSignal()
    @pyqtProperty(bool, notify = isValueUsedChanged)
    def isValueUsed(self):
        if self._value_used is not None:
            return self._value_used
        if not self._stack:
            return False
        definition = self._stack.getSettingDefinition(self._key)
        if not definition:
            return False

        relation_count = 0
        value_used_count = 0
        for key in self._relations:
            # If the setting is not a descendant of this setting, ignore it.
            if not definition.isDescendant(key):
                continue

            relation_count += 1

            if self._stack.getProperty(key, "state") != UM.Settings.InstanceState.User:
                value_used_count += 1

            # If the setting has a formula the value is still used.
            if isinstance(self._stack.getRawProperty(key, "value"), SettingFunction):
                value_used_count += 1

        self._value_used = relation_count == 0 or (relation_count > 0 and value_used_count != 0)
        return self._value_used

    # protected:

    def _onPropertiesChanged(self, key, property_names):
        if key != self._key:
            if key in self._relations:
                self._value_used = None
                self.isValueUsedChanged.emit()
            return

        for property_name in property_names:
            if property_name not in self._watched_properties:
                continue

            self._property_map.insert(property_name, self._getPropertyValue(property_name))

        self._updateStackLevels()

    def _update(self, container = None):
        if not self._stack or not self._watched_properties or not self._key:
            return

        self._updateStackLevels()
        relations = self._stack.getProperty(self._key, "relations")
        if relations:  # If the setting doesn't have the property relations, None is returned
            for relation in filter(lambda r: r.type == UM.Settings.SettingRelation.RelationType.RequiredByTarget and r.role == "value", relations):
                self._relations.add(relation.target.key)

        self._property_map = QQmlPropertyMap(self)

        for property_name in self._watched_properties:
            self._property_map.insert(property_name, self._getPropertyValue(property_name))

        self.propertiesChanged.emit()

        # Force update of value_used
        self._value_used = None
        self.isValueUsedChanged.emit()

    def _updateStackLevels(self):
        levels = []
        # Start looking at the stack this provider is attached to.
        current_stack = self._stack
        index = 0
        while current_stack:
            for container in current_stack.getContainers():
                try:
                    if container.getProperty(self._key, "value") is not None:
                        levels.append(index)
                except AttributeError:
                    pass
                index += 1
            # If there is a next stack, check that one as well.
            current_stack = current_stack.getNextStack()
        if levels != self._stack_levels:
            self._stack_levels = levels
            self.stackLevelChanged.emit()

    def _getPropertyValue(self, property_name):
        property_value = self._stack.getProperty(self._key, property_name)
        if isinstance(property_value, UM.Settings.SettingFunction):
            property_value = property_value(self._stack)

        if property_name == "value":
            property_value = UM.Settings.SettingDefinition.settingValueToString(
                self._stack.getProperty(self._key, "type"), property_value)
        elif property_name == "validationState":
            # Setting is not validated. This can happen if there is only a setting definition.
            # We do need to validate it, because a setting defintions value can be set by a function, which could
            # be an invalid setting.
            if property_value is None:
                if not self._validator:
                    definition = self._stack.getSettingDefinition(self._key)
                    validator_type = UM.Settings.SettingDefinition.getValidatorForType(definition.type)
                    if validator_type:
                        self._validator = validator_type(self._key)
                if self._validator:
                    property_value = self._validator(self._stack)
        return str(property_value)
<|endoftext|>


<commit_before>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Johnson Nyquist noise utilities for both voltage and current noise

# Usage example
>>> from UliEngineering.Physics.JohnsonNyquistNoise import *
>>> from UliEngineering.EngineerIO import autoFormat
>>> print(autoFormat(johnson_nyquist_noise_current, "20 MΩ", 1000, "20 °C"))
>>> print(autoFormat(johnson_nyquist_noise_voltage, "10 MΩ", 1000, 25))
"""
import scipy.constants
from .Temperature import normalize_temperature
from UliEngineering.EngineerIO import normalize_numeric
from UliEngineering.Units import Unit
import math

__all__ = ["johnson_nyquist_noise_current", "johnson_nyquist_noise_voltage"]

def johnson_nyquist_noise_current(r, delta_f, T) -> Unit("A"):
    """
    Compute the Johnson Nyquist noise current in amperes
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    # Support celsius and kelvin inputs
    return math.sqrt((4 * scipy.constants.k * t_kelvin * delta_f)/r)

def johnson_nyquist_noise_voltage(r, delta_f, T) -> Unit("V"):
    """
    Compute the Johnson Nyquist noise voltage in volts
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    return math.sqrt(4 * scipy.constants.k * t_kelvin * delta_f * r)
<commit_msg>Make scipy.constants.k optional but recommended<commit_after>#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Johnson Nyquist noise utilities for both voltage and current noise

# Usage example
>>> from UliEngineering.Physics.JohnsonNyquistNoise import *
>>> from UliEngineering.EngineerIO import autoFormat
>>> print(autoFormat(johnson_nyquist_noise_current, "20 MΩ", 1000, "20 °C"))
>>> print(autoFormat(johnson_nyquist_noise_voltage, "10 MΩ", 1000, 25))
"""
from .Temperature import normalize_temperature
from UliEngineering.EngineerIO import normalize_numeric
from UliEngineering.Units import Unit
import math

__all__ = ["johnson_nyquist_noise_current", "johnson_nyquist_noise_voltage"]

try:
    from scipy.constants import k as boltzmann_k
except ModuleNotFoundError:
    # Accept and use hardcoded but warn
    import warnings
    warnings.warn("Using hardcoded Boltzmann k_b constant value. This is a measured quantity! Installing scipy is recommended!", RuntimeWarning)
    boltzmann_k = 1.38064852e-23 # Recommended value as of 2015

def johnson_nyquist_noise_current(r, delta_f, T) -> Unit("A"):
    """
    Compute the Johnson Nyquist noise current in amperes
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    # Support celsius and kelvin inputs
    return math.sqrt((4 * boltzmann_k * t_kelvin * delta_f)/r)

def johnson_nyquist_noise_voltage(r, delta_f, T) -> Unit("V"):
    """
    Compute the Johnson Nyquist noise voltage in volts
    T must be given in °C whereas r must be given in Ohms.
    The result is given in volts
    """
    r = normalize_numeric(r)
    delta_f = normalize_numeric(delta_f)
    t_kelvin = normalize_temperature(T)
    return math.sqrt(4 * boltzmann_k * t_kelvin * delta_f * r)
<|endoftext|>


<commit_before>
import pathlib2 as pathlib
import six

from . import context, iter, machinery, path
from .nopath import PureNoPath, NoPath
from .urlpath import PureUrlPath, UrlPath

def as_text(x, encoding=None):
  """
  Accepts a binary or unicode string and returns a unicode string. If *x* is
  not a string type, a #TypeError is raised.
  """

  if not isinstance(x, six.string_types):
    raise TypeError('expected string, got {} instead'.format(type(x).__name__))
  if not isinstance(x, six.text_type):
    x = x.decode(encoding or sys.getdefaultencoding())
  return x
<commit_msg>fix missing import of sys<commit_after>
import pathlib2 as pathlib
import six
import sys

from . import context, iter, machinery, path
from .nopath import PureNoPath, NoPath
from .urlpath import PureUrlPath, UrlPath

def as_text(x, encoding=None):
  """
  Accepts a binary or unicode string and returns a unicode string. If *x* is
  not a string type, a #TypeError is raised.
  """

  if not isinstance(x, six.string_types):
    raise TypeError('expected string, got {} instead'.format(type(x).__name__))
  if not isinstance(x, six.text_type):
    x = x.decode(encoding or sys.getdefaultencoding())
  return x
<|endoftext|>


<commit_before><commit_msg>Add bug comment, may investigate at a later point.<commit_after><|endoftext|>


<commit_before>import sys
import os
from pkg_resources import resource_filename

def get_jar_filename():
    """Return the full path to the Closure Templates Java archive."""
    return resource_filename(__name__, "soy.jar")

def main():
    name = sys.argv[0]
    os.execlp("java", name, "-jar", get_jar_filename(), *sys.argv[1:])

main()
<commit_msg>removed execution of main in the __init__.py file<commit_after>import sys
import os
from pkg_resources import resource_filename

def get_jar_filename():
    """Return the full path to the Closure Templates Java archive."""
    return resource_filename(__name__, "soy.jar")

def main():
    name = sys.argv[0]
    os.execlp("java", name, "-jar", get_jar_filename(), *sys.argv[1:])
<|endoftext|>


<commit_before>#!/usr/bin/python

import sys
import re

REGEX = '^(DDC-[0-9]*)\. [\w .,+]*\.$'

def valid_commit_message(message):
  """Function to validate the commit message.

  Args:
    message (str): The message to validate.

  Returns:
    bool: True for valid messages, False otherwise.
  """
  if not re.match(REGEX, message):
    print 'ERROR: Missing Jira number in commmit message.'
    print 'Format "DDC-XXXX. Message."'
    return False

  print 'Commit message is valid.'
  return True

def main():
  """Main function."""
  message_file = sys.argv[1]
  try:
    txt_file = open(message_file, 'r')
    commit_message = txt_file.read()
  finally:
    txt_file.close()

  if not valid_commit_message(commit_message):
    sys.exit(1)

  sys.exit(0)

if __name__ == "__main__":
  main()
<commit_msg>Added Jira issue number hinting<commit_after>#!/usr/bin/python

import sys
import re
import subprocess

REGEX = '^DDC-[\d]{4}\. [\w\d .,:;+]*\.$'

def current_branch_name():
  """Gets the current GIT branch name.

  Returns:
    string: The current branch name.
  """
  return subprocess.check_output(['git', 'rev-parse', '--abbrev-ref', 'HEAD'])

def get_jira_issue_hint(branch_name):
  """Extracts the Jira issue number from the branch name.

  Args:
    branch_name (str): The branch name to parse.

  Returns:
    string: The Jira issue number, or sample issue number.
  """
  match = re.findall('feature/(DDC-[\d]{4})-', branch_name)
  if match and match[0]:
    return match[0]
  return 'DDC-XXXX'

def valid_commit_message(message):
  """Function to validate the commit message.

  Args:
    message (str): The message to validate.

  Returns:
    bool: True for valid messages, False otherwise.
  """
  if not re.match(REGEX, message):
    name = current_branch_name()
    issue_number = get_jira_issue_hint(name)
    print 'ERROR: Missing Jira number in commmit message.'
    print 'Hint: {0}. Commit message.'.format(issue_number)
    return False

  print 'Commit message is valid.'
  return True

def main():
  """Main function."""
  message_file = sys.argv[1]
  try:
    txt_file = open(message_file, 'r')
    commit_message = txt_file.read()
  finally:
    txt_file.close()

  if not valid_commit_message(commit_message):
    sys.exit(1)

  sys.exit(0)

if __name__ == "__main__":
  main()
<|endoftext|>


<commit_before>from dimagi.utils.couch.database import iter_docs
from dimagi.utils.decorators.memoized import memoized
from corehq.apps.locations.models import Location
from corehq.apps.commtrack.models import SupplyPointCase, StockState, SQLLocation
from corehq.apps.products.models import Product
from corehq.apps.domain.models import Domain
from dimagi.utils.couch.loosechange import map_reduce
from corehq.apps.reports.api import ReportDataSource
from datetime import datetime, timedelta
from dateutil import parser
from casexml.apps.stock.models import StockTransaction
from couchforms.models import XFormInstance
from corehq.apps.reports.commtrack.util import get_relevant_supply_point_ids, product_ids_filtered_by_program
from corehq.apps.reports.commtrack.const import STOCK_SECTION_TYPE
from casexml.apps.stock.utils import months_of_stock_remaining, stock_category
from corehq.apps.reports.standard.monitoring import MultiFormDrilldownMixin
from decimal import Decimal
from django.db.models import Sum

def format_decimal(d):
    # https://docs.python.org/2/library/decimal.html#decimal-faq
    if d is not None:
        return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
    else:
        return None

class CommtrackDataSourceMixin(object):

    @property
    def domain(self):
        return self.config.get('domain')

    @property
    @memoized
    def active_location(self):
        return Location.get_in_domain(self.domain, self.config.get('location_id'))

    @property
    @memoized
    def active_product(self):
        prod_id = self.config.get('product_id')
        if prod_id:
            return Product.get(prod_id)

    @property
    @memoized
    def program_id(self):
        prog_id = self.config.get('program_id')
        if prog_id != '':
            return prog_id

    @property
    def start_date(self):
        return self.config.get('startdate') or (datetime.now() - timedelta(30)).date()

    @property
    def end_date(self):
        return self.config.get('enddate') or datetime.now().date()

    @property
    def request(self):
        request = self.config.get('request')
        if request:
            return request

class SimplifiedInventoryDataSource(ReportDataSource, CommtrackDataSourceMixin):
    slug = 'location_inventory'

    def datetime(self):
        """
        Returns a datetime object at the end of the selected
        (or current) date. This is needed to properly filter
        transactions that occur during the day we are filtering
        for
        """
        # note: empty string is parsed as today's date
        date = self.config.get('date', '')

        try:
            date = parser.parse(date).date()
        except ValueError:
            date = datetime.now().date()

        return datetime(date.year, date.month, date.day, 23, 59, 59)

    def get_data(self, slugs=None):
        if self.active_location:
            current_location = self.active_location.sql_location

            if current_location.supply_point_id:
                locations = [current_location]
            else:
                locations = []

            locations += list(
                current_location.get_descendants().filter(
                    supply_point_id__isnull=False
                )
            )
        else:
            locations = SQLLocation.objects.filter(
                domain=self.domain,
                supply_point_id__isnull=False
            )

        # locations at this point will only have location objects
        # that have supply points associated
        for loc in locations[:self.config.get('max_rows', 100)]:
            transactions = StockTransaction.objects.filter(
                case_id=loc.supply_point_id,
            )

            if self.program_id:
                transactions = transactions.filter(
                    sql_product__program_id=self.program_id
                )

            stock_results = transactions.exclude(
                report__date__gt=self.datetime
            ).order_by(
                'product_id', '-report__date'
            ).values_list(
                'product_id', 'stock_on_hand'
            ).distinct(
                'product_id'
            )

            # take a pass over the data to format the stock on hand
            # values properly
            stock_results = [(p, format_decimal(soh)) for p, soh in stock_results]

            yield (loc.name, stock_results)

class StockStatusDataSource(ReportDataSource, CommtrackDataSourceMixin):
    """
    Config:
        domain: The domain to report on.
        location_id: ID of location to get data for. Omit for all locations.
        product_id: ID of product to get data for. Omit for all products.
        aggregate: True to aggregate the indicators by product for the current location.

    Data Slugs:
        product_name: Name of the product
        product_id: ID of the product
        location_id: The ID of the current location.
        location_lineage: The lineage of the current location.
        current_stock: The current stock level
        consumption: The current monthly consumption rate
        months_remaining: The number of months remaining until stock out
        category: The status category. See casexml.apps.stock.models.StockState.stock_category
        resupply_quantity_needed: Max amount - current amount

    """
    slug = 'agg_stock_status'

    SLUG_PRODUCT_NAME = 'product_name'
    SLUG_PRODUCT_ID = 'product_id'
    SLUG_MONTHS_REMAINING = 'months_remaining'
    SLUG_CONSUMPTION = 'consumption'
    SLUG_CURRENT_STOCK = 'current_stock'
    SLUG_LOCATION_ID = 'location_id'
    SLUG_LOCATION_LINEAGE = 'location_lineage'
    SLUG_STOCKOUT_SINCE = 'stockout_since'
    SLUG_STOCKOUT_DURATION = 'stockout_duration'
    SLUG_LAST_REPORTED = 'last_reported'
    SLUG_CATEGORY = 'category'
    SLUG_RESUPPLY_QUANTITY_NEEDED = 'resupply_quantity_needed'

    def _include_advanced_data(self):
        # if this flag is not specified, we default to giving
        # all the data back
        return self.config.get('advanced_columns', True)

    @property
    @memoized
    def _slug_attrib_map(self):
        @memoized
        def product_name(product_id):
            return Product.get(product_id).name
        @memoized
        def supply_point_location(case_id):
            return SupplyPointCase.get(case_id).location_id

        raw_map = {
            self.SLUG_PRODUCT_NAME: lambda s: product_name(s.product_id),
            self.SLUG_PRODUCT_ID: 'product_id',
            self.SLUG_CURRENT_STOCK: 'stock_on_hand',
        }
        if self._include_advanced_data():
            raw_map.update({
                self.SLUG_LOCATION_ID: lambda s: supply_point_location(s.case_id),
                self.SLUG_CONSUMPTION: lambda s: s.get_monthly_consumption(),
                self.SLUG_MONTHS_REMAINING: 'months_remaining',
                self.SLUG_CATEGORY: 'stock_category',
                # SLUG_STOCKOUT_SINCE: 'stocked_out_since',
                # SLUG_STOCKOUT_DURATION: 'stockout_duration_in_months',
                self.SLUG_LAST_REPORTED: 'last_modified_date',
                self.SLUG_RESUPPLY_QUANTITY_NEEDED: 'resupply_quantity_needed',
            })

        # normalize the slug attrib map so everything is callable
        def _normalize_row(slug, function_or_property):
            if not callable(function_or_property):
                function = lambda s: getattr(s, function_or_property, '')
            else:
                function = function_or_property

            return slug, function

        return dict(_normalize_row(k, v) for k, v in raw_map.items())

    def slugs(self):
        return self._slug_attrib_map.keys()

    def filter_by_program(self, stock_states):
        return stock_states.filter(
            product_id__in=product_ids_filtered_by_program(
                self.domain,
                self.program_id
            )
        )

    def get_data(self, slugs=None):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(
            section_id=STOCK_SECTION_TYPE,
            last_modified_date__lte=self.end_date,
            last_modified_date__gte=self.start_date,
        )

        if len(sp_ids) == 1:
            stock_states = stock_states.filter(
                case_id=sp_ids[0],
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            return self.leaf_node_data(stock_states)
        else:
            stock_states = stock_states.filter(
                case_id__in=sp_ids,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            if self.config.get('aggregate'):
                return self.aggregated_data(stock_states)
            else:
                return self.raw_product_states(stock_states, slugs)

    def leaf_node_data(self, stock_states):
        for state in stock_states:
            product = Product.get(state.product_id)

            result = {
                'product_id': product._id,
                'product_name': product.name,
                'current_stock': format_decimal(state.stock_on_hand),
            }

            if self._include_advanced_data():
                result.update({
                    'location_id': SupplyPointCase.get(state.case_id).location_id,
                    'location_lineage': None,
                    'category': state.stock_category,
                    'consumption': state.get_monthly_consumption(),
                    'months_remaining': state.months_remaining,
                    'resupply_quantity_needed': state.resupply_quantity_needed
                })

            yield result

    def aggregated_data(self, stock_states):
        def _convert_to_daily(consumption):
            return consumption / 30 if consumption is not None else None

        if self._include_advanced_data():
            product_aggregation = {}
            for state in stock_states:
                if state.product_id in product_aggregation:
                    product = product_aggregation[state.product_id]
                    product['current_stock'] = format_decimal(
                        product['current_stock'] + state.stock_on_hand
                    )

                    consumption = state.get_monthly_consumption()
                    if product['consumption'] is None:
                        product['consumption'] = consumption
                    elif consumption is not None:
                        product['consumption'] += consumption

                    product['count'] += 1

                    product['category'] = stock_category(
                        product['current_stock'],
                        _convert_to_daily(product['consumption']),
                        Domain.get_by_name(self.domain)
                    )
                    product['months_remaining'] = months_of_stock_remaining(
                        product['current_stock'],
                        _convert_to_daily(product['consumption'])
                    )
                else:
                    product = Product.get(state.product_id)
                    consumption = state.get_monthly_consumption()

                    product_aggregation[state.product_id] = {
                        'product_id': product._id,
                        'location_id': None,
                        'product_name': product.name,
                        'location_lineage': None,
                        'resupply_quantity_needed': None,
                        'current_stock': format_decimal(state.stock_on_hand),
                        'count': 1,
                        'consumption': consumption,
                        'category': stock_category(
                            state.stock_on_hand,
                            _convert_to_daily(consumption),
                            Domain.get_by_name(self.domain)
                        ),
                        'months_remaining': months_of_stock_remaining(
                            state.stock_on_hand,
                            _convert_to_daily(consumption)
                        )
                    }

            return product_aggregation.values()
        else:
            # If we don't need advanced data, we can
            # just do some orm magic.
            #
            # Note: this leaves out some harder to get quickly
            # values like location_id, but shouldn't be needed
            # unless we expand what uses this.
            aggregated_states = stock_states.values_list(
                'sql_product__name',
                'sql_product__product_id',
            ).annotate(stock_on_hand=Sum('stock_on_hand'))
            result = []
            for ag in aggregated_states:
                result.append({
                    'product_name': ag[0],
                    'product_id': ag[1],
                    'current_stock': format_decimal(ag[2])
                })

            return result

    def raw_product_states(self, stock_states, slugs):
        for state in stock_states:
            yield {
                slug: f(state) for slug, f in self._slug_attrib_map.items() if not slugs or slug in slugs
            }

class StockStatusBySupplyPointDataSource(StockStatusDataSource):
    def get_data(self):
        data = list(super(StockStatusBySupplyPointDataSource, self).get_data())

        products = dict((r['product_id'], r['product_name']) for r in data)
        product_ids = sorted(products.keys(), key=lambda e: products[e])

        by_supply_point = map_reduce(lambda e: [(e['location_id'],)], data=data, include_docs=True)
        locs = dict((loc._id, loc) for loc in Location.view(
                '_all_docs',
                keys=by_supply_point.keys(),
                include_docs=True))

        for loc_id, subcases in by_supply_point.iteritems():
            loc = locs[loc_id]
            by_product = dict((c['product_id'], c) for c in subcases)

            rec = {
                'name': loc.name,
                'type': loc.location_type,
                'geo': loc._geopoint,
            }
            for prod in product_ids:
                rec.update(dict(('%s-%s' % (prod, key), by_product.get(prod, {}).get(key)) for key in
                                ('current_stock', 'consumption', 'months_remaining', 'category')))
            yield rec

class ReportingStatusDataSource(ReportDataSource, CommtrackDataSourceMixin, MultiFormDrilldownMixin):
    """
    Config:
        domain: The domain to report on.
        location_id: ID of location to get data for. Omit for all locations.
    """

    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            supply_points = (SupplyPointCase.wrap(doc) for doc in iter_docs(SupplyPointCase.get_db(), sp_ids))
            form_xmlnses = [form['xmlns'] for form in self.all_relevant_forms.values()]

            for supply_point in supply_points:
                # todo: get locations in bulk
                loc = supply_point.location
                transactions = StockTransaction.objects.filter(
                    case_id=supply_point._id,
                ).exclude(
                    report__date__lte=self.start_date
                ).exclude(
                    report__date__gte=self.end_date
                ).order_by('-report__date')
                matched = False
                for trans in transactions:
                    if XFormInstance.get(trans.report.form_id).xmlns in form_xmlnses:
                        yield {
                            'loc_id': loc._id,
                            'loc_path': loc.path,
                            'name': loc.name,
                            'type': loc.location_type,
                            'reporting_status': 'reporting',
                            'geo': loc._geopoint,
                        }
                        matched = True
                        break
                if not matched:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': 'nonreporting',
                        'geo': loc._geopoint,
                    }
<commit_msg>bulk load locations<commit_after>from dimagi.utils.couch.database import iter_docs
from dimagi.utils.decorators.memoized import memoized
from corehq.apps.locations.models import Location
from corehq.apps.commtrack.models import SupplyPointCase, StockState, SQLLocation
from corehq.apps.products.models import Product
from corehq.apps.domain.models import Domain
from dimagi.utils.couch.loosechange import map_reduce
from corehq.apps.reports.api import ReportDataSource
from datetime import datetime, timedelta
from dateutil import parser
from casexml.apps.stock.models import StockTransaction
from couchforms.models import XFormInstance
from corehq.apps.reports.commtrack.util import get_relevant_supply_point_ids, product_ids_filtered_by_program
from corehq.apps.reports.commtrack.const import STOCK_SECTION_TYPE
from casexml.apps.stock.utils import months_of_stock_remaining, stock_category
from corehq.apps.reports.standard.monitoring import MultiFormDrilldownMixin
from decimal import Decimal
from django.db.models import Sum

def format_decimal(d):
    # https://docs.python.org/2/library/decimal.html#decimal-faq
    if d is not None:
        return d.quantize(Decimal(1)) if d == d.to_integral() else d.normalize()
    else:
        return None

class CommtrackDataSourceMixin(object):

    @property
    def domain(self):
        return self.config.get('domain')

    @property
    @memoized
    def active_location(self):
        return Location.get_in_domain(self.domain, self.config.get('location_id'))

    @property
    @memoized
    def active_product(self):
        prod_id = self.config.get('product_id')
        if prod_id:
            return Product.get(prod_id)

    @property
    @memoized
    def program_id(self):
        prog_id = self.config.get('program_id')
        if prog_id != '':
            return prog_id

    @property
    def start_date(self):
        return self.config.get('startdate') or (datetime.now() - timedelta(30)).date()

    @property
    def end_date(self):
        return self.config.get('enddate') or datetime.now().date()

    @property
    def request(self):
        request = self.config.get('request')
        if request:
            return request

class SimplifiedInventoryDataSource(ReportDataSource, CommtrackDataSourceMixin):
    slug = 'location_inventory'

    def datetime(self):
        """
        Returns a datetime object at the end of the selected
        (or current) date. This is needed to properly filter
        transactions that occur during the day we are filtering
        for
        """
        # note: empty string is parsed as today's date
        date = self.config.get('date', '')

        try:
            date = parser.parse(date).date()
        except ValueError:
            date = datetime.now().date()

        return datetime(date.year, date.month, date.day, 23, 59, 59)

    def get_data(self, slugs=None):
        if self.active_location:
            current_location = self.active_location.sql_location

            if current_location.supply_point_id:
                locations = [current_location]
            else:
                locations = []

            locations += list(
                current_location.get_descendants().filter(
                    supply_point_id__isnull=False
                )
            )
        else:
            locations = SQLLocation.objects.filter(
                domain=self.domain,
                supply_point_id__isnull=False
            )

        # locations at this point will only have location objects
        # that have supply points associated
        for loc in locations[:self.config.get('max_rows', 100)]:
            transactions = StockTransaction.objects.filter(
                case_id=loc.supply_point_id,
            )

            if self.program_id:
                transactions = transactions.filter(
                    sql_product__program_id=self.program_id
                )

            stock_results = transactions.exclude(
                report__date__gt=self.datetime
            ).order_by(
                'product_id', '-report__date'
            ).values_list(
                'product_id', 'stock_on_hand'
            ).distinct(
                'product_id'
            )

            # take a pass over the data to format the stock on hand
            # values properly
            stock_results = [(p, format_decimal(soh)) for p, soh in stock_results]

            yield (loc.name, stock_results)

class StockStatusDataSource(ReportDataSource, CommtrackDataSourceMixin):
    """
    Config:
        domain: The domain to report on.
        location_id: ID of location to get data for. Omit for all locations.
        product_id: ID of product to get data for. Omit for all products.
        aggregate: True to aggregate the indicators by product for the current location.

    Data Slugs:
        product_name: Name of the product
        product_id: ID of the product
        location_id: The ID of the current location.
        location_lineage: The lineage of the current location.
        current_stock: The current stock level
        consumption: The current monthly consumption rate
        months_remaining: The number of months remaining until stock out
        category: The status category. See casexml.apps.stock.models.StockState.stock_category
        resupply_quantity_needed: Max amount - current amount

    """
    slug = 'agg_stock_status'

    SLUG_PRODUCT_NAME = 'product_name'
    SLUG_PRODUCT_ID = 'product_id'
    SLUG_MONTHS_REMAINING = 'months_remaining'
    SLUG_CONSUMPTION = 'consumption'
    SLUG_CURRENT_STOCK = 'current_stock'
    SLUG_LOCATION_ID = 'location_id'
    SLUG_LOCATION_LINEAGE = 'location_lineage'
    SLUG_STOCKOUT_SINCE = 'stockout_since'
    SLUG_STOCKOUT_DURATION = 'stockout_duration'
    SLUG_LAST_REPORTED = 'last_reported'
    SLUG_CATEGORY = 'category'
    SLUG_RESUPPLY_QUANTITY_NEEDED = 'resupply_quantity_needed'

    def _include_advanced_data(self):
        # if this flag is not specified, we default to giving
        # all the data back
        return self.config.get('advanced_columns', True)

    @property
    @memoized
    def _slug_attrib_map(self):
        @memoized
        def product_name(product_id):
            return Product.get(product_id).name
        @memoized
        def supply_point_location(case_id):
            return SupplyPointCase.get(case_id).location_id

        raw_map = {
            self.SLUG_PRODUCT_NAME: lambda s: product_name(s.product_id),
            self.SLUG_PRODUCT_ID: 'product_id',
            self.SLUG_CURRENT_STOCK: 'stock_on_hand',
        }
        if self._include_advanced_data():
            raw_map.update({
                self.SLUG_LOCATION_ID: lambda s: supply_point_location(s.case_id),
                self.SLUG_CONSUMPTION: lambda s: s.get_monthly_consumption(),
                self.SLUG_MONTHS_REMAINING: 'months_remaining',
                self.SLUG_CATEGORY: 'stock_category',
                # SLUG_STOCKOUT_SINCE: 'stocked_out_since',
                # SLUG_STOCKOUT_DURATION: 'stockout_duration_in_months',
                self.SLUG_LAST_REPORTED: 'last_modified_date',
                self.SLUG_RESUPPLY_QUANTITY_NEEDED: 'resupply_quantity_needed',
            })

        # normalize the slug attrib map so everything is callable
        def _normalize_row(slug, function_or_property):
            if not callable(function_or_property):
                function = lambda s: getattr(s, function_or_property, '')
            else:
                function = function_or_property

            return slug, function

        return dict(_normalize_row(k, v) for k, v in raw_map.items())

    def slugs(self):
        return self._slug_attrib_map.keys()

    def filter_by_program(self, stock_states):
        return stock_states.filter(
            product_id__in=product_ids_filtered_by_program(
                self.domain,
                self.program_id
            )
        )

    def get_data(self, slugs=None):
        sp_ids = get_relevant_supply_point_ids(self.domain, self.active_location)

        stock_states = StockState.objects.filter(
            section_id=STOCK_SECTION_TYPE,
            last_modified_date__lte=self.end_date,
            last_modified_date__gte=self.start_date,
        )

        if len(sp_ids) == 1:
            stock_states = stock_states.filter(
                case_id=sp_ids[0],
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            return self.leaf_node_data(stock_states)
        else:
            stock_states = stock_states.filter(
                case_id__in=sp_ids,
            )

            if self.program_id:
                stock_states = self.filter_by_program(stock_states)

            if self.config.get('aggregate'):
                return self.aggregated_data(stock_states)
            else:
                return self.raw_product_states(stock_states, slugs)

    def leaf_node_data(self, stock_states):
        for state in stock_states:
            product = Product.get(state.product_id)

            result = {
                'product_id': product._id,
                'product_name': product.name,
                'current_stock': format_decimal(state.stock_on_hand),
            }

            if self._include_advanced_data():
                result.update({
                    'location_id': SupplyPointCase.get(state.case_id).location_id,
                    'location_lineage': None,
                    'category': state.stock_category,
                    'consumption': state.get_monthly_consumption(),
                    'months_remaining': state.months_remaining,
                    'resupply_quantity_needed': state.resupply_quantity_needed
                })

            yield result

    def aggregated_data(self, stock_states):
        def _convert_to_daily(consumption):
            return consumption / 30 if consumption is not None else None

        if self._include_advanced_data():
            product_aggregation = {}
            for state in stock_states:
                if state.product_id in product_aggregation:
                    product = product_aggregation[state.product_id]
                    product['current_stock'] = format_decimal(
                        product['current_stock'] + state.stock_on_hand
                    )

                    consumption = state.get_monthly_consumption()
                    if product['consumption'] is None:
                        product['consumption'] = consumption
                    elif consumption is not None:
                        product['consumption'] += consumption

                    product['count'] += 1

                    product['category'] = stock_category(
                        product['current_stock'],
                        _convert_to_daily(product['consumption']),
                        Domain.get_by_name(self.domain)
                    )
                    product['months_remaining'] = months_of_stock_remaining(
                        product['current_stock'],
                        _convert_to_daily(product['consumption'])
                    )
                else:
                    product = Product.get(state.product_id)
                    consumption = state.get_monthly_consumption()

                    product_aggregation[state.product_id] = {
                        'product_id': product._id,
                        'location_id': None,
                        'product_name': product.name,
                        'location_lineage': None,
                        'resupply_quantity_needed': None,
                        'current_stock': format_decimal(state.stock_on_hand),
                        'count': 1,
                        'consumption': consumption,
                        'category': stock_category(
                            state.stock_on_hand,
                            _convert_to_daily(consumption),
                            Domain.get_by_name(self.domain)
                        ),
                        'months_remaining': months_of_stock_remaining(
                            state.stock_on_hand,
                            _convert_to_daily(consumption)
                        )
                    }

            return product_aggregation.values()
        else:
            # If we don't need advanced data, we can
            # just do some orm magic.
            #
            # Note: this leaves out some harder to get quickly
            # values like location_id, but shouldn't be needed
            # unless we expand what uses this.
            aggregated_states = stock_states.values_list(
                'sql_product__name',
                'sql_product__product_id',
            ).annotate(stock_on_hand=Sum('stock_on_hand'))
            result = []
            for ag in aggregated_states:
                result.append({
                    'product_name': ag[0],
                    'product_id': ag[1],
                    'current_stock': format_decimal(ag[2])
                })

            return result

    def raw_product_states(self, stock_states, slugs):
        for state in stock_states:
            yield {
                slug: f(state) for slug, f in self._slug_attrib_map.items() if not slugs or slug in slugs
            }

class StockStatusBySupplyPointDataSource(StockStatusDataSource):
    def get_data(self):
        data = list(super(StockStatusBySupplyPointDataSource, self).get_data())

        products = dict((r['product_id'], r['product_name']) for r in data)
        product_ids = sorted(products.keys(), key=lambda e: products[e])

        by_supply_point = map_reduce(lambda e: [(e['location_id'],)], data=data, include_docs=True)
        locs = dict((loc._id, loc) for loc in Location.view(
                '_all_docs',
                keys=by_supply_point.keys(),
                include_docs=True))

        for loc_id, subcases in by_supply_point.iteritems():
            loc = locs[loc_id]
            by_product = dict((c['product_id'], c) for c in subcases)

            rec = {
                'name': loc.name,
                'type': loc.location_type,
                'geo': loc._geopoint,
            }
            for prod in product_ids:
                rec.update(dict(('%s-%s' % (prod, key), by_product.get(prod, {}).get(key)) for key in
                                ('current_stock', 'consumption', 'months_remaining', 'category')))
            yield rec

class ReportingStatusDataSource(ReportDataSource, CommtrackDataSourceMixin, MultiFormDrilldownMixin):
    """
    Config:
        domain: The domain to report on.
        location_id: ID of location to get data for. Omit for all locations.
    """

    def get_data(self):
        # todo: this will probably have to paginate eventually
        if self.all_relevant_forms:
            sp_ids = get_relevant_supply_point_ids(
                self.domain,
                self.active_location,
            )

            form_xmlnses = [form['xmlns'] for form in self.all_relevant_forms.values()]
            spoint_loc_map = {
                doc['_id']: doc['location_id']
                for doc in iter_docs(SupplyPointCase.get_db(), sp_ids)
            }
            locations = {
                doc['_id']: Location.wrap(doc)
                for doc in iter_docs(Location.get_db(), spoint_loc_map.values())
            }

            for spoint_id, loc_id in spoint_loc_map.items():
                loc = locations[loc_id]
                transactions = StockTransaction.objects.filter(
                    case_id=spoint_id,
                ).exclude(
                    report__date__lte=self.start_date
                ).exclude(
                    report__date__gte=self.end_date
                ).order_by('-report__date')
                matched = False
                for trans in transactions:
                    if XFormInstance.get(trans.report.form_id).xmlns in form_xmlnses:
                        yield {
                            'loc_id': loc._id,
                            'loc_path': loc.path,
                            'name': loc.name,
                            'type': loc.location_type,
                            'reporting_status': 'reporting',
                            'geo': loc._geopoint,
                        }
                        matched = True
                        break
                if not matched:
                    yield {
                        'loc_id': loc._id,
                        'loc_path': loc.path,
                        'name': loc.name,
                        'type': loc.location_type,
                        'reporting_status': 'nonreporting',
                        'geo': loc._geopoint,
                    }
<|endoftext|>


<commit_before>from .base import INSTALLED_APPS

DEBUG = False
TEMPLATE_DEBUG = DEBUG

ALLOWED_HOSTS = ['coviolations.io']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
    }
}

VIOLATIONS = (
    'violations.pep8',
    'violations.sloccount',
    'violations.py_unittest',
    'violations.pip_review',
    'violations.testem',
    'violations.coverage',
    'violations.jslint',
)

SERVICES = (
    'services.travis_ci',
    'services.token',
)

PUSH_BIND = 'https://coviolations.io/sub'

INSTALLED_APPS += ('raven.contrib.django.raven_compat',)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'root': {
        'level': 'ERROR',
        'handlers': ['sentry'],
    },
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
    },
    'handlers': {
        'sentry': {
            'level': 'INFO',
            'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django.request': {
            'level': 'ERROR',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'raven': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
        'sentry.errors': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
        'coviolations_tasks': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'coviolations_services': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'coviolations_projects': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
    },
}

USE_SSL = True
<commit_msg>Change redis push queue in production<commit_after>from .base import INSTALLED_APPS

DEBUG = False
TEMPLATE_DEBUG = DEBUG

ALLOWED_HOSTS = ['coviolations.io']

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.postgresql_psycopg2',
    }
}

VIOLATIONS = (
    'violations.pep8',
    'violations.sloccount',
    'violations.py_unittest',
    'violations.pip_review',
    'violations.testem',
    'violations.coverage',
    'violations.jslint',
)

SERVICES = (
    'services.travis_ci',
    'services.token',
)

PUSH_BIND = 'https://coviolations.io/sub'
REDIS_PUSH = 'coviolations_push'

INSTALLED_APPS += ('raven.contrib.django.raven_compat',)

LOGGING = {
    'version': 1,
    'disable_existing_loggers': True,
    'root': {
        'level': 'ERROR',
        'handlers': ['sentry'],
    },
    'formatters': {
        'verbose': {
            'format': '%(levelname)s %(asctime)s %(module)s %(process)d %(thread)d %(message)s'
        },
    },
    'handlers': {
        'sentry': {
            'level': 'INFO',
            'class': 'raven.contrib.django.raven_compat.handlers.SentryHandler',
        },
        'console': {
            'level': 'DEBUG',
            'class': 'logging.StreamHandler',
            'formatter': 'verbose'
        }
    },
    'loggers': {
        'django.request': {
            'level': 'ERROR',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'raven': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
        'sentry.errors': {
            'level': 'DEBUG',
            'handlers': ['console'],
            'propagate': False,
        },
        'coviolations_tasks': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'coviolations_services': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
        'coviolations_projects': {
            'level': 'DEBUG',
            'handlers': ['console', 'sentry'],
            'propagate': False,
        },
    },
}

USE_SSL = True
<|endoftext|>


<commit_before>"""Local deployment destination."""

import os
import shutil
from grow.pods import env
from grow.pods.storage import storage as storage_lib
from grow.deployments.destinations import base
from protorpc import messages

class Config(messages.Message):
    out_dir = messages.StringField(1, default='')
    env = messages.MessageField(env.EnvConfig, 2)
    keep_control_dir = messages.BooleanField(3, default=False)
    before_deploy = messages.StringField(4, repeated=True)
    after_deploy = messages.StringField(5, repeated=True)
    control_dir = messages.StringField(6)

class LocalDestination(base.BaseDestination):
    KIND = 'local'
    Config = Config
    storage = storage_lib.FileStorage

    def __str__(self):
        return os.path.abspath(os.path.join(self.out_dir))

    @property
    def out_dir(self):
        return os.path.expanduser(self.config.out_dir)

    def read_file(self, path):
        path = os.path.join(self.out_dir, path.lstrip('/'))
        return self.storage.read(path)

    def delete_file(self, path):
        out_path = os.path.join(self.out_dir, path.lstrip('/'))
        self.storage.delete(out_path)

    def write_file(self, rendered_doc):
        path = rendered_doc.path
        out_path = os.path.join(self.out_dir, path.lstrip('/'))
        # https://github.com/grow/grow/issues/636
        # if rendered_doc.file_path:
        #     dir_name = os.path.dirname(out_path)
        #     if not os.path.isdir(dir_name):
        #         os.makedirs(dir_name)
        #     shutil.copyfile(rendered_doc.file_path, out_path)
        # else:
        #     self.storage.write(out_path, rendered_doc.read())
        self.storage.write(out_path, rendered_doc.read())

    def prelaunch(self, dry_run=False):
        for command in self.config.before_deploy:
            self.command(command)
        super(LocalDestination, self).prelaunch(dry_run)

    def postlaunch(self, dry_run=False):
        if self.success:
            for command in self.config.after_deploy:
                self.command(command)
        super(LocalDestination, self).postlaunch(dry_run)
<commit_msg>Bringing back the file copy with better error handling for makedirs.<commit_after>"""Local deployment destination."""

import errno
import os
import shutil
from grow.pods import env
from grow.pods.storage import storage as storage_lib
from grow.deployments.destinations import base
from protorpc import messages

class Config(messages.Message):
    out_dir = messages.StringField(1, default='')
    env = messages.MessageField(env.EnvConfig, 2)
    keep_control_dir = messages.BooleanField(3, default=False)
    before_deploy = messages.StringField(4, repeated=True)
    after_deploy = messages.StringField(5, repeated=True)
    control_dir = messages.StringField(6)

class LocalDestination(base.BaseDestination):
    KIND = 'local'
    Config = Config
    storage = storage_lib.FileStorage

    def __str__(self):
        return os.path.abspath(os.path.join(self.out_dir))

    @property
    def out_dir(self):
        return os.path.expanduser(self.config.out_dir)

    def read_file(self, path):
        path = os.path.join(self.out_dir, path.lstrip('/'))
        return self.storage.read(path)

    def delete_file(self, path):
        out_path = os.path.join(self.out_dir, path.lstrip('/'))
        self.storage.delete(out_path)

    def write_file(self, rendered_doc):
        path = rendered_doc.path
        out_path = os.path.join(self.out_dir, path.lstrip('/'))
        if rendered_doc.file_path:
            dir_name = os.path.dirname(out_path)
            try:
                os.makedirs(dir_name)
            except OSError as exc:
                if exc.errno == errno.EEXIST and os.path.isdir(dir_name):
                    pass
                else:
                    raise
            shutil.copyfile(rendered_doc.file_path, out_path)
        else:
            self.storage.write(out_path, rendered_doc.read())

    def prelaunch(self, dry_run=False):
        for command in self.config.before_deploy:
            self.command(command)
        super(LocalDestination, self).prelaunch(dry_run)

    def postlaunch(self, dry_run=False):
        if self.success:
            for command in self.config.after_deploy:
                self.command(command)
        super(LocalDestination, self).postlaunch(dry_run)
<|endoftext|>


<commit_before>from .__main__ import main
from .__main__ import parsed_address_to_human

__version__ = '1.0.0'

__title__ = 'address_extractor'
__description__ = ''
__url__ = ''

__author__ = 'Scott Colby'
__email__ = ''

__license__ = 'MIT License'
__copyright__ = 'Copyright (c) 2015 Scott Colby'

__all__ = [
    'main',
    'parsed_address_to_human'
]
<commit_msg>Add description to init<commit_after>from .__main__ import main
from .__main__ import parsed_address_to_human

__version__ = '1.0.0'

__title__ = 'address_extractor'
__description__ = 'A script to extract US-style street addresses from a text file.'
__url__ = ''

__author__ = 'Scott Colby'
__email__ = ''

__license__ = 'MIT License'
__copyright__ = 'Copyright (c) 2015 Scott Colby'

__all__ = [
    'main',
    'parsed_address_to_human'
]
<|endoftext|>


<commit_before>#!/usr/bin/env python

from subprocess import check_call, CalledProcessError
from tempfile import NamedTemporaryFile

from dpms import DPMS
from mss import mss
from PIL import Image, ImageFilter

GAUSSIAN_BLUR_RADIUS = 5
SCREEN_TIMEOUT = (5, 5, 5)  # Standby, Suspend, Off

# Get current DPMS settings
dpms = DPMS()
current_timeouts = dpms.GetTimeouts()

with mss() as sct:
    # Get the "All-in-one" monitor
    monitor = sct.monitors[0]
    # Get raw pixels of the screen
    sct_img = sct.grab(monitor)
    # Create Image object using Pillow
    img = Image.frombytes("RGB", sct_img.size, sct_img.rgb)

with NamedTemporaryFile(suffix=".png") as tempfile:
    # Apply filters to Image
    img = img.filter(ImageFilter.GaussianBlur(radius=GAUSSIAN_BLUR_RADIUS))
    # Save temporary file
    img.save(tempfile.name, optimize=False, compress_level=1)
    # Set monitor timeout to SCREEN_TIMEOUT
    dpms.SetTimeouts(*SCREEN_TIMEOUT)
    try:
        # Load image in i3lock
        check_call(["i3lock", "-nei", tempfile.name])
    except CalledProcessError:
        # Something went wrong, lock it anyway
        check_call(["i3lock", "-ne"])
    finally:
        # Restore DPMS settings
        dpms.SetTimeouts(*current_timeouts)
<commit_msg>i3: Fix lock_screen.py script<commit_after>#!/usr/bin/env python

from subprocess import call
from tempfile import NamedTemporaryFile

from dpms import DPMS
from mss import mss
from PIL import Image, ImageFilter

GAUSSIAN_BLUR_RADIUS = 5
SCREEN_TIMEOUT = (5, 5, 5)  # Standby, Suspend, Off

# Get current DPMS settings
dpms = DPMS()
current_timeouts = dpms.GetTimeouts()

with mss() as sct:
    # Get the "All-in-one" monitor
    monitor = sct.monitors[0]
    # Get raw pixels of the screen
    sct_img = sct.grab(monitor)
    # Create Image object using Pillow
    img = Image.frombytes("RGB", sct_img.size, sct_img.rgb)

with NamedTemporaryFile(suffix=".png") as tempfile:
    # Apply filters to Image
    img = img.filter(ImageFilter.GaussianBlur(radius=GAUSSIAN_BLUR_RADIUS))
    # Save temporary file
    img.save(tempfile.name, optimize=False, compress_level=1)
    # Set monitor timeout to SCREEN_TIMEOUT
    dpms.SetTimeouts(*SCREEN_TIMEOUT)
    # Load image in i3lock
    call(["i3lock", "-nei", tempfile.name])
    # Restore DPMS settings
    dpms.SetTimeouts(*current_timeouts)
<|endoftext|>


<commit_before>import sys
import spotipy
import spotipy.util as util
import time
import pprint
import traceback

labels = ['artists', 'genres', 'popularity', 'acousticness', 'danceability', 'energy', 'instrumentalness', 'key', 'liveness', 'valence']
scope = 'user-library-read'
ARTISTS_INDEX = 0
GENRES_INDEX  = 1

'''
@fn
@brief Get the track data object for each song from a list of song ids
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in ids A list of Spotify song ids
@return out A Spotify features object associated with the track
@detail Fetches the full length track object for each of the songs associated with the list of ids passed in.
'''
def getSongFeatures(sp, ids):
	return sp.audio_features(ids)

'''
@fn
@brief Get the user's songs from their library
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in limit Optional integer representing the number of tracks to fetch
@param in index Optional integer representing the index into the user's library to begin with
@return out A list of Spotify track objects associated with songs in the user's library
@detail Fetches up to limit songs from the user's saved songs library, beginning at the index indicated.
'''
def getSongsUser(sp, limit=20, index=0):
    return sp.current_user_saved_tracks(limit, index)

'''
@fn
@brief Assembles a vector of feature values for a track
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in features A Spotify feature object associated with the track in question
@param in artists A list of Spotify artist objects that are associated with the track in question
@return out A list of qualities associated with the track in question
@detail A vector of features that our app cares about is assembled from the multitude of information in the Spotify objects.
        The features passed in include a number of qualities curated by Spotify to classify a song with.  The artist(s) that
        are associated with the song in question each provide contributions to a list of artist names, a list of genres, and
        an integer representing overall popularity rating.  This popularity is averaged (to account for weird collaborations).
'''
def getVectorFromTrack(sp, features, artists):
	songArtists = []
	genres = []
	popularity = 0
	for entry in artists:
		artist = sp.artist(entry['id'])
		for i in artist['genres']:
			genres.append(str(i))
			temp = str(artist['name'])
			if not temp in songArtists:
				songArtists.append(str(artist['name']))
			popularity += artist['popularity']
			popularity /= len(artists)
	trackVector = [
		songArtists,
		genres,
		popularity,
		features['acousticness'],
		features['danceability'],
		features['energy'],
		features['instrumentalness'],
		features['key'],
		features['liveness'],
		features['valence']
		]
	return trackVector

'''
@fn
@brief Write a list of song vectors to file for processing
@param in vectors A list of song vectors in the format produced by getVectorFromTrack()
@return out void
@detail Steps through the list of song vectors and writes each to SongVectors.txt on its own
        line.  Entries are separated by '###'.  Since artists and genres are lists, they are
        recorded within '{{' '}}' and delimited by ',,'.  For example, the list [1,2,3] would
        be encoded as {{1,,2,,3}}

def dumpSongVectors(vectors):
    x = open('SongVectors.txt', 'w')
    for i in labels:
    return trackVector

    return '{{' + xs.join(',') + '}}'
'''
'''
@fn
@brief Write a list of song vectors to file for processing
@param in vectors A list of song vectors in the format produced by getVectorFromTrack()
@return out void
@detail Steps through the list of song vectors and writes each to SongVectors.txt on its own
        line.  Entries are separated by '###'.  Since artists and genres are lists, they are
        recorded within '{{' '}}' and delimited by ',,'.  For example, the list [1,2,3] would
        be encoded as {{1,,2,,3}}
'''
def dumpSongVectors(vectors):
    x = open('SongVectors.txt', 'w')
    for i in labels:
    	x.write(i)
    	x.write('###')
    x.write('\n')
    for vector in vectors:
        # Write artists and genres lists in a special format we can easily parse later
        x.write('{{' + ',,'.join(vector[0]) + '}}')
        x.write('###')
        x.write('{{' + ',,'.join(vector[1]) + '}}')
        x.write('###')
        for i in range(2, len(vector)):
            x.write(str(vector[i]))
            x.write('###')
        x.write('\n')
    x.close()

'''
@fn
@brief Assembles a list of song vectors for a user
@param in user The spotify username of the user to fetch songs from
@return out A list of song vectors in the format produced by getVectorFromTrack()
@detail Steps through the first 100 songs of the user passed in, preparing a song vector
        for each and aggregating the results into a list.  If the user does not have enough
        songs, or if some other errors are preventing the API calls from completing, the
        method will abandon its task after 3 failures
'''
def getUserSongs(user):
	usageToken = util.prompt_for_user_token(user, scope)
	if usageToken:
		errorCount = 0
		arties = None
		trackid = None
		sp = spotipy.Spotify(auth=usageToken)
		vectors = []
		# Fetch up to the first 1000 songs to establish a data set
		for i in range (50):
			try:
				print "Getting batch..."
				library = getSongsUser(sp, index=(20*i))
				print "Processing songs..."
				if len(library['items']) > 0:
					for item in library['items']:
						trackid = item['track']['id']
						arties = item['track']['artists']
						temp = getVectorFromTrack(sp, sp.audio_features([trackid])[0], arties)
						vectors.append(temp)
				else:
					#Delay so we don't get locked out of API
					time.sleep(0.5)
			except:
				# get out if we continually fail
				print "Error!"
				traceback.print_exc()
				errorCount += 1
				if errorCount >= 3:
					break
		return vectors
	else:
		print "Could not retrieve token for ", user
		sys.exit()

if __name__ == '__main__':
    if len(sys.argv) > 1:
		user = sys.argv[1]
		print "getting songs..."
		songs = getUserSongs(user)
		print "Dumping songs..."
		dumpSongVectors(songs)
    else:
    	print "Usage: %s username" % (sys.argv[0],)
    	sys.exit()
<commit_msg>Correct another indentation error<commit_after>import sys
import spotipy
import spotipy.util as util
import time
import pprint
import traceback

labels = ['artists', 'genres', 'popularity', 'acousticness', 'danceability', 'energy', 'instrumentalness', 'key', 'liveness', 'valence']
scope = 'user-library-read'
ARTISTS_INDEX = 0
GENRES_INDEX  = 1

'''
@fn
@brief Get the track data object for each song from a list of song ids
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in ids A list of Spotify song ids
@return out A Spotify features object associated with the track
@detail Fetches the full length track object for each of the songs associated with the list of ids passed in.
'''
def getSongFeatures(sp, ids):
	return sp.audio_features(ids)

'''
@fn
@brief Get the user's songs from their library
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in limit Optional integer representing the number of tracks to fetch
@param in index Optional integer representing the index into the user's library to begin with
@return out A list of Spotify track objects associated with songs in the user's library
@detail Fetches up to limit songs from the user's saved songs library, beginning at the index indicated.
'''
def getSongsUser(sp, limit=20, index=0):
    return sp.current_user_saved_tracks(limit, index)

'''
@fn
@brief Assembles a vector of feature values for a track
@param in sp The handle to the Spotipy wrapper associated with the current user
@param in features A Spotify feature object associated with the track in question
@param in artists A list of Spotify artist objects that are associated with the track in question
@return out A list of qualities associated with the track in question
@detail A vector of features that our app cares about is assembled from the multitude of information in the Spotify objects.
        The features passed in include a number of qualities curated by Spotify to classify a song with.  The artist(s) that
        are associated with the song in question each provide contributions to a list of artist names, a list of genres, and
        an integer representing overall popularity rating.  This popularity is averaged (to account for weird collaborations).
'''
def getVectorFromTrack(sp, features, artists):
	songArtists = []
	genres = []
	popularity = 0
	for entry in artists:
		artist = sp.artist(entry['id'])
		for i in artist['genres']:
			genres.append(str(i))
			temp = str(artist['name'])
			if not temp in songArtists:
				songArtists.append(str(artist['name']))
			popularity += artist['popularity']
	popularity /= len(artists)
	trackVector = [
		songArtists,
		genres,
		popularity,
		features['acousticness'],
		features['danceability'],
		features['energy'],
		features['instrumentalness'],
		features['key'],
		features['liveness'],
		features['valence']
		]
	return trackVector

'''
@fn
@brief Write a list of song vectors to file for processing
@param in vectors A list of song vectors in the format produced by getVectorFromTrack()
@return out void
@detail Steps through the list of song vectors and writes each to SongVectors.txt on its own
        line.  Entries are separated by '###'.  Since artists and genres are lists, they are
        recorded within '{{' '}}' and delimited by ',,'.  For example, the list [1,2,3] would
        be encoded as {{1,,2,,3}}

def dumpSongVectors(vectors):
    x = open('SongVectors.txt', 'w')
    for i in labels:
    return trackVector

    return '{{' + xs.join(',') + '}}'
'''
'''
@fn
@brief Write a list of song vectors to file for processing
@param in vectors A list of song vectors in the format produced by getVectorFromTrack()
@return out void
@detail Steps through the list of song vectors and writes each to SongVectors.txt on its own
        line.  Entries are separated by '###'.  Since artists and genres are lists, they are
        recorded within '{{' '}}' and delimited by ',,'.  For example, the list [1,2,3] would
        be encoded as {{1,,2,,3}}
'''
def dumpSongVectors(vectors):
    x = open('SongVectors.txt', 'w')
    for i in labels:
    	x.write(i)
    	x.write('###')
    x.write('\n')
    for vector in vectors:
        # Write artists and genres lists in a special format we can easily parse later
        x.write('{{' + ',,'.join(vector[0]) + '}}')
        x.write('###')
        x.write('{{' + ',,'.join(vector[1]) + '}}')
        x.write('###')
        for i in range(2, len(vector)):
            x.write(str(vector[i]))
            x.write('###')
        x.write('\n')
    x.close()

'''
@fn
@brief Assembles a list of song vectors for a user
@param in user The spotify username of the user to fetch songs from
@return out A list of song vectors in the format produced by getVectorFromTrack()
@detail Steps through the first 100 songs of the user passed in, preparing a song vector
        for each and aggregating the results into a list.  If the user does not have enough
        songs, or if some other errors are preventing the API calls from completing, the
        method will abandon its task after 3 failures
'''
def getUserSongs(user):
	usageToken = util.prompt_for_user_token(user, scope)
	if usageToken:
		errorCount = 0
		arties = None
		trackid = None
		sp = spotipy.Spotify(auth=usageToken)
		vectors = []
		# Fetch up to the first 1000 songs to establish a data set
		for i in range (50):
			try:
				print "Getting batch..."
				library = getSongsUser(sp, index=(20*i))
				print "Processing songs..."
				if len(library['items']) > 0:
					for item in library['items']:
						trackid = item['track']['id']
						arties = item['track']['artists']
						temp = getVectorFromTrack(sp, sp.audio_features([trackid])[0], arties)
						vectors.append(temp)
				else:
					#Delay so we don't get locked out of API
					time.sleep(0.5)
			except:
				# get out if we continually fail
				print "Error!"
				traceback.print_exc()
				errorCount += 1
				if errorCount >= 3:
					break
		return vectors
	else:
		print "Could not retrieve token for ", user
		sys.exit()

if __name__ == '__main__':
    if len(sys.argv) > 1:
		user = sys.argv[1]
		print "getting songs..."
		songs = getUserSongs(user)
		print "Dumping songs..."
		dumpSongVectors(songs)
    else:
    	print "Usage: %s username" % (sys.argv[0],)
    	sys.exit()
<|endoftext|>


<commit_before>from sympl import set_constant, get_constants_string

def list_available_constants():
    """
    Prints all the constants currently registered with sympl.

    """

    print(get_constants_string)

def set_constants_from_dict(constant_descriptions):
    """
    Modify/Add constants in the library.

    Args:

       constant_descriptions (dict):
           Dictionary containing the description of the constants.
           The key should be the name of the constant, and the value
           should be a dictionary containing the following keys:

           * value (float):
               The value assigned.

           * units (string):
                   The units of the value, e.g, m/s, J/kg.

    """

    for name in constant_descriptions.keys():

        value = constant_descriptions[name]['value']
        units = constant_descriptions[name]['units']

        set_constant(name, value, units)
<commit_msg>fixed bug<commit_after>from sympl import set_constant, get_constants_string

def list_available_constants():
    """
    Prints all the constants currently registered with sympl.

    """

    print(get_constants_string())

def set_constants_from_dict(constant_descriptions):
    """
    Modify/Add constants in the library.

    Args:

       constant_descriptions (dict):
           Dictionary containing the description of the constants.
           The key should be the name of the constant, and the value
           should be a dictionary containing the following keys:

           * value (float):
               The value assigned.

           * units (string):
                   The units of the value, e.g, m/s, J/kg.

    """

    for name in constant_descriptions.keys():

        value = constant_descriptions[name]['value']
        units = constant_descriptions[name]['units']

        set_constant(name, value, units)
<|endoftext|>


<commit_before>from b3 import B3
<commit_msg>Fixed init<commit_after>from B3score import b3
<|endoftext|>