<commit_before>"""Leetcode 957. Prison Cells After N Days
Medium

URL: https://leetcode.com/problems/prison-cells-after-n-days/

There are 8 prison cells in a row, and each cell is either occupied or vacant.

Each day, whether the cell is occupied or vacant changes according to the
following rules:

If a cell has two adjacent neighbors that are both occupied or both vacant,
then the cell becomes occupied.
Otherwise, it becomes vacant.
(Note that because the prison is a row, the first and the last cells in the row
can't have two adjacent neighbors.)

We describe the current state of the prison in the following way:
cells[i] == 1 if the i-th cell is occupied, else cells[i] == 0.

Given the initial state of the prison, return the state of the prison after N days
(and N such changes described above.)

Example 1:
Input: cells = [0,1,0,1,1,0,0,1], N = 7
Output: [0,0,1,1,0,0,0,0]
Explanation:
The following table summarizes the state of the prison on each day:
Day 0: [0, 1, 0, 1, 1, 0, 0, 1]
Day 1: [0, 1, 1, 0, 0, 0, 0, 0]
Day 2: [0, 0, 0, 0, 1, 1, 1, 0]
Day 3: [0, 1, 1, 0, 0, 1, 0, 0]
Day 4: [0, 0, 0, 0, 0, 1, 0, 0]
Day 5: [0, 1, 1, 1, 0, 1, 0, 0]
Day 6: [0, 0, 1, 0, 1, 1, 0, 0]
Day 7: [0, 0, 1, 1, 0, 0, 0, 0]

Example 2:
Input: cells = [1,0,0,1,0,0,1,0], N = 1000000000
Output: [0,0,1,1,1,1,1,0]

Note:
- cells.length == 8
- cells[i] is in {0, 1}
- 1 <= N <= 10^9
"""

class SolutionPattern(object):
    def prisonAfterNDays(self, cells, N):
        """
        :type cells: List[int]
        :type N: int
        :rtype: List[int]
        """
        # Since the cells transformation will cycle after 14 days.
        N %= 14
        if N == 0:
            N = 14

        for _ in range(N):
            res = [0] * len(cells)

            for i in range(1, len(cells) - 1):
                if cells[i - 1] == cells[i + 1]:
                    res[i] = 1

            cells = res

        return res

def main():
    # Output: [0, 0, 1, 1, 0, 0, 0, 0]
    cells = [0,1,0,1,1,0,0,1]
    N = 7
    print SolutionPattern().prisonAfterNDays(cells, N)

    # Output: [0,0,1,1,1,1,1,0]
    cells = [1,0,0,1,0,0,1,0]
    N = 1000000000
    print SolutionPattern().prisonAfterNDays(cells, N)

if __name__ == '__main__':
    main()
<commit_msg>Add time/space complexity<commit_after>"""Leetcode 957. Prison Cells After N Days
Medium

URL: https://leetcode.com/problems/prison-cells-after-n-days/

There are 8 prison cells in a row, and each cell is either occupied or vacant.

Each day, whether the cell is occupied or vacant changes according to the
following rules:

If a cell has two adjacent neighbors that are both occupied or both vacant,
then the cell becomes occupied.
Otherwise, it becomes vacant.
(Note that because the prison is a row, the first and the last cells in the row
can't have two adjacent neighbors.)

We describe the current state of the prison in the following way:
cells[i] == 1 if the i-th cell is occupied, else cells[i] == 0.

Given the initial state of the prison, return the state of the prison after N days
(and N such changes described above.)

Example 1:
Input: cells = [0,1,0,1,1,0,0,1], N = 7
Output: [0,0,1,1,0,0,0,0]
Explanation:
The following table summarizes the state of the prison on each day:
Day 0: [0, 1, 0, 1, 1, 0, 0, 1]
Day 1: [0, 1, 1, 0, 0, 0, 0, 0]
Day 2: [0, 0, 0, 0, 1, 1, 1, 0]
Day 3: [0, 1, 1, 0, 0, 1, 0, 0]
Day 4: [0, 0, 0, 0, 0, 1, 0, 0]
Day 5: [0, 1, 1, 1, 0, 1, 0, 0]
Day 6: [0, 0, 1, 0, 1, 1, 0, 0]
Day 7: [0, 0, 1, 1, 0, 0, 0, 0]

Example 2:
Input: cells = [1,0,0,1,0,0,1,0], N = 1000000000
Output: [0,0,1,1,1,1,1,0]

Note:
- cells.length == 8
- cells[i] is in {0, 1}
- 1 <= N <= 10^9
"""

class SolutionPattern(object):
    def prisonAfterNDays(self, cells, N):
        """
        :type cells: List[int]
        :type N: int
        :rtype: List[int]

        Time complexity: O(1).
        Space complexity: O(1).
        """
        # Since the cells transformation will cycle after 14 days.
        N %= 14
        if N == 0:
            N = 14

        for _ in range(N):
            res = [0] * len(cells)

            for i in range(1, len(cells) - 1):
                if cells[i - 1] == cells[i + 1]:
                    res[i] = 1

            cells = res

        return res

def main():
    # Output: [0, 0, 1, 1, 0, 0, 0, 0]
    cells = [0,1,0,1,1,0,0,1]
    N = 7
    print SolutionPattern().prisonAfterNDays(cells, N)

    # Output: [0,0,1,1,1,1,1,0]
    cells = [1,0,0,1,0,0,1,0]
    N = 1000000000
    print SolutionPattern().prisonAfterNDays(cells, N)

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


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
#  Copyright 2019 The FATE Authors. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import copy
import numpy as np

from fate_flow.entity.metric import Metric, MetricMeta
from federatedml.model_base import ModelBase
from federatedml.param.sample_weight_param import SampleWeightParam
from federatedml.statistic.data_overview import get_label_count, check_negative_sample_weight
from federatedml.util import consts, LOGGER

class SampleWeight(ModelBase):
    def __init__(self):
        super().__init__()
        self.model_param = SampleWeightParam()
        self.metric_name = "sample_weight"
        self.metric_namespace = "train"
        self.metric_type = "SAMPLE_WEIGHT"
        self.weight_mode = None

    def _init_model(self, params):
        self.model_param = params
        self.class_weight = params.class_weight
        self.sample_weight_name = params.sample_weight_name
        self.normalize = params.normalize
        self.need_run = params.need_run

    @staticmethod
    def get_class_weight(data_instances):
        class_weight = get_label_count(data_instances)
        n_samples = data_instances.count()
        n_classes = len(class_weight.keys())
        res_class_weight = {str(k): n_samples / (n_classes * v) for k, v in class_weight.items()}

        return res_class_weight

    @staticmethod
    def replace_weight(data_instance, class_weight, weight_loc=None, weight_base=None):
        weighted_data_instance = copy.copy(data_instance)
        original_features = weighted_data_instance.features
        if weight_loc is not None:
            if weight_base is not None:
                inst_weight = original_features[weight_loc] / weight_base
            else:
                inst_weight = original_features[weight_loc]
            weighted_data_instance.set_weight(inst_weight)
            weighted_data_instance.features = original_features[np.arange(original_features.shape[0]) != weight_loc]
        else:
            weighted_data_instance.set_weight(class_weight.get(str(data_instance.label), 1))
        return weighted_data_instance

    @staticmethod
    def assign_sample_weight(data_instances, class_weight, weight_loc, normalize):
        weight_base = None
        if weight_loc is not None and normalize:
            def sum_sample_weight(kv_iterator):
                sample_weight = 0
                for _, inst in kv_iterator:
                    sample_weight += inst.features[weight_loc]
                return sample_weight

            weight_sum = data_instances.mapPartitions(sum_sample_weight).reduce(lambda x, y: x + y)
            # LOGGER.debug(f"weight_sum is {weight_sum}")
            weight_base = weight_sum / data_instances.count()
            # LOGGER.debug(f"weight_base is {weight_base}")
        return data_instances.mapValues(lambda v: SampleWeight.replace_weight(v, class_weight, weight_loc, weight_base))

    @staticmethod
    def get_weight_loc(data_instances, sample_weight_name):
        weight_loc = None
        if sample_weight_name:
            try:
                weight_loc = data_instances.schema["header"].index(sample_weight_name)
            except ValueError:
                return
        return weight_loc

    def transform_weighted_instance(self, data_instances, weight_loc):
        if self.class_weight and self.class_weight == 'balanced':
            self.class_weight = SampleWeight.get_class_weight(data_instances)
        return SampleWeight.assign_sample_weight(data_instances, self.class_weight, weight_loc, self.normalize)

    def callback_info(self):
        class_weight = None
        classes = None
        if self.class_weight:
            class_weight = {str(k): v for k, v in self.class_weight.items()}
            classes = sorted([str(k) for k in self.class_weight.keys()])
        # LOGGER.debug(f"callback class weight is: {class_weight}")

        metric_meta = MetricMeta(name='train',
                                 metric_type=self.metric_type,
                                 extra_metas={
                                     "weight_mode": self.weight_mode,
                                     "class_weight": class_weight,
                                     "classes": classes,
                                     "sample_weight_name": self.sample_weight_name
                                 })

        self.callback_metric(metric_name=self.metric_name,
                             metric_namespace=self.metric_namespace,
                             metric_data=[Metric(self.metric_name, 0)])
        self.tracker.set_metric_meta(metric_namespace=self.metric_namespace,
                                     metric_name=self.metric_name,
                                     metric_meta=metric_meta)

    def transform(self, data_instances):
        LOGGER.info(f"Enter Sample Weight Transform")
        if self.class_weight:
            raise ValueError(f"Transform does not support class weight mode.")
        return self.fit(data_instances)

    def fit(self, data_instances):
        if self.sample_weight_name is None and self.class_weight is None:
            return data_instances

        if self.class_weight:
            self.weight_mode = "class weight"

        if self.sample_weight_name and self.class_weight:
            LOGGER.warning(f"Both 'sample_weight_name' and 'class_weight' provided. "
                           f"Only weight from 'sample_weight_name' is used.")

        new_schema = copy.deepcopy(data_instances.schema)
        new_schema["sample_weight"] = "weight"
        weight_loc = None
        if self.sample_weight_name:
            self.weight_mode = "sample weight name"
            weight_loc = SampleWeight.get_weight_loc(data_instances, self.sample_weight_name)
            if weight_loc is not None:
                new_schema["header"].pop(weight_loc)
            else:
                raise ValueError(f"Cannot find weight column of given sample_weight_name '{self.sample_weight_name}'.")
        result_instances = self.transform_weighted_instance(data_instances, weight_loc)
        result_instances.schema = new_schema

        self.callback_info()
        if result_instances.mapPartitions(check_negative_sample_weight).reduce(lambda x, y: x or y):
            LOGGER.warning(f"Negative weight found in weighted instances.")
        return result_instances
