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

"""Functions for tokenizing data, the below can be updated to account for new lines without spaces, or contiguous
non-English languages"""

import shlex
from nltk.tokenize import sent_tokenize

__author__ = "Peter J Usherwood"
__python_version__ = "3.6"

def tokenizer_word(text_string, keep_phrases=False):
    """
    Tokenizer that tokenizes a string of text on spaces and new lines (regardless of however many of each.)

    :param text_string: Python string object to be tokenized.
    :param keep_phrases: Booalean will not split "quoted" text
    :return: Array of strings, each is a word
    """

    text_string = str(text_string)

    if keep_phrases:
        tokens = shlex.split(text_string.replace('\n', ' ').replace('/', ' '))
    else:
        tokens = text_string.replace('\n', ' ').replace('/', ' ').split()

    return tokens

def tokenizer_sentence(text_string):
    """
    Tokenizer that tokenizes a string of text into sentences

    :param text_string: Python string object to be tokenized.
    :return: Array of strings, each is a sentence
    """

    sent_tokenize_list = sent_tokenize(text_string)

    return sent_tokenize_list

def tokenizer_pos(pos_tuplets):
    """
    Tokenizer that tokenizes a list of part of speech tuplets into array of tokens for each word, and an array for each
    tag

    :param pos_tuplets: List of pos tuplets

    :return: tokens, list of word tokens; tokens_tags, list of pos tags
    """

    if type(pos_tuplets) != type(['list']):
        raise TypeError('Input should be a list of POS tuples')
    if set([type(b) for b in pos_tuplets]) != set([type(('Tuple', 'E'))]) and pos_tuplets != []:
        print(pos_tuplets)
        raise TypeError('Input should be a list of POS tuples')

    tokens = []
    tokens_tags = []
    for tup in pos_tuplets:
        tokens.append(tup[0])
        tokens_tags.append(tup[1])

    return tokens, tokens_tags

def de_tokenizer_pos(tokens, tokens_tags):
    """
    Rezips the 2 tokenized lists of the tokenizer_pos into a list of pos tuples

    :param tokens: List of str, word tokens
    :param tokens_tags: List of str, pos tags

    :return: pos_tuplets, List of pos tuplets
    """

    if type(tokens) != type(['list']):
        raise TypeError('tokens should be a list')
    if set([type(b) for b in tokens]) != set([type('String')]):
        raise TypeError('tokens should be a list of strings')
    if type(tokens_tags) != type(['list']):
        raise TypeError('tokens_tags should be a list')
    if set([type(b) for b in tokens_tags]) != set([type('String')]):
        raise TypeError('tokens_tags should be a list of strings')

    pos_tuplets = [(x, y) for x, y in zip(tokens, tokens_tags) if x is not None]

    return pos_tuplets
<commit_msg>updated tokenizer for language model<commit_after>#!/usr/bin/env python

"""Functions for tokenizing data, the below can be updated to account for new lines without spaces, or contiguous
non-English languages"""

import shlex
import re
from nltk.tokenize import sent_tokenize

__author__ = "Peter J Usherwood"
__python_version__ = "3.6"

def tokenizer_word(text_string, keep_phrases=False, tokenize_punc=False):
    """
    Tokenizer that tokenizes a string of text on spaces and new lines (regardless of however many of each.)

    :param text_string: Python string object to be tokenized.
    :param keep_phrases: Booalean will not split "quoted" text
    ?param tokenize_punc: Boolean, if true will tokenize punctuation so "hello," becomes ["hello", ","]

    :return: Array of strings, each is a word
    """

    text_string = str(text_string)

    if keep_phrases:
        tokens = shlex.split(text_string.replace('\n', ' ').replace('/', ' '))
    elif tokenize_punc:
        tokens = re.findall(r"[\w']+|[.,!?;]", text_string)
    else:
        tokens = text_string.replace('\n', ' ').replace('/', ' ').split()

    return tokens

def tokenizer_sentence(text_string):
    """
    Tokenizer that tokenizes a string of text into sentences

    :param text_string: Python string object to be tokenized.
    :return: Array of strings, each is a sentence
    """

    sent_tokenize_list = sent_tokenize(text_string)

    return sent_tokenize_list

def tokenizer_pos(pos_tuplets):
    """
    Tokenizer that tokenizes a list of part of speech tuplets into array of tokens for each word, and an array for each
    tag

    :param pos_tuplets: List of pos tuplets

    :return: tokens, list of word tokens; tokens_tags, list of pos tags
    """

    if type(pos_tuplets) != type(['list']):
        raise TypeError('Input should be a list of POS tuples')
    if set([type(b) for b in pos_tuplets]) != set([type(('Tuple', 'E'))]) and pos_tuplets != []:
        print(pos_tuplets)
        raise TypeError('Input should be a list of POS tuples')

    tokens = []
    tokens_tags = []
    for tup in pos_tuplets:
        tokens.append(tup[0])
        tokens_tags.append(tup[1])

    return tokens, tokens_tags

def de_tokenizer_pos(tokens, tokens_tags):
    """
    Rezips the 2 tokenized lists of the tokenizer_pos into a list of pos tuples

    :param tokens: List of str, word tokens
    :param tokens_tags: List of str, pos tags

    :return: pos_tuplets, List of pos tuplets
    """

    if type(tokens) != type(['list']):
        raise TypeError('tokens should be a list')
    if set([type(b) for b in tokens]) != set([type('String')]):
        raise TypeError('tokens should be a list of strings')
    if type(tokens_tags) != type(['list']):
        raise TypeError('tokens_tags should be a list')
    if set([type(b) for b in tokens_tags]) != set([type('String')]):
        raise TypeError('tokens_tags should be a list of strings')

    pos_tuplets = [(x, y) for x, y in zip(tokens, tokens_tags) if x is not None]

    return pos_tuplets
<|endoftext|>


<commit_before> #########
# Copyright (c) 2013 GigaSpaces Technologies Ltd. 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.

__author__ = 'ran'

import os
import json
from models import BlueprintState, Deployment, Execution, \
    DeploymentNode

STORAGE_FILE_PATH = '/tmp/manager-rest-tests-storage.json'

NODES = 'nodes'
BLUEPRINTS = 'blueprints'
DEPLOYMENTS = 'deployments'
EXECUTIONS = 'executions'

class FileStorageManager(object):
    """
    file based storage manager for tests.
    """

    def __init__(self, storage_path):
        self._storage_path = storage_path
        if os.path.isfile(storage_path):
            os.remove(storage_path)

    def _init_file(self):
        data = {
            NODES: {},
            BLUEPRINTS: {},
            DEPLOYMENTS: {},
            EXECUTIONS: {}
        }
        self._dump_data(data)

    def _load_data(self):
        if not os.path.isfile(self._storage_path):
            self._init_file()
        with open(self._storage_path, 'r') as f:
            data = json.load(f)
            deserialized_data = dict()
            deserialized_data[NODES] = \
                {key: DeploymentNode(**val) for key, val in data[NODES]
                    .iteritems()}
            deserialized_data[BLUEPRINTS] = \
                {key: BlueprintState(**val) for key, val in data[BLUEPRINTS]
                    .iteritems()}
            deserialized_data[DEPLOYMENTS] = \
                {key: Deployment(**val) for key, val in data[DEPLOYMENTS]
                    .iteritems()}
            deserialized_data[EXECUTIONS] = \
                {key: Execution(**val) for key, val in data[EXECUTIONS]
                    .iteritems()}
            return deserialized_data

    def _dump_data(self, data):
        with open(self._storage_path, 'w') as f:
            serialized_data = dict()
            serialized_data[NODES] = {key: val.to_dict() for key, val in
                                      data[NODES].iteritems()}
            serialized_data[BLUEPRINTS] =\
                {key: val.to_dict() for key, val in data[BLUEPRINTS]
                    .iteritems()}
            serialized_data[DEPLOYMENTS] =\
                {key: val.to_dict() for key, val in data[DEPLOYMENTS]
                    .iteritems()}
            serialized_data[EXECUTIONS] =\
                {key: val.to_dict() for key, val in data[EXECUTIONS]
                    .iteritems()}
            json.dump(serialized_data, f)

    def nodes_list(self):
        data = self._load_data()
        return data[NODES].values()

    def get_node(self, node_id):
        data = self._load_data()
        if node_id in data[NODES]:
            return data[NODES][node_id]
        return None

    def put_node(self, node_id, node):
        data = self._load_data()
        if str(node_id) in data[NODES]:
            raise RuntimeError('Node {0} already exists'.format(
                node_id))
        data[NODES][str(node_id)] = node
        self._dump_data(data)

    def update_node(self, node_id, node):
        data = self._load_data()
        if node_id not in data[NODES]:
            self.put_node(node_id, node)
            return

        prev_rt_info = DeploymentNode(**data[NODES][node_id].to_dict())\
            .runtime_info
        merged_rt_info = dict(prev_rt_info.items() +
                              node.runtime_info.items())
        #TODO: merge reachable field?
        node = DeploymentNode(id=node_id, runtime_info=merged_rt_info)
        data[NODES][node_id] = node
        self._dump_data(data)
        return merged_rt_info

    def blueprints_list(self):
        data = self._load_data()
        return data[BLUEPRINTS].values()

    def deployments_list(self):
        data = self._load_data()
        return data[DEPLOYMENTS].values()

    def executions_list(self):
        data = self._load_data()
        return data[EXECUTIONS].values()

    def get_deployment_executions(self, deployment_id):
        executions = self.executions_list()
        return [execution for execution in executions if execution
                .deployment_id == deployment_id]

    def get_blueprint(self, blueprint_id):
        data = self._load_data()
        return data[BLUEPRINTS].get(blueprint_id, None)

    def get_deployment(self, deployment_id):
        data = self._load_data()
        return data[DEPLOYMENTS].get(deployment_id, None)

    def get_execution(self, execution_id):
        data = self._load_data()
        return data[EXECUTIONS].get(execution_id, None)

    def put_blueprint(self, blueprint_id, blueprint):
        data = self._load_data()
        if str(blueprint_id) in data[BLUEPRINTS]:
            raise RuntimeError('Blueprint {0} already exists'.format(
                blueprint_id))
        data[BLUEPRINTS][str(blueprint_id)] = blueprint
        self._dump_data(data)

    def put_deployment(self, deployment_id, deployment):
        data = self._load_data()
        if str(deployment_id) in data[DEPLOYMENTS]:
            raise RuntimeError('Deployment {0} already exists'.format(
                deployment_id))
        data[DEPLOYMENTS][str(deployment_id)] = deployment
        self._dump_data(data)

    def put_execution(self, execution_id, execution):
        data = self._load_data()
        if str(execution_id) in data[EXECUTIONS]:
            raise RuntimeError('Execution {0} already exists'.format(
                execution_id))
        data[EXECUTIONS][str(execution_id)] = execution
        self._dump_data(data)

