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

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//toolchains/kubectl:kubectl_configure.bzl", "kubectl_configure")
load(":with-defaults.bzl", _k8s_defaults = "k8s_defaults")

k8s_defaults = _k8s_defaults

def k8s_repositories():
    """Download dependencies of k8s rules."""

    excludes = native.existing_rules().keys()

    if "com_github_yaml_pyyaml" not in excludes:
        # Used by utilities for roundtripping yaml.
        http_archive(
            name = "com_github_yaml_pyyaml",
            build_file_content = """
py_library(
    name = "yaml",
    srcs = glob(["lib/yaml/*.py"]),
    imports = [
        "lib",
    ],
    visibility = ["//visibility:public"],
)""",
            sha256 = "6b4314b1b2051ddb9d4fcd1634e1fa9c1bb4012954273c9ff3ef689f6ec6c93e",
            strip_prefix = "pyyaml-3.12",
            urls = ["https://github.com/yaml/pyyaml/archive/3.12.zip"],
        )

    # Register the default kubectl toolchain targets for supported platforms
    # note these work with the autoconfigured toolchain
    native.register_toolchains(
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_linux_toolchain",
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_osx_toolchain",
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_windows_toolchain",
    )
    if "io_bazel_rules_go" not in excludes:
        http_archive(
            name = "io_bazel_rules_go",
            sha256 = "513c12397db1bc9aa46dd62f02dd94b49a9b5d17444d49b5a04c5a89f3053c1c",
            urls = [
                "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.19.5/rules_go-v0.19.5.tar.gz",
                "https://github.com/bazelbuild/rules_go/releases/download/0.19.5/rules_go-0.19.5.tar.gz",
            ],
        )
    if "bazel_gazelle" not in excludes:
        http_archive(
            name = "bazel_gazelle",
            sha256 = "7fc87f4170011201b1690326e8c16c5d802836e3a0d617d8f75c3af2b23180c4",
            urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.18.2/bazel-gazelle-0.18.2.tar.gz"],
        )
    if "io_bazel_rules_docker" not in excludes:
        http_archive(
            name = "io_bazel_rules_docker",
            sha256 = "5fcad5748a03d961c457ae15348684aa6eceb8f1cd6ae5fd7271fb5a271acdaf",
            strip_prefix = "rules_docker-7476c25fcf188dbfc4eb154ad309eda7df24652c",
            urls = ["https://github.com/bazelbuild/rules_docker/archive/7476c25fcf188dbfc4eb154ad309eda7df24652c.tar.gz"],
        )
    if "bazel_skylib" not in excludes:
        http_archive(
            name = "bazel_skylib",
            sha256 = "2ea8a5ed2b448baf4a6855d3ce049c4c452a6470b1efd1504fdb7c1c134d220a",
            strip_prefix = "bazel-skylib-0.8.0",
            urls = ["https://github.com/bazelbuild/bazel-skylib/archive/0.8.0.tar.gz"],
        )
    if "k8s_config" not in excludes:
        # WORKSPACE target to configure the kubectl tool
        kubectl_configure(name = "k8s_config", build_srcs = False)
<commit_msg>Update bazel_skylib + rules_go (#458)<commit_after># Copyright 2017 The Bazel Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Rules for manipulation of K8s constructs."""

load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
load("//toolchains/kubectl:kubectl_configure.bzl", "kubectl_configure")
load(":with-defaults.bzl", _k8s_defaults = "k8s_defaults")

k8s_defaults = _k8s_defaults

def k8s_repositories():
    """Download dependencies of k8s rules."""

    excludes = native.existing_rules().keys()

    if "com_github_yaml_pyyaml" not in excludes:
        # Used by utilities for roundtripping yaml.
        http_archive(
            name = "com_github_yaml_pyyaml",
            build_file_content = """
py_library(
    name = "yaml",
    srcs = glob(["lib/yaml/*.py"]),
    imports = [
        "lib",
    ],
    visibility = ["//visibility:public"],
)""",
            sha256 = "6b4314b1b2051ddb9d4fcd1634e1fa9c1bb4012954273c9ff3ef689f6ec6c93e",
            strip_prefix = "pyyaml-3.12",
            urls = ["https://github.com/yaml/pyyaml/archive/3.12.zip"],
        )

    # Register the default kubectl toolchain targets for supported platforms
    # note these work with the autoconfigured toolchain
    native.register_toolchains(
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_linux_toolchain",
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_osx_toolchain",
        "@io_bazel_rules_k8s//toolchains/kubectl:kubectl_windows_toolchain",
    )
    if "io_bazel_rules_go" not in excludes:
        http_archive(
            name = "io_bazel_rules_go",
            sha256 = "b480589f57e8b09f4b0892437b9afe889e0d6660e92f5d53d3f0546c01e67ca5",
            urls = [
                "https://storage.googleapis.com/bazel-mirror/github.com/bazelbuild/rules_go/releases/download/v0.19.7/rules_go-v0.19.7.tar.gz",
                "https://github.com/bazelbuild/rules_go/releases/download/v0.19.7/rules_go-v0.19.7.tar.gz",
            ],
        )
    if "bazel_gazelle" not in excludes:
        http_archive(
            name = "bazel_gazelle",
            sha256 = "7fc87f4170011201b1690326e8c16c5d802836e3a0d617d8f75c3af2b23180c4",
            urls = ["https://github.com/bazelbuild/bazel-gazelle/releases/download/0.18.2/bazel-gazelle-0.18.2.tar.gz"],
        )
    if "io_bazel_rules_docker" not in excludes:
        http_archive(
            name = "io_bazel_rules_docker",
            sha256 = "5fcad5748a03d961c457ae15348684aa6eceb8f1cd6ae5fd7271fb5a271acdaf",
            strip_prefix = "rules_docker-7476c25fcf188dbfc4eb154ad309eda7df24652c",
            urls = ["https://github.com/bazelbuild/rules_docker/archive/7476c25fcf188dbfc4eb154ad309eda7df24652c.tar.gz"],
        )
    if "bazel_skylib" not in excludes:
        http_archive(
            name = "bazel_skylib",
            sha256 = "e5d90f0ec952883d56747b7604e2a15ee36e288bb556c3d0ed33e818a4d971f2",
            strip_prefix = "bazel-skylib-1.0.2",
            urls = ["https://github.com/bazelbuild/bazel-skylib/archive/1.0.2.tar.gz"],
        )
    if "k8s_config" not in excludes:
        # WORKSPACE target to configure the kubectl tool
        kubectl_configure(name = "k8s_config", build_srcs = False)
<|endoftext|>


<commit_before># Module:   core
# Date:     2nd August 2005
# Author:   James Mills, prologic at shortcircuit dot net dot au

"""core - Core Component

Core management component and main loop handler.
All events are processes by this component and
also handles system signals to help reload the
configuration and terminate the system.
"""

import os
import signal
import socket
from time import sleep
from traceback import format_exc

from circuits.tools import graph
from circuits.lib.irc import Quit
from circuits.lib.sockets import Connect
from circuits import listener, Event, Component
from circuits.lib.log import (
        Debug as LogDebug,
        Exception as LogException)

###
### Events
###

class Start(Event):
    """Start(Event) -> Start Event"""

class Run(Event):
    """Run(Event) -> Run Event"""

class Stop(Event):
    """Stop(Event) -> Stop Event"""

class ErrorHandler(Component):

    def __init__(self, env, core, *args, **kwargs):
        super(ErrorHandler, self).__init__(*args, **kwargs)

        self.env = env
        self.core = core

    def error(self, *args, **kwargs):
        if len(args) == 3 and issubclass(args[0], BaseException):
            type, value, traceback = args

            self.env.errors += 1

            log = self.env.log.channel
            self.push(LogException("ERROR: %s" % args[1]), "exception", log)
            self.push(LogDebug(args[2]), "debug", log)

            if self.env.debug and type not in (SystemExit, KeyboardInterrupt):
                if self.core._running:
                    self.push(Stop(), "stop", self.core.channel)

class EventCounter(Component):

    def __init__(self, env, *args, **kwargs):
        super(EventCounter, self).__init__(*args, **kwargs)

        self.env = env

    @listener(type="filter")
    def onEVENT(self, *args, **kwargs):
        self.env.events += 1

class Core(Component):

    channel = "core"

    def __init__(self, env):
        super(Core, self).__init__()

        self._running = True

        signal.signal(signal.SIGHUP, self.rehash)
        signal.signal(signal.SIGTERM, self.stop)

        self.env = env

        self.errorhandler = ErrorHandler(self.env, self)
        self.eventcounter = EventCounter(self.env)
        self.manager += self.errorhandler
        self.manager += self.eventcounter

    def registered(self, manager):
        self.env.loadPlugins()
        self.push(Connect(), "connect", self.env.bot)

    def stop(self, signal=0, stack=0):
        self._running = False
        if self.env.bot.client.isConnected():
            self.push(Quit("Received SIGTERM, terminating..."), self.env.bot)
        self.env.unloadPlugins()
        raise SystemExit, 0

    def rehash(self, signal=0, stack=0):
        self.env.reload()
<commit_msg>core: 'registered' event handlers now get an additional argument, the component being registered with<commit_after># Module:   core
# Date:     2nd August 2005
# Author:   James Mills, prologic at shortcircuit dot net dot au

"""core - Core Component

Core management component and main loop handler.
All events are processes by this component and
also handles system signals to help reload the
configuration and terminate the system.
"""

import os
import signal
import socket
from time import sleep
from traceback import format_exc

from circuits.tools import graph
from circuits.lib.irc import Quit
from circuits.lib.sockets import Connect
from circuits import listener, Event, Component
from circuits.lib.log import (
        Debug as LogDebug,
        Exception as LogException)

###
### Events
###

class Start(Event):
    """Start(Event) -> Start Event"""

class Run(Event):
    """Run(Event) -> Run Event"""

class Stop(Event):
    """Stop(Event) -> Stop Event"""

class ErrorHandler(Component):

    def __init__(self, env, core, *args, **kwargs):
        super(ErrorHandler, self).__init__(*args, **kwargs)

        self.env = env
        self.core = core

    def error(self, *args, **kwargs):
        if len(args) == 3 and issubclass(args[0], BaseException):
            type, value, traceback = args

            self.env.errors += 1

            log = self.env.log.channel
            self.push(LogException("ERROR: %s" % args[1]), "exception", log)
            self.push(LogDebug(args[2]), "debug", log)

            if self.env.debug and type not in (SystemExit, KeyboardInterrupt):
                if self.core._running:
                    self.push(Stop(), "stop", self.core.channel)

class EventCounter(Component):

    def __init__(self, env, *args, **kwargs):
        super(EventCounter, self).__init__(*args, **kwargs)

        self.env = env

    @listener(type="filter")
    def onEVENT(self, *args, **kwargs):
        self.env.events += 1

class Core(Component):

    channel = "core"

    def __init__(self, env):
        super(Core, self).__init__()

        self._running = True

        signal.signal(signal.SIGHUP, self.rehash)
        signal.signal(signal.SIGTERM, self.stop)

        self.env = env

        self.errorhandler = ErrorHandler(self.env, self)
        self.eventcounter = EventCounter(self.env)
        self.manager += self.errorhandler
        self.manager += self.eventcounter

    def registered(self, component, manager):
        self.env.loadPlugins()
        self.push(Connect(), "connect", self.env.bot)

    def stop(self, signal=0, stack=0):
        self._running = False
        if self.env.bot.client.isConnected():
            self.push(Quit("Received SIGTERM, terminating..."), self.env.bot)
        self.env.unloadPlugins()
        raise SystemExit, 0

    def rehash(self, signal=0, stack=0):
        self.env.reload()
<|endoftext|>


<commit_before># stdlib
import json
import ssl

# requests
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager

# keen exceptions
from keen import exceptions

# json
from requests.compat import json

__author__ = 'dkador'

class HTTPMethods(object):

    """ HTTP methods that can be used with Keen's API. """

    GET = 'get'
    POST = 'post'
    DELETE = 'delete'

class KeenAdapter(HTTPAdapter):

    """ Adapt :py:mod:`requests` to Keen IO. """

    def init_poolmanager(self, connections, maxsize, block=False):

        """ Initialize pool manager with forced TLSv1 support. """

        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)