<commit_msg>edit sample weight<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

#
#  Copyright 2019 The FATE Authors. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

import copy
import numpy as np

from fate_flow.entity.metric import Metric, MetricMeta
from federatedml.model_base import ModelBase
from federatedml.param.sample_weight_param import SampleWeightParam
from federatedml.statistic.data_overview import get_label_count, check_negative_sample_weight
from federatedml.util import consts, LOGGER

class SampleWeight(ModelBase):
    def __init__(self):
        super().__init__()
        self.model_param = SampleWeightParam()
        self.metric_name = "sample_weight"
        self.metric_namespace = "train"
        self.metric_type = "SAMPLE_WEIGHT"
        self.weight_mode = None

    def _init_model(self, params):
        self.model_param = params
        self.class_weight = params.class_weight
        self.sample_weight_name = params.sample_weight_name
        self.normalize = params.normalize
        self.need_run = params.need_run

    @staticmethod
    def get_class_weight(data_instances):
        class_weight = get_label_count(data_instances)
        n_samples = data_instances.count()
        n_classes = len(class_weight.keys())
        res_class_weight = {str(k): n_samples / (n_classes * v) for k, v in class_weight.items()}

        return res_class_weight

    @staticmethod
    def replace_weight(data_instance, class_weight, weight_loc=None, weight_base=None):
        weighted_data_instance = copy.copy(data_instance)
        original_features = weighted_data_instance.features
        if weight_loc is not None:
            if weight_base is not None:
                inst_weight = original_features[weight_loc] / weight_base
            else:
                inst_weight = original_features[weight_loc]
            weighted_data_instance.set_weight(inst_weight)
            weighted_data_instance.features = original_features[np.arange(original_features.shape[0]) != weight_loc]
        else:
            weighted_data_instance.set_weight(class_weight.get(str(data_instance.label), 1))
        return weighted_data_instance

    @staticmethod
    def assign_sample_weight(data_instances, class_weight, weight_loc, normalize):
        weight_base = None
        if weight_loc is not None and normalize:
            def sum_sample_weight(kv_iterator):
                sample_weight = 0
                for _, inst in kv_iterator:
                    sample_weight += inst.features[weight_loc]
                return sample_weight

            weight_sum = data_instances.mapPartitions(sum_sample_weight).reduce(lambda x, y: x + y)
            # LOGGER.debug(f"weight_sum is {weight_sum}")
            weight_base = weight_sum / data_instances.count()
            # LOGGER.debug(f"weight_base is {weight_base}")
        return data_instances.mapValues(lambda v: SampleWeight.replace_weight(v, class_weight, weight_loc, weight_base))

    @staticmethod
    def get_weight_loc(data_instances, sample_weight_name):
        weight_loc = None
        if sample_weight_name:
            try:
                weight_loc = data_instances.schema["header"].index(sample_weight_name)
            except ValueError:
                return
        return weight_loc

    def transform_weighted_instance(self, data_instances, weight_loc):
        if self.class_weight and self.class_weight == 'balanced':
            self.class_weight = SampleWeight.get_class_weight(data_instances)
        return SampleWeight.assign_sample_weight(data_instances, self.class_weight, weight_loc, self.normalize)

    def callback_info(self):
        class_weight = None
        classes = None
        if self.class_weight:
            class_weight = {str(k): v for k, v in self.class_weight.items()}
            classes = sorted([str(k) for k in self.class_weight.keys()])
        # LOGGER.debug(f"callback class weight is: {class_weight}")

        metric_meta = MetricMeta(name='train',
                                 metric_type=self.metric_type,
                                 extra_metas={
                                     "weight_mode": self.weight_mode,
                                     "class_weight": class_weight,
                                     "classes": classes,
                                     "sample_weight_name": self.sample_weight_name
                                 })

        self.callback_metric(metric_name=self.metric_name,
                             metric_namespace=self.metric_namespace,
                             metric_data=[Metric(self.metric_name, 0)])
        self.tracker.set_metric_meta(metric_namespace=self.metric_namespace,
                                     metric_name=self.metric_name,
                                     metric_meta=metric_meta)

    def transform(self, data_instances):
        LOGGER.info(f"Enter Sample Weight Transform")
        if self.class_weight is not None:
            raise ValueError(f"Transform does not support class weight mode.")
        return self.fit(data_instances)

    def fit(self, data_instances):
        if self.sample_weight_name is None and self.class_weight is None:
            return data_instances

        if self.class_weight:
            self.weight_mode = "class weight"

        if self.sample_weight_name and self.class_weight:
            LOGGER.warning(f"Both 'sample_weight_name' and 'class_weight' provided. "
                           f"Only weight from 'sample_weight_name' is used.")

        new_schema = copy.deepcopy(data_instances.schema)
        new_schema["sample_weight"] = "weight"
        weight_loc = None
        if self.sample_weight_name:
            self.weight_mode = "sample weight name"
            weight_loc = SampleWeight.get_weight_loc(data_instances, self.sample_weight_name)
            if weight_loc is not None:
                new_schema["header"].pop(weight_loc)
            else:
                raise ValueError(f"Cannot find weight column of given sample_weight_name '{self.sample_weight_name}'.")
        result_instances = self.transform_weighted_instance(data_instances, weight_loc)
        result_instances.schema = new_schema

        self.callback_info()
        if result_instances.mapPartitions(check_negative_sample_weight).reduce(lambda x, y: x or y):
            LOGGER.warning(f"Negative weight found in weighted instances.")
        return result_instances
<|endoftext|>


<commit_before>"""Leetcode 720. Longest Word in Dictionary
Easy

URL: https://leetcode.com/problems/longest-word-in-dictionary/

Given a list of strings words representing an English Dictionary,
find the longest word in words that can be built one character at a time by
other words in words. If there is more than one possible answer, return the
longest word with the smallest lexicographical order.

If there is no answer, return the empty string.

Example 1:
Input:
words = ["w","wo","wor","worl", "world"]
Output: "world"
Explanation:
The word "world" can be built one character at a time by
"w", "wo", "wor", and "worl".

Example 2:
Input:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
Output: "apple"
Explanation:
Both "apply" and "apple" can be built from other words in the dictionary.
However, "apple" is lexicographically smaller than "apply".

Note:
All the strings in the input will only contain lowercase letters.
The length of words will be in the range [1, 1000].
The length of words[i] will be in the range [1, 30].
"""

