<commit_before>"""Configuration details for specific server types.

This module contains functions that help with initializing a Fabric environment
for standard server types.
"""
import os
import subprocess

from fabric.api import env

from cloudbio.fabutils import configure_runsudo

def _setup_distribution_environment(ignore_distcheck=False):
    """Setup distribution environment
    """
    env.logger.info("Distribution %s" % env.distribution)

    if env.hosts == ["vagrant"]:
        _setup_vagrant_environment()
    elif env.hosts == ["localhost"]:
        _setup_local_environment()
    configure_runsudo(env)
    if env.distribution == "__auto__":
        env.distribution = _determine_distribution(env)
    if env.distribution == "ubuntu":
        ## TODO: Determine if dist_name check works with debian.
        if env.dist_name == "__auto__":
            env.dist_name = _ubuntu_dist_name(env)
        _setup_ubuntu()
    elif env.distribution == "centos":
        _setup_centos()
    elif env.distribution == "scientificlinux":
        _setup_scientificlinux()
    elif env.distribution == "debian":
        _setup_debian()
    else:
        raise ValueError("Unexpected distribution %s" % env.distribution)
    if not ignore_distcheck:
        _validate_target_distribution(env.distribution, env.get('dist_name', None))
    _cloudman_compatibility(env)
    _setup_nixpkgs()
    _setup_fullpaths(env)
    # allow us to check for packages only available on 64bit machines
    machine = env.safe_run_output("uname -m")
    env.is_64bit = machine.find("_64") > 0

def _setup_fullpaths(env):
    home_dir = env.safe_run_output("echo $HOME")
    for attr in ["data_files", "galaxy_home", "local_install"]:
        if hasattr(env, attr):
            x = getattr(env, attr)
            if x.startswith("~"):
                x = x.replace("~", home_dir)
                setattr(env, attr, x)

def _cloudman_compatibility(env):
    """Environmental variable naming for compatibility with CloudMan.
    """
    env.install_dir = env.system_install

def _validate_target_distribution(dist, dist_name=None):
    """Check target matches environment setting (for sanity)

    Throws exception on error
    """
    env.logger.debug("Checking target distribution " + env.distribution)
    if dist in ["debian", "ubuntu"]:
        tag = env.safe_run_output("cat /proc/version")
        if tag.lower().find(dist) == -1:
           # hmmm, test issue file
            tag2 = env.safe_run_output("cat /etc/issue")
            if tag2.lower().find(dist) == -1:
                raise ValueError("Distribution does not match machine; are you using correct fabconfig for " + dist)
        if env.edition.short_name in ["minimal"]:
            # "minimal editions don't actually change any of the apt
            # source except adding biolinux, so won't cause this
            # problem and don't need to match dist_name"
            return
        if not dist_name:
            raise ValueError("Must specify a dist_name property when working with distribution %s" % dist)
        # Does this new method work with CentOS, do we need this.
        actual_dist_name = _ubuntu_dist_name(env)
        if actual_dist_name != dist_name:
            raise ValueError("Distribution does not match machine; are you using correct fabconfig for " + dist)
    else:
        env.logger.debug("Unknown target distro")

def _setup_ubuntu():
    env.logger.info("Ubuntu setup")
    shared_sources = _setup_deb_general()
    # package information. This is ubuntu/debian based and could be generalized.
    sources = [
      "deb http://us.archive.ubuntu.com/ubuntu/ %s universe",  # unsupported repos
      "deb http://us.archive.ubuntu.com/ubuntu/ %s multiverse",
      "deb http://us.archive.ubuntu.com/ubuntu/ %s-updates universe",
      "deb http://us.archive.ubuntu.com/ubuntu/ %s-updates multiverse",
      "deb http://archive.canonical.com/ubuntu %s partner",  # partner repositories
      "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen",  # mongodb
      "deb http://watson.nci.nih.gov/cran_mirror/bin/linux/ubuntu %s/",  # lastest R versions
      "deb http://archive.cloudera.com/debian maverick-cdh3 contrib",  # Hadoop
      "deb http://archive.canonical.com/ubuntu %s partner",  # sun-java
      "deb http://ppa.launchpad.net/freenx-team/ppa/ubuntu precise main",  # Free-NX
      "deb http://ppa.launchpad.net/nebc/bio-linux/ubuntu precise main",  # Free-NX
      "deb [arch=amd64 trusted=yes] http://research.cs.wisc.edu/htcondor/debian/stable/ squeeze contrib"  # HTCondor
    ] + shared_sources
    env.std_sources = _add_source_versions(env.dist_name, sources)

def _setup_debian():
    env.logger.info("Debian setup")
    unstable_remap = {"sid": "squeeze"}
    shared_sources = _setup_deb_general()
    sources = [
        "deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen", # mongodb
        "deb http://watson.nci.nih.gov/cran_mirror/bin/linux/debian %s-cran/", # lastest R versions
        "deb http://archive.cloudera.com/debian lenny-cdh3 contrib" # Hadoop
        ] + shared_sources
    # fill in %s
    dist_name = unstable_remap.get(env.dist_name, env.dist_name)
    env.std_sources = _add_source_versions(dist_name, sources)

def _setup_deb_general():
    """Shared settings for different debian based/derived distributions.
    """
    env.logger.debug("Debian-shared setup")
    env.sources_file = "/etc/apt/sources.list.d/cloudbiolinux.list"
    env.global_sources_file = "/etc/apt/sources.list"
    env.apt_preferences_file = "/etc/apt/preferences"
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = ""
    if not hasattr(env, "ruby_version_ext"):
        env.ruby_version_ext = "1.9.1"
    if not env.has_key("java_home"):
        # XXX look for a way to find JAVA_HOME automatically
        env.java_home = "/usr/lib/jvm/java-7-openjdk-amd64"
    shared_sources = [
        "deb http://nebc.nerc.ac.uk/bio-linux/ unstable bio-linux", # Bio-Linux
        "deb http://download.virtualbox.org/virtualbox/debian %s contrib", # virtualbox
    ]
    return shared_sources

def _setup_centos():
    env.logger.info("CentOS setup")
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = "2.6"
    if not hasattr(env, "ruby_version_ext"):
        env.ruby_version_ext = ""
    env.pip_cmd = "pip-python"
    if not env.has_key("java_home"):
        env.java_home = "/etc/alternatives/java_sdk"

def _setup_scientificlinux():
    env.logger.info("ScientificLinux setup")
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = ""
    env.pip_cmd = "pip-python"
    if not env.has_key("java_home"):
        env.java_home = "/etc/alternatives/java_sdk"

def _setup_nixpkgs():
    # for now, Nix packages are only supported in Debian - it can
    # easily be done for others - just get Nix installed from the .rpm
    nixpkgs = False
    if env.has_key("nixpkgs"):
        if env.distribution in ["debian", "ubuntu"]:
            if env.nixpkgs == "True":
                nixpkgs = True
            else:
                nixpkgs = False
        else:
            env.logger.warn("NixPkgs are currently not supported for " + env.distribution)
    if nixpkgs:
        env.logger.info("NixPkgs: supported")
    else:
        env.logger.debug("NixPkgs: Ignored")
    env.nixpkgs = nixpkgs

def _setup_local_environment():
    """Setup a localhost environment based on system variables.
    """
    env.logger.info("Get local environment")
    if not env.has_key("user"):
        env.user = os.environ["USER"]
    if not env.has_key("java_home"):
        env.java_home = os.environ.get("JAVA_HOME", "/usr/lib/jvm/java-6-openjdk")

def _setup_vagrant_environment():
    """Use vagrant commands to get connection information.
    https://gist.github.com/1d4f7c3e98efdf860b7e
    """
    env.logger.info("Get vagrant environment")
    raw_ssh_config = subprocess.Popen(["vagrant", "ssh-config"],
                                      stdout=subprocess.PIPE).communicate()[0]
    env.logger.info(raw_ssh_config)
    ssh_config = dict([l.strip().split() for l in raw_ssh_config.split("\n") if l])
    env.user = ssh_config["User"]
    env.hosts = [ssh_config["HostName"]]
    env.port = ssh_config["Port"]
    env.host_string = "%s@%s:%s" % (env.user, env.hosts[0], env.port)
    env.key_filename = ssh_config["IdentityFile"].replace('"', '')
    env.logger.debug("ssh %s" % env.host_string)

def _add_source_versions(version, sources):
    """Patch package source strings for version, e.g. Debian 'stable'
    """
    name = version
    env.logger.debug("Source=%s" % name)
    final = []
    for s in sources:
        if s.find("%s") > 0:
            s = s % name
        final.append(s)
    return final

def _ubuntu_dist_name(env):
    """
    Determine Ubuntu dist name (e.g. precise or quantal).
    """
    return env.safe_run_output("cat /etc/*release | grep DISTRIB_CODENAME | cut -f 2 -d =")

def _determine_distribution(env):
    """
    Attempt to automatically determine the distribution of the target machine.

    Currently works for Ubuntu and CentOS.

    TODO: Add ability to auto-determine scientificlinux and Debian as well.
    """
    output = env.safe_run_output("cat /etc/*release").lower()
    if output.find("distrib_id=ubuntu") >= 0:
        return "ubuntu"
    elif output.find("centos release") >= 0:
        return "centos"
    else:
        raise Exception("Attempt to automatically determine Linux distribution of target machine failed, please manually specify distribution in fabricrc.txt")
<commit_msg>Add automatic distribution checks for debian, scientific linux and mac os x. #81<commit_after>"""Configuration details for specific server types.