def create():
    return FileStorageManager(STORAGE_FILE_PATH)
<commit_msg>cleanup<commit_after> #########
# Copyright (c) 2013 GigaSpaces Technologies Ltd. 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.

__author__ = 'ran'

import os
import json
from models import BlueprintState, Deployment, Execution, \
    DeploymentNode

STORAGE_FILE_PATH = '/tmp/manager-rest-tests-storage.json'

NODES = 'nodes'
BLUEPRINTS = 'blueprints'
DEPLOYMENTS = 'deployments'
EXECUTIONS = 'executions'

class FileStorageManager(object):
    """
    file based storage manager for tests.
    """

    def __init__(self, storage_path):
        self._storage_path = storage_path
        if os.path.isfile(storage_path):
            os.remove(storage_path)
            # print "deleting storage path!"

    def _init_file(self):
        data = {
            NODES: {},
            BLUEPRINTS: {},
            DEPLOYMENTS: {},
            EXECUTIONS: {}
        }
        self._dump_data(data)

    def _load_data(self):
        if not os.path.isfile(self._storage_path):
            self._init_file()
        with open(self._storage_path, 'r') as f:
            data = json.load(f)
            deserialized_data = dict()
            deserialized_data[NODES] = \
                {key: DeploymentNode(**val) for key, val in data[NODES]
                    .iteritems()}
            deserialized_data[BLUEPRINTS] = \
                {key: BlueprintState(**val) for key, val in data[BLUEPRINTS]
                    .iteritems()}
            deserialized_data[DEPLOYMENTS] = \
                {key: Deployment(**val) for key, val in data[DEPLOYMENTS]
                    .iteritems()}
            deserialized_data[EXECUTIONS] = \
                {key: Execution(**val) for key, val in data[EXECUTIONS]
                    .iteritems()}
            return deserialized_data

    def _dump_data(self, data):
        with open(self._storage_path, 'w') as f:
            serialized_data = dict()
            serialized_data[NODES] = {key: val.to_dict() for key, val in
                                      data[NODES].iteritems()}
            serialized_data[BLUEPRINTS] =\
                {key: val.to_dict() for key, val in data[BLUEPRINTS]
                    .iteritems()}
            serialized_data[DEPLOYMENTS] =\
                {key: val.to_dict() for key, val in data[DEPLOYMENTS]
                    .iteritems()}
            serialized_data[EXECUTIONS] =\
                {key: val.to_dict() for key, val in data[EXECUTIONS]
                    .iteritems()}
            json.dump(serialized_data, f)

    def nodes_list(self):
        data = self._load_data()
        return data[NODES].values()

    def get_node(self, node_id):
        data = self._load_data()
        if node_id in data[NODES]:
            return data[NODES][node_id]
        return None

    def put_node(self, node_id, node):
        data = self._load_data()
        if str(node_id) in data[NODES]:
            raise RuntimeError('Node {0} already exists'.format(
                node_id))
        data[NODES][str(node_id)] = node
        self._dump_data(data)

    def update_node(self, node_id, node):
        data = self._load_data()
        if node_id not in data[NODES]:
            self.put_node(node_id, node)
            return

        prev_rt_info = DeploymentNode(**data[NODES][node_id].to_dict())\
            .runtime_info
        merged_rt_info = dict(prev_rt_info.items() +
                              node.runtime_info.items())
        #TODO: merge reachable field?
        node = DeploymentNode(id=node_id, runtime_info=merged_rt_info)
        data[NODES][node_id] = node
        self._dump_data(data)
        return merged_rt_info

    def blueprints_list(self):
        data = self._load_data()
        return data[BLUEPRINTS].values()

    def deployments_list(self):
        data = self._load_data()
        return data[DEPLOYMENTS].values()

    def executions_list(self):
        data = self._load_data()
        return data[EXECUTIONS].values()

    def get_deployment_executions(self, deployment_id):
        executions = self.executions_list()
        return [execution for execution in executions if execution
                .deployment_id == deployment_id]

    def get_blueprint(self, blueprint_id):
        data = self._load_data()
        return data[BLUEPRINTS].get(blueprint_id, None)

    def get_deployment(self, deployment_id):
        data = self._load_data()
        return data[DEPLOYMENTS].get(deployment_id, None)

    def get_execution(self, execution_id):
        data = self._load_data()
        return data[EXECUTIONS].get(execution_id, None)

    def put_blueprint(self, blueprint_id, blueprint):
        data = self._load_data()
        if str(blueprint_id) in data[BLUEPRINTS]:
            raise RuntimeError('Blueprint {0} already exists'.format(
                blueprint_id))
        data[BLUEPRINTS][str(blueprint_id)] = blueprint
        self._dump_data(data)

    def put_deployment(self, deployment_id, deployment):
        data = self._load_data()
        if str(deployment_id) in data[DEPLOYMENTS]:
            raise RuntimeError('Deployment {0} already exists'.format(
                deployment_id))
        data[DEPLOYMENTS][str(deployment_id)] = deployment
        self._dump_data(data)

    def put_execution(self, execution_id, execution):
        data = self._load_data()
        if str(execution_id) in data[EXECUTIONS]:
            raise RuntimeError('Execution {0} already exists'.format(
                execution_id))
        data[EXECUTIONS][str(execution_id)] = execution
        self._dump_data(data)

def create():
    return FileStorageManager(STORAGE_FILE_PATH)
<|endoftext|>


<commit_before># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *
import spack
import spack.store