class Solution(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str

        Time complexity: O(nm), where n is the length of words.
        Space complexity: O(m), where m is the max length of word.
        """
        prefix = longest = ''
        for w in sorted(words):
            if w[:len(w) - 1] == prefix[:len(w) - 1]:
                prefix = w
                longest = max([longest, prefix], key=len)
        return longest

class SolutionTrie(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str

        Time complexity: O(??).
        Space complexity: O(??).
        """
        pass

def main():
    # Ans: "world".
    words = ["w","wo","wor","worl", "world"]
    print(Solution().longestWord(words))

    # Ans: "apple".
    words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
    print(Solution().longestWord(words))

if __name__ == '__main__':
    main()
<commit_msg>Complete solution by Trie<commit_after>"""Leetcode 720. Longest Word in Dictionary
Easy

URL: https://leetcode.com/problems/longest-word-in-dictionary/

Given a list of strings words representing an English Dictionary,
find the longest word in words that can be built one character at a time by
other words in words. If there is more than one possible answer, return the
longest word with the smallest lexicographical order.

If there is no answer, return the empty string.

Example 1:
Input:
words = ["w","wo","wor","worl", "world"]
Output: "world"
Explanation:
The word "world" can be built one character at a time by
"w", "wo", "wor", and "worl".

Example 2:
Input:
words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]
Output: "apple"
Explanation:
Both "apply" and "apple" can be built from other words in the dictionary.
However, "apple" is lexicographically smaller than "apply".

Note:
All the strings in the input will only contain lowercase letters.
The length of words will be in the range [1, 1000].
The length of words[i] will be in the range [1, 30].
"""

class Solution(object):
    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str

        Time complexity: O(nm), where n is the length of words.
        Space complexity: O(m), where m is the max length of word.
        """
        prefix = longest = ''
        for w in sorted(words):
            if w[:len(w) - 1] == prefix[:len(w) - 1]:
                prefix = w
                longest = max([longest, prefix], key=len)
        return longest

class Node(object):
    def __init__(self, key=None, word=None):
        self.key = key
        self.word = word
        self.children = {}

class SolutionTrie(object):
    def __init__(self):
        self.root = Node()

    def longestWord(self, words):
        """
        :type words: List[str]
        :rtype: str

        Time complexity: O(??).
        Space complexity: O(??).
        """
        # Build Trie for words in dictionary.
        for w in words:
            current = self.root
            for c in w:
                if c in current.children:
                    current = current.children[c]
                else:
                    new = Node(c)
                    current.children[c] = new
                    current = new
            current.word = w

        # DFS for longest word.
        stack = list(self.root.children.values())
        longest = ''

        while stack:
            current = stack.pop()
            if current.word:
                if (len(longest) < len(current.word) or
                    (len(longest) == len(current.word) and
                     current.word < longest)):
                    longest = current.word
                stack.extend(list(current.children.values()))

        return longest

def main():
    import time

    # Ans: "world".
    words = ["w", "wo", "wor", "worl", "world"]

    start_time = time.time()
    print('By string slice: {}'.format(Solution().longestWord(words)))
    print('Time: {}'.format(time.time() - start_time))

    start_time = time.time()
    print('By Trie: {}'.format(SolutionTrie().longestWord(words)))
    print('Time: {}'.format(time.time() - start_time))

    # Ans: "apple".
    words = ["a", "banana", "app", "appl", "ap", "apply", "apple"]

    start_time = time.time()
    print('By string slice: {}'.format(Solution().longestWord(words)))
    print('Time: {}'.format(time.time() - start_time))

    start_time = time.time()
    print('By Trie: {}'.format(SolutionTrie().longestWord(words)))
    print('Time: {}'.format(time.time() - start_time))

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


<commit_before>import pytest

from common import storage
from core import command, cmdconf, template as tmpl

_DCOS_CONFIG = r'''
package:
  - path: {{ windows_dcos_install_path }}\file1.txt
    content: |
      word
      {{ color }}
          {{ provider }}
      {{ escaped }}
  - path: {{ windows_dcos_install_path }}\subdir\file2.json
    content: |
        {
            value: {{ escaped }}
        }

'''

_FILE1_CONTENTS = r'''word
red
    aws
"true"
'''

# Files ending in .json are treated the same as other files, with no special escaping.
_FILE2_CONTENTS = r'''{
    value: "true"
}
'''

@cmdconf.cmdconf_type('test')
class SetupConf:

    def __init__(self, **cmd_opts):
        self._opts = cmd_opts

    def __getattr__(self, name):
        return self._opts[name]

def test_dcos_config_ok(tmp_path):
    """
    Files are templated and indented according to YAML.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'aws',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    setup._deploy_dcos_conf()

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'subdir' / 'file2.json'

    assert file1_path.exists()
    assert file2_path.exists()
    assert file1_path.read_text() == _FILE1_CONTENTS
    assert file2_path.read_text() == _FILE2_CONTENTS

_DCOS_CONFIG_SWITCH = r'''
package:
{% switch provider %}
{% case "aws" %}
  - path: {{ windows_dcos_install_path }}\file1.txt
    permissions: "0600"
    content: {{ color }}
{% case "azure" %}
{% endswitch %}
  - path: {{ windows_dcos_install_path }}\file2.txt
    content: |
{% switch provider %}
{% case "aws" %}
        1
{% case "azure" %}
        2
{% endswitch %}
        {{ escaped }}
'''

_FILE2_CONTENTS_AWS = r'''
1

"true"
'''

_FILE2_CONTENTS_AZURE = r'''
2

"true"
'''

def test_dcos_config_aws(tmp_path):
    """
    First replacement is used.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'aws',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG_SWITCH)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    setup._deploy_dcos_conf()

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'file2.txt'

    assert file1_path.exists()
    assert file2_path.exists()
    assert file1_path.read_text() == 'red'
    assert file2_path.read_text() == _FILE2_CONTENTS_AWS

def test_dcos_config_azure(tmp_path):
    """
    Second replacement is used.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'azure',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG_SWITCH)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    setup._deploy_dcos_conf()

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'file2.txt'

    assert not file1_path.exists()
    assert file2_path.exists()
    assert file2_path.read_text() == _FILE2_CONTENTS_AZURE

def test_dcos_config_missing_variable(tmp_path):
    """
    Templating fails if a parameter is not set.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'provider': 'aws',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    with pytest.raises(tmpl.UnsetParameter):
        setup._deploy_dcos_conf()
<commit_msg>Fix tests<commit_after>import pytest

from common import storage
from core import command, cmdconf, template as tmpl

_DCOS_CONFIG = r'''
package:
  - path: {{ windows_dcos_install_path }}\file1.txt
    content: |
      word
      {{ color }}
          {{ provider }}
      {{ escaped }}
  - path: {{ windows_dcos_install_path }}\subdir\file2.json
    content: |
        {
            value: {{ escaped }}
        }

'''

_FILE1_CONTENTS = r'''word
red
    aws
"true"
'''

# Files ending in .json are treated the same as other files, with no special escaping.
_FILE2_CONTENTS = r'''{
    value: "true"
}
'''

@cmdconf.cmdconf_type('test')
class SetupConf:

    def __init__(self, **cmd_opts):
        self._opts = cmd_opts

    def __getattr__(self, name):
        return self._opts[name]

def test_dcos_config_ok(tmp_path):
    """
    Files are templated and indented according to YAML.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'aws',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    command._deploy_dcos_conf(setup.config.dcos_conf)

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'subdir' / 'file2.json'

    assert file1_path.exists()
    assert file2_path.exists()
    assert file1_path.read_text() == _FILE1_CONTENTS
    assert file2_path.read_text() == _FILE2_CONTENTS

_DCOS_CONFIG_SWITCH = r'''
package:
{% switch provider %}
{% case "aws" %}
  - path: {{ windows_dcos_install_path }}\file1.txt
    permissions: "0600"
    content: {{ color }}
{% case "azure" %}
{% endswitch %}
  - path: {{ windows_dcos_install_path }}\file2.txt
    content: |
{% switch provider %}
{% case "aws" %}
        1
{% case "azure" %}
        2
{% endswitch %}
        {{ escaped }}
'''

_FILE2_CONTENTS_AWS = r'''
1

"true"
'''

_FILE2_CONTENTS_AZURE = r'''
2

"true"
'''

def test_dcos_config_aws(tmp_path):
    """
    First replacement is used.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'aws',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG_SWITCH)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    command._deploy_dcos_conf(setup.config.dcos_conf)

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'file2.txt'

    assert file1_path.exists()
    assert file2_path.exists()
    assert file1_path.read_text() == 'red'
    assert file2_path.read_text() == _FILE2_CONTENTS_AWS

def test_dcos_config_azure(tmp_path):
    """
    Second replacement is used.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'color': 'red',
        'provider': 'azure',
        'escaped': '"true"',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG_SWITCH)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    command._deploy_dcos_conf(setup.config.dcos_conf)

    file1_path = root_path / 'file1.txt'
    file2_path = root_path / 'file2.txt'

    assert not file1_path.exists()
    assert file2_path.exists()
    assert file2_path.read_text() == _FILE2_CONTENTS_AZURE

def test_dcos_config_missing_variable(tmp_path):
    """
    Templating fails if a parameter is not set.
    """
    root_path = tmp_path / 'root'
    values = {
        'windows_dcos_install_path': str(root_path),
        'provider': 'aws',
    }
    dcos_config_path = tmp_path / 'dcos-config-windows.yaml'
    dcos_config_path.write_text(_DCOS_CONFIG)

    template = cmdconf.CmdConfigSetup.load_dcos_conf_template(dcos_config_path)
    dcos_conf = {'template': template, 'values': values}

    inst_storage = storage.InstallationStorage(
        root_dpath=str(tmp_path / 'root')
    )

    cluster_conf = None

    setup = command.CmdSetup(
        command_name='test',
        dcos_conf=dcos_conf,
        cluster_conf=cluster_conf,
        inst_storage=inst_storage,
    )
    with pytest.raises(tmpl.UnsetParameter):
        command._deploy_dcos_conf(setup.config.dcos_conf)