This module contains functions that help with initializing a Fabric environment
for standard server types.
"""
import os
import subprocess

from fabric.api import env, quiet

from cloudbio.fabutils import configure_runsudo

def _setup_distribution_environment(ignore_distcheck=False):
    """Setup distribution environment
    """
    env.logger.info("Distribution %s" % env.distribution)

    if env.hosts == ["vagrant"]:
        _setup_vagrant_environment()
    elif env.hosts == ["localhost"]:
        _setup_local_environment()
    configure_runsudo(env)
    if env.distribution == "__auto__":
        env.distribution = _determine_distribution(env)
    if env.distribution == "ubuntu":
        ## TODO: Determine if dist_name check works with debian.
        if env.dist_name == "__auto__":
            env.dist_name = _ubuntu_dist_name(env)
        _setup_ubuntu()
    elif env.distribution == "centos":
        _setup_centos()
    elif env.distribution == "scientificlinux":
        _setup_scientificlinux()
    elif env.distribution == "debian":
        _setup_debian()
    else:
        raise ValueError("Unexpected distribution %s" % env.distribution)
    if not ignore_distcheck:
        _validate_target_distribution(env.distribution, env.get('dist_name', None))
    _cloudman_compatibility(env)
    _setup_nixpkgs()
    _setup_fullpaths(env)
    # allow us to check for packages only available on 64bit machines
    machine = env.safe_run_output("uname -m")
    env.is_64bit = machine.find("_64") > 0

def _setup_fullpaths(env):
    home_dir = env.safe_run_output("echo $HOME")
    for attr in ["data_files", "galaxy_home", "local_install"]:
        if hasattr(env, attr):
            x = getattr(env, attr)
            if x.startswith("~"):
                x = x.replace("~", home_dir)
                setattr(env, attr, x)

def _cloudman_compatibility(env):
    """Environmental variable naming for compatibility with CloudMan.
    """
    env.install_dir = env.system_install

def _validate_target_distribution(dist, dist_name=None):
    """Check target matches environment setting (for sanity)

    Throws exception on error
    """
    env.logger.debug("Checking target distribution " + env.distribution)
    if dist in ["debian", "ubuntu"]:
        tag = env.safe_run_output("cat /proc/version")
        if tag.lower().find(dist) == -1:
           # hmmm, test issue file
            tag2 = env.safe_run_output("cat /etc/issue")
            if tag2.lower().find(dist) == -1:
                raise ValueError("Distribution does not match machine; are you using correct fabconfig for " + dist)
        if env.edition.short_name in ["minimal"]:
            # "minimal editions don't actually change any of the apt
            # source except adding biolinux, so won't cause this
            # problem and don't need to match dist_name"
            return
        if not dist_name:
            raise ValueError("Must specify a dist_name property when working with distribution %s" % dist)
        # Does this new method work with CentOS, do we need this.
        actual_dist_name = _ubuntu_dist_name(env)
        if actual_dist_name != dist_name:
            raise ValueError("Distribution does not match machine; are you using correct fabconfig for " + dist)
    else:
        env.logger.debug("Unknown target distro")

def _setup_ubuntu():
    env.logger.info("Ubuntu setup")
    shared_sources = _setup_deb_general()
    # package information. This is ubuntu/debian based and could be generalized.
    sources = [
      "deb http://us.archive.ubuntu.com/ubuntu/ %s universe",  # unsupported repos
      "deb http://us.archive.ubuntu.com/ubuntu/ %s multiverse",
      "deb http://us.archive.ubuntu.com/ubuntu/ %s-updates universe",
      "deb http://us.archive.ubuntu.com/ubuntu/ %s-updates multiverse",
      "deb http://archive.canonical.com/ubuntu %s partner",  # partner repositories
      "deb http://downloads-distro.mongodb.org/repo/ubuntu-upstart dist 10gen",  # mongodb
      "deb http://watson.nci.nih.gov/cran_mirror/bin/linux/ubuntu %s/",  # lastest R versions
      "deb http://archive.cloudera.com/debian maverick-cdh3 contrib",  # Hadoop
      "deb http://archive.canonical.com/ubuntu %s partner",  # sun-java
      "deb http://ppa.launchpad.net/freenx-team/ppa/ubuntu precise main",  # Free-NX
      "deb http://ppa.launchpad.net/nebc/bio-linux/ubuntu precise main",  # Free-NX
      "deb [arch=amd64 trusted=yes] http://research.cs.wisc.edu/htcondor/debian/stable/ squeeze contrib"  # HTCondor
    ] + shared_sources
    env.std_sources = _add_source_versions(env.dist_name, sources)

def _setup_debian():
    env.logger.info("Debian setup")
    unstable_remap = {"sid": "squeeze"}
    shared_sources = _setup_deb_general()
    sources = [
        "deb http://downloads-distro.mongodb.org/repo/debian-sysvinit dist 10gen", # mongodb
        "deb http://watson.nci.nih.gov/cran_mirror/bin/linux/debian %s-cran/", # lastest R versions
        "deb http://archive.cloudera.com/debian lenny-cdh3 contrib" # Hadoop
        ] + shared_sources
    # fill in %s
    dist_name = unstable_remap.get(env.dist_name, env.dist_name)
    env.std_sources = _add_source_versions(dist_name, sources)

def _setup_deb_general():
    """Shared settings for different debian based/derived distributions.
    """
    env.logger.debug("Debian-shared setup")
    env.sources_file = "/etc/apt/sources.list.d/cloudbiolinux.list"
    env.global_sources_file = "/etc/apt/sources.list"
    env.apt_preferences_file = "/etc/apt/preferences"
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = ""
    if not hasattr(env, "ruby_version_ext"):
        env.ruby_version_ext = "1.9.1"
    if not env.has_key("java_home"):
        # XXX look for a way to find JAVA_HOME automatically
        env.java_home = "/usr/lib/jvm/java-7-openjdk-amd64"
    shared_sources = [
        "deb http://nebc.nerc.ac.uk/bio-linux/ unstable bio-linux", # Bio-Linux
        "deb http://download.virtualbox.org/virtualbox/debian %s contrib", # virtualbox
    ]
    return shared_sources

def _setup_centos():
    env.logger.info("CentOS setup")
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = "2.6"
    if not hasattr(env, "ruby_version_ext"):
        env.ruby_version_ext = ""
    env.pip_cmd = "pip-python"
    if not env.has_key("java_home"):
        env.java_home = "/etc/alternatives/java_sdk"

def _setup_scientificlinux():
    env.logger.info("ScientificLinux setup")
    if not hasattr(env, "python_version_ext"):
        env.python_version_ext = ""
    env.pip_cmd = "pip-python"
    if not env.has_key("java_home"):
        env.java_home = "/etc/alternatives/java_sdk"

def _setup_nixpkgs():
    # for now, Nix packages are only supported in Debian - it can
    # easily be done for others - just get Nix installed from the .rpm
    nixpkgs = False
    if env.has_key("nixpkgs"):
        if env.distribution in ["debian", "ubuntu"]:
            if env.nixpkgs == "True":
                nixpkgs = True
            else:
                nixpkgs = False
        else:
            env.logger.warn("NixPkgs are currently not supported for " + env.distribution)
    if nixpkgs:
        env.logger.info("NixPkgs: supported")
    else:
        env.logger.debug("NixPkgs: Ignored")
    env.nixpkgs = nixpkgs

def _setup_local_environment():
    """Setup a localhost environment based on system variables.
    """
    env.logger.info("Get local environment")
    if not env.has_key("user"):
        env.user = os.environ["USER"]
    if not env.has_key("java_home"):
        env.java_home = os.environ.get("JAVA_HOME", "/usr/lib/jvm/java-6-openjdk")

def _setup_vagrant_environment():
    """Use vagrant commands to get connection information.
    https://gist.github.com/1d4f7c3e98efdf860b7e
    """
    env.logger.info("Get vagrant environment")
    raw_ssh_config = subprocess.Popen(["vagrant", "ssh-config"],
                                      stdout=subprocess.PIPE).communicate()[0]
    env.logger.info(raw_ssh_config)
    ssh_config = dict([l.strip().split() for l in raw_ssh_config.split("\n") if l])
    env.user = ssh_config["User"]
    env.hosts = [ssh_config["HostName"]]
    env.port = ssh_config["Port"]
    env.host_string = "%s@%s:%s" % (env.user, env.hosts[0], env.port)
    env.key_filename = ssh_config["IdentityFile"].replace('"', '')
    env.logger.debug("ssh %s" % env.host_string)

def _add_source_versions(version, sources):
    """Patch package source strings for version, e.g. Debian 'stable'
    """
    name = version
    env.logger.debug("Source=%s" % name)
    final = []
    for s in sources:
        if s.find("%s") > 0:
            s = s % name
        final.append(s)
    return final

def _ubuntu_dist_name(env):
    """
    Determine Ubuntu dist name (e.g. precise or quantal).
    """
    return env.safe_run_output("cat /etc/*release | grep DISTRIB_CODENAME | cut -f 2 -d =")

def _determine_distribution(env):
    """
    Attempt to automatically determine the distribution of the target machine.

    Currently works for Ubuntu, CentOS, Debian, Scientific Linux and Mac OS X.
    """
    with quiet():
        output = env.safe_run_output("cat /etc/*release").lower()
    if output.find("distrib_id=ubuntu") >= 0:
        return "ubuntu"
    elif output.find("centos release") >= 0:
        return "centos"
    elif output.find("scientific linux release") >= 0:
        return "scientificlinux"
    elif env.safe_exists("/etc/debian_version"):
        return "debian"
    # check for file used by Python's platform.mac_ver
    elif env.safe_exists("/System/Library/CoreServices/SystemVersion.plist"):
        return "macosx"
    else:
        raise Exception("Attempt to automatically determine Linux distribution of target machine failed, please manually specify distribution in fabricrc.txt")
<|endoftext|>


<commit_before># Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
import logging
import re
from pathlib import Path
from typing import Any, Dict

import yaml
from pkg_resources import resource_isdir, resource_listdir, resource_stream

from superset.commands.exceptions import CommandInvalidError
from superset.commands.importers.v1.examples import ImportExamplesCommand
from superset.commands.importers.v1.utils import METADATA_FILE_NAME

_logger = logging.getLogger(__name__)

YAML_EXTENSIONS = {".yaml", ".yml"}

def load_examples_from_configs(
    force_data: bool = False, load_test_data: bool = False
) -> None:
    """
    Load all the examples inside superset/examples/configs/.
    """
    contents = load_contents(load_test_data)
    command = ImportExamplesCommand(contents, overwrite=True, force_data=force_data)
    command.run()

def load_contents(load_test_data: bool = False) -> Dict[str, Any]:
    """Traverse configs directory and load contents"""
    root = Path("examples/configs")
    resource_names = resource_listdir("superset", str(root))
    queue = [root / resource_name for resource_name in resource_names]

    contents: Dict[Path, str] = {}
    while queue:
        path_name = queue.pop()
        test_re = re.compile(r"\.test\.|metadata\.yaml$")

        if resource_isdir("superset", str(path_name)):
            queue.extend(
                path_name / child_name
                for child_name in resource_listdir("superset", str(path_name))
            )
        elif path_name.suffix.lower() in YAML_EXTENSIONS:
            if load_test_data and test_re.search(str(path_name)) is None:
                continue
            contents[path_name] = (
                resource_stream("superset", str(path_name)).read().decode("utf-8")
            )

    return {str(path.relative_to(root)): content for path, content in contents.items()}

def load_configs_from_directory(
    root: Path, overwrite: bool = True, force_data: bool = False
) -> None:
    """
    Load all the examples from a given directory.
    """
    contents: Dict[str, str] = {}
    queue = [root]
    while queue:
        path_name = queue.pop()
        if path_name.is_dir():
            queue.extend(path_name.glob("*"))
        elif path_name.suffix.lower() in YAML_EXTENSIONS:
            with open(path_name) as fp:
                contents[str(path_name.relative_to(root))] = fp.read()

    # removing "type" from the metadata allows us to import any exported model
    # from the unzipped directory directly
    metadata = yaml.load(contents.get(METADATA_FILE_NAME, "{}"))
    if "type" in metadata:
        del metadata["type"]
    contents[METADATA_FILE_NAME] = yaml.dump(metadata)

    command = ImportExamplesCommand(
        contents, overwrite=overwrite, force_data=force_data
    )
    try:
        command.run()
    except CommandInvalidError as ex:
        _logger.error("An error occurred: %s", ex.normalized_messages())
<commit_msg>fix: CI is blocked by mypy checking (#17213)<commit_after># Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
# KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
import logging
import re
from pathlib import Path
from typing import Any, Dict

import yaml
from pkg_resources import resource_isdir, resource_listdir, resource_stream

from superset.commands.exceptions import CommandInvalidError
from superset.commands.importers.v1.examples import ImportExamplesCommand
from superset.commands.importers.v1.utils import METADATA_FILE_NAME

_logger = logging.getLogger(__name__)

YAML_EXTENSIONS = {".yaml", ".yml"}

def load_examples_from_configs(
    force_data: bool = False, load_test_data: bool = False
) -> None:
    """
    Load all the examples inside superset/examples/configs/.
    """
    contents = load_contents(load_test_data)
    command = ImportExamplesCommand(contents, overwrite=True, force_data=force_data)
    command.run()

def load_contents(load_test_data: bool = False) -> Dict[str, Any]:
    """Traverse configs directory and load contents"""
    root = Path("examples/configs")
    resource_names = resource_listdir("superset", str(root))
    queue = [root / resource_name for resource_name in resource_names]

    contents: Dict[Path, str] = {}
    while queue:
        path_name = queue.pop()
        test_re = re.compile(r"\.test\.|metadata\.yaml$")

        if resource_isdir("superset", str(path_name)):
            queue.extend(
                path_name / child_name
                for child_name in resource_listdir("superset", str(path_name))
            )
        elif path_name.suffix.lower() in YAML_EXTENSIONS:
            if load_test_data and test_re.search(str(path_name)) is None:
                continue
            contents[path_name] = (
                resource_stream("superset", str(path_name)).read().decode("utf-8")
            )

    return {str(path.relative_to(root)): content for path, content in contents.items()}

def load_configs_from_directory(
    root: Path, overwrite: bool = True, force_data: bool = False
) -> None:
    """
    Load all the examples from a given directory.
    """
    contents: Dict[str, str] = {}
    queue = [root]
    while queue:
        path_name = queue.pop()
        if path_name.is_dir():
            queue.extend(path_name.glob("*"))
        elif path_name.suffix.lower() in YAML_EXTENSIONS:
            with open(path_name) as fp:
                contents[str(path_name.relative_to(root))] = fp.read()

    # removing "type" from the metadata allows us to import any exported model
    # from the unzipped directory directly
    metadata = yaml.load(contents.get(METADATA_FILE_NAME, "{}"), Loader=None)
    if "type" in metadata:
        del metadata["type"]
    contents[METADATA_FILE_NAME] = yaml.dump(metadata)

    command = ImportExamplesCommand(
        contents, overwrite=overwrite, force_data=force_data
    )
    try:
        command.run()
    except CommandInvalidError as ex:
        _logger.error("An error occurred: %s", ex.normalized_messages())
<|endoftext|>


<commit_before>from werkzeug.exceptions import BadRequest

from .participant_summary_dao import ParticipantSummaryDao
from model.participant_summary import ParticipantSummary
from participant_enums import EnrollmentStatus, TEST_HPO_NAME, TEST_EMAIL_PATTERN
from participant_enums import WithdrawalStatus
from dao.hpo_dao import HPODao

class ParticipantCountsOverTimeService(ParticipantSummaryDao):

  def __init__(self):
    super(ParticipantSummaryDao, self).__init__(ParticipantSummary)

  def get_filtered_results(self, start_date, end_date, filters, stratification='ENROLLMENT_STATUS'):
    """Queries DB, returns results in format consumed by front-end

    :param start_date: Start date object
    :param end_date: End date object
    :param filters: Objects representing filters specified in UI
    :param stratification: How to stratify (layer) results, as in a stacked bar chart
    :return: Filtered, stratified results by date
    """

    self.test_hpo_id = HPODao().get_by_name(TEST_HPO_NAME).hpoId
    self.test_email_pattern = TEST_EMAIL_PATTERN

    # Filters for participant_summary (ps) and participant (p) table
    # filters_sql_ps is used in the general case when we're querying participant_summary
    # filters_sql_p is used when also LEFT OUTER JOINing p and ps
    filters_sql_ps = self.get_facets_sql(filters)
    filters_sql_p = self.get_facets_sql(filters, table_prefix='p')

    if str(stratification) == 'TOTAL':
      strata = ['TOTAL']
      sql = self.get_total_sql(filters_sql_ps)
    elif str(stratification) == 'ENROLLMENT_STATUS':
      strata = [str(val) for val in EnrollmentStatus]
      sql = self.get_enrollment_status_sql(filters_sql_ps, filters_sql_p)
    else:
      raise BadRequest('Invalid stratification: %s' % stratification)

    params = {'start_date': start_date, 'end_date': end_date}

    results_by_date = []

    with self.session() as session:
      cursor = session.execute(sql, params)

    # Iterate through each result (by date), transforming tabular SQL results
    # into expected list-of-dictionaries response format
    try:
      results = cursor.fetchall()
      for result in results:
        date = result[-1]
        metrics = {}
        values = result[:-1]
        for i, value in enumerate(values):
          key = strata[i]
          if value == None:
            value = 0
          metrics[key] = int(value)
        results_by_date.append({
          'date': str(date),
          'metrics': metrics
        })
    finally:
      cursor.close()

    return results_by_date

  def get_facets_sql(self, facets, table_prefix='ps'):
    """Helper function to transform facets/filters selection into SQL

    :param facets: Object representing facets and filters to apply to query results
    :param table_prefix: Either 'ps' (for participant_summary) or 'p' (for participant)
    :return: SQL for 'WHERE' clause, reflecting filters specified in UI
    """

    facets_sql = 'WHERE'
    facets_sql_list = []

    facet_map = {
      'awardee_ids': 'hpo_id',
      'enrollment_statuses': 'enrollment_status'
    }

    for facet in facets:
      filters_sql = []
      db_field = facet_map[facet]
      filters = facets[facet]

      if db_field == 'enrollment_status':
        table_prefix = 'ps'

      # TODO:
      # Consider using an IN clause with bound parameters, instead, which
      # would be simpler than this,
      #
      # TODO:
      # Consider using bound parameters here instead of inlining the values
      # in the SQL. We do that in other places using this function:
      #
      # dao/database_utils.py#L16
      #
      # This may help the SQL perform slightly better since the execution
      # plan for the query can be cached when the only thing changing are
      # the bound params.
      for q_filter in filters:
        if str(q_filter) != '':
          filters_sql.append(table_prefix + '.' + db_field + ' = ' + str(int(q_filter)))
      if len(filters_sql) > 0:
        filters_sql = '(' + ' OR '.join(filters_sql) + ')'
        facets_sql_list.append(filters_sql)

    if len(facets_sql_list) > 0:
      facets_sql += ' AND '.join(facets_sql_list) + ' AND'

    # TODO: use bound parameters
    # See https://github.com/all-of-us/raw-data-repository/pull/669/files/a08be0ffe445da60ebca13b41d694368e4d42617#diff-6c62346e0cbe4a7fd7a45af6d4559c3e  # pylint: disable=line-too-long
    facets_sql += ' %(table_prefix)s.hpo_id != %(test_hpo_id)s ' % {
      'table_prefix': table_prefix, 'test_hpo_id': self.test_hpo_id}
    facets_sql += ' AND (ps.email IS NULL OR NOT ps.email LIKE "%(test_email_pattern)s")' % {
      'test_email_pattern': self.test_email_pattern}
    facets_sql += ' AND %(table_prefix)s.withdrawal_status = %(not_withdrawn)i' % {
      'table_prefix': table_prefix, 'not_withdrawn': WithdrawalStatus.NOT_WITHDRAWN}

    return facets_sql

  def get_total_sql(self, filters_sql):

    sql = """
        SELECT
            SUM(ps_sum.cnt * (ps_sum.day <= calendar.day)) registered_count,
            calendar.day start_date
        FROM calendar,
        (SELECT COUNT(*) cnt, DATE(p.sign_up_time) day
        FROM participant p
        LEFT OUTER JOIN participant_summary ps ON p.participant_id = ps.participant_id
        %(filters)s
        GROUP BY day) ps_sum
        WHERE calendar.day >= :start_date
        AND calendar.day <= :end_date
        GROUP BY calendar.day
        ORDER BY calendar.day;
      """ % {'filters': filters_sql}

    return sql

  def get_enrollment_status_sql(self, filters_sql_ps, filters_sql_p):

    # Noteworthy comments / documentation from Dan (and lightly adapted)
    #
    # This SQL works OK but hardcodes the baseline questionnaires and the
    # fact that 1ED04 and 1SAL are the samples needed to be a full
    # participant into the SQL. Previously this was done with config:
    #
    # rest-api/config/base_config.json#L29
    #
    # For the samples, MySQL doesn't make it easy to do the LEAST of N
    # nullable values, so this is probably OK...
    #
    # For the baseline questionnaires, note that we might want to use the config to
    # generate the GREATEST statement instead, but for now are hardcoding as
    # we do with samples.

    # TODO when implementing unit testing for service class:
    # Add macros for GREATEST and LEAST, as they don't work in SQLite
    # Example: master/rest-api/dao/database_utils.py#L50

    sql = """
      SELECT
         SUM(registered_cnt * (cnt_day <= calendar.day)) registered_participants,
         SUM(member_cnt * (cnt_day <= calendar.day)) member_participants,
         SUM(full_cnt * (cnt_day <= calendar.day)) full_participants,
         calendar.day
       FROM
       (SELECT c2.day cnt_day,
               registered.cnt registered_cnt,
               member.cnt member_cnt,
               full.cnt full_cnt
            FROM calendar c2
            LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
                (CASE WHEN (enrollment_status = 1 OR enrollment_status IS NULL) THEN
                  DATE(p.sign_up_time)
                  ELSE NULL END) day
                FROM participant p
                LEFT OUTER JOIN participant_summary ps ON p.participant_id = ps.participant_id
              %(filters_p)s
              GROUP BY day) registered
             ON c2.day = registered.day
           LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
                   (CASE WHEN enrollment_status = 2 THEN
                    DATE(ps.consent_for_electronic_health_records_time)
                    ELSE NULL END) day
               FROM participant_summary ps
              %(filters_ps)s
           GROUP BY day) member
             ON c2.day = member.day
           LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
             DATE(CASE WHEN enrollment_status = 3 THEN
                   GREATEST(consent_for_electronic_health_records_time,
                            questionnaire_on_the_basics_time,
                            questionnaire_on_lifestyle_time,
                            questionnaire_on_overall_health_time,
                            physical_measurements_finalized_time,
                           CASE WHEN
                                LEAST(
                                    COALESCE(sample_order_status_1ed04_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1ed10_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal2_time, '3000-01-01')
                                    ) = '3001-01-01' THEN NULL
                                ELSE LEAST(
                                    COALESCE(sample_order_status_1ed04_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1ed10_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal2_time, '3000-01-01')
                                    )
                           END)
                END) day
               FROM participant_summary ps
              %(filters_ps)s
           GROUP BY day) full
             ON c2.day = full.day) day_sums, calendar
          WHERE calendar.day >= :start_date
            AND calendar.day <= :end_date
          GROUP BY calendar.day
          ORDER BY calendar.day;
      """ % {'filters_ps': filters_sql_ps, 'filters_p': filters_sql_p}

    return sql
<commit_msg>Fix INTERESTED filter in Metrics API 2 (#685)<commit_after>from werkzeug.exceptions import BadRequest

from .participant_summary_dao import ParticipantSummaryDao
from model.participant_summary import ParticipantSummary
from participant_enums import EnrollmentStatus, TEST_HPO_NAME, TEST_EMAIL_PATTERN
from participant_enums import WithdrawalStatus
from dao.hpo_dao import HPODao

class ParticipantCountsOverTimeService(ParticipantSummaryDao):

  def __init__(self):
    super(ParticipantSummaryDao, self).__init__(ParticipantSummary)

  def get_filtered_results(self, start_date, end_date, filters, stratification='ENROLLMENT_STATUS'):
    """Queries DB, returns results in format consumed by front-end

    :param start_date: Start date object
    :param end_date: End date object
    :param filters: Objects representing filters specified in UI
    :param stratification: How to stratify (layer) results, as in a stacked bar chart
    :return: Filtered, stratified results by date
    """

    self.test_hpo_id = HPODao().get_by_name(TEST_HPO_NAME).hpoId
    self.test_email_pattern = TEST_EMAIL_PATTERN

    # Filters for participant_summary (ps) and participant (p) table
    # filters_sql_ps is used in the general case when we're querying participant_summary
    # filters_sql_p is used when also LEFT OUTER JOINing p and ps
    filters_sql_ps = self.get_facets_sql(filters)
    filters_sql_p = self.get_facets_sql(filters, table_prefix='p')

    if str(stratification) == 'TOTAL':
      strata = ['TOTAL']
      sql = self.get_total_sql(filters_sql_ps)
    elif str(stratification) == 'ENROLLMENT_STATUS':
      strata = [str(val) for val in EnrollmentStatus]
      sql = self.get_enrollment_status_sql(filters_sql_ps, filters_sql_p)
    else:
      raise BadRequest('Invalid stratification: %s' % stratification)

    params = {'start_date': start_date, 'end_date': end_date}

    results_by_date = []

    with self.session() as session:
      cursor = session.execute(sql, params)

    # Iterate through each result (by date), transforming tabular SQL results
    # into expected list-of-dictionaries response format
    try:
      results = cursor.fetchall()
      for result in results:
        date = result[-1]
        metrics = {}
        values = result[:-1]
        for i, value in enumerate(values):
          key = strata[i]
          if value == None:
            value = 0
          metrics[key] = int(value)
        results_by_date.append({
          'date': str(date),
          'metrics': metrics
        })
    finally:
      cursor.close()

    return results_by_date

  def get_facets_sql(self, facets, table_prefix='ps'):
    """Helper function to transform facets/filters selection into SQL

    :param facets: Object representing facets and filters to apply to query results
    :param table_prefix: Either 'ps' (for participant_summary) or 'p' (for participant)
    :return: SQL for 'WHERE' clause, reflecting filters specified in UI
    """

    facets_sql = 'WHERE'
    facets_sql_list = []

    facet_map = {
      'awardee_ids': 'hpo_id',
      'enrollment_statuses': 'enrollment_status'
    }

    for facet in facets:
      filter_prefix = table_prefix
      filters_sql = []
      db_field = facet_map[facet]
      filters = facets[facet]

      allow_null = False
      if db_field == 'enrollment_status':
        filter_prefix = 'ps'
        allow_null = True

      # TODO:
      # Consider using an IN clause with bound parameters, instead, which
      # would be simpler than this,
      #
      # TODO:
      # Consider using bound parameters here instead of inlining the values
      # in the SQL. We do that in other places using this function:
      #
      # dao/database_utils.py#L16
      #
      # This may help the SQL perform slightly better since the execution
      # plan for the query can be cached when the only thing changing are
      # the bound params.
      for q_filter in filters:
        if str(q_filter) != '':
          filter_sql = filter_prefix + '.' + db_field + ' = ' + str(int(q_filter))
          if allow_null:
            filters_sql.append('(' + filter_sql + ' or ' + filter_prefix
                               + '.' + db_field + ' IS NULL)')
          else:
            filters_sql.append(filter_sql)
      if len(filters_sql) > 0:
        filters_sql = '(' + ' OR '.join(filters_sql) + ')'
        facets_sql_list.append(filters_sql)

    if len(facets_sql_list) > 0:
      facets_sql += ' AND '.join(facets_sql_list) + ' AND'

    # TODO: use bound parameters
    # See https://github.com/all-of-us/raw-data-repository/pull/669/files/a08be0ffe445da60ebca13b41d694368e4d42617#diff-6c62346e0cbe4a7fd7a45af6d4559c3e  # pylint: disable=line-too-long
    facets_sql += ' %(table_prefix)s.hpo_id != %(test_hpo_id)s ' % {
      'table_prefix': table_prefix, 'test_hpo_id': self.test_hpo_id}
    facets_sql += ' AND (ps.email IS NULL OR NOT ps.email LIKE "%(test_email_pattern)s")' % {
      'test_email_pattern': self.test_email_pattern}
    facets_sql += ' AND %(table_prefix)s.withdrawal_status = %(not_withdrawn)i' % {
      'table_prefix': table_prefix, 'not_withdrawn': WithdrawalStatus.NOT_WITHDRAWN}

    return facets_sql

  def get_total_sql(self, filters_sql):

    sql = """
        SELECT
            SUM(ps_sum.cnt * (ps_sum.day <= calendar.day)) registered_count,
            calendar.day start_date
        FROM calendar,
        (SELECT COUNT(*) cnt, DATE(p.sign_up_time) day
        FROM participant p
        LEFT OUTER JOIN participant_summary ps ON p.participant_id = ps.participant_id
        %(filters)s
        GROUP BY day) ps_sum
        WHERE calendar.day >= :start_date
        AND calendar.day <= :end_date
        GROUP BY calendar.day
        ORDER BY calendar.day;
      """ % {'filters': filters_sql}

    return sql

  def get_enrollment_status_sql(self, filters_sql_ps, filters_sql_p):

    # Noteworthy comments / documentation from Dan (and lightly adapted)
    #
    # This SQL works OK but hardcodes the baseline questionnaires and the
    # fact that 1ED04 and 1SAL are the samples needed to be a full
    # participant into the SQL. Previously this was done with config:
    #
    # rest-api/config/base_config.json#L29
    #
    # For the samples, MySQL doesn't make it easy to do the LEAST of N
    # nullable values, so this is probably OK...
    #
    # For the baseline questionnaires, note that we might want to use the config to
    # generate the GREATEST statement instead, but for now are hardcoding as
    # we do with samples.

    # TODO when implementing unit testing for service class:
    # Add macros for GREATEST and LEAST, as they don't work in SQLite
    # Example: master/rest-api/dao/database_utils.py#L50

    sql = """
      SELECT
         SUM(registered_cnt * (cnt_day <= calendar.day)) registered_participants,
         SUM(member_cnt * (cnt_day <= calendar.day)) member_participants,
         SUM(full_cnt * (cnt_day <= calendar.day)) full_participants,
         calendar.day
       FROM
       (SELECT c2.day cnt_day,
               registered.cnt registered_cnt,
               member.cnt member_cnt,
               full.cnt full_cnt
            FROM calendar c2
            LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
                (CASE WHEN (enrollment_status = 1 OR enrollment_status IS NULL) THEN
                  DATE(p.sign_up_time)
                  ELSE NULL END) day
                FROM participant p
                LEFT OUTER JOIN participant_summary ps ON p.participant_id = ps.participant_id
              %(filters_p)s
              GROUP BY day) registered
             ON c2.day = registered.day
           LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
                   (CASE WHEN enrollment_status = 2 THEN
                    DATE(ps.consent_for_electronic_health_records_time)
                    ELSE NULL END) day
               FROM participant_summary ps
              %(filters_ps)s
           GROUP BY day) member
             ON c2.day = member.day
           LEFT OUTER JOIN
            (SELECT COUNT(*) cnt,
             DATE(CASE WHEN enrollment_status = 3 THEN
                   GREATEST(consent_for_electronic_health_records_time,
                            questionnaire_on_the_basics_time,
                            questionnaire_on_lifestyle_time,
                            questionnaire_on_overall_health_time,
                            physical_measurements_finalized_time,
                           CASE WHEN
                                LEAST(
                                    COALESCE(sample_order_status_1ed04_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1ed10_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal2_time, '3000-01-01')
                                    ) = '3001-01-01' THEN NULL
                                ELSE LEAST(
                                    COALESCE(sample_order_status_1ed04_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1ed10_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal_time, '3000-01-01'),
                                    COALESCE(sample_order_status_1sal2_time, '3000-01-01')
                                    )
                           END)
                END) day
               FROM participant_summary ps
              %(filters_ps)s
           GROUP BY day) full
             ON c2.day = full.day) day_sums, calendar
          WHERE calendar.day >= :start_date
            AND calendar.day <= :end_date
          GROUP BY calendar.day
          ORDER BY calendar.day;
      """ % {'filters_ps': filters_sql_ps, 'filters_p': filters_sql_p}

    return sql
<|endoftext|>


<commit_before>import logging
from rex import Vulnerability
from rex.exploit import CannotExploit
from rex.exploit.cgc import CGCType1CircumstantialExploit
from ..technique import Technique

l = logging.getLogger("rex.exploit.techniques.linux.circumstantial_set_register")

class CircumstantialSetRegister(Technique):

    name = "circumstantially_set_register"

    applicable_to = ['cgc']

    cgc_registers = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"]

    bitmask_threshold = 20

    # this technique should create an exploit which is a type1 pov
    pov_type = 1

    def set_register(self, register):
        '''
        set a register with shellcode on cgc
        '''

        # can only exploit ip overwrites
        ct = self.crash.crash_type
        if ct != Vulnerability.IP_OVERWRITE and ct != Vulnerability.PARTIAL_IP_OVERWRITE:
            raise CannotExploit("[%s] cannot control ip" % self.name)

        state = self.crash.state

        # see if the register value is nearly unconstrained
        reg = getattr(state.regs, register)

        # test each bit of the register
        unconstrained_bitcnt = 0
        for bit in xrange(reg.size()):
            l.debug("testing symbolic control of bit %d in register %s", bit, register)
            set_bit = state.satisfiable(extra_constraints=((reg & 1 << (bit)) == (1 << bit),))
            unset_bit = state.satisfiable(extra_constraints=((reg & ~(1 << (bit))) == 0,))
            if set_bit and unset_bit:
                unconstrained_bitcnt += 1

        if unconstrained_bitcnt >= CircumstantialSetRegister.bitmask_threshold:
            l.info("can circumstantially set register %s", register)

            return CGCType1CircumstantialExploit(self.crash, register)
        else:
            raise CannotExploit("register %s's value does not appear to be unconstrained" % register)

    def apply(self, **kwargs):

        register_setters = [ ]
        for register in CircumstantialSetRegister.cgc_registers:
            try:
                register_setters.append(self.set_register(register))
            except CannotExploit as e:
                l.warning("could not set register %s circumstantially (%s)", register, e.message)

        return register_setters
<commit_msg>Extra check in circumstantial register setting techinique which verifies that the register trying to be set circumstantially doesn't conflict with the program counter<commit_after>import logging
from rex import Vulnerability
from rex.exploit import CannotExploit
from rex.exploit.cgc import CGCType1CircumstantialExploit
from ..technique import Technique

l = logging.getLogger("rex.exploit.techniques.linux.circumstantial_set_register")

class CircumstantialSetRegister(Technique):

    name = "circumstantially_set_register"

    applicable_to = ['cgc']

    cgc_registers = ["eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi"]

    bitmask_threshold = 20

    # this technique should create an exploit which is a type1 pov
    pov_type = 1

    def set_register(self, register):
        '''
        set a register with shellcode on cgc
        '''

        # can only exploit ip overwrites
        ct = self.crash.crash_type
        if ct != Vulnerability.IP_OVERWRITE and ct != Vulnerability.PARTIAL_IP_OVERWRITE:
            raise CannotExploit("[%s] cannot control ip" % self.name)

        state = self.crash.state

        # see if the register value is nearly unconstrained
        reg = getattr(state.regs, register)

        # we need to make sure that the pc and this register don't conflict
        conflict = not state.satisfiable(extra_constraints=(reg != state.regs.pc,))
        if conflict:
            raise CannotExploit("register %s conflicts with pc, pc and register must be equal" % register)

        # test each bit of the register
        unconstrained_bitcnt = 0
        for bit in xrange(reg.size()):
            l.debug("testing symbolic control of bit %d in register %s", bit, register)
            set_bit = state.satisfiable(extra_constraints=((reg & 1 << (bit)) == (1 << bit),))
            unset_bit = state.satisfiable(extra_constraints=((reg & ~(1 << (bit))) == 0,))
            if set_bit and unset_bit:
                unconstrained_bitcnt += 1

        if unconstrained_bitcnt >= CircumstantialSetRegister.bitmask_threshold:
            l.info("can circumstantially set register %s", register)

            return CGCType1CircumstantialExploit(self.crash, register)
        else:
            raise CannotExploit("register %s's value does not appear to be unconstrained" % register)

    def apply(self, **kwargs):

        register_setters = [ ]
        for register in CircumstantialSetRegister.cgc_registers:
            try:
                register_setters.append(self.set_register(register))
            except CannotExploit as e:
                l.warning("could not set register %s circumstantially (%s)", register, e.message)

        return register_setters
<|endoftext|>


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

# Cloudeebus
#
# Copyright 2012 Intel Corporation.
#
# 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.
#
# Luc Yriarte <luc.yriarte@intel.com>
# Christophe Guiraud <christophe.guiraud@intel.com>
#

import argparse, dbus, json, sys

from twisted.internet import glib2reactor
# Configure the twisted mainloop to be run inside the glib mainloop.
# This must be done before importing the other twisted modules
glib2reactor.install()
from twisted.internet import reactor, defer

from autobahn.websocket import listenWS
from autobahn.wamp import exportRpc, WampServerFactory, WampCraServerProtocol

from dbus.mainloop.glib import DBusGMainLoop

import gobject
gobject.threads_init()

from dbus import glib
glib.init_threads()

# enable debug log
from twisted.python import log

###############################################################################

VERSION = "0.2"
OPENDOOR = False
CREDENTIALS = {}
WHITELIST = []

###############################################################################
class DbusCache:
    '''
    Global cache of DBus connexions and signal handlers
    '''
    def __init__(self):
        self.dbusConnexions = {}
        self.signalHandlers = {}

    def reset(self):
        '''
        Disconnect signal handlers before resetting cache.
        '''
        self.dbusConnexions = {}
        # disconnect signal handlers
        for key in self.signalHandlers:
            self.signalHandlers[key].disconnect()
        self.signalHandlers = {}

    def dbusConnexion(self, busName):
        if not self.dbusConnexions.has_key(busName):
            if busName == "session":
                self.dbusConnexions[busName] = dbus.SessionBus()
            elif busName == "system":
                self.dbusConnexions[busName] = dbus.SystemBus()
            else:
                raise Exception("Error: invalid bus: %s" % busName)
        return self.dbusConnexions[busName]

###############################################################################
class DbusSignalHandler:
    '''
    signal hash id as busName#senderName#objectName#interfaceName#signalName
    '''
    def __init__(self, busName, senderName, objectName, interfaceName, signalName):
        self.id = "#".join([busName, senderName, objectName, interfaceName, signalName])
        # connect handler to signal
        self.bus = cache.dbusConnexion(busName)
        self.bus.add_signal_receiver(self.handleSignal, signalName, interfaceName, senderName, objectName)

    def disconnect(self):
        names = self.id.split("#")
        self.bus.remove_signal_receiver(self.handleSignal, names[4], names[3], names[1], names[2])

    def handleSignal(self, *args):
        '''
        publish dbus args under topic hash id
        '''
        factory.dispatch(self.id, json.dumps(args))

###############################################################################
class DbusCallHandler:
    '''
    deferred reply to return dbus results
    '''
    def __init__(self, method, args):
        self.pending = False
        self.request = defer.Deferred()
        self.method = method
        self.args = args

    def callMethod(self):
        '''
        dbus method async call
        '''
        self.pending = True
        self.method(*self.args, reply_handler=self.dbusSuccess, error_handler=self.dbusError)
        return self.request

    def dbusSuccess(self, *result):
        '''
        return JSON string result array
        '''
        self.request.callback(json.dumps(result))
        self.pending = False

    def dbusError(self, error):
        '''
        return dbus error message
        '''
        self.request.errback(error.get_dbus_message())
        self.pending = False

###############################################################################
class CloudeebusService:
    '''
    support for sending DBus messages and registering for DBus signals
    '''
    def __init__(self, permissions):
        self.permissions = permissions;
        self.proxyObjects = {}
        self.proxyMethods = {}
        self.pendingCalls = []

    def proxyObject(self, busName, serviceName, objectName):
        '''
        object hash id as serviceName#objectName
        '''
        id = "#".join([serviceName, objectName])
        if not self.proxyObjects.has_key(id):
            if not OPENDOOR:
                # check permissions, array.index throws exception
                self.permissions.index(serviceName)
            bus = cache.dbusConnexion(busName)
            self.proxyObjects[id] = bus.get_object(serviceName, objectName)
        return self.proxyObjects[id]

    def proxyMethod(self, busName, serviceName, objectName, interfaceName, methodName):
        '''
        method hash id as serviceName#objectName#interfaceName#methodName
        '''
        id = "#".join([serviceName, objectName, interfaceName, methodName])
        if not self.proxyMethods.has_key(id):
            obj = self.proxyObject(busName, serviceName, objectName)
            self.proxyMethods[id] = obj.get_dbus_method(methodName, interfaceName)
        return self.proxyMethods[id]

    @exportRpc
    def dbusRegister(self, list):
        '''
        arguments: bus, sender, object, interface, signal
        '''
        if len(list) < 5:
            raise Exception("Error: expected arguments: bus, sender, object, interface, signal)")

        if not OPENDOOR:
            # check permissions, array.index throws exception
            self.permissions.index(list[1])

        # check if a handler exists
        sigId = "#".join(list)
        if cache.signalHandlers.has_key(sigId):
            return sigId

        # create a handler that will publish the signal
        dbusSignalHandler = DbusSignalHandler(*list)
        cache.signalHandlers[sigId] = dbusSignalHandler

        return dbusSignalHandler.id

    @exportRpc
    def dbusSend(self, list):
        '''
        arguments: bus, destination, object, interface, message, [args]
        '''
        # clear pending calls
        for call in self.pendingCalls:
            if not call.pending:
                self.pendingCalls.remove(call)

        if len(list) < 5:
            raise Exception("Error: expected arguments: bus, destination, object, interface, message, [args])")

        # parse JSON arg list
        args = []
        if len(list) == 6:
            args = json.loads(list[5])

        # get dbus proxy method
        method = self.proxyMethod(*list[0:5])

        # use a deferred call handler to manage dbus results
        dbusCallHandler = DbusCallHandler(method, args)
        self.pendingCalls.append(dbusCallHandler)
        return dbusCallHandler.callMethod()

    @exportRpc
    def getVersion(self):
        '''
        return current version string
        '''
        return VERSION

###############################################################################
class CloudeebusServerProtocol(WampCraServerProtocol):
    '''
    connexion and session authentication management
    '''

    def onSessionOpen(self):
        # CRA authentication options
        self.clientAuthTimeout = 0
        self.clientAuthAllowAnonymous = OPENDOOR
        # CRA authentication init
        WampCraServerProtocol.onSessionOpen(self)

    def getAuthPermissions(self, key, extra):
        return json.loads(extra.get("permissions", "[]"))

    def getAuthSecret(self, key):
        secret = CREDENTIALS.get(key, None)
        if secret is None:
            return None
        # secret must be of str type to be hashed
        return secret.encode('utf-8')

    def onAuthenticated(self, key, permissions):
        if not OPENDOOR:
            # check authentication key
            if key is None:
                raise Exception("Authentication failed")
            # check permissions, array.index throws exception
            for req in permissions:
                WHITELIST.index(req)
        # create cloudeebus service instance
        self.cloudeebusService = CloudeebusService(permissions)
        # register it for RPC
        self.registerForRpc(self.cloudeebusService)
        # register for Publish / Subscribe
        self.registerForPubSub("", True)

    def connectionLost(self, reason):
        WampCraServerProtocol.connectionLost(self, reason)
        if factory.getConnectionCount() == 0:
            cache.reset()

###############################################################################

if __name__ == '__main__':

    cache = DbusCache()

    parser = argparse.ArgumentParser(description='Javascript DBus bridge.')
    parser.add_argument('-v', '--version', action='store_true',
        help='print version and exit')
    parser.add_argument('-d', '--debug', action='store_true',
        help='log debug info on standard output')
    parser.add_argument('-o', '--opendoor', action='store_true',
        help='allow anonymous access to all services')
    parser.add_argument('-p', '--port', default='9000',
        help='port number')
    parser.add_argument('-c', '--credentials',
        help='path to credentials file')
    parser.add_argument('-w', '--whitelist',
        help='path to whitelist file')

    args = parser.parse_args(sys.argv[1:])

    if args.version:
        print("Cloudeebus version " + VERSION)
        exit(0)

    if args.debug:
        log.startLogging(sys.stdout)

    OPENDOOR = args.opendoor

    if args.credentials:
        jfile = open(args.credentials)
        CREDENTIALS = json.load(jfile)
        jfile.close()

    if args.whitelist:
        jfile = open(args.whitelist)
        WHITELIST = json.load(jfile)
        jfile.close()

    uri = "ws://localhost:" + args.port

    factory = WampServerFactory(uri, debugWamp = args.debug)
    factory.protocol = CloudeebusServerProtocol
    factory.setProtocolOptions(allowHixie76 = True)

    listenWS(factory)

    DBusGMainLoop(set_as_default=True)

    reactor.run()
<commit_msg>make cached object and method proxies local to bus connexion<commit_after>#!/usr/bin/env python

# Cloudeebus
#
# Copyright 2012 Intel Corporation.
#
# 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.
#
# Luc Yriarte <luc.yriarte@intel.com>
# Christophe Guiraud <christophe.guiraud@intel.com>
#

import argparse, dbus, json, sys

from twisted.internet import glib2reactor
# Configure the twisted mainloop to be run inside the glib mainloop.
# This must be done before importing the other twisted modules
glib2reactor.install()
from twisted.internet import reactor, defer

from autobahn.websocket import listenWS
from autobahn.wamp import exportRpc, WampServerFactory, WampCraServerProtocol

from dbus.mainloop.glib import DBusGMainLoop

import gobject
gobject.threads_init()

from dbus import glib
glib.init_threads()

# enable debug log
from twisted.python import log

###############################################################################

VERSION = "0.2"
OPENDOOR = False
CREDENTIALS = {}
WHITELIST = []

###############################################################################
class DbusCache:
    '''
    Global cache of DBus connexions and signal handlers
    '''
    def __init__(self):
        self.dbusConnexions = {}
        self.signalHandlers = {}

    def reset(self):
        '''
        Disconnect signal handlers before resetting cache.
        '''
        self.dbusConnexions = {}
        # disconnect signal handlers
        for key in self.signalHandlers:
            self.signalHandlers[key].disconnect()
        self.signalHandlers = {}

    def dbusConnexion(self, busName):
        if not self.dbusConnexions.has_key(busName):
            if busName == "session":
                self.dbusConnexions[busName] = dbus.SessionBus()
            elif busName == "system":
                self.dbusConnexions[busName] = dbus.SystemBus()
            else:
                raise Exception("Error: invalid bus: %s" % busName)
        return self.dbusConnexions[busName]

###############################################################################
class DbusSignalHandler:
    '''
    signal hash id as busName#senderName#objectName#interfaceName#signalName
    '''
    def __init__(self, busName, senderName, objectName, interfaceName, signalName):
        self.id = "#".join([busName, senderName, objectName, interfaceName, signalName])
        # connect handler to signal
        self.bus = cache.dbusConnexion(busName)
        self.bus.add_signal_receiver(self.handleSignal, signalName, interfaceName, senderName, objectName)

    def disconnect(self):
        names = self.id.split("#")
        self.bus.remove_signal_receiver(self.handleSignal, names[4], names[3], names[1], names[2])

    def handleSignal(self, *args):
        '''
        publish dbus args under topic hash id
        '''
        factory.dispatch(self.id, json.dumps(args))

###############################################################################
class DbusCallHandler:
    '''
    deferred reply to return dbus results
    '''
    def __init__(self, method, args):
        self.pending = False
        self.request = defer.Deferred()
        self.method = method
        self.args = args

    def callMethod(self):
        '''
        dbus method async call
        '''
        self.pending = True
        self.method(*self.args, reply_handler=self.dbusSuccess, error_handler=self.dbusError)
        return self.request

    def dbusSuccess(self, *result):
        '''
        return JSON string result array
        '''
        self.request.callback(json.dumps(result))
        self.pending = False

    def dbusError(self, error):
        '''
        return dbus error message
        '''
        self.request.errback(error.get_dbus_message())
        self.pending = False

###############################################################################
class CloudeebusService:
    '''
    support for sending DBus messages and registering for DBus signals
    '''
    def __init__(self, permissions):
        self.permissions = permissions;
        self.proxyObjects = {}
        self.proxyMethods = {}
        self.pendingCalls = []

    def proxyObject(self, busName, serviceName, objectName):
        '''
        object hash id as busName#serviceName#objectName
        '''
        id = "#".join([busName, serviceName, objectName])
        if not self.proxyObjects.has_key(id):
            if not OPENDOOR:
                # check permissions, array.index throws exception
                self.permissions.index(serviceName)
            bus = cache.dbusConnexion(busName)
            self.proxyObjects[id] = bus.get_object(serviceName, objectName)
        return self.proxyObjects[id]

    def proxyMethod(self, busName, serviceName, objectName, interfaceName, methodName):
        '''
        method hash id as busName#serviceName#objectName#interfaceName#methodName
        '''
        id = "#".join([busName, serviceName, objectName, interfaceName, methodName])
        if not self.proxyMethods.has_key(id):
            obj = self.proxyObject(busName, serviceName, objectName)
            self.proxyMethods[id] = obj.get_dbus_method(methodName, interfaceName)
        return self.proxyMethods[id]

    @exportRpc
    def dbusRegister(self, list):
        '''
        arguments: bus, sender, object, interface, signal
        '''
        if len(list) < 5:
            raise Exception("Error: expected arguments: bus, sender, object, interface, signal)")

        if not OPENDOOR:
            # check permissions, array.index throws exception
            self.permissions.index(list[1])

        # check if a handler exists
        sigId = "#".join(list)
        if cache.signalHandlers.has_key(sigId):
            return sigId

        # create a handler that will publish the signal
        dbusSignalHandler = DbusSignalHandler(*list)
        cache.signalHandlers[sigId] = dbusSignalHandler

        return dbusSignalHandler.id

    @exportRpc
    def dbusSend(self, list):
        '''
        arguments: bus, destination, object, interface, message, [args]
        '''
        # clear pending calls
        for call in self.pendingCalls:
            if not call.pending:
                self.pendingCalls.remove(call)

        if len(list) < 5:
            raise Exception("Error: expected arguments: bus, destination, object, interface, message, [args])")

        # parse JSON arg list
        args = []
        if len(list) == 6:
            args = json.loads(list[5])

        # get dbus proxy method
        method = self.proxyMethod(*list[0:5])

        # use a deferred call handler to manage dbus results
        dbusCallHandler = DbusCallHandler(method, args)
        self.pendingCalls.append(dbusCallHandler)
        return dbusCallHandler.callMethod()

    @exportRpc
    def getVersion(self):
        '''
        return current version string
        '''
        return VERSION

###############################################################################
class CloudeebusServerProtocol(WampCraServerProtocol):
    '''
    connexion and session authentication management
    '''

    def onSessionOpen(self):
        # CRA authentication options
        self.clientAuthTimeout = 0
        self.clientAuthAllowAnonymous = OPENDOOR
        # CRA authentication init
        WampCraServerProtocol.onSessionOpen(self)

    def getAuthPermissions(self, key, extra):
        return json.loads(extra.get("permissions", "[]"))

    def getAuthSecret(self, key):
        secret = CREDENTIALS.get(key, None)
        if secret is None:
            return None
        # secret must be of str type to be hashed
        return secret.encode('utf-8')

    def onAuthenticated(self, key, permissions):
        if not OPENDOOR:
            # check authentication key
            if key is None:
                raise Exception("Authentication failed")
            # check permissions, array.index throws exception
            for req in permissions:
                WHITELIST.index(req)
        # create cloudeebus service instance
        self.cloudeebusService = CloudeebusService(permissions)
        # register it for RPC
        self.registerForRpc(self.cloudeebusService)
        # register for Publish / Subscribe
        self.registerForPubSub("", True)

    def connectionLost(self, reason):
        WampCraServerProtocol.connectionLost(self, reason)
        if factory.getConnectionCount() == 0:
            cache.reset()

###############################################################################

if __name__ == '__main__':

    cache = DbusCache()

    parser = argparse.ArgumentParser(description='Javascript DBus bridge.')
    parser.add_argument('-v', '--version', action='store_true',
        help='print version and exit')
    parser.add_argument('-d', '--debug', action='store_true',
        help='log debug info on standard output')
    parser.add_argument('-o', '--opendoor', action='store_true',
        help='allow anonymous access to all services')
    parser.add_argument('-p', '--port', default='9000',
        help='port number')
    parser.add_argument('-c', '--credentials',
        help='path to credentials file')
    parser.add_argument('-w', '--whitelist',
        help='path to whitelist file')

    args = parser.parse_args(sys.argv[1:])

    if args.version:
        print("Cloudeebus version " + VERSION)
        exit(0)

    if args.debug:
        log.startLogging(sys.stdout)

    OPENDOOR = args.opendoor

    if args.credentials:
        jfile = open(args.credentials)
        CREDENTIALS = json.load(jfile)
        jfile.close()

    if args.whitelist:
        jfile = open(args.whitelist)
        WHITELIST = json.load(jfile)
        jfile.close()

    uri = "ws://localhost:" + args.port

    factory = WampServerFactory(uri, debugWamp = args.debug)
    factory.protocol = CloudeebusServerProtocol
    factory.setProtocolOptions(allowHixie76 = True)

    listenWS(factory)

    DBusGMainLoop(set_as_default=True)

    reactor.run()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2021 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.

from openquake.hazardlib.gsim.munson_thurber_1997 import (
                                                  MunsonThurber1997,
                                                  MunsonThurber1997Hawaii)

from openquake.hazardlib.tests.gsim.utils import BaseGSIMTestCase

class MunsonThurber1997TestCase(BaseGSIMTestCase):
    GSIM_CLASS = MunsonThurber1997

    # Test data were taken from Table 5 of Munson and Thurber (1997)
    # (some decimals are added manually, due to lack of precision)
    # Standard deviation is a fixed value

    def test_mean(self):
        self.check('MT97/MT97_MEAN.csv', max_discrep_percentage=0.6)

    def test_std_total(self):
        self.check('MT97/MT97_STD_TOTAL.csv', max_discrep_percentage=0.1)

class MunsonThurber1997HawaiiTestCase(BaseGSIMTestCase):
    GSIM_CLASS = MunsonThurber1997Hawaii

    # Test data were taken from Table 5 of Munson and Thurber (1997)
    # (some decimals are added manually, due to lack of precision)
    # Standard deviation is a fixed value

    def test_mean(self):
        self.check('MT97/MT97_HA_MEAN.csv', max_discrep_percentage=0.6)

    def test_std_total(self):
        self.check('MT97/MT97_HA_STD_TOTAL.csv', max_discrep_percentage=0.1)
<commit_msg>Ported some GMPE test<commit_after># -*- coding: utf-8 -*-
# vim: tabstop=4 shiftwidth=4 softtabstop=4
#
# Copyright (C) 2017-2021 GEM Foundation
#
# OpenQuake is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# OpenQuake is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with OpenQuake. If not, see <http://www.gnu.org/licenses/>.

from openquake.hazardlib.gsim.munson_thurber_1997 import (
                                                  MunsonThurber1997,
                                                  MunsonThurber1997Hawaii)

from openquake.hazardlib.tests.gsim.utils import BaseGSIMTestCase

class MunsonThurber1997TestCase(BaseGSIMTestCase):
    GSIM_CLASS = MunsonThurber1997

    # Test data were taken from Table 5 of Munson and Thurber (1997)
    # (some decimals are added manually, due to lack of precision)
    # Standard deviation is a fixed value

    def test_all(self):
        self.check_all('MT97/MT97_MEAN.csv',
                       'MT97/MT97_STD_TOTAL.csv',
                       mean_discrep_percentage=0.6,
                       std_discrep_percentage=0.1)

class MunsonThurber1997HawaiiTestCase(BaseGSIMTestCase):
    GSIM_CLASS = MunsonThurber1997Hawaii

    # Test data were taken from Table 5 of Munson and Thurber (1997)
    # (some decimals are added manually, due to lack of precision)
    # Standard deviation is a fixed value

    def test_all(self):
        self.check_all('MT97/MT97_HA_MEAN.csv',
                       'MT97/MT97_HA_STD_TOTAL.csv',
                       mean_discrep_percentage=0.6,
                       std_discrep_percentage=0.1)
<|endoftext|>


<commit_before>from shinymud.commands.attacks import *
from shinymud.data.config import EQUIP_SLOTS
from shinymud.lib.registers import IntRegister, DictRegister, DamageRegister
from shinymud.models import Model, Column, model_list
from shinymud.models.shiny_types import *
from random import randint

class Character(Model):
    """The basic functionality that both player characters (players) and
    non-player characters share.
    """
    db_columns = Model.db_columns + [
        Column('gender', default='neutral'),
        Column('hp', type="INTEGER", default=20, read=read_int, write=int),
        Column('mp', type="INTEGER", default=5, read=read_int, write=int),
        Column('max_mp', type="INTEGER", default=5, read=read_int, write=int),
        Column('max_hp', type="INTEGER", default=20, read=read_int, write=int),
        Column('currency', type="INTEGER", default=0, read=read_int, write=int),
        Column('description', default="You see nothing special about this person.")
    ]
    def characterize(self, args={}):
        Model.__init__(self, args)
        self.atk = 0
        self.battle = None
        self._battle_target = None
        self.inventory = []
        self.equipped = {} #Stores current item in each slot from EQUIP_SLOTS
        for i in EQUIP_SLOTS.keys():
            self.equipped[i] = ''
        self.isequipped = [] #Is a list of the currently equipped items
        self._attack_queue = []
        self.hit = IntRegister()
        self.evade = IntRegister()
        self.absorb = DictRegister()
        self.damage = DamageRegister()
        self.effects = {}
        self.position = ('standing', None)

    def __str__(self):
        return self.fancy_name()

    def load_inventory(self):
        pass

    def is_npc(self):
        """Return True if this character is an npc, false if it is not."""
        if self.char_type == 'npc':
            return True
        return False

    def item_add(self, item):
        """Add an item to the character's inventory."""
        if not self.is_npc():
            # Don't save this item if it's added to an npc
            item.owner = self
            item.save()
        self.inventory.append(item)

    def item_remove(self, item):
        """Remove an item from the character's inventory."""
        if item in self.inventory:
            if not self.is_npc():
                # items don't get saved when they're added to npc inventories
                # Don't bother removing the owner if we're taking it out of
                # an npc's inventory
                item.owner = None
                item.save()
            self.inventory.remove(item)

    def has_item(self, build_item):
        """Check if the player has a GameItem in their inventory that descended
        from the given build_item prototype.
        """
        found = False
        for i in self.inventory:
            if i.build_id == build_item.id and i.build_area == build_item.area.name:
                found = True
                break
        return found

    def check_inv_for_keyword(self, keyword):
        """Check all of the items in a character's inventory for a specific
        keyword. Return the item that matches that keyword, else return None.
        """
        keyword = keyword.strip().lower()
        for item in self.inventory:
            if keyword in item.keywords:
                return item
        return None

    def go(self, room, tell_new=None, tell_old=None):
        """Go to a specific room."""
        if self.position[0] == 'standing':
            if room:
                if self.location:
                    prev = '%s_%s' % (self.location.id, self.location.area.name)
                    if tell_old:
                        self.location.tell_room(tell_old, [self.name])
                    self.location.remove_char(self)
                else:
                    prev = 'void'
                if self.location and self.location == room:
                    self.update_output('You\'re already there.\n')
                else:
                    self.location = room
                    self.update_output(self.look_at_room())
                    self.location.add_char(self, prev)
                    if tell_new:
                        self.location.tell_room(tell_new, [self.name])
            else:
                self.log.debug('We gave %s a nonexistant room.' % self.name)
        else:
            self.update_output('You better stand up first.')

    def change_position(self, pos, furniture=None):
        """Change the player's position."""

        if self.position[1]:
            self.position[1].item_types['furniture'].player_remove(self)
        if furniture:
            furniture.item_types['furniture'].player_add(self)
        self.position = (pos, furniture)
        # self.log.debug(pos + ' ' + str(furniture))

    # Battle specific commands
    def _get_battle_target(self):
        if self in self.battle.teamA:
            other_team = self.battle.teamB
        else:
            other_team = self.battle.teamA
        if self._battle_target:
            if not self._battle_target in other_team:
                self._battle_target = other_team[0]
            self.log.debug("%s attack target: %s" % (self.fancy_name(), self._battle_target.fancy_name()))
            return self._battle_target

    def _set_battle_target(self, target):
        self._battle_target = target

    battle_target = property(_get_battle_target, _set_battle_target)

    def _get_next_action(self):
        if len(self._attack_queue):
            self.log.debug("next action: %s" % self._attack_queue[0].__class__.__name__)
            return self._attack_queue.pop(0)
        self.log.debug('next action: Attack')
        return Action_list['attack'](self, self.battle_target, self.battle)

    def _queue_attack(self, attack):
        self._attack_queue.append(attack)

    next_action = property(_get_next_action, _queue_attack)

    def next_action_cost(self):
        if len(self._attack_queue):
            self.log.debug("next action cost: %s" % str(self._attack_queue[0].cost ))
            return self._attack_queue[0].cost
        self.log.debug("next action cost %s:" % str(Action_list['attack'].cost))
        return Action_list['attack'].cost

    def attack(self):
        self.log.debug(self.fancy_name() + " is attacking:")
        current_attack = self.next_action
        current_attack.roll_to_hit()

    def free_attack(self):
        self.atk += self.next_action_cost()
        self.attack()

    def takes_damage(self, damages, attacker=None):
        total = 0
        absorb = self.absorb.calculate()
        for damage_type, damage in damages.items():
            d = (damage - absorb.get(damage_type, 0))
            if d >0:
                total += d
        self.log.debug("%s hit for %s damage" % (self.fancy_name(), str(total)))
        self.hp -= total
        if attacker:
            self.update_output("%s hit you for %s damage." % (attacker, str(total)))
        else:
            self.update_output("You were hit for %s damage." % str(total))
        if self.hp <= 0:
            self.battle.remove_character(self)
            self.battle = None
            self.set_mode('normal')
            self.death()
        # Call any events related to being hit or hp
        return total

    def enter_battle(self):
        if self.char_type == 'player':
            self.set_mode('battle')
            self.change_position('standing')

    def death(self):
        raise Exception("Not Implemented")

        <commit_msg>fixed old code trying to reference wrong logger.<commit_after>from shinymud.commands.attacks import *