class KeenApi(object):
    """
    Responsible for communicating with the Keen API. Used by multiple
    persistence strategies or async processing.
    """

    # the default base URL of the Keen API
    base_url = "https://api.keen.io"
    # the default version of the Keen API
    api_version = "3.0"

    # self says it belongs to KeenApi/andOr is the object passed into KeenApi
    # __init__ create keenapi object whenever KeenApi class is invoked
    def __init__(self, project_id, write_key=None, read_key=None,
                 base_url=None, api_version=None, get_timeout=None, post_timeout=None,
                 master_key=None):
        """
        Initializes a KeenApi object

        :param project_id: the Keen project ID
        :param write_key: a Keen IO Scoped Key for Writes
        :param read_key: a Keen IO Scoped Key for Reads
        :param base_url: optional, set this to override where API requests
        are sent
        :param api_version: string, optional, set this to override what API
        version is used
        :param get_timeout: optional, the timeout on GET requests
        :param post_timeout: optional, the timeout on POST requests
        :param master_key: a Keen IO Master API Key, needed for deletes
        """
        # super? recreates the object with values passed into KeenApi
        super(KeenApi, self).__init__()
        self.project_id = project_id
        self.write_key = write_key
        self.read_key = read_key
        self.master_key = master_key
        if base_url:
            self.base_url = base_url
        if api_version:
            self.api_version = api_version
        self.get_timeout = get_timeout
        self.post_timeout = post_timeout
        self.session = self._create_session()

    def fulfill(self, method, *args, **kwargs):

        """ Fulfill an HTTP request to Keen's API. """

        return getattr(self.session, method)(*args, **kwargs)

    def post_event(self, event):
        """
        Posts a single event to the Keen IO API. The write key must be set first.

        :param event: an Event to upload
        """
        if not self.write_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a write key to send events. "
                "Please set a 'write_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url, self.api_version,
                                                       self.project_id,
                                                       event.event_collection)
        headers = {"Content-Type": "application/json", "Authorization": self.write_key}
        payload = event.to_json()
        response = self.fulfill(HTTPMethods.POST, url, data=payload, headers=headers, timeout=self.post_timeout)
        self._error_handling(response)

    def post_events(self, events):

        """
        Posts a single event to the Keen IO API. The write key must be set first.

        :param events: an Event to upload
        """
        if not self.write_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a write key to send events. "
                "Please set a 'write_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/events".format(self.base_url, self.api_version,
                                                   self.project_id)
        headers = {"Content-Type": "application/json", "Authorization": self.write_key}
        payload = json.dumps(events)
        response = self.fulfill(HTTPMethods.POST, url, data=payload, headers=headers, timeout=self.post_timeout)
        self._error_handling(response)

    def query(self, analysis_type, params, all_keys=False):
        """
        Performs a query using the Keen IO analysis API.  A read key must be set first.

        """
        if not self.read_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a read key to perform queries. "
                "Please set a 'read_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/queries/{3}".format(self.base_url, self.api_version,
                                                        self.project_id, analysis_type)

        headers = {"Authorization": self.read_key}
        payload = params
        response = self.fulfill(HTTPMethods.GET, url, params=payload, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        response = response.json()

        if not all_keys:
            response = response["result"]

        return response

    def delete_events(self, event_collection, params):
        """
        Deletes events via the Keen IO API. A master key must be set first.

        :param event_collection: string, the event collection from which event are being deleted

        """
        self._check_for_master_key()

        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url,
                                                       self.api_version,
                                                       self.project_id,
                                                       event_collection)
        headers = {"Content-Type": "application/json", "Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.DELETE, url, params=params, headers=headers, timeout=self.post_timeout)

        self._error_handling(response)
        return True

    def get_collection(self, event_collection):
        """
        Extracts info about a collection using the Keen IO API. A master key must be set first.

        :param event_collection: the name of the collection to retrieve info for
        """
        self._check_for_master_key()
        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url, self.api_version,
                                                       self.project_id, event_collection)
        headers = {"Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.GET, url, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        return response.json()

    def get_all_collections(self):
        """
        Extracts schema for all collections using the Keen IO API. A master key must be set first.

        """
        self._check_for_master_key()
        url = "{0}/{1}/projects/{2}/events".format(self.base_url, self.api_version, self.project_id)
        headers = {"Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.GET, url, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        return response.json()

    def _error_handling(self, res):
        """
        Helper function to do the error handling

        :params res: the response from a request
        """
        # making the error handling generic so if an status_code starting with 2 doesn't exist, we raise the error
        if res.status_code // 100 != 2:
            try:
                error = res.json()
            except ValueError:
                error = {
                    "message": "The API did not respond with JSON, but: {}".format(res.text[:1000]),
                    "error_code": "{}".format(res.status_code)
                }
            raise exceptions.KeenApiError(error)

    def _create_session(self):

        """ Build a session that uses KeenAdapter for SSL """

        s = requests.Session()
        s.mount('https://', KeenAdapter())
        return s

    def _check_for_master_key(self):
        if not self.master_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a master key to perform this operation. "
                "Please set a 'master_key' when initializing the "
                "KeenApi object."
            )
<commit_msg>Added indices back to the error formatting. <commit_after># stdlib
import json
import ssl

# requests
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.poolmanager import PoolManager

# keen exceptions
from keen import exceptions

# json
from requests.compat import json

__author__ = 'dkador'

class HTTPMethods(object):

    """ HTTP methods that can be used with Keen's API. """

    GET = 'get'
    POST = 'post'
    DELETE = 'delete'

class KeenAdapter(HTTPAdapter):

    """ Adapt :py:mod:`requests` to Keen IO. """

    def init_poolmanager(self, connections, maxsize, block=False):

        """ Initialize pool manager with forced TLSv1 support. """

        self.poolmanager = PoolManager(num_pools=connections,
                                       maxsize=maxsize,
                                       block=block,
                                       ssl_version=ssl.PROTOCOL_TLSv1)

class KeenApi(object):
    """
    Responsible for communicating with the Keen API. Used by multiple
    persistence strategies or async processing.
    """

    # the default base URL of the Keen API
    base_url = "https://api.keen.io"
    # the default version of the Keen API
    api_version = "3.0"

    # self says it belongs to KeenApi/andOr is the object passed into KeenApi
    # __init__ create keenapi object whenever KeenApi class is invoked
    def __init__(self, project_id, write_key=None, read_key=None,
                 base_url=None, api_version=None, get_timeout=None, post_timeout=None,
                 master_key=None):
        """
        Initializes a KeenApi object

        :param project_id: the Keen project ID
        :param write_key: a Keen IO Scoped Key for Writes
        :param read_key: a Keen IO Scoped Key for Reads
        :param base_url: optional, set this to override where API requests
        are sent
        :param api_version: string, optional, set this to override what API
        version is used
        :param get_timeout: optional, the timeout on GET requests
        :param post_timeout: optional, the timeout on POST requests
        :param master_key: a Keen IO Master API Key, needed for deletes
        """
        # super? recreates the object with values passed into KeenApi
        super(KeenApi, self).__init__()
        self.project_id = project_id
        self.write_key = write_key
        self.read_key = read_key
        self.master_key = master_key
        if base_url:
            self.base_url = base_url
        if api_version:
            self.api_version = api_version
        self.get_timeout = get_timeout
        self.post_timeout = post_timeout
        self.session = self._create_session()

    def fulfill(self, method, *args, **kwargs):

        """ Fulfill an HTTP request to Keen's API. """

        return getattr(self.session, method)(*args, **kwargs)

    def post_event(self, event):
        """
        Posts a single event to the Keen IO API. The write key must be set first.

        :param event: an Event to upload
        """
        if not self.write_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a write key to send events. "
                "Please set a 'write_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url, self.api_version,
                                                       self.project_id,
                                                       event.event_collection)
        headers = {"Content-Type": "application/json", "Authorization": self.write_key}
        payload = event.to_json()
        response = self.fulfill(HTTPMethods.POST, url, data=payload, headers=headers, timeout=self.post_timeout)
        self._error_handling(response)

    def post_events(self, events):

        """
        Posts a single event to the Keen IO API. The write key must be set first.

        :param events: an Event to upload
        """
        if not self.write_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a write key to send events. "
                "Please set a 'write_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/events".format(self.base_url, self.api_version,
                                                   self.project_id)
        headers = {"Content-Type": "application/json", "Authorization": self.write_key}
        payload = json.dumps(events)
        response = self.fulfill(HTTPMethods.POST, url, data=payload, headers=headers, timeout=self.post_timeout)
        self._error_handling(response)

    def query(self, analysis_type, params, all_keys=False):
        """
        Performs a query using the Keen IO analysis API.  A read key must be set first.

        """
        if not self.read_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a read key to perform queries. "
                "Please set a 'read_key' when initializing the "
                "KeenApi object."
            )

        url = "{0}/{1}/projects/{2}/queries/{3}".format(self.base_url, self.api_version,
                                                        self.project_id, analysis_type)

        headers = {"Authorization": self.read_key}
        payload = params
        response = self.fulfill(HTTPMethods.GET, url, params=payload, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        response = response.json()

        if not all_keys:
            response = response["result"]

        return response

    def delete_events(self, event_collection, params):
        """
        Deletes events via the Keen IO API. A master key must be set first.

        :param event_collection: string, the event collection from which event are being deleted

        """
        self._check_for_master_key()

        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url,
                                                       self.api_version,
                                                       self.project_id,
                                                       event_collection)
        headers = {"Content-Type": "application/json", "Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.DELETE, url, params=params, headers=headers, timeout=self.post_timeout)

        self._error_handling(response)
        return True

    def get_collection(self, event_collection):
        """
        Extracts info about a collection using the Keen IO API. A master key must be set first.

        :param event_collection: the name of the collection to retrieve info for
        """
        self._check_for_master_key()
        url = "{0}/{1}/projects/{2}/events/{3}".format(self.base_url, self.api_version,
                                                       self.project_id, event_collection)
        headers = {"Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.GET, url, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        return response.json()

    def get_all_collections(self):
        """
        Extracts schema for all collections using the Keen IO API. A master key must be set first.

        """
        self._check_for_master_key()
        url = "{0}/{1}/projects/{2}/events".format(self.base_url, self.api_version, self.project_id)
        headers = {"Authorization": self.master_key}
        response = self.fulfill(HTTPMethods.GET, url, headers=headers, timeout=self.get_timeout)
        self._error_handling(response)

        return response.json()

    def _error_handling(self, res):
        """
        Helper function to do the error handling

        :params res: the response from a request
        """
        # making the error handling generic so if an status_code starting with 2 doesn't exist, we raise the error
        if res.status_code // 100 != 2:
            try:
                error = res.json()
            except ValueError:
                error = {
                    "message": "The API did not respond with JSON, but: {0}".format(res.text[:1000]),
                    "error_code": "{0}".format(res.status_code)
                }
            raise exceptions.KeenApiError(error)

    def _create_session(self):

        """ Build a session that uses KeenAdapter for SSL """

        s = requests.Session()
        s.mount('https://', KeenAdapter())
        return s

    def _check_for_master_key(self):
        if not self.master_key:
            raise exceptions.InvalidEnvironmentError(
                "The Keen IO API requires a master key to perform this operation. "
                "Please set a 'master_key' when initializing the "
                "KeenApi object."
            )
<|endoftext|>


<commit_before>#
# This file is part of the PyMeasure package.
#
# Copyright (c) 2013-2021 PyMeasure Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

from pymeasure.instruments import Instrument
from pymeasure.instruments.validators import truncated_discrete_set, truncated_range, modular_range, modular_range_bidirectional, strict_discrete_set

from time import sleep
import numpy as np

class DSP7265(Instrument):
    """This is the class for the DSP 7265 lockin amplifier"""
    # TODO: add regultors on most of these

    SENSITIVITIES = [
            0.0, 2.0e-9, 5.0e-9, 10.0e-9, 20.0e-9, 50.0e-9, 100.0e-9,
            200.0e-9, 500.0e-9, 1.0e-6, 2.0e-6, 5.0e-6, 10.0e-6,
            20.0e-6, 50.0e-6, 100.0e-6, 200.0e-6, 500.0e-6, 1.0e-3,
            2.0e-3, 5.0e-3, 10.0e-3, 20.0e-3, 50.0e-3, 100.0e-3,
            200.0e-3, 500.0e-3, 1.0
        ]

    TIME_CONSTANTS = [
            10.0e-6, 20.0e-6, 40.0e-6, 80.0e-6, 160.0e-6, 320.0e-6,
            640.0e-6, 5.0e-3, 10.0e-3, 20.0e-3, 50.0e-3, 100.0e-3,
            200.0e-3, 500.0e-3, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0,
            100.0, 200.0, 500.0, 1.0e3, 2.0e3, 5.0e3, 10.0e3,
            20.0e3, 50.0e3
        ]
    REFERENCES = ['internal', 'external rear', 'external front']

    CURVE_BITS = {
            'x': 0,
            'y': 1,
            'mag': 2,
            'phase': 3,
            'sens': 4,
            'ADC1': 5,
            'ADC2': 6,
            'ADC3': 7,
            'DAC1': 8,
            'DAC2': 9,
            'noise': 10,
            'ratio': 11,
            'log ratio': 12,
            'EVENT': 13,
            'frequency': 14,
            'frequency2': 15,

            # Dual modes
            'x2': 16,
            'y2': 17,
            'mag2': 18,
            'phase2': 19,
            'sense2': 20
        }

    voltage = Instrument.control(
        "OA.", "OA. %g",
        """ A floating point property that represents the voltage
        in Volts. This property can be set. """,
        validator=truncated_range,
        values=[0,5]
    )
    frequency = Instrument.control(
        "OF.", "OF. %g",
        """ A floating point property that represents the lock-in
        frequency in Hz. This property can be set. """,
        validator=truncated_range,
        values=[0,2.5e5]
    )
    dac1 = Instrument.control(
        "DAC. 1", "DAC. 1 %g",
        """ A floating point property that represents the output
        value on DAC1 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac2 = Instrument.control(
        "DAC. 2", "DAC. 2 %g",
        """ A floating point property that represents the output
        value on DAC2 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac3 = Instrument.control(
        "DAC. 3", "DAC. 3 %g",
        """ A floating point property that represents the output
        value on DAC3 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac4 = Instrument.control(
        "DAC. 4", "DAC. 4 %g",
        """ A floating point property that represents the output
        value on DAC4 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    harmonic = Instrument.control(
        "REFN", "REFN %d",
        """ An integer property that represents the reference
        harmonic mode control, taking values from 1 to 65535.
        This property can be set. """,
        validator=truncated_discrete_set,
        values=list(range(65535))
    )
    phase = Instrument.control(
        "REFP.", "REFP. %g",
        """ A floating point property that represents the reference
        harmonic phase in degrees. This property can be set. """,
        validator=modular_range_bidirectional,
        values=[0,360]
    )
    x = Instrument.measurement("X.",
        """ Reads the X value in Volts """
    )
    y = Instrument.measurement("Y.",
        """ Reads the Y value in Volts """
    )
    xy = Instrument.measurement("X.Y.",
        """ Reads both the X and Y values in Volts """
    )
    mag = Instrument.measurement("MAG.",
        """ Reads the magnitude in Volts """
    )
    adc1 = Instrument.measurement("ADC. 1",
        """ Reads the input value of ADC1 in Volts """
    )
    adc2 = Instrument.measurement("ADC. 2",
        """ Reads the input value of ADC2 in Volts """
    )
    id = Instrument.measurement("ID",
        """ Reads the instrument identification """
    )
    reference = Instrument.control(
        "IE", "IE %d",
        """Controls the oscillator reference. Can be "internal",
        "external rear" or "external front" """,
        validator=strict_discrete_set,
        values=REFERENCES,
        map_values=True
    )
    sensitivity = Instrument.control(
        "SEN", "SEN %d",
        """ A floating point property that controls the sensitivity
        range in Volts, which can take discrete values from 2 nV to
        1 V. This property can be set. """,
        validator=truncated_discrete_set,
        values=SENSITIVITIES,
        map_values=True
    )
    slope = Instrument.control(
        "SLOPE", "SLOPE %d",
        """ A integer property that controls the filter slope in
        dB/octave, which can take the values 6, 12, 18, or 24 dB/octave.
        This property can be set. """,
        validator=truncated_discrete_set,
        values=[6, 12, 18, 24],
        map_values=True
    )
    time_constant = Instrument.control(
        "TC", "TC %d",
        """ A floating point property that controls the time constant
        in seconds, which takes values from 10 microseconds to 50,000
        seconds. This property can be set. """,
        validator=truncated_discrete_set,
        values=TIME_CONSTANTS,
        map_values=True
    )

    def __init__(self, resourceName, **kwargs):
        super().__init__(
            resourceName,
            "Signal Recovery DSP 7265",
            includeSCPI=False,
            # Remove extra unicode character
            # TODO: (find a way to) test if the line underneath indeed correctly replaces the reimplemented values method
            preprocess_reply=lambda r: r.replace('\x00', ''),
            **kwargs
        )

    def set_voltage_mode(self):
        self.write("IMODE 0")

    def setDifferentialMode(self, lineFiltering=True):
        """Sets lockin to differential mode, measuring A-B"""
        self.write("VMODE 3")
        self.write("LF %d 0" % 3 if lineFiltering else 0)

    def setChannelAMode(self):
        self.write("VMODE 1")

    @property
    def adc3(self):
        # 50,000 for 1V signal over 1 s
        integral = self.values("ADC 3")
        return float(integral)/(50000.0*self.adc3_time)

    @property
    def adc3_time(self):
        # Returns time in seconds
        return self.values("ADC3TIME")/1000.0

    @adc3_time.setter
    def adc3_time(self, value):
        # Takes time in seconds
        self.write("ADC3TIME %g" % int(1000*value))
        sleep(value*1.2)

    @property
    def auto_gain(self):
        return (int(self.values("AUTOMATIC")) == 1)

    @auto_gain.setter
    def auto_gain(self, value):
        if value:
            self.write("AUTOMATIC 1")
        else:
            self.write("AUTOMATIC 0")

    def auto_sensitivity(self):
        self.write("AS")

    def auto_phase(self):
        self.write("AQN")

    @property
    def gain(self):
        return self.values("ACGAIN")

    @gain.setter
    def gain(self, value):
        self.write("ACGAIN %d" % int(value/10.0))

    curve_buffer_bits = Instrument.control(
        "CBD", "CBD %d",
        """ An integer property that controls which data outputs are stored
        in the curve buffer. Valid values are values between 1 and 65,535 (or
        2,097,151 in dual reference mode). """,
        values=[1, 2097151],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_length = Instrument.control(
        "LEN", "LEN %d",
        """ An integer property that controls the length of the curve buffer.
        Valid values are values between 1 and 32,768, but the actual maximum
        amount of points is determined by the amount of curves that are stored,
        as set via the curve_buffer_bits property (32,768 / n) """,
        values=[1, 32768],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_interval = Instrument.control(
        "STR", "STR %d",
        """ An integer property that controls Sets the time interval between
        successive points being acquired in the curve buffer. The time interval
        is specified in ms with a resolution of 5 ms; input values are rounded
        up to a multiple of 5. Valid values are values between 0 and 1,000,000,000
        (corresponding to 12 days).
        The interval may be set to 0, which sets the rate of data storage to the
        curve buffer to 1.25 ms/point (800 Hz). However this only allows storage
        of the X and Y channel outputs. There is no need to issue a CBD 3 command
        to set this up since it happens automatically when acquisition starts.
        """,
        values=[1, 1000000000],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_status = Instrument.measurement(
        "M",
        """ A property that represents the status of the curve buffer acquisition
        with four values:
        the first value represents the status with 5 possibilities (0: no activity,
        1: acquisition via TD command running, 2: acquisition bya TDC command running,
        5: acquisition via TD command halted, 6: acquisition bia TDC command halted);
        the second value is the number of sweeps that is acquired;
        the third value is the decimal representation of the status byte (the same
        response as the ST command;
        the fourth value is the number of points acquired in the curve buffer.
        """,
        cast=int,
    )

    def init_curve_buffer(self):
        """ Initializes the curve storage memory and status variables. All record
        of previously taken curves is removed.
        """
        self.write("NC")

    def set_buffer(self, points, quantities=None, interval=10.0e-3):
        """ Method that prepares the curve buffer for a measurement.

        :param int points:
            Number of points to be recorded in the curve buffer

        :param list quantities:
            List containing the quantities (strings) that are to be
            recorded in the curve buffer

        :param float interval:
            The interval between two subsequent points stored in the
            curve buffer in ms
        """
        if quantities is None:
            quantities = ["x", "y"]

        bits = 0
        for q in quantities:
            bits += 2**self.CURVE_BITS[q]

        self.curve_buffer_bits = bits
        self.curve_buffer_length = points

        # TODO: check if this results in the correct interval length
        self.curve_buffer_interval = int(interval / 1e-3)
        self.init_curve_buffer()

    def start_buffer(self):
        """ Initiates data acquisition. Acquisition starts at the current position
        in the curve buffer and continues at the rate set by the STR command until
        the buffer is full.
        """
        self.write("TD")

    def get_buffer(self, quantity='x', timeout=1.00, average=False):
        count = 0
        maxCount = int(timeout/0.05)
        failed = False
        while self.curve_buffer_status[0] != 0:
            # Sleeping
            sleep(0.05)
            if count > maxCount:
                # Count reached max value, wait longer before asking!
                failed = True
                break
        if not failed:
            data = []
            # Getting data
            for i in range(self.length):
                val = self.values("DC. %d" % self.curve_bits[quantity])
                data.append(val)
            if average:
                return np.mean(data)
            else:
                return data
        else:
            return [0.0]

    def shutdown(self):
        log.info("Shutting down %s." % self.name)
        self.voltage = 0.
        self.isShutdown = True
<commit_msg>Implement wait_for_buffer method<commit_after>#
# This file is part of the PyMeasure package.
#
# Copyright (c) 2013-2021 PyMeasure Developers
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

import logging
log = logging.getLogger(__name__)
log.addHandler(logging.NullHandler())

from pymeasure.instruments import Instrument
from pymeasure.instruments.validators import truncated_discrete_set, truncated_range, modular_range, modular_range_bidirectional, strict_discrete_set

from time import sleep, time
import numpy as np

class DSP7265(Instrument):
    """This is the class for the DSP 7265 lockin amplifier"""
    # TODO: add regultors on most of these

    SENSITIVITIES = [
            0.0, 2.0e-9, 5.0e-9, 10.0e-9, 20.0e-9, 50.0e-9, 100.0e-9,
            200.0e-9, 500.0e-9, 1.0e-6, 2.0e-6, 5.0e-6, 10.0e-6,
            20.0e-6, 50.0e-6, 100.0e-6, 200.0e-6, 500.0e-6, 1.0e-3,
            2.0e-3, 5.0e-3, 10.0e-3, 20.0e-3, 50.0e-3, 100.0e-3,
            200.0e-3, 500.0e-3, 1.0
        ]

    TIME_CONSTANTS = [
            10.0e-6, 20.0e-6, 40.0e-6, 80.0e-6, 160.0e-6, 320.0e-6,
            640.0e-6, 5.0e-3, 10.0e-3, 20.0e-3, 50.0e-3, 100.0e-3,
            200.0e-3, 500.0e-3, 1.0, 2.0, 5.0, 10.0, 20.0, 50.0,
            100.0, 200.0, 500.0, 1.0e3, 2.0e3, 5.0e3, 10.0e3,
            20.0e3, 50.0e3
        ]
    REFERENCES = ['internal', 'external rear', 'external front']

    CURVE_BITS = {
            'x': 0,
            'y': 1,
            'mag': 2,
            'phase': 3,
            'sens': 4,
            'ADC1': 5,
            'ADC2': 6,
            'ADC3': 7,
            'DAC1': 8,
            'DAC2': 9,
            'noise': 10,
            'ratio': 11,
            'log ratio': 12,
            'EVENT': 13,
            'frequency': 14,
            'frequency2': 15,

            # Dual modes
            'x2': 16,
            'y2': 17,
            'mag2': 18,
            'phase2': 19,
            'sense2': 20
        }

    voltage = Instrument.control(
        "OA.", "OA. %g",
        """ A floating point property that represents the voltage
        in Volts. This property can be set. """,
        validator=truncated_range,
        values=[0,5]
    )
    frequency = Instrument.control(
        "OF.", "OF. %g",
        """ A floating point property that represents the lock-in
        frequency in Hz. This property can be set. """,
        validator=truncated_range,
        values=[0,2.5e5]
    )
    dac1 = Instrument.control(
        "DAC. 1", "DAC. 1 %g",
        """ A floating point property that represents the output
        value on DAC1 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac2 = Instrument.control(
        "DAC. 2", "DAC. 2 %g",
        """ A floating point property that represents the output
        value on DAC2 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac3 = Instrument.control(
        "DAC. 3", "DAC. 3 %g",
        """ A floating point property that represents the output
        value on DAC3 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    dac4 = Instrument.control(
        "DAC. 4", "DAC. 4 %g",
        """ A floating point property that represents the output
        value on DAC4 in Volts. This property can be set. """,
        validator=truncated_range,
        values=[-12,12]
    )
    harmonic = Instrument.control(
        "REFN", "REFN %d",
        """ An integer property that represents the reference
        harmonic mode control, taking values from 1 to 65535.
        This property can be set. """,
        validator=truncated_discrete_set,
        values=list(range(65535))
    )
    phase = Instrument.control(
        "REFP.", "REFP. %g",
        """ A floating point property that represents the reference
        harmonic phase in degrees. This property can be set. """,
        validator=modular_range_bidirectional,
        values=[0,360]
    )
    x = Instrument.measurement("X.",
        """ Reads the X value in Volts """
    )
    y = Instrument.measurement("Y.",
        """ Reads the Y value in Volts """
    )
    xy = Instrument.measurement("X.Y.",
        """ Reads both the X and Y values in Volts """
    )
    mag = Instrument.measurement("MAG.",
        """ Reads the magnitude in Volts """
    )
    adc1 = Instrument.measurement("ADC. 1",
        """ Reads the input value of ADC1 in Volts """
    )
    adc2 = Instrument.measurement("ADC. 2",
        """ Reads the input value of ADC2 in Volts """
    )
    id = Instrument.measurement("ID",
        """ Reads the instrument identification """
    )
    reference = Instrument.control(
        "IE", "IE %d",
        """Controls the oscillator reference. Can be "internal",
        "external rear" or "external front" """,
        validator=strict_discrete_set,
        values=REFERENCES,
        map_values=True
    )
    sensitivity = Instrument.control(
        "SEN", "SEN %d",
        """ A floating point property that controls the sensitivity
        range in Volts, which can take discrete values from 2 nV to
        1 V. This property can be set. """,
        validator=truncated_discrete_set,
        values=SENSITIVITIES,
        map_values=True
    )
    slope = Instrument.control(
        "SLOPE", "SLOPE %d",
        """ A integer property that controls the filter slope in
        dB/octave, which can take the values 6, 12, 18, or 24 dB/octave.
        This property can be set. """,
        validator=truncated_discrete_set,
        values=[6, 12, 18, 24],
        map_values=True
    )
    time_constant = Instrument.control(
        "TC", "TC %d",
        """ A floating point property that controls the time constant
        in seconds, which takes values from 10 microseconds to 50,000
        seconds. This property can be set. """,
        validator=truncated_discrete_set,
        values=TIME_CONSTANTS,
        map_values=True
    )

    def __init__(self, resourceName, **kwargs):
        super().__init__(
            resourceName,
            "Signal Recovery DSP 7265",
            includeSCPI=False,
            # Remove extra unicode character
            # TODO: (find a way to) test if the line underneath indeed correctly replaces the reimplemented values method
            preprocess_reply=lambda r: r.replace('\x00', ''),
            **kwargs
        )

    def set_voltage_mode(self):
        self.write("IMODE 0")

    def setDifferentialMode(self, lineFiltering=True):
        """Sets lockin to differential mode, measuring A-B"""
        self.write("VMODE 3")
        self.write("LF %d 0" % 3 if lineFiltering else 0)

    def setChannelAMode(self):
        self.write("VMODE 1")

    @property
    def adc3(self):
        # 50,000 for 1V signal over 1 s
        integral = self.values("ADC 3")
        return float(integral)/(50000.0*self.adc3_time)

    @property
    def adc3_time(self):
        # Returns time in seconds
        return self.values("ADC3TIME")/1000.0

    @adc3_time.setter
    def adc3_time(self, value):
        # Takes time in seconds
        self.write("ADC3TIME %g" % int(1000*value))
        sleep(value*1.2)

    @property
    def auto_gain(self):
        return (int(self.values("AUTOMATIC")) == 1)

    @auto_gain.setter
    def auto_gain(self, value):
        if value:
            self.write("AUTOMATIC 1")
        else:
            self.write("AUTOMATIC 0")

    def auto_sensitivity(self):
        self.write("AS")

    def auto_phase(self):
        self.write("AQN")

    @property
    def gain(self):
        return self.values("ACGAIN")

    @gain.setter
    def gain(self, value):
        self.write("ACGAIN %d" % int(value/10.0))

    curve_buffer_bits = Instrument.control(
        "CBD", "CBD %d",
        """ An integer property that controls which data outputs are stored
        in the curve buffer. Valid values are values between 1 and 65,535 (or
        2,097,151 in dual reference mode). """,
        values=[1, 2097151],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_length = Instrument.control(
        "LEN", "LEN %d",
        """ An integer property that controls the length of the curve buffer.
        Valid values are values between 1 and 32,768, but the actual maximum
        amount of points is determined by the amount of curves that are stored,
        as set via the curve_buffer_bits property (32,768 / n) """,
        values=[1, 32768],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_interval = Instrument.control(
        "STR", "STR %d",
        """ An integer property that controls Sets the time interval between
        successive points being acquired in the curve buffer. The time interval
        is specified in ms with a resolution of 5 ms; input values are rounded
        up to a multiple of 5. Valid values are values between 0 and 1,000,000,000
        (corresponding to 12 days).
        The interval may be set to 0, which sets the rate of data storage to the
        curve buffer to 1.25 ms/point (800 Hz). However this only allows storage
        of the X and Y channel outputs. There is no need to issue a CBD 3 command
        to set this up since it happens automatically when acquisition starts.
        """,
        values=[1, 1000000000],
        validator=truncated_range,
        cast=int,
    )

    curve_buffer_status = Instrument.measurement(
        "M",
        """ A property that represents the status of the curve buffer acquisition
        with four values:
        the first value represents the status with 5 possibilities (0: no activity,
        1: acquisition via TD command running, 2: acquisition bya TDC command running,
        5: acquisition via TD command halted, 6: acquisition bia TDC command halted);
        the second value is the number of sweeps that is acquired;
        the third value is the decimal representation of the status byte (the same
        response as the ST command;
        the fourth value is the number of points acquired in the curve buffer.
        """,
        cast=int,
    )

    def init_curve_buffer(self):
        """ Initializes the curve storage memory and status variables. All record
        of previously taken curves is removed.
        """
        self.write("NC")

    def set_buffer(self, points, quantities=None, interval=10.0e-3):
        """ Method that prepares the curve buffer for a measurement.

        :param int points:
            Number of points to be recorded in the curve buffer

        :param list quantities:
            List containing the quantities (strings) that are to be
            recorded in the curve buffer

        :param float interval:
            The interval between two subsequent points stored in the
            curve buffer in ms
        """
        if quantities is None:
            quantities = ["x", "y"]

        bits = 0
        for q in quantities:
            bits += 2**self.CURVE_BITS[q]

        self.curve_buffer_bits = bits
        self.curve_buffer_length = points

        # TODO: check if this results in the correct interval length
        self.curve_buffer_interval = int(interval / 1e-3)
        self.init_curve_buffer()

    def start_buffer(self):
        """ Initiates data acquisition. Acquisition starts at the current position
        in the curve buffer and continues at the rate set by the STR command until
        the buffer is full.
        """
        self.write("TD")

    def wait_for_buffer(self, delay=0.1, timeout=None):
        """ Method that waits until the curve buffer is filled
        """
        start = time()
        while self.curve_buffer_status[0] == 1:
            sleep(delay)
            if timeout is not None and time() < start + timeout:
                break

    def get_buffer(self, quantity='x', timeout=1.00, average=False):
        count = 0
        maxCount = int(timeout/0.05)
        failed = False
        while self.curve_buffer_status[0] != 0:
            # Sleeping
            sleep(0.05)
            if count > maxCount:
                # Count reached max value, wait longer before asking!
                failed = True
                break
        if not failed:
            data = []
            # Getting data
            for i in range(self.length):
                val = self.values("DC. %d" % self.curve_bits[quantity])
                data.append(val)
            if average:
                return np.mean(data)
            else:
                return data
        else:
            return [0.0]

    def shutdown(self):
        log.info("Shutting down %s." % self.name)
        self.voltage = 0.
        self.isShutdown = True
<|endoftext|>


<commit_before>import cis_publisher

# from moto import mock_lambda
## import boto3
import json

class TestHRIS(object):
    def test_parse_hris(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(hris_data, {}, {}, [])
        print("parsed {} profiles".format(len(profiles)))

        # Check access information is populated
        assert profiles[0].access_information.hris["values"]["employee_id"] == "31337"

        c = 0
        # Verify data consistency
        for p in profiles:
            assert p.primary_email.value is not None
            if hris_data["Report_Entry"][c]["IsManager"] == "TRUE":
                assert p.staff_information.manager.value is True
            else:
                assert p.staff_information.manager.value is False

            # Just info for debugging
            d = p.as_dict()
            si = {}
            for i in d["staff_information"]:
                si[i] = d["staff_information"][i]["value"]
            print(p.primary_email.value, p.last_name.value, d["access_information"]["hris"]["values"], si)

            for i in d["access_information"]["hris"]["values"]:
                si[i] = d["access_information"]["hris"]["values"]
            print(si)
            c = c + 1

    def test_single_user_id(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(
            hris_data,
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|flastname": "flastnamehere@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "flastnamehere@mozilla.com": "ad|mozilla-LDAP|flastname"},
            user_ids=["ad|Mozilla-LDAP|NDonna"],
        )
        assert profiles[0].access_information.hris["values"]["employee_id"] == "31337"

    def test_user_deactivate(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(
            hris_data,
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|notexist": "nolongerexists@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "nolongerexists@mozilla.com": "ad|Mozilla-LDAP|notexist"},
            user_ids=["ad|Mozilla-LDAP|NDonna", "ad|Mozilla-LDAP|notexist"],
        )
        profiles = hris.deactivate_users(
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|notexist": "nolongerexists@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "nolongerexists@mozilla.com": "ad|Mozilla-LDAP|notexist"},
            profiles,
            hris_data,
        )
        # nolongerexist is returned by fake cis reply, but is not in hris workday fixture, so it should be active.value
        # = false
        assert profiles[1].active.value == False
        assert profiles[0].active.value == True

# Not yet supported by moto
#    def test_reentrancy(self):
#        hris_data = {}
#        with open("tests/fixture/workday.json") as fd:
#            hris_data = json.load(fd)
#
#        hris = cis_publisher.hris.HRISPublisher(context={"function_name": "test"})
#        hris.publish()
<commit_msg>fix test<commit_after>import cis_publisher

# from moto import mock_lambda
## import boto3
import json

class TestHRIS(object):
    def test_parse_hris(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(
            hris_data,
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|flastname": "flastnamehere@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "flastnamehere@mozilla.com": "ad|mozilla-LDAP|flastname"},
            user_ids=["ad|Mozilla-LDAP|NDonna"],
        )

        print("parsed {} profiles".format(len(profiles)))

        # Check access information is populated
        assert profiles[0].access_information.hris["values"]["employee_id"] == "31337"

        c = 0
        # Verify data consistency
        for p in profiles:
            assert p.primary_email.value is not None
            if hris_data["Report_Entry"][c]["IsManager"] == "TRUE":
                assert p.staff_information.manager.value is True
            else:
                assert p.staff_information.manager.value is False

            # Just info for debugging
            d = p.as_dict()
            si = {}
            for i in d["staff_information"]:
                si[i] = d["staff_information"][i]["value"]
            print(p.primary_email.value, p.last_name.value, d["access_information"]["hris"]["values"], si)

            for i in d["access_information"]["hris"]["values"]:
                si[i] = d["access_information"]["hris"]["values"]
            print(si)
            c = c + 1

    def test_single_user_id(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(
            hris_data,
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|flastname": "flastnamehere@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "flastnamehere@mozilla.com": "ad|mozilla-LDAP|flastname"},
            user_ids=["ad|Mozilla-LDAP|NDonna"],
        )
        assert profiles[0].access_information.hris["values"]["employee_id"] == "31337"

    def test_user_deactivate(self):
        hris_data = {}
        with open("tests/fixture/workday.json") as fd:
            hris_data = json.load(fd)

        hris = cis_publisher.hris.HRISPublisher()
        profiles = hris.convert_hris_to_cis_profiles(
            hris_data,
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|notexist": "nolongerexists@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "nolongerexists@mozilla.com": "ad|Mozilla-LDAP|notexist"},
            user_ids=["ad|Mozilla-LDAP|NDonna", "ad|Mozilla-LDAP|notexist"],
        )
        profiles = hris.deactivate_users(
            {"ad|Mozilla-LDAP|NDonna": "ndonna@mozilla.com", "ad|Mozilla-LDAP|notexist": "nolongerexists@mozilla.com"},
            {"ndonna@mozilla.com": "ad|Mozilla-LDAP|NDonna", "nolongerexists@mozilla.com": "ad|Mozilla-LDAP|notexist"},
            profiles,
            hris_data,
        )
        # nolongerexist is returned by fake cis reply, but is not in hris workday fixture, so it should be active.value
        # = false
        assert profiles[1].active.value == False
        assert profiles[0].active.value == True

# Not yet supported by moto
#    def test_reentrancy(self):
#        hris_data = {}
#        with open("tests/fixture/workday.json") as fd:
#            hris_data = json.load(fd)
#
#        hris = cis_publisher.hris.HRISPublisher(context={"function_name": "test"})
#        hris.publish()
<|endoftext|>


<commit_before>#* This file is part of the MOOSE framework
#* https://www.mooseframework.org
#*
#* All rights reserved, see COPYRIGHT for full restrictions
#* https://github.com/idaholab/moose/blob/master/COPYRIGHT
#*
#* Licensed under LGPL 2.1, please see LICENSE for details
#* https://www.gnu.org/licenses/lgpl-2.1.html

"""Tools for extracting C++ class information."""
import os
import re

import mooseutils

import MooseDocs
from .read import read

#: Locates class definitions in header files
# string starts with register(AD)MooseObject(Aliased)
# then the App name in double quotes, which must finish by App
# then either a comma and one or more spaces, or a comma, spaces, a word (for aliased registration)
# then the name of the registered class, captured in <class>, can be followed by quotes (alias)
# then the registering function closing parenthesis and the C++ semicolon
DEFINITION_RE = re.compile(r'register(|AD)MooseObject(|Aliased)\(\"\w+App\"(,\s+|,\s+\w+,\s+\")(?P<class>\w+)\"?\);')

#: Locates class inheritance
# <key> is captured as the first word after the 'public' word at the beginning of the expression
# with a space before and with some text (or not) after
CHILD_RE = re.compile(r'\bpublic\s+(?P<key>\w+)\b')

#: Locates class use in input files
# expression starts with type, spaces or not, an equal, spaces or not
# <key> is captured as the first word after this
INPUT_RE = re.compile(r'\btype\s*=\s*(?P<key>\w+)\b')

class DatabaseItem(object):
    """Storage container for class information."""
    def __init__(self, name, header, source):
        self.name = name
        self.source = source
        self.header = header
        self.inputs = set()
        self.children = set()

def build_class_database(source_dirs=None, include_dirs=None, input_dirs=None):
    """
    Create the class database.

    Returns a dict() of DatabaseItem objects. The key is the class name e.g., Diffusion.

    Inputs:
        source_dirs[list]: A space separated str or a list of source directories.
        include_dirs[list]: A space separated str or a list of include directories.
        input_dirs[list]: A space separated str or a list of input file directories.
    """

    # Handle environment variables
    if source_dirs:
        source_dirs = [mooseutils.eval_path(x) for x in source_dirs]
    else:
        source_dirs = [MooseDocs.ROOT_DIR]

    if include_dirs:
        include_dirs = [mooseutils.eval_path(x) for x in include_dirs]
    else:
        include_dirs = [MooseDocs.ROOT_DIR]

    if input_dirs:
        input_dirs = [mooseutils.eval_path(x) for x in input_dirs]
    else:
        input_dirs = [MooseDocs.ROOT_DIR]

    # Locate filenames
    sources = _locate_filenames(source_dirs, '.C')
    headers = _locate_filenames(include_dirs, '.h')
    inputs = _locate_filenames(input_dirs, '.i')

    # Create the database
    objects = dict()
    _process(objects, sources, DEFINITION_RE, _match_definition)
    _process(objects, headers, CHILD_RE, _match_child)
    _process(objects, inputs, INPUT_RE, _match_input)
    return objects

def _locate_filenames(directories, ext):
    """Locate files in the directories with the given extension."""

    out = set()
    for location in directories:
        for filename in mooseutils.git_ls_files(os.path.join(MooseDocs.ROOT_DIR, location)):
            if filename.endswith(ext) and not os.path.islink(filename):
                out.add(filename)
    return out

def _process(objects, filenames, regex, func):
    """Process regex"""
    for filename in filenames:
        content = read(filename)
        for match in regex.finditer(content):
            func(objects, filename, match)

def _match_definition(objects, filename, match):
    """Class definition match function."""
    name = match.group('class')

    hdr = filename.replace('/src/', '/include/')[:-2] + '.h'
    if not os.path.exists(hdr):
        hdr = None
    else:
        hdr = os.path.relpath(hdr, MooseDocs.ROOT_DIR)

    src = os.path.relpath(filename, MooseDocs.ROOT_DIR)
    objects[name] = DatabaseItem(name, hdr, src)

def _match_child(objects, filename, match):
    """Child class match function."""
    key = match.group('key')
    if key in objects:
        filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key].children.add(filename)

def _match_input(objects, filename, match):
    """Input use match function."""
    key = match.group('key')

    # AD instances are caught for both the regular and AD object. This is done because:
    # - in all cases I know of, the AD/nonAD are from the same template
    # - as they share parameters, it does not hurt to merge both documentations
    # - only one documentation file has been created for both classes usually
    # This would be problematic if the classes were separate and had different parameters
    if key.replace('AD', '') in objects:
        full_filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key.replace('AD', '')].inputs.add(full_filename)
    if 'AD' in key and key in objects:
        full_filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key].inputs.add(full_filename)
<commit_msg>Address Casey's review, solidify AD/nonAD input file collection by verifying that they come from the same source file, refs #17426<commit_after>#* This file is part of the MOOSE framework
#* https://www.mooseframework.org
#*
#* All rights reserved, see COPYRIGHT for full restrictions
#* https://github.com/idaholab/moose/blob/master/COPYRIGHT
#*
#* Licensed under LGPL 2.1, please see LICENSE for details
#* https://www.gnu.org/licenses/lgpl-2.1.html

"""Tools for extracting C++ class information."""
import os
import re

import mooseutils

import MooseDocs
from .read import read

#: Locates class definitions in header files
# string starts with register(AD)MooseObject(Aliased)
# then the App name in double quotes, which must finish by App
# then either a comma and one or more spaces, or a comma, spaces, a word (for aliased registration)
# then the name of the registered class, captured in <class>, can be followed by quotes (alias)
# then the registering function closing parenthesis and the C++ semicolon
DEFINITION_RE = re.compile(r'register(|AD)MooseObject(|Aliased)\(\"\w+App\"(,\s+|,\s+\w+,\s+\")(?P<class>\w+)\"?\);')

#: Locates class inheritance
# <key> is captured as the first word after the 'public' word at the beginning of the expression
# with a space before and with some text (or not) after
CHILD_RE = re.compile(r'\bpublic\s+(?P<key>\w+)\b')

#: Locates class use in input files
# expression starts with type, spaces or not, an equal, spaces or not
# <key> is captured as the first word after this
INPUT_RE = re.compile(r'\btype\s*=\s*(?P<key>\w+)\b')

class DatabaseItem(object):
    """Storage container for class information."""
    def __init__(self, name, header, source):
        self.name = name
        self.source = source
        self.header = header
        self.inputs = set()
        self.children = set()

def build_class_database(source_dirs=None, include_dirs=None, input_dirs=None):
    """
    Create the class database.

    Returns a dict() of DatabaseItem objects. The key is the class name e.g., Diffusion.

    Inputs:
        source_dirs[list]: A space separated str or a list of source directories.
        include_dirs[list]: A space separated str or a list of include directories.
        input_dirs[list]: A space separated str or a list of input file directories.
    """

    # Handle environment variables
    if source_dirs:
        source_dirs = [mooseutils.eval_path(x) for x in source_dirs]
    else:
        source_dirs = [MooseDocs.ROOT_DIR]

    if include_dirs:
        include_dirs = [mooseutils.eval_path(x) for x in include_dirs]
    else:
        include_dirs = [MooseDocs.ROOT_DIR]

    if input_dirs:
        input_dirs = [mooseutils.eval_path(x) for x in input_dirs]
    else:
        input_dirs = [MooseDocs.ROOT_DIR]

    # Locate filenames
    sources = _locate_filenames(source_dirs, '.C')
    headers = _locate_filenames(include_dirs, '.h')
    inputs = _locate_filenames(input_dirs, '.i')

    # Create the database
    objects = dict()
    _process(objects, sources, DEFINITION_RE, _match_definition)
    _process(objects, headers, CHILD_RE, _match_child)
    _process(objects, inputs, INPUT_RE, _match_input)
    return objects

def _locate_filenames(directories, ext):
    """Locate files in the directories with the given extension."""

    out = set()
    for location in directories:
        for filename in mooseutils.git_ls_files(os.path.join(MooseDocs.ROOT_DIR, location)):
            if filename.endswith(ext) and not os.path.islink(filename):
                out.add(filename)
    return out

def _process(objects, filenames, regex, func):
    """Process regex"""
    for filename in filenames:
        content = read(filename)
        for match in regex.finditer(content):
            func(objects, filename, match)

def _match_definition(objects, filename, match):
    """Class definition match function."""
    name = match.group('class')

    hdr = filename.replace('/src/', '/include/')[:-2] + '.h'
    if not os.path.exists(hdr):
        hdr = None
    else:
        hdr = os.path.relpath(hdr, MooseDocs.ROOT_DIR)

    src = os.path.relpath(filename, MooseDocs.ROOT_DIR)
    objects[name] = DatabaseItem(name, hdr, src)

def _match_child(objects, filename, match):
    """Child class match function."""
    key = match.group('key')
    if key in objects:
        filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key].children.add(filename)

def _match_input(objects, filename, match):
    """Input use match function."""
    key = match.group('key')

    # AD instances are caught for both the regular and AD object. This is done because:
    # - in many cases, the AD/nonAD are from the same template
    # - as they share parameters, it does not hurt to merge both documentations
    # - only one documentation file (the non AD) has been created for both classes usually
    # We avoid doing this when the classes source were separate and may have different parameters
    if key.replace('AD', '') in objects and (key not in objects or
         (objects[key.replace('AD', '')].source == objects[key].source)):
        full_filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key.replace('AD', '')].inputs.add(full_filename)
    if 'AD' in key and key in objects:
        full_filename = os.path.relpath(filename, MooseDocs.ROOT_DIR)
        objects[key].inputs.add(full_filename)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
#
#    Copyright (C) 2013-15 Agile Business Group sagl
#    (<http://www.agilebg.com>)
#
#    This program 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.
#
#    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
#
#

from openerp.osv import fields, osv

class SaleConfigSettings(osv.TransientModel):
    _inherit = 'sale.config.settings'

    _columns = {
        'group_use_product_description_per_so_line': fields.boolean(
            """Allow using only the product sale description
            on the sales order lines""",
            implied_group="sale_order_line_description."
            "group_use_product_description_per_so_line",
            help="""Allows you to use only product sale description on the
            sales order line."""
        ),
    }
<commit_msg>[IMP] sale_order_line_description: res_config => new api<commit_after># -*- coding: utf-8 -*-
#
#
#    Copyright (C) 2013-15 Agile Business Group sagl
#    (<http://www.agilebg.com>)
#
#    This program 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.
#
#    This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
#
#

from openerp import models, fields

class SaleConfigSettings(models.TransientModel):
    _inherit = 'sale.config.settings'

    group_use_product_description_per_so_line = fields.Boolean(
        """Allow using only the product sale description on the sales
        order lines""", implied_group="sale_order_line_description."
        "group_use_product_description_per_so_line",
        help="""Allows you to use only product sale description on the
        sales order line."""
        )
<|endoftext|>


<commit_before>import ray
from ray import serve
from ray.serve.config import BackendConfig

def test_imported_backend(serve_instance):
    config = BackendConfig(user_config="config", max_batch_size=2)
    serve.create_backend(
        "imported",
        "ray.serve.utils.MockImportedBackend",
        "input_arg",
        config=config)
    serve.create_endpoint("imported", backend="imported")

    # Basic sanity check.
    handle = serve.get_handle("imported")
    assert ray.get(handle.remote()) == {"arg": "input_arg", "config": "config"}

    # Check that updating backend config works.
    serve.update_backend_config(
        "imported", BackendConfig(user_config="new_config"))
    assert ray.get(handle.remote()) == {
        "arg": "input_arg",
        "config": "new_config"
    }

    # Check that other call methods work.
    handle = handle.options(method_name="other_method")
    assert ray.get(handle.remote("hello")) == "hello"

    # Check that functions work as well.
    serve.create_backend(
        "imported_func",
        "ray.serve.utils.mock_imported_function",
        config=BackendConfig(max_batch_size=2))
    serve.create_endpoint("imported_func", backend="imported_func")
    handle = serve.get_handle("imported_func")
    assert ray.get(handle.remote("hello")) == "hello"
<commit_msg>[serve] Make sure test_imported_backend is ran (#15043)<commit_after>import ray
from ray import serve
from ray.serve.config import BackendConfig

def test_imported_backend(serve_instance):
    config = BackendConfig(user_config="config", max_batch_size=2)
    serve.create_backend(
        "imported",
        "ray.serve.utils.MockImportedBackend",
        "input_arg",
        config=config)
    serve.create_endpoint("imported", backend="imported")

    # Basic sanity check.
    handle = serve.get_handle("imported")
    assert ray.get(handle.remote()) == {"arg": "input_arg", "config": "config"}

    # Check that updating backend config works.
    serve.update_backend_config(
        "imported", BackendConfig(user_config="new_config"))
    assert ray.get(handle.remote()) == {
        "arg": "input_arg",
        "config": "new_config"
    }

    # Check that other call methods work.
    handle = handle.options(method_name="other_method")
    assert ray.get(handle.remote("hello")) == "hello"

    # Check that functions work as well.
    serve.create_backend(
        "imported_func",
        "ray.serve.utils.mock_imported_function",
        config=BackendConfig(max_batch_size=2))
    serve.create_endpoint("imported_func", backend="imported_func")
    handle = serve.get_handle("imported_func")
    assert ray.get(handle.remote("hello")) == "hello"

if __name__ == "__main__":
    import sys
    import pytest
    sys.exit(pytest.main(["-v", "-s", __file__]))
<|endoftext|>


<commit_before>import datetime
from collections import OrderedDict

from numpy.ma import MaskedArray
from numpy import array
from numpy.testing import assert_equal
import numpy
import pytest

import turbodbc

from query_fixture import query_fixture
from helpers import open_cursor, for_each_database, for_one_database

@for_one_database
def test_column_of_unsupported_type_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = ["this is not a NumPy MaskedArray"]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_columns_of_unequal_sizes_raise(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([1, 2, 3], mask=False),
                       MaskedArray([1, 2], mask=False)]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_incompatible_dtype_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([1, 2, 3], mask=False, dtype='int16')]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_multiple_dimensions_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            two_dimensional = array([[1, 2, 3], [4, 5, 6]])
            columns = [two_dimensional]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_non_contiguous_data_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            two_dimensional = array([[1, 2, 3], [4, 5, 6]])
            one_dimensional = two_dimensional[:, 1]
            assert one_dimensional.flags.c_contiguous == False
            columns = [one_dimensional]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_number_of_columns_does_not_match_parameter_count(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([42]), array([17])]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_passing_empty_list_is_ok(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            cursor.executemanycolumns("INSERT INTO {} VALUES (42)".format(table_name), [])

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[42]]

@for_each_database
def test_integer_column(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([17, 23, 42])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_integer_column_exceeds_buffer_size(dsn, configuration):
    with open_cursor(configuration, parameter_sets_to_buffer=2) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([17, 23, 42])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_masked_integer_column(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=[False, True, False])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [42], [None]]

@for_each_database
def test_masked_integer_column_with_shrunk_mask(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=False)]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_masked_integer_column_exceeds_buffer_size(dsn, configuration):
    with open_cursor(configuration, parameter_sets_to_buffer=2) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=[True, False, True])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[23], [None], [None]]

@for_each_database
def test_multiple_columns(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT TWO INTEGER COLUMNS') as table_name:
            columns = [array([17, 23, 42]), array([3, 2, 1])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?, ?)".format(table_name), columns)

            results = cursor.execute("SELECT A, B FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17, 3], [23, 2], [42, 1]]

# TODO test zero length parameters
<commit_msg>Add test for empty parameter sets<commit_after>import datetime
from collections import OrderedDict

from numpy.ma import MaskedArray
from numpy import array
from numpy.testing import assert_equal
import numpy
import pytest

import turbodbc

from query_fixture import query_fixture
from helpers import open_cursor, for_each_database, for_one_database

@for_one_database
def test_column_of_unsupported_type_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = ["this is not a NumPy MaskedArray"]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_columns_of_unequal_sizes_raise(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([1, 2, 3], mask=False),
                       MaskedArray([1, 2], mask=False)]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_incompatible_dtype_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([1, 2, 3], mask=False, dtype='int16')]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_multiple_dimensions_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            two_dimensional = array([[1, 2, 3], [4, 5, 6]])
            columns = [two_dimensional]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_column_with_non_contiguous_data_raises(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            two_dimensional = array([[1, 2, 3], [4, 5, 6]])
            one_dimensional = two_dimensional[:, 1]
            assert one_dimensional.flags.c_contiguous == False
            columns = [one_dimensional]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_number_of_columns_does_not_match_parameter_count(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([42]), array([17])]
            with pytest.raises(turbodbc.InterfaceError):
                cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

@for_one_database
def test_passing_empty_list_of_columns_is_ok(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            cursor.executemanycolumns("INSERT INTO {} VALUES (42)".format(table_name), [])

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[42]]

@for_one_database
def test_passing_empty_column_is_ok(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([], dtype='int64')]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == []

@for_each_database
def test_integer_column(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([17, 23, 42])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_integer_column_exceeds_buffer_size(dsn, configuration):
    with open_cursor(configuration, parameter_sets_to_buffer=2) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [array([17, 23, 42])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_masked_integer_column(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=[False, True, False])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [42], [None]]

@for_each_database
def test_masked_integer_column_with_shrunk_mask(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=False)]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17], [23], [42]]

@for_each_database
def test_masked_integer_column_exceeds_buffer_size(dsn, configuration):
    with open_cursor(configuration, parameter_sets_to_buffer=2) as cursor:
        with query_fixture(cursor, configuration, 'INSERT INTEGER') as table_name:
            columns = [MaskedArray([17, 23, 42], mask=[True, False, True])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?)".format(table_name), columns)

            results = cursor.execute("SELECT A FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[23], [None], [None]]

@for_each_database
def test_multiple_columns(dsn, configuration):
    with open_cursor(configuration) as cursor:
        with query_fixture(cursor, configuration, 'INSERT TWO INTEGER COLUMNS') as table_name:
            columns = [array([17, 23, 42]), array([3, 2, 1])]
            cursor.executemanycolumns("INSERT INTO {} VALUES (?, ?)".format(table_name), columns)

            results = cursor.execute("SELECT A, B FROM {} ORDER BY A".format(table_name)).fetchall()
            assert results == [[17, 3], [23, 2], [42, 1]]
<|endoftext|>