<|endoftext|>


<commit_before>#Copyright 2017 Google Inc. All rights reserved.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Rule for configuring apt GPG keys"""

load("@io_bazel_rules_docker//container:container.bzl", _container = "container")
load("@base_images_docker//util:run.bzl", _extract = "extract")

def _impl(ctx, name=None, keys=None, image_tar=None, gpg_image=None, output_executable=None, output_tarball=None, output_layer=None):
    """Implementation for the add_apt_key rule.

    Args:
        ctx: The bazel rule context
        name: str, overrides ctx.label.name
        keys: File list, overrides ctx.files.keys
        image_tar: File, overrides ctx.file.image
        gpg_image: File, overrides ctx.file.gpg_image
        output_executable: File to use as output for script to load docker image,
            overrides ctx.outputs.executable
        output_tarball: File, overrides ctx.outputs.out
        output_layer: File, overrides ctx.outputs.layer
    """
    name = name or ctx.label.name
    keys = keys or ctx.files.keys
    image_tar = image_tar or ctx.file.image
    gpg_image = gpg_image or ctx.file.gpg_image
    output_executable = output_executable or ctx.outputs.executable
    output_tarball = output_tarball or ctx.outputs.out
    output_layer = output_layer or ctx.outputs.layer

    # First build an image capable of adding an apt-key.
    # This requires the keyfile and the "gnupg package."

    # If the user specified an alternate base for this, use it.
    # Otherwise use the same base image we want the key in.
    if gpg_image == None:
        gpg_image = image_tar

    key_image = "%s.key" % name
    key_image_output_executable = ctx.actions.declare_file("%s" % key_image)
    key_image_output_tarball = ctx.actions.declare_file("%s.tar" % key_image)
    key_image_output_layer = ctx.actions.declare_file("%s-layer.tar" % key_image)

    key_image_result = _container.image.implementation(
        ctx,
        name=key_image,
        base=gpg_image,
        directory="/gpg",
        files=keys,
        output_executable=key_image_output_executable,
        output_tarball=key_image_output_tarball,
        output_layer=key_image_output_layer
    )

    commands = [
        "apt-get update",
        "apt-get install -y -q gnupg",
        # Put keys in a special directory and use glob.
        "for file in /gpg/*; do apt-key add \$file; done"
    ]
    extract_file_name = "/etc/apt/trusted.gpg"
    extract_file_out = ctx.actions.declare_file(name + "-trusted.gpg")

    _extract.implementation(
        ctx,
        name = name,
        image = key_image_output_tarball,
        commands = commands,
        extract_file = extract_file_name,
        output_file = extract_file_out,
    )

    # Build the final image with additional gpg keys in it.

    result = _container.image.implementation(
        ctx,
        name=name,
        base=image_tar,
        directory="/etc/apt/trusted.gpg.d/",
        files=[extract_file_out],
        output_executable=output_executable,
        output_tarball=output_tarball,
        output_layer=output_layer
    )

    return struct(runfiles = result.runfiles,
                  files = result.files,
                  container_parts = result.container_parts)

_attrs = dict(_container.image.attrs)
_attrs.update(_extract.attrs)
_attrs.update({
    "keys": attr.label_list(
        allow_files = True,
        mandatory = True,
    ),
    "gpg_image": attr.label(
        allow_files = True,
        single_file = True,
    ),
    # Redeclare following attributes of _extract to be non-mandatory.
    "commands": attr.string_list(doc = "commands to run"),
    "extract_file": attr.string(doc = "path to file to extract from container"),
    "output_file": attr.string()
})

_outputs = _container.image.outputs

# Export add_apt_key rule for other bazel rules to depend on.
key = struct(
    attrs = _attrs,
    outputs = _outputs,
    implementation = _impl,
)

add_apt_key = rule(
    attrs = _attrs,
    outputs = _outputs,
    implementation = _impl,
    executable = True,
)
<commit_msg>Fix container_image provider.<commit_after>#Copyright 2017 Google Inc. All rights reserved.

# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at

#     http://www.apache.org/licenses/LICENSE-2.0

# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Rule for configuring apt GPG keys"""

load("@io_bazel_rules_docker//container:container.bzl", _container = "container")
load("@base_images_docker//util:run.bzl", _extract = "extract")

def _impl(ctx, name=None, keys=None, image_tar=None, gpg_image=None, output_executable=None, output_tarball=None, output_layer=None):
    """Implementation for the add_apt_key rule.

    Args:
        ctx: The bazel rule context
        name: str, overrides ctx.label.name
        keys: File list, overrides ctx.files.keys
        image_tar: File, overrides ctx.file.image
        gpg_image: File, overrides ctx.file.gpg_image
        output_executable: File to use as output for script to load docker image,
            overrides ctx.outputs.executable
        output_tarball: File, overrides ctx.outputs.out
        output_layer: File, overrides ctx.outputs.layer
    """
    name = name or ctx.label.name
    keys = keys or ctx.files.keys
    image_tar = image_tar or ctx.file.image
    gpg_image = gpg_image or ctx.file.gpg_image
    output_executable = output_executable or ctx.outputs.executable
    output_tarball = output_tarball or ctx.outputs.out
    output_layer = output_layer or ctx.outputs.layer

    # First build an image capable of adding an apt-key.
    # This requires the keyfile and the "gnupg package."

    # If the user specified an alternate base for this, use it.
    # Otherwise use the same base image we want the key in.
    if gpg_image == None:
        gpg_image = image_tar

    key_image = "%s.key" % name
    key_image_output_executable = ctx.actions.declare_file("%s" % key_image)
    key_image_output_tarball = ctx.actions.declare_file("%s.tar" % key_image)
    key_image_output_layer = ctx.actions.declare_file("%s-layer.tar" % key_image)

    key_image_result = _container.image.implementation(
        ctx,
        name=key_image,
        base=gpg_image,
        directory="/gpg",
        files=keys,
        output_executable=key_image_output_executable,
        output_tarball=key_image_output_tarball,
        output_layer=key_image_output_layer
    )

    commands = [
        "apt-get update",
        "apt-get install -y -q gnupg",
        # Put keys in a special directory and use glob.
        "for file in /gpg/*; do apt-key add \$file; done"
    ]
    extract_file_name = "/etc/apt/trusted.gpg"
    extract_file_out = ctx.actions.declare_file(name + "-trusted.gpg")

    _extract.implementation(
        ctx,
        name = name,
        image = key_image_output_tarball,
        commands = commands,
        extract_file = extract_file_name,
        output_file = extract_file_out,
    )

    # Build the final image with additional gpg keys in it.

    return _container.image.implementation(
        ctx,
        name=name,
        base=image_tar,
        directory="/etc/apt/trusted.gpg.d/",
        files=[extract_file_out],
        output_executable=output_executable,
        output_tarball=output_tarball,
        output_layer=output_layer
    )

_attrs = dict(_container.image.attrs)
_attrs.update(_extract.attrs)
_attrs.update({
    "keys": attr.label_list(
        allow_files = True,
        mandatory = True,
    ),
    "gpg_image": attr.label(
        allow_files = True,
        single_file = True,
    ),
    # Redeclare following attributes of _extract to be non-mandatory.
    "commands": attr.string_list(doc = "commands to run"),
    "extract_file": attr.string(doc = "path to file to extract from container"),
    "output_file": attr.string()
})

_outputs = _container.image.outputs

# Export add_apt_key rule for other bazel rules to depend on.
key = struct(
    attrs = _attrs,
    outputs = _outputs,
    implementation = _impl,
)

add_apt_key = rule(
    attrs = _attrs,
    outputs = _outputs,
    implementation = _impl,
    executable = True,
)
<|endoftext|>