from shinymud.data.config import EQUIP_SLOTS
from shinymud.lib.registers import IntRegister, DictRegister, DamageRegister
from shinymud.models import Model, Column, model_list
from shinymud.models.shiny_types import *
from random import randint

class Character(Model):
    """The basic functionality that both player characters (players) and
    non-player characters share.
    """
    db_columns = Model.db_columns + [
        Column('gender', default='neutral'),
        Column('hp', type="INTEGER", default=20, read=read_int, write=int),
        Column('mp', type="INTEGER", default=5, read=read_int, write=int),
        Column('max_mp', type="INTEGER", default=5, read=read_int, write=int),
        Column('max_hp', type="INTEGER", default=20, read=read_int, write=int),
        Column('currency', type="INTEGER", default=0, read=read_int, write=int),
        Column('description', default="You see nothing special about this person.")
    ]
    def characterize(self, args={}):
        Model.__init__(self, args)
        self.atk = 0
        self.battle = None
        self._battle_target = None
        self.inventory = []
        self.equipped = {} #Stores current item in each slot from EQUIP_SLOTS
        for i in EQUIP_SLOTS.keys():
            self.equipped[i] = ''
        self.isequipped = [] #Is a list of the currently equipped items
        self._attack_queue = []
        self.hit = IntRegister()
        self.evade = IntRegister()
        self.absorb = DictRegister()
        self.damage = DamageRegister()
        self.effects = {}
        self.position = ('standing', None)

    def __str__(self):
        return self.fancy_name()

    def load_inventory(self):
        pass

    def is_npc(self):
        """Return True if this character is an npc, false if it is not."""
        if self.char_type == 'npc':
            return True
        return False

    def item_add(self, item):
        """Add an item to the character's inventory."""
        if not self.is_npc():
            # Don't save this item if it's added to an npc
            item.owner = self
            item.save()
        self.inventory.append(item)

    def item_remove(self, item):
        """Remove an item from the character's inventory."""
        if item in self.inventory:
            if not self.is_npc():
                # items don't get saved when they're added to npc inventories
                # Don't bother removing the owner if we're taking it out of
                # an npc's inventory
                item.owner = None
                item.save()
            self.inventory.remove(item)

    def has_item(self, build_item):
        """Check if the player has a GameItem in their inventory that descended
        from the given build_item prototype.
        """
        found = False
        for i in self.inventory:
            if i.build_id == build_item.id and i.build_area == build_item.area.name:
                found = True
                break
        return found

    def check_inv_for_keyword(self, keyword):
        """Check all of the items in a character's inventory for a specific
        keyword. Return the item that matches that keyword, else return None.
        """
        keyword = keyword.strip().lower()
        for item in self.inventory:
            if keyword in item.keywords:
                return item
        return None

    def go(self, room, tell_new=None, tell_old=None):
        """Go to a specific room."""
        if self.position[0] == 'standing':
            if room:
                if self.location:
                    prev = '%s_%s' % (self.location.id, self.location.area.name)
                    if tell_old:
                        self.location.tell_room(tell_old, [self.name])
                    self.location.remove_char(self)
                else:
                    prev = 'void'
                if self.location and self.location == room:
                    self.update_output('You\'re already there.\n')
                else:
                    self.location = room
                    self.update_output(self.look_at_room())
                    self.location.add_char(self, prev)
                    if tell_new:
                        self.location.tell_room(tell_new, [self.name])
            else:
                self.world.log.debug('We gave %s a nonexistant room.' % self.name)
        else:
            self.update_output('You better stand up first.')

    def change_position(self, pos, furniture=None):
        """Change the player's position."""

        if self.position[1]:
            self.position[1].item_types['furniture'].player_remove(self)
        if furniture:
            furniture.item_types['furniture'].player_add(self)
        self.position = (pos, furniture)
        # self.world.log.debug(pos + ' ' + str(furniture))

    # Battle specific commands
    def _get_battle_target(self):
        if self in self.battle.teamA:
            other_team = self.battle.teamB
        else:
            other_team = self.battle.teamA
        if self._battle_target:
            if not self._battle_target in other_team:
                self._battle_target = other_team[0]
            self.world.log.debug("%s attack target: %s" % (self.fancy_name(), self._battle_target.fancy_name()))
            return self._battle_target

    def _set_battle_target(self, target):
        self._battle_target = target

    battle_target = property(_get_battle_target, _set_battle_target)

    def _get_next_action(self):
        if len(self._attack_queue):
            self.world.log.debug("next action: %s" % self._attack_queue[0].__class__.__name__)
            return self._attack_queue.pop(0)
        self.world.log.debug('next action: Attack')
        return Action_list['attack'](self, self.battle_target, self.battle)

    def _queue_attack(self, attack):
        self._attack_queue.append(attack)

    next_action = property(_get_next_action, _queue_attack)

    def next_action_cost(self):
        if len(self._attack_queue):
            self.world.log.debug("next action cost: %s" % str(self._attack_queue[0].cost ))
            return self._attack_queue[0].cost
        self.world.log.debug("next action cost %s:" % str(Action_list['attack'].cost))
        return Action_list['attack'].cost

    def attack(self):
        self.world.log.debug(self.fancy_name() + " is attacking:")
        current_attack = self.next_action
        current_attack.roll_to_hit()

    def free_attack(self):
        self.atk += self.next_action_cost()
        self.attack()

    def takes_damage(self, damages, attacker=None):
        total = 0
        absorb = self.absorb.calculate()
        for damage_type, damage in damages.items():
            d = (damage - absorb.get(damage_type, 0))
            if d >0:
                total += d
        self.world.log.debug("%s hit for %s damage" % (self.fancy_name(), str(total)))
        self.hp -= total
        if attacker:
            self.update_output("%s hit you for %s damage." % (attacker, str(total)))
        else:
            self.update_output("You were hit for %s damage." % str(total))
        if self.hp <= 0:
            self.battle.remove_character(self)
            self.battle = None
            self.set_mode('normal')
            self.death()
        # Call any events related to being hit or hp
        return total

    def enter_battle(self):
        if self.char_type == 'player':
            self.set_mode('battle')
            self.change_position('standing')

    def death(self):
        raise Exception("Not Implemented")

        <|endoftext|>