class CbtfKrell(CMakePackage):
    """CBTF Krell project contains the Krell Institute contributions to the
       CBTF project.  These contributions include many performance data
       collectors and support libraries as well as some example tools
       that drive the data collection at HPC levels of scale.
    """
    homepage = "http://sourceforge.net/p/cbtf/wiki/Home/"
    git      = "https://github.com/OpenSpeedShop/cbtf-krell.git"

    version('develop', branch='master')
    version('1.9.3', branch='1.9.3')
    version('1.9.2', branch='1.9.2')
    version('1.9.1.2', branch='1.9.1.2')
    version('1.9.1.1', branch='1.9.1.1')
    version('1.9.1.0', branch='1.9.1.0')

    # MPI variants
    variant('openmpi', default=False,
            description="Build mpi experiment collector for openmpi MPI..")
    variant('mpt', default=False,
            description="Build mpi experiment collector for SGI MPT MPI.")
    variant('mvapich2', default=False,
            description="Build mpi experiment collector for mvapich2 MPI.")
    variant('mvapich', default=False,
            description="Build mpi experiment collector for mvapich MPI.")
    variant('mpich2', default=False,
            description="Build mpi experiment collector for mpich2 MPI.")
    variant('mpich', default=False,
            description="Build mpi experiment collector for mpich MPI.")
    variant('runtime', default=False,
            description="build only the runtime libraries and collectors.")
    variant('build_type', default='None', values=('None'),
            description='CMake build type')
    variant('cti', default=False,
            description="Build MRNet with the CTI startup option")
    variant('crayfe', default=False,
            description="build only the FE tool using the runtime_dir \
                         to point to target build.")

    # Dependencies for cbtf-krell
    depends_on("cmake@3.0.2:", type='build')

    # For binutils
    depends_on("binutils")

    # For boost
    depends_on("boost@1.66.0:1.69.0")

    # For Dyninst
    depends_on("dyninst@develop", when='@develop')
    depends_on("dyninst@10:", when='@1.9.1.0:9999')

    # For MRNet
    depends_on("mrnet@5.0.1-3:+cti", when='@develop+cti', type=('build', 'link', 'run'))
    depends_on("mrnet@5.0.1-3:+lwthreads", when='@develop', type=('build', 'link', 'run'))

    depends_on("mrnet@5.0.1-3+cti", when='@1.9.1.0:9999+cti', type=('build', 'link', 'run'))
    depends_on("mrnet@5.0.1-3+lwthreads", when='@1.9.1.0:9999', type=('build', 'link', 'run'))

    # For Xerces-C
    depends_on("xerces-c")

    # For CBTF
    depends_on("cbtf@develop", when='@develop', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999", when='@1.9.1.0:9999', type=('build', 'link', 'run'))

    # For CBTF with cti
    depends_on("cbtf@develop+cti", when='@develop+cti', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999+cti", when='@1.9.1.0:9999+cti', type=('build', 'link', 'run'))

    # For CBTF with runtime
    depends_on("cbtf@develop+runtime", when='@develop+runtime', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999+runtime", when='@1.9.1.0:9999+runtime', type=('build', 'link', 'run'))

    # for services and collectors
    depends_on("libmonitor@2013.02.18+krellpatch", type=('build', 'link', 'run'))

    depends_on("libunwind", when='@develop')
    depends_on("libunwind@1.2.1", when='@1.9.1.0:9999')

    depends_on("papi@5.4.1:", type=('build', 'link', 'run'))

    depends_on("llvm-openmp-ompt@tr6_forwards+standalone")

    # MPI Installations
    depends_on("openmpi", when='+openmpi')
    depends_on("mpich", when='+mpich')
    depends_on("mpich2", when='+mpich2')
    depends_on("mvapich2", when='+mvapich2')
    depends_on("mvapich", when='+mvapich')
    depends_on("mpt", when='+mpt')

    depends_on("python", when='@develop', type=('build', 'run'))
    depends_on("python@2.7.14:2.7.15", when='@2.3.1.3:9999', type=('build', 'run'))

    depends_on("gotcha")

    patch('arm.patch', when='target=aarch64:')

    parallel = False

    build_directory = 'build_cbtf_krell'

    def set_rt_only_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable the appropriate
        # MPI implementations

        rt_only_options = []
        rt_only_options.append('-DRUNTIME_ONLY=true')
        cmake_options.extend(rt_only_options)

    def set_mpi_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable the appropriate
        # MPI implementations

        mpi_options = []

        # openmpi
        if spec.satisfies('+openmpi'):
            mpi_options.append('-DOPENMPI_DIR=%s' % spec['openmpi'].prefix)
        # mpich
        if spec.satisfies('+mpich'):
            mpi_options.append('-DMPICH_DIR=%s' % spec['mpich'].prefix)
        # mpich2
        if spec.satisfies('+mpich2'):
            mpi_options.append('-DMPICH2_DIR=%s' % spec['mpich2'].prefix)
        # mvapich
        if spec.satisfies('+mvapich'):
            mpi_options.append('-DMVAPICH_DIR=%s' % spec['mvapich'].prefix)
        # mvapich2
        if spec.satisfies('+mvapich2'):
            mpi_options.append('-DMVAPICH2_DIR=%s' % spec['mvapich2'].prefix)
        # mpt
        if spec.satisfies('+mpt'):
            mpi_options.append('-DMPT_DIR=%s' % spec['mpt'].prefix)

        cmake_options.extend(mpi_options)

    def set_cray_login_node_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable
        # the appropriate Cray login node libraries

        cray_login_node_options = []
        rt_platform = "cray"
        # How do we get the compute node (CNL) cbtf package
        # install directory path. spec['cbtf'].prefix is the
        # login node path for this build, as we are building
        # the login node components with this spack invocation. We
        # need these paths to be the ones created in the CNL
        # spack invocation.
        be_cbtf = spack.store.db.query_one('cbtf arch=cray-CNL-haswell')
        be_cbtfk = spack.store.db.query_one('cbtf-krell arch=cray-CNL-haswell')
        be_papi = spack.store.db.query_one('papi arch=cray-CNL-haswell')
        be_boost = spack.store.db.query_one('boost arch=cray-CNL-haswell')
        be_mont = spack.store.db.query_one('libmonitor arch=cray-CNL-haswell')
        be_unw = spack.store.db.query_one('libunwind arch=cray-CNL-haswell')
        be_xer = spack.store.db.query_one('xerces-c arch=cray-CNL-haswell')
        be_dyn = spack.store.db.query_one('dyninst arch=cray-CNL-haswell')
        be_mrnet = spack.store.db.query_one('mrnet arch=cray-CNL-haswell')

        cray_login_node_options.append(
            '-DCN_RUNTIME_PLATFORM=%s' % rt_platform)

        # Use install directories as CMAKE args for the building
        # of login cbtf-krell
        cray_login_node_options.append(
            '-DCBTF_CN_RUNTIME_DIR=%s' % be_cbtf.prefix)
        cray_login_node_options.append(
            '-DCBTF_KRELL_CN_RUNTIME_DIR=%s' % be_cbtfk.prefix)
        cray_login_node_options.append(
            '-DPAPI_CN_RUNTIME_DIR=%s' % be_papi.prefix)
        cray_login_node_options.append(
            '-DBOOST_CN_RUNTIME_DIR=%s' % be_boost.prefix)
        cray_login_node_options.append(
            '-DLIBMONITOR_CN_RUNTIME_DIR=%s' % be_mont.prefix)
        cray_login_node_options.append(
            '-DLIBUNWIND_CN_RUNTIME_DIR=%s' % be_unw.prefix)
        cray_login_node_options.append(
            '-DXERCESC_CN_RUNTIME_DIR=%s' % be_xer.prefix)
        cray_login_node_options.append(
            '-DDYNINST_CN_RUNTIME_DIR=%s' % be_dyn.prefix)
        cray_login_node_options.append(
            '-DMRNET_CN_RUNTIME_DIR=%s' % be_mrnet.prefix)

        cmake_options.extend(cray_login_node_options)

    def cmake_args(self):
        spec = self.spec

        compile_flags = "-O2 -g"

        # Add in paths for finding package config files that tell us
        # where to find these packages
        cmake_args = [
            '-DCMAKE_CXX_FLAGS=%s'         % compile_flags,
            '-DCMAKE_C_FLAGS=%s'           % compile_flags,
            '-DCBTF_DIR=%s' % spec['cbtf'].prefix,
            '-DBINUTILS_DIR=%s' % spec['binutils'].prefix,
            '-DLIBMONITOR_DIR=%s' % spec['libmonitor'].prefix,
            '-DLIBUNWIND_DIR=%s' % spec['libunwind'].prefix,
            '-DPAPI_DIR=%s' % spec['papi'].prefix,
            '-DBOOST_DIR=%s' % spec['boost'].prefix,
            '-DMRNET_DIR=%s' % spec['mrnet'].prefix,
            '-DDYNINST_DIR=%s' % spec['dyninst'].prefix,
            '-DLIBIOMP_DIR=%s' % spec['llvm-openmp-ompt'].prefix,
            '-DGOTCHA_DIR=%s' % spec['gotcha'].prefix,
            '-DXERCESC_DIR=%s' % spec['xerces-c'].prefix]

        if self.spec.satisfies('+runtime'):
            self.set_rt_only_cmake_options(spec, cmake_args)

        # Add any MPI implementations coming from variant settings
        self.set_mpi_cmake_options(spec, cmake_args)

        if self.spec.satisfies('+crayfe'):
            # We need to build target/compute node components/libraries first
            # then pass those libraries to the cbtf-krell login node build
            self.set_cray_login_node_cmake_options(spec, cmake_args)

        return cmake_args

    def setup_run_environment(self, env):
        """Set up the compile and runtime environments for a package."""

        # Environment settings for cbtf-krell, bin is automatically
        # added to the path in the module file
        env.prepend_path('PATH', self.prefix.sbin)

        env.set('XPLAT_RSH', 'ssh')
        env.set('MRNET_COMM_PATH', self.prefix.sbin.cbtf_mrnet_commnode)

        # Set CBTF_MPI_IMPLEMENTATON to the appropriate mpi implementation
        # This is needed by CBTF tools to deploy the correct
        # mpi runtimes for cbtfsummary
        # Users may have to set the CBTF_MPI_IMPLEMENTATION variable
        # manually if multiple mpi's are specified in the build

        if self.spec.satisfies('+mpich'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mpich")

        if self.spec.satisfies('+mvapich'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mvapich")

        if self.spec.satisfies('+mvapich2'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mvapich2")

        if self.spec.satisfies('+mpt'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mpt")

        if self.spec.satisfies('+openmpi'):
            env.set('CBTF_MPI_IMPLEMENTATION', "openmpi")

        env.set('CBTF_MRNET_BACKEND_PATH',
                self.prefix.sbin.cbtf_libcbtf_mrnet_backend)

        env.prepend_path('PATH', self.spec['libmonitor'].prefix.bin)
        env.prepend_path('PATH', self.spec['papi'].prefix.bin)
        env.prepend_path('PATH', self.spec['mrnet'].prefix.bin)
<commit_msg>cbtf-krell: add rpcsvc-proto and libtirpc dependency. (#13800)<commit_after># Copyright 2013-2019 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *
import spack
import spack.store

class CbtfKrell(CMakePackage):
    """CBTF Krell project contains the Krell Institute contributions to the
       CBTF project.  These contributions include many performance data
       collectors and support libraries as well as some example tools
       that drive the data collection at HPC levels of scale.
    """
    homepage = "http://sourceforge.net/p/cbtf/wiki/Home/"
    git      = "https://github.com/OpenSpeedShop/cbtf-krell.git"

    version('develop', branch='master')
    version('1.9.3', branch='1.9.3')
    version('1.9.2', branch='1.9.2')
    version('1.9.1.2', branch='1.9.1.2')
    version('1.9.1.1', branch='1.9.1.1')
    version('1.9.1.0', branch='1.9.1.0')

    # MPI variants
    variant('openmpi', default=False,
            description="Build mpi experiment collector for openmpi MPI..")
    variant('mpt', default=False,
            description="Build mpi experiment collector for SGI MPT MPI.")
    variant('mvapich2', default=False,
            description="Build mpi experiment collector for mvapich2 MPI.")
    variant('mvapich', default=False,
            description="Build mpi experiment collector for mvapich MPI.")
    variant('mpich2', default=False,
            description="Build mpi experiment collector for mpich2 MPI.")
    variant('mpich', default=False,
            description="Build mpi experiment collector for mpich MPI.")
    variant('runtime', default=False,
            description="build only the runtime libraries and collectors.")
    variant('build_type', default='None', values=('None'),
            description='CMake build type')
    variant('cti', default=False,
            description="Build MRNet with the CTI startup option")
    variant('crayfe', default=False,
            description="build only the FE tool using the runtime_dir \
                         to point to target build.")

    # Dependencies for cbtf-krell
    depends_on("cmake@3.0.2:", type='build')

    # For rpcgen
    depends_on("rpcsvc-proto", type='build')

    # For rpc
    depends_on("libtirpc", type='link')

    # For binutils
    depends_on("binutils")

    # For boost
    depends_on("boost@1.66.0:1.69.0")

    # For Dyninst
    depends_on("dyninst@develop", when='@develop')
    depends_on("dyninst@10:", when='@1.9.1.0:9999')

    # For MRNet
    depends_on("mrnet@5.0.1-3:+cti", when='@develop+cti', type=('build', 'link', 'run'))
    depends_on("mrnet@5.0.1-3:+lwthreads", when='@develop', type=('build', 'link', 'run'))

    depends_on("mrnet@5.0.1-3+cti", when='@1.9.1.0:9999+cti', type=('build', 'link', 'run'))
    depends_on("mrnet@5.0.1-3+lwthreads", when='@1.9.1.0:9999', type=('build', 'link', 'run'))

    # For Xerces-C
    depends_on("xerces-c")

    # For CBTF
    depends_on("cbtf@develop", when='@develop', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999", when='@1.9.1.0:9999', type=('build', 'link', 'run'))

    # For CBTF with cti
    depends_on("cbtf@develop+cti", when='@develop+cti', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999+cti", when='@1.9.1.0:9999+cti', type=('build', 'link', 'run'))

    # For CBTF with runtime
    depends_on("cbtf@develop+runtime", when='@develop+runtime', type=('build', 'link', 'run'))
    depends_on("cbtf@1.9.1.0:9999+runtime", when='@1.9.1.0:9999+runtime', type=('build', 'link', 'run'))

    # for services and collectors
    depends_on("libmonitor@2013.02.18+krellpatch", type=('build', 'link', 'run'))

    depends_on("libunwind", when='@develop')
    depends_on("libunwind@1.2.1", when='@1.9.1.0:9999')

    depends_on("papi@5.4.1:", type=('build', 'link', 'run'))

    depends_on("llvm-openmp-ompt@tr6_forwards+standalone")

    # MPI Installations
    depends_on("openmpi", when='+openmpi')
    depends_on("mpich", when='+mpich')
    depends_on("mpich2", when='+mpich2')
    depends_on("mvapich2", when='+mvapich2')
    depends_on("mvapich", when='+mvapich')
    depends_on("mpt", when='+mpt')

    depends_on("python", when='@develop', type=('build', 'run'))
    depends_on("python@2.7.14:2.7.15", when='@2.3.1.3:9999', type=('build', 'run'))

    depends_on("gotcha")

    patch('arm.patch', when='target=aarch64:')

    parallel = False

    build_directory = 'build_cbtf_krell'

    def set_rt_only_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable the appropriate
        # MPI implementations

        rt_only_options = []
        rt_only_options.append('-DRUNTIME_ONLY=true')
        cmake_options.extend(rt_only_options)

    def set_mpi_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable the appropriate
        # MPI implementations

        mpi_options = []

        # openmpi
        if spec.satisfies('+openmpi'):
            mpi_options.append('-DOPENMPI_DIR=%s' % spec['openmpi'].prefix)
        # mpich
        if spec.satisfies('+mpich'):
            mpi_options.append('-DMPICH_DIR=%s' % spec['mpich'].prefix)
        # mpich2
        if spec.satisfies('+mpich2'):
            mpi_options.append('-DMPICH2_DIR=%s' % spec['mpich2'].prefix)
        # mvapich
        if spec.satisfies('+mvapich'):
            mpi_options.append('-DMVAPICH_DIR=%s' % spec['mvapich'].prefix)
        # mvapich2
        if spec.satisfies('+mvapich2'):
            mpi_options.append('-DMVAPICH2_DIR=%s' % spec['mvapich2'].prefix)
        # mpt
        if spec.satisfies('+mpt'):
            mpi_options.append('-DMPT_DIR=%s' % spec['mpt'].prefix)

        cmake_options.extend(mpi_options)

    def set_cray_login_node_cmake_options(self, spec, cmake_options):
        # Appends to cmake_options the options that will enable
        # the appropriate Cray login node libraries

        cray_login_node_options = []
        rt_platform = "cray"
        # How do we get the compute node (CNL) cbtf package
        # install directory path. spec['cbtf'].prefix is the
        # login node path for this build, as we are building
        # the login node components with this spack invocation. We
        # need these paths to be the ones created in the CNL
        # spack invocation.
        be_cbtf = spack.store.db.query_one('cbtf arch=cray-CNL-haswell')
        be_cbtfk = spack.store.db.query_one('cbtf-krell arch=cray-CNL-haswell')
        be_papi = spack.store.db.query_one('papi arch=cray-CNL-haswell')
        be_boost = spack.store.db.query_one('boost arch=cray-CNL-haswell')
        be_mont = spack.store.db.query_one('libmonitor arch=cray-CNL-haswell')
        be_unw = spack.store.db.query_one('libunwind arch=cray-CNL-haswell')
        be_xer = spack.store.db.query_one('xerces-c arch=cray-CNL-haswell')
        be_dyn = spack.store.db.query_one('dyninst arch=cray-CNL-haswell')
        be_mrnet = spack.store.db.query_one('mrnet arch=cray-CNL-haswell')

        cray_login_node_options.append(
            '-DCN_RUNTIME_PLATFORM=%s' % rt_platform)

        # Use install directories as CMAKE args for the building
        # of login cbtf-krell
        cray_login_node_options.append(
            '-DCBTF_CN_RUNTIME_DIR=%s' % be_cbtf.prefix)
        cray_login_node_options.append(
            '-DCBTF_KRELL_CN_RUNTIME_DIR=%s' % be_cbtfk.prefix)
        cray_login_node_options.append(
            '-DPAPI_CN_RUNTIME_DIR=%s' % be_papi.prefix)
        cray_login_node_options.append(
            '-DBOOST_CN_RUNTIME_DIR=%s' % be_boost.prefix)
        cray_login_node_options.append(
            '-DLIBMONITOR_CN_RUNTIME_DIR=%s' % be_mont.prefix)
        cray_login_node_options.append(
            '-DLIBUNWIND_CN_RUNTIME_DIR=%s' % be_unw.prefix)
        cray_login_node_options.append(
            '-DXERCESC_CN_RUNTIME_DIR=%s' % be_xer.prefix)
        cray_login_node_options.append(
            '-DDYNINST_CN_RUNTIME_DIR=%s' % be_dyn.prefix)
        cray_login_node_options.append(
            '-DMRNET_CN_RUNTIME_DIR=%s' % be_mrnet.prefix)

        cmake_options.extend(cray_login_node_options)

    def cmake_args(self):
        spec = self.spec

        compile_flags = "-O2 -g"

        # Add in paths for finding package config files that tell us
        # where to find these packages
        cmake_args = [
            '-DCMAKE_CXX_FLAGS=%s'         % compile_flags,
            '-DCMAKE_C_FLAGS=%s'           % compile_flags,
            '-DCBTF_DIR=%s' % spec['cbtf'].prefix,
            '-DBINUTILS_DIR=%s' % spec['binutils'].prefix,
            '-DLIBMONITOR_DIR=%s' % spec['libmonitor'].prefix,
            '-DLIBUNWIND_DIR=%s' % spec['libunwind'].prefix,
            '-DPAPI_DIR=%s' % spec['papi'].prefix,
            '-DBOOST_DIR=%s' % spec['boost'].prefix,
            '-DMRNET_DIR=%s' % spec['mrnet'].prefix,
            '-DDYNINST_DIR=%s' % spec['dyninst'].prefix,
            '-DLIBIOMP_DIR=%s' % spec['llvm-openmp-ompt'].prefix,
            '-DGOTCHA_DIR=%s' % spec['gotcha'].prefix,
            '-DXERCESC_DIR=%s' % spec['xerces-c'].prefix]

        if self.spec.satisfies('+runtime'):
            self.set_rt_only_cmake_options(spec, cmake_args)

        # Add any MPI implementations coming from variant settings
        self.set_mpi_cmake_options(spec, cmake_args)

        if self.spec.satisfies('+crayfe'):
            # We need to build target/compute node components/libraries first
            # then pass those libraries to the cbtf-krell login node build
            self.set_cray_login_node_cmake_options(spec, cmake_args)

        return cmake_args

    def setup_run_environment(self, env):
        """Set up the compile and runtime environments for a package."""

        # Environment settings for cbtf-krell, bin is automatically
        # added to the path in the module file
        env.prepend_path('PATH', self.prefix.sbin)

        env.set('XPLAT_RSH', 'ssh')
        env.set('MRNET_COMM_PATH', self.prefix.sbin.cbtf_mrnet_commnode)

        # Set CBTF_MPI_IMPLEMENTATON to the appropriate mpi implementation
        # This is needed by CBTF tools to deploy the correct
        # mpi runtimes for cbtfsummary
        # Users may have to set the CBTF_MPI_IMPLEMENTATION variable
        # manually if multiple mpi's are specified in the build

        if self.spec.satisfies('+mpich'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mpich")

        if self.spec.satisfies('+mvapich'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mvapich")

        if self.spec.satisfies('+mvapich2'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mvapich2")

        if self.spec.satisfies('+mpt'):
            env.set('CBTF_MPI_IMPLEMENTATION', "mpt")

        if self.spec.satisfies('+openmpi'):
            env.set('CBTF_MPI_IMPLEMENTATION', "openmpi")

        env.set('CBTF_MRNET_BACKEND_PATH',
                self.prefix.sbin.cbtf_libcbtf_mrnet_backend)

        env.prepend_path('PATH', self.spec['libmonitor'].prefix.bin)
        env.prepend_path('PATH', self.spec['papi'].prefix.bin)
        env.prepend_path('PATH', self.spec['mrnet'].prefix.bin)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
#  This file is part of django-powerdns-manager.
#
#  django-powerdns-manager is a web based PowerDNS administration panel.
#
#  Development Web Site:
#    - http://www.codetrax.org/projects/django-powerdns-manager
#  Public Source Code Repository:
#    - https://source.codetrax.org/hgroot/django-powerdns-manager
#
#  Copyright 2012 George Notaras <gnot [at] g-loaded.eu>
#
#  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 time

from django.contrib import admin
from django.db.models.loading import cache
from django.contrib import messages
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _

from powerdns_manager.forms import SoaRecordModelForm
from powerdns_manager.forms import SoaRecordInlineModelFormset

from powerdns_manager.forms import GenericRecordModelForm
from powerdns_manager.forms import GenericRecordInlineModelFormset

from powerdns_manager.forms import NsRecordInlineModelFormset

from powerdns_manager.forms import MxRecordInlineModelFormset

from powerdns_manager.forms import SrvRecordInlineModelFormset

# Action for
# - set change date
# - set serial (?)
# - set TTL to 300, 3600, 86400
#
#def test_action(modeladmin, request, queryset):
#    messages.add_message(request, messages.INFO, 'The test action was successful.')
#test_action.short_description = "Test Action"

class SoaRecordInline(admin.StackedInline):
    model = cache.get_model('powerdns_manager', 'Record')
    form = SoaRecordModelForm
    formset = SoaRecordInlineModelFormset
    # Show exactly one form
    extra = 1
    max_num = 1
    verbose_name = 'SOA Resource Record'
    verbose_name_plural = 'SOA Resource Record' # Only one SOA RR per zone
    fields = ('name', 'ttl', 'primary', 'hostmaster', 'serial', 'refresh', 'retry', 'expire', 'default_ttl', 'date_modified')
    readonly_fields = ('date_modified', )
    can_delete = False

    def queryset(self, request):
        """Return only SOA records"""
        qs = super(SoaRecordInline, self).queryset(request)
        return qs.filter(type='SOA')

class NsRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = NsRecordInlineModelFormset
    extra = 0
    verbose_name = 'NS Resource Record'
    verbose_name_plural = 'NS Resource Records'
    fields = ('name', 'ttl', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only NS records"""
        qs = super(NsRecordInline, self).queryset(request)
        return qs.filter(type='NS')

class MxRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = MxRecordInlineModelFormset
    extra = 0
    verbose_name = 'MX Resource Record'
    verbose_name_plural = 'MX Resource Records'
    fields = ('name', 'ttl', 'prio', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only MX records"""
        qs = super(MxRecordInline, self).queryset(request)
        return qs.filter(type='MX')

class SrvRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = SrvRecordInlineModelFormset
    extra = 0
    verbose_name = 'SRV Resource Record'
    verbose_name_plural = 'SRV Resource Records'
    fields = ('name', 'ttl', 'prio', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only SRV records"""
        qs = super(SrvRecordInline, self).queryset(request)
        return qs.filter(type='SRV')

class GenericRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    form = GenericRecordModelForm
    formset = GenericRecordInlineModelFormset
    fields = ('name', 'type_avail', 'ttl', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 3
    verbose_name = 'Resource Record'
    verbose_name_plural = 'Resource Records' # Only one SOA RR per zone

    def queryset(self, request):
        """Exclude resource records which are editable in an Inline"""
        qs = super(GenericRecordInline, self).queryset(request)
        qs = qs.exclude(type='SOA')
        qs = qs.exclude(type='NS')
        qs = qs.exclude(type='MX')
        qs = qs.exclude(type='SRV')
        return qs

class DomainMetadataInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'DomainMetadata')
    fields = ('kind', 'content', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 0
    verbose_name_plural = 'Domain Metadata'

class CryptoKeyInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'CryptoKey')
    fields = ('flags', 'active', 'content', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 0
    verbose_name_plural = 'Crypto Keys'

class DomainAdmin(admin.ModelAdmin):
    #form = DomainModelForm
    #actions = [test_action, ]

    fields = ('name', 'type', 'master', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('name', 'type', 'master', 'date_modified')
    list_filter = ('type', )
    search_fields = ('name', 'master')
    inlines = [
        SoaRecordInline,
        NsRecordInline,
        MxRecordInline,
        SrvRecordInline,
        GenericRecordInline,
        DomainMetadataInline,
        CryptoKeyInline
    ]
    verbose_name = 'zone'
    verbose_name_plural = 'zones'

    def queryset(self, request):
        qs = super(DomainAdmin, self).queryset(request)
        if not request.user.is_superuser:
            # Non-superusers see the domains they have created
            qs = qs.filter(created_by=request.user)
        return qs

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        obj.save()

admin.site.register(cache.get_model('powerdns_manager', 'Domain'), DomainAdmin)

class TsigKeyAdmin(admin.ModelAdmin):
    fields = ('name', 'algorithm', 'secret', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('name', 'algorithm', 'date_modified')
    list_filter = ('algorithm', )
    search_fields = ('name', )
    verbose_name = 'TSIG Key'
    verbose_name_plural = 'TSIG Keys'

    def queryset(self, request):
        qs = super(TsigKeyAdmin, self).queryset(request)
        if not request.user.is_superuser:
            # Non-superusers see the records they have created
            qs = qs.filter(created_by=request.user)
        return qs

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        obj.save()

admin.site.register(cache.get_model('powerdns_manager', 'TsigKey'), TsigKeyAdmin)

class SuperMasterAdmin(admin.ModelAdmin):
    fields = ('ip', 'nameserver', 'account', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('ip', 'nameserver', 'account', 'date_modified')
    search_fields = ('nameserver', 'account')
    verbose_name = 'SuperMaster'
    verbose_name_plural = 'SuperMasters'

admin.site.register(cache.get_model('powerdns_manager', 'SuperMaster'), SuperMasterAdmin)

<commit_msg>Removed unused import.<commit_after># -*- coding: utf-8 -*-
#
#  This file is part of django-powerdns-manager.
#
#  django-powerdns-manager is a web based PowerDNS administration panel.
#
#  Development Web Site:
#    - http://www.codetrax.org/projects/django-powerdns-manager
#  Public Source Code Repository:
#    - https://source.codetrax.org/hgroot/django-powerdns-manager
#
#  Copyright 2012 George Notaras <gnot [at] g-loaded.eu>
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.
#

from django.contrib import admin
from django.db.models.loading import cache
from django.contrib import messages
from django.contrib.admin import SimpleListFilter
from django.utils.translation import ugettext_lazy as _

from powerdns_manager.forms import SoaRecordModelForm
from powerdns_manager.forms import SoaRecordInlineModelFormset

from powerdns_manager.forms import GenericRecordModelForm
from powerdns_manager.forms import GenericRecordInlineModelFormset

from powerdns_manager.forms import NsRecordInlineModelFormset

from powerdns_manager.forms import MxRecordInlineModelFormset

from powerdns_manager.forms import SrvRecordInlineModelFormset

# Action for
# - set change date
# - set serial (?)
# - set TTL to 300, 3600, 86400
#
#def test_action(modeladmin, request, queryset):
#    messages.add_message(request, messages.INFO, 'The test action was successful.')
#test_action.short_description = "Test Action"

class SoaRecordInline(admin.StackedInline):
    model = cache.get_model('powerdns_manager', 'Record')
    form = SoaRecordModelForm
    formset = SoaRecordInlineModelFormset
    # Show exactly one form
    extra = 1
    max_num = 1
    verbose_name = 'SOA Resource Record'
    verbose_name_plural = 'SOA Resource Record' # Only one SOA RR per zone
    fields = ('name', 'ttl', 'primary', 'hostmaster', 'serial', 'refresh', 'retry', 'expire', 'default_ttl', 'date_modified')
    readonly_fields = ('date_modified', )
    can_delete = False

    def queryset(self, request):
        """Return only SOA records"""
        qs = super(SoaRecordInline, self).queryset(request)
        return qs.filter(type='SOA')

class NsRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = NsRecordInlineModelFormset
    extra = 0
    verbose_name = 'NS Resource Record'
    verbose_name_plural = 'NS Resource Records'
    fields = ('name', 'ttl', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only NS records"""
        qs = super(NsRecordInline, self).queryset(request)
        return qs.filter(type='NS')

class MxRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = MxRecordInlineModelFormset
    extra = 0
    verbose_name = 'MX Resource Record'
    verbose_name_plural = 'MX Resource Records'
    fields = ('name', 'ttl', 'prio', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only MX records"""
        qs = super(MxRecordInline, self).queryset(request)
        return qs.filter(type='MX')

class SrvRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    #form =
    formset = SrvRecordInlineModelFormset
    extra = 0
    verbose_name = 'SRV Resource Record'
    verbose_name_plural = 'SRV Resource Records'
    fields = ('name', 'ttl', 'prio', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )

    def queryset(self, request):
        """Return only SRV records"""
        qs = super(SrvRecordInline, self).queryset(request)
        return qs.filter(type='SRV')

class GenericRecordInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'Record')
    form = GenericRecordModelForm
    formset = GenericRecordInlineModelFormset
    fields = ('name', 'type_avail', 'ttl', 'content', 'auth', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 3
    verbose_name = 'Resource Record'
    verbose_name_plural = 'Resource Records' # Only one SOA RR per zone

    def queryset(self, request):
        """Exclude resource records which are editable in an Inline"""
        qs = super(GenericRecordInline, self).queryset(request)
        qs = qs.exclude(type='SOA')
        qs = qs.exclude(type='NS')
        qs = qs.exclude(type='MX')
        qs = qs.exclude(type='SRV')
        return qs

class DomainMetadataInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'DomainMetadata')
    fields = ('kind', 'content', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 0
    verbose_name_plural = 'Domain Metadata'

class CryptoKeyInline(admin.TabularInline):
    model = cache.get_model('powerdns_manager', 'CryptoKey')
    fields = ('flags', 'active', 'content', 'date_modified')
    readonly_fields = ('date_modified', )
    extra = 0
    verbose_name_plural = 'Crypto Keys'

class DomainAdmin(admin.ModelAdmin):
    #form = DomainModelForm
    #actions = [test_action, ]

    fields = ('name', 'type', 'master', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('name', 'type', 'master', 'date_modified')
    list_filter = ('type', )
    search_fields = ('name', 'master')
    inlines = [
        SoaRecordInline,
        NsRecordInline,
        MxRecordInline,
        SrvRecordInline,
        GenericRecordInline,
        DomainMetadataInline,
        CryptoKeyInline
    ]
    verbose_name = 'zone'
    verbose_name_plural = 'zones'

    def queryset(self, request):
        qs = super(DomainAdmin, self).queryset(request)
        if not request.user.is_superuser:
            # Non-superusers see the domains they have created
            qs = qs.filter(created_by=request.user)
        return qs

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        obj.save()

admin.site.register(cache.get_model('powerdns_manager', 'Domain'), DomainAdmin)

class TsigKeyAdmin(admin.ModelAdmin):
    fields = ('name', 'algorithm', 'secret', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('name', 'algorithm', 'date_modified')
    list_filter = ('algorithm', )
    search_fields = ('name', )
    verbose_name = 'TSIG Key'
    verbose_name_plural = 'TSIG Keys'

    def queryset(self, request):
        qs = super(TsigKeyAdmin, self).queryset(request)
        if not request.user.is_superuser:
            # Non-superusers see the records they have created
            qs = qs.filter(created_by=request.user)
        return qs

    def save_model(self, request, obj, form, change):
        if not change:
            obj.created_by = request.user
        obj.save()

admin.site.register(cache.get_model('powerdns_manager', 'TsigKey'), TsigKeyAdmin)

class SuperMasterAdmin(admin.ModelAdmin):
    fields = ('ip', 'nameserver', 'account', 'date_modified')
    readonly_fields = ('date_modified', )
    list_display = ('ip', 'nameserver', 'account', 'date_modified')
    search_fields = ('nameserver', 'account')
    verbose_name = 'SuperMaster'
    verbose_name_plural = 'SuperMasters'

admin.site.register(cache.get_model('powerdns_manager', 'SuperMaster'), SuperMasterAdmin)

<|endoftext|>


<commit_before># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Gperftools(AutotoolsPackage):
    """Google's fast malloc/free implementation, especially for
       multi-threaded applications.  Contains tcmalloc, heap-checker,
       heap-profiler, and cpu-profiler.

    """
    homepage = "https://github.com/gperftools/gperftools"
    url      = "https://github.com/gperftools/gperftools/releases/download/gperftools-2.7/gperftools-2.7.tar.gz"
    maintainers = ['albestro', 'eschnett', 'msimberg', 'teonnik']

    version('2.9.1', sha256='ea566e528605befb830671e359118c2da718f721c27225cbbc93858c7520fee3')
    version('2.8.1', sha256='12f07a8ba447f12a3ae15e6e3a6ad74de35163b787c0c7b76288d7395f2f74e0')
    version('2.7', sha256='1ee8c8699a0eff6b6a203e59b43330536b22bbcbe6448f54c7091e5efb0763c9')
    version('2.4', sha256='982a37226eb42f40714e26b8076815d5ea677a422fb52ff8bfca3704d9c30a2d')
    version('2.3', sha256='093452ad45d639093c144b4ec732a3417e8ee1f3744f2b0f8d45c996223385ce')

    depends_on("unwind")
<commit_msg>gperftools package: add variants (#26032)<commit_after># Copyright 2013-2021 Lawrence Livermore National Security, LLC and other
# Spack Project Developers. See the top-level COPYRIGHT file for details.
#
# SPDX-License-Identifier: (Apache-2.0 OR MIT)

from spack import *

class Gperftools(AutotoolsPackage):
    """Google's fast malloc/free implementation, especially for
       multi-threaded applications.  Contains tcmalloc, heap-checker,
       heap-profiler, and cpu-profiler.

    """
    homepage = "https://github.com/gperftools/gperftools"
    url      = "https://github.com/gperftools/gperftools/releases/download/gperftools-2.7/gperftools-2.7.tar.gz"
    maintainers = ['albestro', 'eschnett', 'msimberg', 'teonnik']

    version('2.9.1', sha256='ea566e528605befb830671e359118c2da718f721c27225cbbc93858c7520fee3')
    version('2.8.1', sha256='12f07a8ba447f12a3ae15e6e3a6ad74de35163b787c0c7b76288d7395f2f74e0')
    version('2.7', sha256='1ee8c8699a0eff6b6a203e59b43330536b22bbcbe6448f54c7091e5efb0763c9')
    version('2.4', sha256='982a37226eb42f40714e26b8076815d5ea677a422fb52ff8bfca3704d9c30a2d')
    version('2.3', sha256='093452ad45d639093c144b4ec732a3417e8ee1f3744f2b0f8d45c996223385ce')

    variant('sized_delete', default=False, description="Build sized delete operator")
    variant('dynamic_sized_delete_support', default=False, description="Try to build run-time switch for sized delete operator")
    variant('debugalloc', default=True, description="Build versions of libs with debugalloc")
    variant('libunwind', default=True, description="Enable libunwind linking")

    depends_on("unwind", when="+libunwind")

    def configure_args(self):
        args = []
        args += self.enable_or_disable("sized-delete", variant='sized_delete')
        args += self.enable_or_disable("dynamic-sized-delete-support",
                                       variant='dynamic_sized_delete_support')
        args += self.enable_or_disable("debugalloc")
        args += self.enable_or_disable("libunwind")

        return args
<|endoftext|>


<commit_before>import networkx as nx
import pydot

from .ExpressionNode import ExpressionNode as Node
from .ExpressionGraph import ExpressionGraph
from .modules import modules
from .util import lg
from .util import get_matching_port

class ExpressionTree(ExpressionGraph):
    """Defines a tree of binary expressions

    Attributes:
        root (ExpressionNode): The root node of the tree
        width (int): The number of leaves in the tree
        radix (int): The radix of the tree
        idem (bool): Whether the tree's main operator is idempotent
        node_defs (dict): A dictionary that defines the tree's nodes
        in_shape (list of int): The shape of each leaf node's input
        out_shape (list of int): The shape of the root node's output
        black_shape (int, int): The shape of the main recurrence node's output

    Attributes inherited from ExpressionGraph:
        name (string): The name of the graph
        next_net (int): The next net name to be used
        next_block (int): The next block name to be used
        blocks (list): The list of blocks in the graph
        in_ports (list of ((string, int), string)): The list of input ports
        out_ports (list of ((string, int), string)): The list of output ports
    """

    def __init__(self,
                 width,
                 in_ports,
                 out_ports,
                 name="tree",
                 start_point="serial",
                 radix=2,
                 idem=False,
                 node_defs={}
                ):
        """Initializes the ExpressionTree

        Args:
            width (int): The number of leaves in the tree
            in_ports (list of ((string, int), string)): List of input ports
            out_ports (list of ((string, int), string)): List of output ports
            name (string): The name of the graph
            start_point (string): The starting structure of the tree
            radix (int): The radix of the tree
            idem (bool): Whether the tree's main operator is idempotent
            node_defs (dict): A dictionary that must define these nodes:
                - "pre": Pre-processing node
                - "root": Root node
                - "black": Main expression node used in the tree
                - "buffer": Buffer node

            Optional node definitions include but are not limited to:
                - "grey": Black node that feeds into the root node
                - "lspine": Nodes that lie along the left spine of the tree
                - "lspine_pre": Pre- node that feeds into the left spine
                - "first_pre": Right-most pre-processing node
        """
        if not isinstance(width, int):
            raise TypeError("Tree width must be an integer")
        if width < 1:
            raise ValueError("Tree width must be at least 1")
        if start_point not in ["serial", "rbalanced", "balanced"]:
            error = "Tree start point {0} is not implemented"
            error = error.format(start_point)
            raise NotImplementedError(error)
        if not isinstance(radix, int):
            raise TypeError("Tree radix must be an integer")
        if not isinstance(name, str):
            raise TypeError("Tree name must be a string")
        if not isinstance(idem, bool):
            raise TypeError("Tree idempotency must be a boolean")
        if not isinstance(node_defs, dict):
            raise TypeError("Tree node definitions must be a dictionary")
        for required in ["pre", "root", "black", "buffer"]:
            if required not in node_defs:
                raise ValueError(("Tree node definitions must contain"
                                  " the node {}").format(required))

        # Save constructor arguments
        self.width = width
        self.radix = radix
        self.idem = idem
        self.node_defs = node_defs

        # Get node port shapes from the module definitions
        self.in_shape = [x[1] for x in modules[node_defs["pre"]]["ins"]]
        self.out_shape = [x[1] for x in modules[node_defs["root"]]["outs"]]

        self.black_shape = [x[1] for x in modules[node_defs["black"]]["ins"]]
        black_out_shape = [x[1] for x in modules[node_defs["black"]]["outs"]]
        black_out_shape = [self.radix*x for x in black_out_shape]
        if black_out_shape != self.black_shape:
            raise ValueError(("The main recurrence node of the tree"
                              " must have the same input and output shape"))
        del black_out_shape

        # Check that node shapes are compatible with port shapes
        ### NOTE: INPUT SHAPE IS CURRENTLY ASSUMED TO BE [1,1,1,..]
        ### TO-DO: Allow for arbitrary input shape
        ### Need to check whole file for this implicit assumption
        for a in range(len(self.in_shape)):
            if a > len(in_ports)-1 or in_ports[a][0][1] != self.width:
                raise ValueError(("Input port {} of the tree must have the"
                                  " compatible shape with input shape of the"
                                  " pre-processing node").format(a))
        for a in range(len(self.out_shape)):
            if a > len(out_ports)-1 or self.out_shape[a] != out_ports[a][0][1]:
                raise ValueError(("Output port {} of the tree must have the"
                                  " same shape as the output shape of the"
                                  " root node").format(a))

        # Initialize the graph
        super().__init__(name=name,in_ports=in_ports,out_ports=out_ports)

        # Initialize the tree

        ## Initialize the root node
        self.root = Node(node_defs["root"], x_pos = 0, y_pos = 0)
        self.root = self.add_node(self.root)
        ### Connect the root node to the tree's ports
        self._connect_outports(self.root)

        ## Initialize the rest of the tree
        prev_root = self.root
        pre_counter = self.width-1
        while pre_counter > -1:
            for a in range(radix):
                ## Place pre-processing nodes
                if a == 0 or pre_counter < radix-1:
                    # Left spine is special
                    if pre_counter == self.width-1:
                        pre = node_defs.get("lspine_pre", node_defs["pre"])
                    # Right-most pre- may be special
                    elif pre_counter == 0:
                        pre = node_defs.get("first_pre", node_defs["pre"])
                    else:
                        pre = node_defs["pre"]
                    pre_node = Node(pre)
                    self.add_node(pre_node)
                    self.add_edge(prev_root, pre_node, a)
                    self._connect_inports(pre_node, pre_counter)
                    pre_node._recalculate_leafs(leafs=pre_counter)
                    pre_counter -= 1
                else:
                    black_node = Node(node_defs["black"])
                    self.add_node(black_node)
                    self.add_edge(prev_root, black_node, a)
                # Advance prev_root
                if a == radix-1:
                    prev_root = prev_root.children[1]

    def __len__(self):
        """Redefine the len() function to return the depth of the tree"""
        depth = 0
        for n in self.nodes:
            if n.y_pos > depth:
                depth = n.y_pos
        return depth+1

    def __getitem__(self, key):
        """Redefine the [] operator to readily access nodes

        Calling tree[x][y] will return the xth node from the right at depth y
        """
        if isinstance(key, tuple) and len(key) == 2:
            nodes = [n for n in self.nodes if n.y_pos == key[0]]
            nodes = sorted(nodes, key=lambda x: -x.x_pos)
            return nodes[key[1]]
        else:
            return super().__getitem__(key)

    def _connect_outports(self, root):
        """Connect the tree's output ports to the root node"""
        for a in range(len(self.out_shape)):
            port_name = self.out_ports[a][0][0]
            if self.out_shape[a] == 1:
                net_name = "${}".format(port_name)
                root.out_nets[port_name][0] = net_name
                continue
            for b in range(self.out_shape[a]):
                net_name = "${}[{}]".format(port_name,b)
                root.out_nets[port_name][b] = net_name

    def _connect_inports(self, node, index):
        """Connect the tree's input ports to a pre-processing node"""
        for a in range(len(self.in_shape)):
            port_name = self.in_ports[a][0][0]
            net_name = "${}[{}]".format(port_name,index)
            node.in_nets[port_name][0] = net_name

    def add_edge(self, parent, child, index):
        """Adds a directed edge to the tree, from child output to parent input
        All index ports on the parents's port list are connected to the child

        Args:
            parent (Node): The parent node
            child (Node): The child node
            index (int): The index of the parent's input port
        """
        if not isinstance(parent, Node):
            raise TypeError("Parent must be an Node")
        if not isinstance(child, Node):
            raise TypeError("Child must be an Node")
        if not isinstance(index, int):
            raise TypeError("index must be an integer")
        if index < -self.radix or index > self.radix-1:
            raise ValueError(("Tree nodes may not have more edges"
                              "than the radix of the tree"))

        # Normalize index
        index = index % self.radix

        # Get the parent and child ports
        parent_ports = modules[parent.value]["ins"]
        child_ports = modules[child.value]["outs"]

        # Attempt to connect all ports
        for port in parent_ports:
            if port[2+index] == 0:
                continue
            # This will raise an exception if the port is not found
            matching_port = get_matching_port(port, child_ports)
            # Figure out which bits of the port to connect to
            offset = 0
            for x in range(index):
                offset += port[2+x]
            # Add an edge for each bit of the port
            for b in range(port[2+index]):
                pin1 = (port[0], b+offset)
                pin2 = (matching_port[0], b)
                super().add_edge(parent, pin1, child, pin2)

        # Adjust x-pos and y-pos of the child
        ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
        ### TO-DO: Make this more general
        y_pos = parent.y_pos+1
        x_diff = 1

        if index == 0:
            x_pos = parent.x_pos + x_diff
        elif index == 1:
            x_pos = parent.x_pos - x_diff

        child.x_pos = x_pos
        child.y_pos = y_pos

        diagram_pos = "{0},{1}!".format(child.x_pos*-1, child.y_pos*-1)
        self.nodes[child]["pos"] = diagram_pos

    ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
    ### TO-DO: Make this more general
    def left_rotate(self, node):
        """Rotate a node to the left

        Args:
            node (Node): The node to rotate
        """
        if not isinstance(node, Node):
            raise TypeError("node must be an Node")
        if node.parent is None or len(node.parent.children) != self.radix:
            raise ValueError("Can only rotate nodes with full families")
        if node.parent[1] != node:
            raise ValueError("Can only rotate right children")

        # Get the parent and child nodes
        parent = node.parent
        lchild = node[0]
        rchild = node[1]
        plchild = node.parent[0]
        if parent.parent is None:
            thru_root = True
        else:
            thru_root = False
            parent_dir = parent.parent.children.index(parent)

        # Disconnect the nodes
        if not thru_root:
            self.remove_edge(parent.parent, parent)
        self.remove_edge(parent, node)
        self.remove_edge(node, lchild)
        if thru_root:
            self.remove_edge(parent, plchild)
            self.remove_edge(node, rchild)

        # If rotating through root, nodes must be morphed
        if thru_root:
            parent.morph(self.node_defs["lspine"])
            child.morph(self.node_defs["root"])

        # Adjust the y-pos
        parent.iter_down(lambda x: setattr(x, "y_pos", x.y_pos-1))
        child.iter_down(lambda x: setattr(x, "y_pos", x.y_pos+1))

        # Rotate the nodes
        if not thru_root:
            self.add_edge(parent.parent, parent, parent_dir)
        self.add_edge(parent, lchild, 1)
        self.add_edge(node, parent, 0)
        if thru_root:
            self.add_edge(parent, plchild, 0)
            self.add_edge(node, rchild, 1)

        return node

    ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
    ### TO-DO: Make this more general
    def right_rotate(self, node):
        """Rotate a node to the right

        Args:
            node (Node): The node to rotate
        """
        if not isinstance(node, Node):
            raise TypeError("node must be an Node")
        if node.parent is None or len(node.parent.children) != self.radix:
            raise ValueError("Can only rotate nodes with full families")
        if node.parent[0] != node:
            raise ValueError("Can only rotate left children")

        # Get the parent and child nodes
        parent = node.parent
        rchild = node[1]
        lchild = node[0]
        prchild = node.parent[1]
        if parent.parent is None:
            thru_root = True
        else:
            thru_root = False
            parent_dir = parent.parent.children.index(parent)

        # Disconnect the nodes
        if not thru_root:
            self.remove_edge(parent.parent, parent)
        self.remove_edge(parent, node)
        self.remove_edge(node, rchild)
        if thru_root:
            self.remove_edge(parent, prchild)
            self.remove_edge(node, lchild)

        # If rotating through root, nodes must be morphed
        if thru_root:
            parent.morph(self.node_defs["black"])
            child.morph(self.node_defs["root"])

        # Adjust the y-pos
        parent.iter_down(lambda x: setattr(x, "y_pos", x.y_pos-1))
        child.iter_down(lambda x: setattr(x, "y_pos", x.y_pos+1))

        # Rotate the nodes
        if not thru_root:
            self.add_edge(parent.parent, parent, parent_dir)
        self.add_edge(parent, rchild, 0)
        self.add_edge(node, parent, 1)
        if thru_root:
            self.add_edge(parent, prchild, 1)
            self.add_edge(node, lchild, 0)

        return node

    def png(self, fname="tree.png"):
        """Generate a PNG representation of the tree using GraphViz"""

        # Convert the graph to pydot
        pg = nx.drawing.nx_pydot.to_pydot(self)
#        pg.set_rankdir("LR")
        pg.set_splines("false")
        pg.set_concentrate("true")

        pg.write_dot(fname.replace(".png", ".dot"))
        pg.write_png(fname, prog="neato")

if __name__ == "__main__":
    raise RuntimeError("This file is importable, but not executable")
<commit_msg>Add _fix_diagram_positions method to Tree<commit_after>import networkx as nx
import pydot

from .ExpressionNode import ExpressionNode as Node
from .ExpressionGraph import ExpressionGraph
from .modules import modules
from .util import lg
from .util import get_matching_port

class ExpressionTree(ExpressionGraph):
    """Defines a tree of binary expressions

    Attributes:
        root (ExpressionNode): The root node of the tree
        width (int): The number of leaves in the tree
        radix (int): The radix of the tree
        idem (bool): Whether the tree's main operator is idempotent
        node_defs (dict): A dictionary that defines the tree's nodes
        in_shape (list of int): The shape of each leaf node's input
        out_shape (list of int): The shape of the root node's output
        black_shape (int, int): The shape of the main recurrence node's output

    Attributes inherited from ExpressionGraph:
        name (string): The name of the graph
        next_net (int): The next net name to be used
        next_block (int): The next block name to be used
        blocks (list): The list of blocks in the graph
        in_ports (list of ((string, int), string)): The list of input ports
        out_ports (list of ((string, int), string)): The list of output ports
    """

    def __init__(self,
                 width,
                 in_ports,
                 out_ports,
                 name="tree",
                 start_point="serial",
                 radix=2,
                 idem=False,
                 node_defs={}
                ):
        """Initializes the ExpressionTree

        Args:
            width (int): The number of leaves in the tree
            in_ports (list of ((string, int), string)): List of input ports
            out_ports (list of ((string, int), string)): List of output ports
            name (string): The name of the graph
            start_point (string): The starting structure of the tree
            radix (int): The radix of the tree
            idem (bool): Whether the tree's main operator is idempotent
            node_defs (dict): A dictionary that must define these nodes:
                - "pre": Pre-processing node
                - "root": Root node
                - "black": Main expression node used in the tree
                - "buffer": Buffer node

            Optional node definitions include but are not limited to:
                - "grey": Black node that feeds into the root node
                - "lspine": Nodes that lie along the left spine of the tree
                - "lspine_pre": Pre- node that feeds into the left spine
                - "first_pre": Right-most pre-processing node
        """
        if not isinstance(width, int):
            raise TypeError("Tree width must be an integer")
        if width < 1:
            raise ValueError("Tree width must be at least 1")
        if start_point not in ["serial", "rbalanced", "balanced"]:
            error = "Tree start point {0} is not implemented"
            error = error.format(start_point)
            raise NotImplementedError(error)
        if not isinstance(radix, int):
            raise TypeError("Tree radix must be an integer")
        if not isinstance(name, str):
            raise TypeError("Tree name must be a string")
        if not isinstance(idem, bool):
            raise TypeError("Tree idempotency must be a boolean")
        if not isinstance(node_defs, dict):
            raise TypeError("Tree node definitions must be a dictionary")
        for required in ["pre", "root", "black", "buffer"]:
            if required not in node_defs:
                raise ValueError(("Tree node definitions must contain"
                                  " the node {}").format(required))

        # Save constructor arguments
        self.width = width
        self.radix = radix
        self.idem = idem
        self.node_defs = node_defs

        # Get node port shapes from the module definitions
        self.in_shape = [x[1] for x in modules[node_defs["pre"]]["ins"]]
        self.out_shape = [x[1] for x in modules[node_defs["root"]]["outs"]]

        self.black_shape = [x[1] for x in modules[node_defs["black"]]["ins"]]
        black_out_shape = [x[1] for x in modules[node_defs["black"]]["outs"]]
        black_out_shape = [self.radix*x for x in black_out_shape]
        if black_out_shape != self.black_shape:
            raise ValueError(("The main recurrence node of the tree"
                              " must have the same input and output shape"))
        del black_out_shape

        # Check that node shapes are compatible with port shapes
        ### NOTE: INPUT SHAPE IS CURRENTLY ASSUMED TO BE [1,1,1,..]
        ### TO-DO: Allow for arbitrary input shape
        ### Need to check whole file for this implicit assumption
        for a in range(len(self.in_shape)):
            if a > len(in_ports)-1 or in_ports[a][0][1] != self.width:
                raise ValueError(("Input port {} of the tree must have the"
                                  " compatible shape with input shape of the"
                                  " pre-processing node").format(a))
        for a in range(len(self.out_shape)):
            if a > len(out_ports)-1 or self.out_shape[a] != out_ports[a][0][1]:
                raise ValueError(("Output port {} of the tree must have the"
                                  " same shape as the output shape of the"
                                  " root node").format(a))

        # Initialize the graph
        super().__init__(name=name,in_ports=in_ports,out_ports=out_ports)

        # Initialize the tree

        ## Initialize the root node
        self.root = Node(node_defs["root"], x_pos = 0, y_pos = 0)
        self.root = self.add_node(self.root)
        ### Connect the root node to the tree's ports
        self._connect_outports(self.root)

        ## Initialize the rest of the tree
        prev_root = self.root
        pre_counter = self.width-1
        while pre_counter > -1:
            for a in range(radix):
                ## Place pre-processing nodes
                if a == 0 or pre_counter < radix-1:
                    # Left spine is special
                    if pre_counter == self.width-1:
                        pre = node_defs.get("lspine_pre", node_defs["pre"])
                    # Right-most pre- may be special
                    elif pre_counter == 0:
                        pre = node_defs.get("first_pre", node_defs["pre"])
                    else:
                        pre = node_defs["pre"]
                    pre_node = Node(pre)
                    self.add_node(pre_node)
                    self.add_edge(prev_root, pre_node, a)
                    self._connect_inports(pre_node, pre_counter)
                    pre_node._recalculate_leafs(leafs=pre_counter)
                    pre_counter -= 1
                else:
                    black_node = Node(node_defs["black"])
                    self.add_node(black_node)
                    self.add_edge(prev_root, black_node, a)
                # Advance prev_root
                if a == radix-1:
                    prev_root = prev_root.children[1]

    def __len__(self):
        """Redefine the len() function to return the depth of the tree"""
        depth = 0
        for n in self.nodes:
            if n.y_pos > depth:
                depth = n.y_pos
        return depth+1

    def __getitem__(self, key):
        """Redefine the [] operator to readily access nodes

        Calling tree[x,y] will return the xth node from the right at depth y
        """
        if isinstance(key, tuple) and len(key) == 2:
            nodes = self._get_row(key[0])
            return nodes[key[1]]
        else:
            return super().__getitem__(key)

    def _get_row(self, depth):
        """Return the nodes at a given depth"""
        nodes = [n for n in self.nodes if n.y_pos == depth]
        return sorted(nodes, key=lambda x: -x.x_pos)

    def _get_leafs(self):
        """Return a list of leaf nodes"""
        leafs = []
        for n in self.nodes:
            if len(n.children) == 0:
                leafs.append(n)
        return sorted(leafs, key=lambda x: -x.x_pos)

    def _connect_outports(self, root):
        """Connect the tree's output ports to the root node"""
        for a in range(len(self.out_shape)):
            port_name = self.out_ports[a][0][0]
            if self.out_shape[a] == 1:
                net_name = "${}".format(port_name)
                root.out_nets[port_name][0] = net_name
                continue
            for b in range(self.out_shape[a]):
                net_name = "${}[{}]".format(port_name,b)
                root.out_nets[port_name][b] = net_name

    def _connect_inports(self, node, index):
        """Connect the tree's input ports to a pre-processing node"""
        for a in range(len(self.in_shape)):
            port_name = self.in_ports[a][0][0]
            net_name = "${}[{}]".format(port_name,index)
            node.in_nets[port_name][0] = net_name

    def add_edge(self, parent, child, index):
        """Adds a directed edge to the tree, from child output to parent input
        All index ports on the parents's port list are connected to the child

        Args:
            parent (Node): The parent node
            child (Node): The child node
            index (int): The index of the parent's input port
        """
        if not isinstance(parent, Node):
            raise TypeError("Parent must be an Node")
        if not isinstance(child, Node):
            raise TypeError("Child must be an Node")
        if not isinstance(index, int):
            raise TypeError("index must be an integer")
        if index < -self.radix or index > self.radix-1:
            raise ValueError(("Tree nodes may not have more edges"
                              "than the radix of the tree"))

        # Normalize index
        index = index % self.radix

        # Get the parent and child ports
        parent_ports = modules[parent.value]["ins"]
        child_ports = modules[child.value]["outs"]

        # Attempt to connect all ports
        for port in parent_ports:
            if port[2+index] == 0:
                continue
            # This will raise an exception if the port is not found
            matching_port = get_matching_port(port, child_ports)
            # Figure out which bits of the port to connect to
            offset = 0
            for x in range(index):
                offset += port[2+x]
            # Add an edge for each bit of the port
            for b in range(port[2+index]):
                pin1 = (port[0], b+offset)
                pin2 = (matching_port[0], b)
                super().add_edge(parent, pin1, child, pin2)

        # Adjust x-pos and y-pos of the child
        ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
        ### TO-DO: Make this more general
        y_pos = parent.y_pos+1
        x_diff = 1

        if index == 0:
            x_pos = parent.x_pos + x_diff
        elif index == 1:
            x_pos = parent.x_pos - x_diff

        child.x_pos = x_pos
        child.y_pos = y_pos

        diagram_pos = "{0},{1}!".format(x_pos*-1, y_pos*-1)
        self.nodes[child]["pos"] = diagram_pos

    ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
    ### TO-DO: Make this more general
    def left_rotate(self, node):
        """Rotate a node to the left

        Args:
            node (Node): The node to rotate
        """
        if not isinstance(node, Node):
            raise TypeError("node must be an Node")
        if node.parent is None or len(node.parent.children) != self.radix:
            raise ValueError("Can only rotate nodes with full families")
        if node.parent[1] != node:
            raise ValueError("Can only rotate right children")

        # Get the parent and child nodes
        parent = node.parent
        lchild = node[0]
        rchild = node[1]
        plchild = node.parent[0]
        if parent.parent is None:
            thru_root = True
        else:
            thru_root = False
            parent_dir = parent.parent.children.index(parent)

        # Adjust the y-pos
        parent.y_pos += 1
        plchild.iter_down(lambda x: setattr(x, "y_pos", x.y_pos+1))
        lchild.y_pos -= 1
        node.iter_down(lambda x: setattr(x, "y_pos", x.y_pos-1))

        # Disconnect the nodes
        if not thru_root:
            self.remove_edge(parent.parent, parent)
        self.remove_edge(parent, node)
        self.remove_edge(node, lchild)
        if thru_root:
            self.remove_edge(parent, plchild)
            self.remove_edge(node, rchild)

        # If rotating through root, nodes must be morphed
        if thru_root:
            self.remove_node(parent)
            parent = parent.morph(self.node_defs["lspine"])
            self.add_node(parent)

            print(node)
            self.remove_node(node)
            node = node.morph(self.node_defs["root"])
            self.add_node(node)
            self.root = node
            self._connect_outports(self.root)
            print(node)

        # Rotate the nodes
        if not thru_root:
            self.add_edge(parent.parent, parent, parent_dir)
        self.add_edge(parent, lchild, 1)
        self.add_edge(node, parent, 0)
        if thru_root:
            self.add_edge(parent, plchild, 0)
            self.add_edge(node, rchild, 1)

        return node

    ### NOTE: THIS IS HARD-CODED FOR RADIX OF 2
    ### TO-DO: Make this more general
    def right_rotate(self, node):
        """Rotate a node to the right

        Args:
            node (Node): The node to rotate
        """
        if not isinstance(node, Node):
            raise TypeError("node must be an Node")
        if node.parent is None or len(node.parent.children) != self.radix:
            raise ValueError("Can only rotate nodes with full families")
        if node.parent[0] != node:
            raise ValueError("Can only rotate left children")

        # Get the parent and child nodes
        parent = node.parent
        rchild = node[1]
        lchild = node[0]
        prchild = node.parent[1]
        if parent.parent is None:
            thru_root = True
        else:
            thru_root = False
            parent_dir = parent.parent.children.index(parent)

        # Adjust the y-pos
        parent.y_pos -= 1
        prchild.iter_down(lambda x: setattr(x, "y_pos", x.y_pos-1))
        rchild.y_pos += 1
        node.iter_down(lambda x: setattr(x, "y_pos", x.y_pos+1))

        # Disconnect the nodes
        if not thru_root:
            self.remove_edge(parent.parent, parent)
        self.remove_edge(parent, node)
        self.remove_edge(node, rchild)
        if thru_root:
            self.remove_edge(parent, prchild)
            self.remove_edge(node, lchild)

        # If rotating through root, nodes must be morphed
        if thru_root:
            self.remove_node(parent)
            parent = parent.morph(self.node_defs["black"])
            self.add_node(parent)

            self.remove_node(node)
            node = node.morph(self.node_defs["root"])
            self.add_node(node)
            self.root = node
            self._connect_outports(self.root)

        # Rotate the nodes
        if not thru_root:
            self.add_edge(parent.parent, parent, parent_dir)
        self.add_edge(parent, rchild, 0)
        self.add_edge(node, parent, 1)
        if thru_root:
            self.add_edge(parent, prchild, 1)
            self.add_edge(node, lchild, 0)

        return node

    def _fix_diagram_positions(self):
        """Fix the positions of the nodes in the diagram"""

        depth = len(self)
        leafs = self._get_leafs()
        # Set x_pos of the leafs to consecutive numbers
        ctr = 0
        for leaf in leafs:
            leaf.x_pos = ctr
            ctr -= 1
        leafs[-1].x_pos -= 1
        # Adjust other nodes' x_pos based on the leafs
        for d in range(depth-1, -1, -1):
            for node in self._get_row(d):
                if len(node.children) > 0:
                    avg = sum([x.x_pos for x in node.children])/self.radix
                    node.x_pos = avg
                x_pos = node.x_pos
                y_pos = node.y_pos
                diagram_pos = "{0},{1}!".format(x_pos*-1, y_pos*-1)
                self.nodes[node]["pos"] = diagram_pos

    def png(self, fname="tree.png"):
        """Generate a PNG representation of the tree using GraphViz"""

        # Correct the positions of the nodes
        self._fix_diagram_positions()
        # Convert the graph to pydot
        pg = nx.drawing.nx_pydot.to_pydot(self)
        pg.set_splines("false")
        pg.set_concentrate("true")

        pg.write_dot(fname.replace(".png", ".dot"))
        pg.write_png(fname, prog="neato")

if __name__ == "__main__":
    raise RuntimeError("This file is importable, but not executable")
<|endoftext|>