<commit_before>def gpu_queue(options):
    """
    Queued up containers waiting for GPU resources
    """
    import docker
    import json
    status = (False, None)

    # !! TODO wait until resources are available
    print ("gpu queue", str(options)

    try:
        d_client = docker.from_env()
        options = json.loads(options)
        configs = options['configs']
        del options[configs]
        params = options.copy()
        params.update(configs)
        print(str(params))
        d_client.containers.run(**params)
        status = (True, None)
    except Exception as e:  # pragma: no cover
        status = (False, str(e))

    return status

def file_queue(path, template_path="/vent/"):
    """
    Processes files that have been added from the rq-worker, starts plugins
    that match the mime type for the new file.
    """
    import ConfigParser
    import docker
    import json
    import requests

    from redis import Redis
    from rq import Queue
    from subprocess import check_output, Popen, PIPE

    status = (True, None)
    images = []
    configs = {}

    try:
        d_client = docker.from_env()

        # get the correct path for binding
        vent_config = ConfigParser.RawConfigParser()
        vent_config.optionxform = str
        vent_config.read(template_path+'vent.cfg')
        if (vent_config.has_section('main') and
           vent_config.has_option('main', 'files')):
            files = vent_config.get('main', 'files')
        else:
            files = '/'

        _, path = path.split('_', 1)
        directory = path.rsplit('/', 1)[0]
        path = path.replace('/files', files, 1)

        labels = {'vent-plugin': '', 'file': path}
        # read in configuration of plugins to get the ones that should run
        # against the path.
        # keep track of images that failed getting configurations for
        failed_images = set()
        config = ConfigParser.RawConfigParser()
        config.optionxform = str
        config.read(template_path+'plugin_manifest.cfg')
        sections = config.sections()
        for section in sections:
            image_name = config.get(section, 'image_name')
            # doesn't matter if it's a repository or registry because both in manifest
            if config.has_option(section, 'service'):
                try:
                    options_dict = json.loads(config.get(section, 'service'))
                    for option in options_dict:
                        value = options_dict[option]
                        labels[option] = value
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))
            if config.has_option(section, 'settings'):
                try:
                    options_dict = json.loads(config.get(section, 'settings'))
                    in_base = directory == '/files'
                    # process base by default
                    process_file = True if in_base else False
                    # check if this tool shouldn't process the base by default
                    if 'process_base' in options_dict:
                        if options_dict['process_base'] == 'no':
                            process_file = False
                    # check if this tool should look at subdirs created by
                    # other tools' output
                    if 'process_from_tool' in options_dict and not in_base:
                        for tool in options_dict['process_from_tool'].split(','):
                            if tool.replace(' ', '-') in directory:
                                process_file = True
                    if 'ext_types' in options_dict and process_file:
                        ext_types = options_dict['ext_types'].split(',')
                        for ext_type in ext_types:
                            if path.endswith(ext_type):
                                images.append(image_name)
                                configs[image_name] = {}
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))
            if config.has_option(section, 'gpu') and image_name in configs:
                try:
                    options_dict = json.loads(config.get(section, 'gpu'))
                    if 'enabled' in options_dict:
                        enabled = options_dict['enabled']
                        if enabled == 'yes':
                            if 'labels' in configs[image_name]:
                                configs[image_name]['labels']['vent.gpu'] = 'yes'
                            else:
                                configs[image_name]['labels'] = {'vent.gpu': 'yes'}
                            port = ''
                            host = ''
                            if (vent_config.has_section('nvidia-docker-plugin') and
                               vent_config.has_option('nvidia-docker-plugin', 'port')):
                                port = vent_config.get('nvidia-docker-plugin', 'port')
                            else:
                                port = '3476'
                            if (vent_config.has_section('nvidia-docker-plugin') and
                               vent_config.has_option('nvidia-docker-plugin', 'host')):
                                host = vent_config.get('nvidia-docker-plugin', 'host')
                            else:
                                route = Popen(('/sbin/ip', 'route'), stdout=PIPE)
                                h = check_output(('awk', '/default/ {print $3}'),
                                                 stdin=route.stdout)
                                route.wait()
                                host = h.strip()
                            nd_url = 'http://' + host + ':' + port + '/v1.0/docker/cli'
                            params = {'vol': 'nvidia_driver'}
                            try:
                                r = requests.get(nd_url, params=params)
                                if r.status_code == 200:
                                    options = r.text.split()
                                    for option in options:
                                        if option.startswith('--volume-driver='):
                                            configs[image_name]['volume_driver'] = option.split("=", 1)[1]
                                        elif option.startswith('--volume='):
                                            vol = option.split("=", 1)[1].split(":")
                                            if 'volumes' in configs[image_name]:
                                                # !! TODO handle if volumes is a list
                                                configs[image_name]['volumes'][vol[0]] = {'bind': vol[1],
                                                                                'mode': vol[2]}
                                            else:
                                                configs[image_name]['volumes'] = {vol[0]:
                                                                                {'bind': vol[1],
                                                                                'mode': vol[2]}}
                                        elif option.startswith('--device='):
                                            dev = option.split("=", 1)[1]
                                            if 'devices' in configs[image_name]:
                                                configs[image_name]['devices'].append(dev +
                                                                                ":" +
                                                                                dev +
                                                                                ":rwm")
                                            else:
                                                configs[image_name]['devices'] = [dev + ":" + dev + ":rwm"]
                                        else:
                                            # unable to parse option provided by
                                            # nvidia-docker-plugin
                                            pass
                            except Exception as e:  # pragma: no cover
                                failed_images.add(image_name)
                                status = (False, str(e))
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))

        # TODO add connections to syslog, labels, and file path etc.
        # TODO get syslog address rather than hardcode
        # TODO get group and name for tag
        # TODO add rw volume for plugin output to be plugin input
        log_config = {'type': 'syslog',
                      'config': {'syslog-address': 'tcp://0.0.0.0:514',
                                 'syslog-facility': 'daemon',
                                 'tag': path.rsplit('.', 1)[-1]}}
        dir_path = path.rsplit('/', 1)[0]
        volumes = {dir_path: {'bind': dir_path, 'mode': 'rw'}}

        # setup gpu queue
        can_queue_gpu = True
        try:
            q = Queue(connection=Redis(host='redis'), default_timeout=86400)
        except Exception as e:  # pragma: no cover
            can_queue_gpu = False

        # start containers
        for image in images:
            if image not in failed_images:
                # TODO check for availability of gpu(s),
                #      otherwise queue it up until it's
                #      available
                if 'volumes' in configs[image]:
                    for volume in volumes:
                        configs[image]['volumes'][volume] = volumes[volume]
                else:
                    configs[image]['volumes'] = volumes
                if ('labels' in configs[image] and
                   'vent.gpu' in configs[image]['labels'] and
                   configs[image]['labels']['vent.gpu'] == 'yes'):
                    if can_queue_gpu:
                        # queue up containers requiring a gpu
                        q_str = json.dumps({'image': image,
                                            'command': path,
                                            'labels': labels,
                                            'detach': True,
                                            'log_config': log_config,
                                            'configs': configs[image]})
                        q.enqueue('watch.gpu_queue', q_str, ttl=2592000)
                    else:
                        failed_images.add(image)
                else:
                    d_client.containers.run(image=image,
                                            command=path,
                                            labels=labels,
                                            detach=True,
                                            log_config=log_config,
                                            **configs[image])
        if failed_images:
            status = (False, failed_images)
        else:
            status = (True, images)
    except Exception as e:  # pragma: no cover
        status = (False, str(e))

    print(str(status))
    return status
<commit_msg>syntax error<commit_after>def gpu_queue(options):
    """
    Queued up containers waiting for GPU resources
    """
    import docker
    import json
    status = (False, None)

    # !! TODO wait until resources are available
    print ("gpu queue", str(options))

    try:
        d_client = docker.from_env()
        options = json.loads(options)
        configs = options['configs']
        del options[configs]
        params = options.copy()
        params.update(configs)
        print(str(params))
        d_client.containers.run(**params)
        status = (True, None)
    except Exception as e:  # pragma: no cover
        status = (False, str(e))

    return status

def file_queue(path, template_path="/vent/"):
    """
    Processes files that have been added from the rq-worker, starts plugins
    that match the mime type for the new file.
    """
    import ConfigParser
    import docker
    import json
    import requests

    from redis import Redis
    from rq import Queue
    from subprocess import check_output, Popen, PIPE

    status = (True, None)
    images = []
    configs = {}

    try:
        d_client = docker.from_env()

        # get the correct path for binding
        vent_config = ConfigParser.RawConfigParser()
        vent_config.optionxform = str
        vent_config.read(template_path+'vent.cfg')
        if (vent_config.has_section('main') and
           vent_config.has_option('main', 'files')):
            files = vent_config.get('main', 'files')
        else:
            files = '/'

        _, path = path.split('_', 1)
        directory = path.rsplit('/', 1)[0]
        path = path.replace('/files', files, 1)

        labels = {'vent-plugin': '', 'file': path}
        # read in configuration of plugins to get the ones that should run
        # against the path.
        # keep track of images that failed getting configurations for
        failed_images = set()
        config = ConfigParser.RawConfigParser()
        config.optionxform = str
        config.read(template_path+'plugin_manifest.cfg')
        sections = config.sections()
        for section in sections:
            image_name = config.get(section, 'image_name')
            # doesn't matter if it's a repository or registry because both in manifest
            if config.has_option(section, 'service'):
                try:
                    options_dict = json.loads(config.get(section, 'service'))
                    for option in options_dict:
                        value = options_dict[option]
                        labels[option] = value
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))
            if config.has_option(section, 'settings'):
                try:
                    options_dict = json.loads(config.get(section, 'settings'))
                    in_base = directory == '/files'
                    # process base by default
                    process_file = True if in_base else False
                    # check if this tool shouldn't process the base by default
                    if 'process_base' in options_dict:
                        if options_dict['process_base'] == 'no':
                            process_file = False
                    # check if this tool should look at subdirs created by
                    # other tools' output
                    if 'process_from_tool' in options_dict and not in_base:
                        for tool in options_dict['process_from_tool'].split(','):
                            if tool.replace(' ', '-') in directory:
                                process_file = True
                    if 'ext_types' in options_dict and process_file:
                        ext_types = options_dict['ext_types'].split(',')
                        for ext_type in ext_types:
                            if path.endswith(ext_type):
                                images.append(image_name)
                                configs[image_name] = {}
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))
            if config.has_option(section, 'gpu') and image_name in configs:
                try:
                    options_dict = json.loads(config.get(section, 'gpu'))
                    if 'enabled' in options_dict:
                        enabled = options_dict['enabled']
                        if enabled == 'yes':
                            if 'labels' in configs[image_name]:
                                configs[image_name]['labels']['vent.gpu'] = 'yes'
                            else:
                                configs[image_name]['labels'] = {'vent.gpu': 'yes'}
                            port = ''
                            host = ''
                            if (vent_config.has_section('nvidia-docker-plugin') and
                               vent_config.has_option('nvidia-docker-plugin', 'port')):
                                port = vent_config.get('nvidia-docker-plugin', 'port')
                            else:
                                port = '3476'
                            if (vent_config.has_section('nvidia-docker-plugin') and
                               vent_config.has_option('nvidia-docker-plugin', 'host')):
                                host = vent_config.get('nvidia-docker-plugin', 'host')
                            else:
                                route = Popen(('/sbin/ip', 'route'), stdout=PIPE)
                                h = check_output(('awk', '/default/ {print $3}'),
                                                 stdin=route.stdout)
                                route.wait()
                                host = h.strip()
                            nd_url = 'http://' + host + ':' + port + '/v1.0/docker/cli'
                            params = {'vol': 'nvidia_driver'}
                            try:
                                r = requests.get(nd_url, params=params)
                                if r.status_code == 200:
                                    options = r.text.split()
                                    for option in options:
                                        if option.startswith('--volume-driver='):
                                            configs[image_name]['volume_driver'] = option.split("=", 1)[1]
                                        elif option.startswith('--volume='):
                                            vol = option.split("=", 1)[1].split(":")
                                            if 'volumes' in configs[image_name]:
                                                # !! TODO handle if volumes is a list
                                                configs[image_name]['volumes'][vol[0]] = {'bind': vol[1],
                                                                                'mode': vol[2]}
                                            else:
                                                configs[image_name]['volumes'] = {vol[0]:
                                                                                {'bind': vol[1],
                                                                                'mode': vol[2]}}
                                        elif option.startswith('--device='):
                                            dev = option.split("=", 1)[1]
                                            if 'devices' in configs[image_name]:
                                                configs[image_name]['devices'].append(dev +
                                                                                ":" +
                                                                                dev +
                                                                                ":rwm")
                                            else:
                                                configs[image_name]['devices'] = [dev + ":" + dev + ":rwm"]
                                        else:
                                            # unable to parse option provided by
                                            # nvidia-docker-plugin
                                            pass
                            except Exception as e:  # pragma: no cover
                                failed_images.add(image_name)
                                status = (False, str(e))
                except Exception as e:   # pragma: no cover
                    failed_images.add(image_name)
                    status = (False, str(e))

        # TODO add connections to syslog, labels, and file path etc.
        # TODO get syslog address rather than hardcode
        # TODO get group and name for tag
        # TODO add rw volume for plugin output to be plugin input
        log_config = {'type': 'syslog',
                      'config': {'syslog-address': 'tcp://0.0.0.0:514',
                                 'syslog-facility': 'daemon',
                                 'tag': path.rsplit('.', 1)[-1]}}
        dir_path = path.rsplit('/', 1)[0]
        volumes = {dir_path: {'bind': dir_path, 'mode': 'rw'}}

        # setup gpu queue
        can_queue_gpu = True
        try:
            q = Queue(connection=Redis(host='redis'), default_timeout=86400)
        except Exception as e:  # pragma: no cover
            can_queue_gpu = False

        # start containers
        for image in images:
            if image not in failed_images:
                # TODO check for availability of gpu(s),
                #      otherwise queue it up until it's
                #      available
                if 'volumes' in configs[image]:
                    for volume in volumes:
                        configs[image]['volumes'][volume] = volumes[volume]
                else:
                    configs[image]['volumes'] = volumes
                if ('labels' in configs[image] and
                   'vent.gpu' in configs[image]['labels'] and
                   configs[image]['labels']['vent.gpu'] == 'yes'):
                    if can_queue_gpu:
                        # queue up containers requiring a gpu
                        q_str = json.dumps({'image': image,
                                            'command': path,
                                            'labels': labels,
                                            'detach': True,
                                            'log_config': log_config,
                                            'configs': configs[image]})
                        q.enqueue('watch.gpu_queue', q_str, ttl=2592000)
                    else:
                        failed_images.add(image)
                else:
                    d_client.containers.run(image=image,
                                            command=path,
                                            labels=labels,
                                            detach=True,
                                            log_config=log_config,
                                            **configs[image])
        if failed_images:
            status = (False, failed_images)
        else:
            status = (True, images)
    except Exception as e:  # pragma: no cover
        status = (False, str(e))

    print(str(status))
    return status
<|endoftext|>


<commit_before>import numpy as np
import matplotlib.pyplot as plt

from qcodes.instrument.base import Instrument
from qcodes.instrument.parameter import ManualParameter
from qcodes.utils import validators as vals
from qcodes.instrument_drivers.tektronix.AWG5014 import Tektronix_AWG5014

class VirtualAWG5014(Tektronix_AWG5014):
    def __init__(self, name, timeout=5, address=''):
        Instrument.__init__(self, name)
        self._address = address
        self._terminator = ''
        self.add_parameter(
            'timeout',
            unit='s',
            initial_value=5,
            parameter_class=ManualParameter,
            vals=vals.MultiType(vals.Numbers(min_value=0), vals.Enum(None)))
        self.add_parameter(
            'address',
            unit='',
            initial_value='',
            parameter_class=ManualParameter,
            vals=vals.Strings())
        self.add_parameter(
            'DC_output',
            label='DC Output (ON/OFF)',
            parameter_class=ManualParameter,
            vals=vals.Ints(0, 1))

        for i in range(1, 5):
            self.add_parameter(
                'ch{}_state'.format(i),
                initial_value=1,
                label='Status channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Ints(0, 1))
            self.add_parameter(
                'ch{}_amp'.format(i),
                initial_value=1.,
                label='Amplitude channel {}'.format(i),
                unit='Vpp',
                parameter_class=ManualParameter,
                vals=vals.Numbers(0.02, 4.5))
            self.add_parameter(
                'ch{}_offset'.format(i),
                initial_value=0,
                label='Offset channel {}'.format(i),
                unit='V',
                parameter_class=ManualParameter,
                vals=vals.Numbers(-.1, .1))
            self.add_parameter(
                'ch{}_waveform'.format(i),
                initial_value="",
                label='Waveform channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Strings())
            self.add_parameter(
                'ch{}_direct_output'.format(i),
                initial_value=1,
                label='Direct output channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Ints(0, 1))
            self.add_parameter(
                'ch{}_filter'.format(i),
                initial_value='INF',
                label='Low pass filter channel {}'.format(i),
                unit='Hz',
                parameter_class=ManualParameter,
                vals=vals.Enum(20e6, 100e6, 9.9e37, 'INF', 'INFinity'))
            self.add_parameter(
                'ch{}_DC_out'.format(i),
                initial_value=0,
                label='DC output level channel {}'.format(i),
                unit='V',
                parameter_class=ManualParameter,
                vals=vals.Numbers(-3, 5))

            for j in range(1, 3):
                self.add_parameter(
                    'ch{}_m{}_del'.format(i, j),
                    initial_value=0,
                    label='Channel {} Marker {} delay'.format(i, j),
                    unit='ns',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(0, 1))
                self.add_parameter(
                    'ch{}_m{}_high'.format(i, j),
                    initial_value=2,
                    label='Channel {} Marker {} high level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))
                self.add_parameter(
                    'ch{}_m{}_low'.format(i, j),
                    initial_value=0,
                    label='Channel {} Marker {} low level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))

        self.add_parameter(
            'clock_freq',
            label='Clock frequency',
            unit='Hz',
            vals=vals.Numbers(1e6, 1.2e9),
            parameter_class=ManualParameter,
            initial_value=1.2e9)

        self.awg_files = {}
        self.file = None

    def stop(self):
        pass

    def pack_waveform(self, wf, m1, m2):
        # Input validation
        if not ((len(wf) == len(m1)) and ((len(m1) == len(m2)))):
            raise Exception('error: sizes of the waveforms do not match')
        if min(wf) < -1 or max(wf) > 1:
            raise TypeError('Waveform values out of bonds.' +
                            ' Allowed values: -1 to 1 (inclusive)')
        if (list(m1).count(0) + list(m1).count(1)) != len(m1):
            raise TypeError('Marker 1 contains invalid values.' +
                            ' Only 0 and 1 are allowed')
        if (list(m2).count(0) + list(m2).count(1)) != len(m2):
            raise TypeError('Marker 2 contains invalid values.' +
                            ' Only 0 and 1 are allowed')

        wflen = len(wf)
        packed_wf = np.zeros(wflen, dtype=np.uint16)
        packed_wf += np.uint16(
            np.round(wf * 8191) + 8191 + np.round(16384 * m1) +
            np.round(32768 * m2))
        if len(np.where(packed_wf == -1)[0]) > 0:
            print(np.where(packed_wf == -1))
        return packed_wf

    def generate_awg_file(self,
                          packed_waveforms,
                          wfname_l,
                          nrep_l,
                          wait_l,
                          goto_l,
                          logic_jump_l,
                          channel_cfg,
                          sequence_cfg=None,
                          preservechannelsettings=False):
        return {
            'p_wfs': packed_waveforms,
            'names': wfname_l,
            'nreps': nrep_l,
            'waits': wait_l,
            'gotos': goto_l,
            'jumps': logic_jump_l,
            'chans': channel_cfg
        }

    def send_awg_file(self, filename, awg_file):
        self.awg_files[filename] = awg_file

    def load_awg_file(self, filename):
        self.file = self.awg_files[filename]

    def __str__(self):
        if self.file is None:
            return "{}: no file loaded".format(self.name)
        else:
            return """{}:
    wf_names: {}
              {}
              {}
              {}""".format(self.name, self.file['names'][0],
                           self.file['names'][1], self.file['names'][2],
                           self.file['names'][3])

    def is_awg_ready(self):
        return True

    def plot_waveforms(self,
                       seg=0,
                       cids='all',
                       xlim='All',
                       ylim='All',
                       costum_ylabels=None):
        if cids == 'all':
            cids = []
            for i in range(1, 5):
                cids.append('ch{}'.format(i))
                cids.append('ch{}_m1'.format(i))
                cids.append('ch{}_m2'.format(i))

        #fig, axs = plt.subplots(len(cids), 1, sharex=True)
        fig, axs = plt.subplots(len(cids), 1, sharex=False)
        # fig, axs = plt.subplots(len(cids), 1, sharex=False)

        i = 0
        for cid in cids:
            try:
                el_name = self.file['names'][int(cid[2]) - 1][seg]
            except IndexError:
                continue
            pwfs = self.file['p_wfs'][el_name]

            ax = axs[i]

            i += 1

            if cid[4:] == 'm1':
                ydata = np.float_((pwfs // 16384) % 2)
            elif cid[4:] == 'm2':
                ydata = np.float_((pwfs // 32768) % 2)
            else:
                ydata = (np.float_(np.bitwise_and(pwfs, 16383)) - 8191) / 8191
            xdata = np.arange(len(ydata)) / self.clock_freq()

            ax.plot(xdata / 1e-9, ydata)
            if costum_ylabels is None:
                ax.set_ylabel(cid, rotation=0)
            else:
                ax.set_ylabel(costum_ylabels[cid], rotation=0)
            # ax.set_ylabel(cid,rotation=0,fontsize=8)
            # ax.set_yticklabels(ax.get_yticks(),fontsize=5)
            ax.yaxis.set_label_coords(-.15, 0.5)
            # if costum_ylabels is None:
            #     ax.set_ylabel(cid,rotation=0)
            # else:
            #     ax.set_ylabel(costum_ylabels[cid],rotation=0)
            # # ax.set_ylabel(cid,rotation=0,fontsize=8)
            # # ax.set_yticklabels(ax.get_yticks(),fontsize=5)
            # ax.yaxis.set_label_coords(-.15, 0.5)
            if xlim != 'All':
                ax.set_xlim(xlim)
            if ylim != 'All':
                ax.set_ylim(ylim)
            if i == len(cids):
                ax.set_xlabel('Time (ns)')

        return fig
<commit_msg>VirtualAWG5014: added methods start and get_state<commit_after>import numpy as np
import matplotlib.pyplot as plt

from qcodes.instrument.base import Instrument
from qcodes.instrument.parameter import ManualParameter
from qcodes.utils import validators as vals
from qcodes.instrument_drivers.tektronix.AWG5014 import Tektronix_AWG5014

class VirtualAWG5014(Tektronix_AWG5014):
    def __init__(self, name, timeout=5, address=''):
        Instrument.__init__(self, name)
        self._address = address
        self._terminator = ''
        self.add_parameter(
            'timeout',
            unit='s',
            initial_value=5,
            parameter_class=ManualParameter,
            vals=vals.MultiType(vals.Numbers(min_value=0), vals.Enum(None)))
        self.add_parameter(
            'address',
            unit='',
            initial_value='',
            parameter_class=ManualParameter,
            vals=vals.Strings())
        self.add_parameter(
            'DC_output',
            label='DC Output (ON/OFF)',
            parameter_class=ManualParameter,
            vals=vals.Ints(0, 1))

        for i in range(1, 5):
            self.add_parameter(
                'ch{}_state'.format(i),
                initial_value=1,
                label='Status channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Ints(0, 1))
            self.add_parameter(
                'ch{}_amp'.format(i),
                initial_value=1.,
                label='Amplitude channel {}'.format(i),
                unit='Vpp',
                parameter_class=ManualParameter,
                vals=vals.Numbers(0.02, 4.5))
            self.add_parameter(
                'ch{}_offset'.format(i),
                initial_value=0,
                label='Offset channel {}'.format(i),
                unit='V',
                parameter_class=ManualParameter,
                vals=vals.Numbers(-.1, .1))
            self.add_parameter(
                'ch{}_waveform'.format(i),
                initial_value="",
                label='Waveform channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Strings())
            self.add_parameter(
                'ch{}_direct_output'.format(i),
                initial_value=1,
                label='Direct output channel {}'.format(i),
                parameter_class=ManualParameter,
                vals=vals.Ints(0, 1))
            self.add_parameter(
                'ch{}_filter'.format(i),
                initial_value='INF',
                label='Low pass filter channel {}'.format(i),
                unit='Hz',
                parameter_class=ManualParameter,
                vals=vals.Enum(20e6, 100e6, 9.9e37, 'INF', 'INFinity'))
            self.add_parameter(
                'ch{}_DC_out'.format(i),
                initial_value=0,
                label='DC output level channel {}'.format(i),
                unit='V',
                parameter_class=ManualParameter,
                vals=vals.Numbers(-3, 5))

            for j in range(1, 3):
                self.add_parameter(
                    'ch{}_m{}_del'.format(i, j),
                    initial_value=0,
                    label='Channel {} Marker {} delay'.format(i, j),
                    unit='ns',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(0, 1))
                self.add_parameter(
                    'ch{}_m{}_high'.format(i, j),
                    initial_value=2,
                    label='Channel {} Marker {} high level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))
                self.add_parameter(
                    'ch{}_m{}_low'.format(i, j),
                    initial_value=0,
                    label='Channel {} Marker {} low level'.format(i, j),
                    unit='V',
                    parameter_class=ManualParameter,
                    vals=vals.Numbers(-2.7, 2.7))

        self.add_parameter(
            'clock_freq',
            label='Clock frequency',
            unit='Hz',
            vals=vals.Numbers(1e6, 1.2e9),
            parameter_class=ManualParameter,
            initial_value=1.2e9)

        self.awg_files = {}
        self.file = None
        self.stop()  # to init self._state

    def stop(self):
        self._state = 'Idle'

    def start(self):
        self._state = 'Waiting for trigger'

    def get_state(self):
        return self._state

    def pack_waveform(self, wf, m1, m2):
        # Input validation
        if not ((len(wf) == len(m1)) and ((len(m1) == len(m2)))):
            raise Exception('error: sizes of the waveforms do not match')
        if min(wf) < -1 or max(wf) > 1:
            raise TypeError('Waveform values out of bonds.' +
                            ' Allowed values: -1 to 1 (inclusive)')
        if (list(m1).count(0) + list(m1).count(1)) != len(m1):
            raise TypeError('Marker 1 contains invalid values.' +
                            ' Only 0 and 1 are allowed')
        if (list(m2).count(0) + list(m2).count(1)) != len(m2):
            raise TypeError('Marker 2 contains invalid values.' +
                            ' Only 0 and 1 are allowed')

        wflen = len(wf)
        packed_wf = np.zeros(wflen, dtype=np.uint16)
        packed_wf += np.uint16(
            np.round(wf * 8191) + 8191 + np.round(16384 * m1) +
            np.round(32768 * m2))
        if len(np.where(packed_wf == -1)[0]) > 0:
            print(np.where(packed_wf == -1))
        return packed_wf

    def generate_awg_file(self,
                          packed_waveforms,
                          wfname_l,
                          nrep_l,
                          wait_l,
                          goto_l,
                          logic_jump_l,
                          channel_cfg,
                          sequence_cfg=None,
                          preservechannelsettings=False):
        return {
            'p_wfs': packed_waveforms,
            'names': wfname_l,
            'nreps': nrep_l,
            'waits': wait_l,
            'gotos': goto_l,
            'jumps': logic_jump_l,
            'chans': channel_cfg
        }

    def send_awg_file(self, filename, awg_file):
        self.awg_files[filename] = awg_file

    def load_awg_file(self, filename):
        self.file = self.awg_files[filename]

    def __str__(self):
        if self.file is None:
            return "{}: no file loaded".format(self.name)
        else:
            return """{}:
    wf_names: {}
              {}
              {}
              {}""".format(self.name, self.file['names'][0],
                           self.file['names'][1], self.file['names'][2],
                           self.file['names'][3])

    def is_awg_ready(self):
        return True

    def plot_waveforms(self,
                       seg=0,
                       cids='all',
                       xlim='All',
                       ylim='All',
                       costum_ylabels=None):
        if cids == 'all':
            cids = []
            for i in range(1, 5):
                cids.append('ch{}'.format(i))
                cids.append('ch{}_m1'.format(i))
                cids.append('ch{}_m2'.format(i))

        #fig, axs = plt.subplots(len(cids), 1, sharex=True)
        fig, axs = plt.subplots(len(cids), 1, sharex=False)
        # fig, axs = plt.subplots(len(cids), 1, sharex=False)

        i = 0
        for cid in cids:
            try:
                el_name = self.file['names'][int(cid[2]) - 1][seg]
            except IndexError:
                continue
            pwfs = self.file['p_wfs'][el_name]

            ax = axs[i]

            i += 1

            if cid[4:] == 'm1':
                ydata = np.float_((pwfs // 16384) % 2)
            elif cid[4:] == 'm2':
                ydata = np.float_((pwfs // 32768) % 2)
            else:
                ydata = (np.float_(np.bitwise_and(pwfs, 16383)) - 8191) / 8191
            xdata = np.arange(len(ydata)) / self.clock_freq()

            ax.plot(xdata / 1e-9, ydata)
            if costum_ylabels is None:
                ax.set_ylabel(cid, rotation=0)
            else:
                ax.set_ylabel(costum_ylabels[cid], rotation=0)
            # ax.set_ylabel(cid,rotation=0,fontsize=8)
            # ax.set_yticklabels(ax.get_yticks(),fontsize=5)
            ax.yaxis.set_label_coords(-.15, 0.5)
            # if costum_ylabels is None:
            #     ax.set_ylabel(cid,rotation=0)
            # else:
            #     ax.set_ylabel(costum_ylabels[cid],rotation=0)
            # # ax.set_ylabel(cid,rotation=0,fontsize=8)
            # # ax.set_yticklabels(ax.get_yticks(),fontsize=5)
            # ax.yaxis.set_label_coords(-.15, 0.5)
            if xlim != 'All':
                ax.set_xlim(xlim)
            if ylim != 'All':
                ax.set_ylim(ylim)
            if i == len(cids):
                ax.set_xlabel('Time (ns)')

        return fig
<|endoftext|>


<commit_before>from .device import Device
from .. import config as c

class DigitalOutput(Device):

    DEVICE_CODE =   c.devices.digital_output.code
    WRITE_CODE =    c.devices.digital_output.write_code

    def __init__(self, tamproxy, pin):
        self.pin = pin
        super(DigitalOutput, self).__init__(tamproxy)

    def __repr__(self):
        return super(DigitalOutput, self).__repr__(pin)

    @property
    def add_payload(self):
        return self.DEVICE_CODE + chr(self.pin)

    def write(self, value):
        self.tamp.send_request(self.id, self.WRITE_CODE + chr(value))
<commit_msg>fix self.pin in digital_output<commit_after>from .device import Device
from .. import config as c

class DigitalOutput(Device):

    DEVICE_CODE =   c.devices.digital_output.code
    WRITE_CODE =    c.devices.digital_output.write_code

    def __init__(self, tamproxy, pin):
        self.pin = pin
        super(DigitalOutput, self).__init__(tamproxy)

    def __repr__(self):
        return super(DigitalOutput, self).__repr__(self.pin)

    @property
    def add_payload(self):
        return self.DEVICE_CODE + chr(self.pin)

    def write(self, value):
        self.tamp.send_request(self.id, self.WRITE_CODE + chr(value))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""Test Module for sphinx_rtd_theme."""

class Foo:

    r"""Docstring for class Foo.

    This text tests for the formatting of docstrings generated from output
    ``sphinx.ext.autodoc``. Which contain reST, but sphinx nests it in the
    ``<dl>``, and ``<dt>`` tags. Also, ``<tt>`` is used for class, method names
    and etc, but those will *always* have the ``.descname`` or
    ``.descclassname`` class.

    Normal ``<tt>`` (like the <tt> I just wrote here) needs to be shown with
    the same style as anything else with ````this type of markup````.

    It's common for programmers to give a code example inside of their
    docstring::

        from test_py_module import Foo

        myclass = Foo()
        myclass.dothismethod('with this argument')
        myclass.flush()

        print(myclass)

    Here is a link to :py:meth:`capitalize`.
    Here is a link to :py:meth:`__init__`.

    """

    #: Doc comment for class attribute Foo.bar.
    #: It can have multiple lines.
    bar = 1

    flox = 1.5   #: Doc comment for Foo.flox. One line only.

    baz = 2
    """Docstring for class attribute Foo.baz."""

    def __init__(self, qux, spam=False):
        """Start the Foo.

        :param qux: The first argument to initialize class.
        :type qux: string
        :param spam: Spam me yes or no...
        :type spam: bool

        """
        #: Doc comment for instance attribute qux.
        self.qux = 3

        self.spam = 4
        """Docstring for instance attribute spam."""

    def add(self, val1, val2):
        """Return the added values.

        :param val1: First number to add.
        :type val1: int
        :param val2: Second number to add.
        :type val2: int
        :rtype: int

        """

        return val1 + val2

    def capitalize(self, myvalue):
        """Return a string as uppercase.

        :param myvalue: String to change
        :type myvalue: string
        :rtype: string

        """

        return myvalue.upper()

    def another_function(self, a, b, **kwargs):
        """
        Here is another function.

        :param a: The number of green hats you own.
        :type a: int

        :param b: The number of non-green hats you own.
        :type b: int

        :param kwargs: Additional keyword arguments. Each keyword parameter
                       should specify the name of your favorite cuisine.
                       The values should be floats, specifying the mean price
                       of your favorite dish in that cooking style.
        :type kwargs: float

        :returns: A 2-tuple.  The first element is the mean price of all dishes
                  across cuisines.  The second element is the total number of
                  hats you own: :math:`a + b`.
        :rtype: tuple

        :raises ValueError: When ``a`` is not an integer.

        """
        return sum(kwargs.values()) / len(kwargs), a + b
<commit_msg>[TASK] Update py module<commit_after># -*- coding: utf-8 -*-
"""Test Module for sphinx_rtd_theme."""

class Foo:

    """Docstring for class Foo.
    This text tests for the formatting of docstrings generated from output
    ``sphinx.ext.autodoc``. Which contain reST, but sphinx nests it in the
    ``<dl>``, and ``<dt>`` tags. Also, ``<tt>`` is used for class, method names
    and etc, but those will *always* have the ``.descname`` or
    ``.descclassname`` class.
    Normal ``<tt>`` (like the <tt> I just wrote here) needs to be shown with
    the same style as anything else with ````this type of markup````.
    It's common for programmers to give a code example inside of their
    docstring::
        from test_py_module import Foo
        myclass = Foo()
        myclass.dothismethod('with this argument')
        myclass.flush()
        print(myclass)
    Here is a link to :py:meth:`capitalize`.
    Here is a link to :py:meth:`__init__`.
    """

    #: Doc comment for class attribute Foo.bar.
    #: It can have multiple lines.
    bar = 1

    flox = 1.5   #: Doc comment for Foo.flox. One line only.

    baz = 2
    """Docstring for class attribute Foo.baz."""

    def __init__(self, qux, spam=False):
        """Start the Foo.
        :param qux: The first argument to initialize class.
        :type qux: string
        :param spam: Spam me yes or no...
        :type spam: bool
        """
        #: Doc comment for instance attribute qux.
        self.qux = 3

        self.spam = 4
        """Docstring for instance attribute spam."""

    def add(self, val1, val2):
        """Return the added values.
        :param val1: First number to add.
        :type val1: int
        :param val2: Second number to add.
        :type val2: int
        :rtype: int
        """

        return val1 + val2

    def capitalize(self, myvalue):
        """Return a string as uppercase.
        :param myvalue: String to change
        :type myvalue: string
        :rtype: string
        """

        return myvalue.upper()

    def another_function(self, a, b, **kwargs):
        """
        Here is another function.
        :param a: The number of green hats you own.
        :type a: int
        :param b: The number of non-green hats you own.
        :type b: int
        :param kwargs: Additional keyword arguments. Each keyword parameter
                       should specify the name of your favorite cuisine.
                       The values should be floats, specifying the mean price
                       of your favorite dish in that cooking style.
        :type kwargs: float
        :returns: A 2-tuple.  The first element is the mean price of all dishes
                  across cuisines.  The second element is the total number of
                  hats you own: :math:`a + b`.
        :rtype: tuple
        :raises ValueError: When ``a`` is not an integer.
        .. versionadded:: 1.0
            This was added in 1.0
        .. versionchanged:: 2.0
            This was changed in 2.0
        .. deprecated:: 3.0
            This is deprecated since 3.0
        """
        return sum(kwargs.values()) / len(kwargs), a + b
<|endoftext|>