text:
"""
Vultr Driver
"""
import time
import json
import base64
from functools import update_wrapper
from typing import Optional, List, Dict, Union, Any

from libcloud.common.base import ConnectionKey, JsonResponse
from libcloud.common.types import InvalidCredsError
from libcloud.common.types import LibcloudError
from libcloud.common.types import ServiceUnavailableError
from libcloud.compute.base import Node, NodeImage, NodeSize, NodeLocation
from libcloud.compute.base import KeyPair, StorageVolume
from libcloud.compute.base import NodeDriver
from libcloud.compute.types import NodeState, StorageVolumeState
from libcloud.compute.types import Provider, VolumeSnapshotState
from libcloud.utils.iso8601 import parse_date
from libcloud.utils.py3 import httplib
from libcloud.utils.py3 import urlencode
from libcloud.utils.publickey import get_pubkey_openssh_fingerprint
from libcloud.common.vultr import DEFAULT_API_VERSION
from libcloud.common.vultr import VultrConnectionV2
from libcloud.common.vultr import VultrNetwork, VultrNodeSnapshot

# For matching region by id
VULTR_COMPUTE_INSTANCE_LOCATIONS = {
    "1": {
        "DCID": "1",
        "name": "New Jersey",
        "country": "US",
        "continent": "North America",
        "state": "NJ",
        "regioncode": "EWR",
    },
    "2": {
        "DCID": "2",
        "name": "Chicago",
        "country": "US",
        "continent": "North America",
        "state": "IL",
        "regioncode": "ORD",
    },
    "3": {
        "DCID": "3",
        "name": "Dallas",
        "country": "US",
        "continent": "North America",
        "state": "TX",
        "regioncode": "DFW",
    },
    "4": {
        "DCID": "4",
        "name": "Seattle",
        "country": "US",
        "continent": "North America",
        "state": "WA",
        "regioncode": "SEA",
    },
    "5": {
        "DCID": "5",
        "name": "Los Angeles",
        "country": "US",
        "continent": "North America",
        "state": "CA",
        "regioncode": "LAX",
    },
    "6": {
        "DCID": "6",
        "name": "Atlanta",
        "country": "US",
        "continent": "North America",
        "state": "GA",
        "regioncode": "ATL",
    },
    "7": {
        "DCID": "7",
        "name": "Amsterdam",
        "country": "NL",
        "continent": "Europe",
        "state": "",
        "regioncode": "AMS",
    },
    "8": {
        "DCID": "8",
        "name": "London",
        "country": "GB",
        "continent": "Europe",
        "state": "",
        "regioncode": "LHR",
    },
    "9": {
        "DCID": "9",
        "name": "Frankfurt",
        "country": "DE",
        "continent": "Europe",
        "state": "",
        "regioncode": "FRA",
    },
    "12": {
        "DCID": "12",
        "name": "Silicon Valley",
        "country": "US",
        "continent": "North America",
        "state": "CA",
        "regioncode": "SJC",
    },
    "19": {
        "DCID": "19",
        "name": "Sydney",
        "country": "AU",
        "continent": "Australia",
        "state": "",
        "regioncode": "SYD",
    },
    "22": {
        "DCID": "22",
        "name": "Toronto",
        "country": "CA",
        "continent": "North America",
        "state": "",
        "regioncode": "YTO",
    },
    "24": {
        "DCID": "24",
        "name": "Paris",
        "country": "FR",
        "continent": "Europe",
        "state": "",
        "regioncode": "CDG",
    },
    "25": {
        "DCID": "25",
        "name": "Tokyo",
        "country": "JP",
        "continent": "Asia",
        "state": "",
        "regioncode": "NRT",
    },
    "34": {
        "DCID": "34",
        "name": "Seoul",
        "country": "KR",
        "continent": "Asia",
        "state": "",
        "regioncode": "ICN",
    },
    "39": {
        "DCID": "39",
        "name": "Miami",
        "country": "US",
        "continent": "North America",
        "state": "FL",
        "regioncode": "MIA",
    },
    "40": {
        "DCID": "40",
        "name": "Singapore",
        "country": "SG",
        "continent": "Asia",
        "state": "",
        "regioncode": "SGP",
    },
}
# For matching image by id
VULTR_COMPUTE_INSTANCE_IMAGES = {
    "127": {
        "OSID": 127,
        "name": "CentOS 6 x64",
        "arch": "x64",
        "family": "centos",
        "windows": False,
    },
    "147": {
        "OSID": 147,
        "name": "CentOS 6 i386",
        "arch": "i386",
        "family": "centos",
        "windows": False,
    },
    "167": {
        "OSID": 167,
        "name": "CentOS 7 x64",
        "arch": "x64",
        "family": "centos",
        "windows": False,
    },
    "381": {
        "OSID": 381,
        "name": "CentOS 7 SELinux x64",
        "arch": "x64",
        "family": "centos",
        "windows": False,
    },
    "362": {
        "OSID": 362,
        "name": "CentOS 8 x64",
        "arch": "x64",
        "family": "centos",
        "windows": False,
    },
    "401": {
        "OSID": 401,
        "name": "CentOS 8 Stream x64",
        "arch": "x64",
        "family": "centos",
        "windows": False,
    },
    "215": {
        "OSID": 215,
        "name": "Ubuntu 16.04 x64",
        "arch": "x64",
        "family": "ubuntu",
        "windows": False,
    },
    "216": {
        "OSID": 216,
        "name": "Ubuntu 16.04 i386",
        "arch": "i386",
        "family": "ubuntu",
        "windows": False,
    },
    "270": {
        "OSID": 270,
        "name": "Ubuntu 18.04 x64",
        "arch": "x64",
        "family": "ubuntu",
        "windows": False,
    },
    "387": {
        "OSID": 387,
        "name": "Ubuntu 20.04 x64",
        "arch": "x64",
        "family": "ubuntu",
        "windows": False,
    },
    "194": {
        "OSID": 194,
        "name": "Debian 8 i386 (jessie)",
        "arch": "i386",
        "family": "debian",
        "windows": False,
    },
    "244": {
        "OSID": 244,
        "name": "Debian 9 x64 (stretch)",
        "arch": "x64",
        "family": "debian",
        "windows": False,
    },
    "352": {
        "OSID": 352,
        "name": "Debian 10 x64 (buster)",
        "arch": "x64",
        "family": "debian",
        "windows": False,
    },
    "230": {
        "OSID": 230,
        "name": "FreeBSD 11 x64",
        "arch": "x64",
        "family": "freebsd",
        "windows": False,
    },
    "327": {
        "OSID": 327,
        "name": "FreeBSD 12 x64",
        "arch": "x64",
        "family": "freebsd",
        "windows": False,
    },
    "366": {
        "OSID": 366,
        "name": "OpenBSD 6.6 x64",
        "arch": "x64",
        "family": "openbsd",
        "windows": False,
    },
    "394": {
        "OSID": 394,
        "name": "OpenBSD 6.7 x64",
        "arch": "x64",
        "family": "openbsd",
        "windows": False,
    },
    "391": {
        "OSID": 391,
        "name": "Fedora CoreOS",
        "arch": "x64",
        "family": "fedora-coreos",
        "windows": False,
    },
    "367": {
        "OSID": 367,
        "name": "Fedora 31 x64",
        "arch": "x64",
        "family": "fedora",
        "windows": False,
    },
    "389": {
        "OSID": 389,
        "name": "Fedora 32 x64",
        "arch": "x64",
        "family": "fedora",
        "windows": False,
    },
    "124": {
        "OSID": 124,
        "name": "Windows 2012 R2 x64",
        "arch": "x64",
        "family": "windows",
        "windows": False,
    },
    "240": {
        "OSID": 240,
        "name": "Windows 2016 x64",
        "arch": "x64",
        "family": "windows",
        "windows": False,
    },
    "159": {
        "OSID": 159,
        "name": "Custom",
        "arch": "x64",
        "family": "iso",
        "windows": False,
    },
    "164": {
        "OSID": 164,
        "name": "Snapshot",
        "arch": "x64",
        "family": "snapshot",
        "windows": False,
    },
    "180": {
        "OSID": 180,
        "name": "Backup",
        "arch": "x64",
        "family": "backup",
        "windows": False,
    },
    "186": {
        "OSID": 186,
        "name": "Application",
        "arch": "x64",
        "family": "application",
        "windows": False,
    },
}
VULTR_COMPUTE_INSTANCE_SIZES = {
    "201": {
        "VPSPLANID": "201",
        "name": "1024 MB RAM,25 GB SSD,1.00 TB BW",
        "vcpu_count": "1",
        "ram": "1024",
        "disk": "25",
        "bandwidth": "1.00",
        "bandwidth_gb": "1024",
        "price_per_month": "5.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "202": {
        "VPSPLANID": "202",
        "name": "2048 MB RAM,55 GB SSD,2.00 TB BW",
        "vcpu_count": "1",
        "ram": "2048",
        "disk": "55",
        "bandwidth": "2.00",
        "bandwidth_gb": "2048",
        "price_per_month": "10.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "203": {
        "VPSPLANID": "203",
        "name": "4096 MB RAM,80 GB SSD,3.00 TB BW",
        "vcpu_count": "2",
        "ram": "4096",
        "disk": "80",
        "bandwidth": "3.00",
        "bandwidth_gb": "3072",
        "price_per_month": "20.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "204": {
        "VPSPLANID": "204",
        "name": "8192 MB RAM,160 GB SSD,4.00 TB BW",
        "vcpu_count": "4",
        "ram": "8192",
        "disk": "160",
        "bandwidth": "4.00",
        "bandwidth_gb": "4096",
        "price_per_month": "40.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "205": {
        "VPSPLANID": "205",
        "name": "16384 MB RAM,320 GB SSD,5.00 TB BW",
        "vcpu_count": "6",
        "ram": "16384",
        "disk": "320",
        "bandwidth": "5.00",
        "bandwidth_gb": "5120",
        "price_per_month": "80.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "206": {
        "VPSPLANID": "206",
        "name": "32768 MB RAM,640 GB SSD,6.00 TB BW",
        "vcpu_count": "8",
        "ram": "32768",
        "disk": "640",
        "bandwidth": "6.00",
        "bandwidth_gb": "6144",
        "price_per_month": "160.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "207": {
        "VPSPLANID": "207",
        "name": "65536 MB RAM,1280 GB SSD,10.00 TB BW",
        "vcpu_count": "16",
        "ram": "65536",
        "disk": "1280",
        "bandwidth": "10.00",
        "bandwidth_gb": "10240",
        "price_per_month": "320.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "208": {
        "VPSPLANID": "208",
        "name": "98304 MB RAM,1600 GB SSD,15.00 TB BW",
        "vcpu_count": "24",
        "ram": "98304",
        "disk": "1600",
        "bandwidth": "15.00",
        "bandwidth_gb": "15360",
        "price_per_month": "640.00",
        "plan_type": "SSD",
        "windows": False,
    },
    "115": {
        "VPSPLANID": "115",
        "name": "8192 MB RAM,110 GB SSD,10.00 TB BW",
        "vcpu_count": "2",
        "ram": "8192",
        "disk": "110",
        "bandwidth": "10.00",
        "bandwidth_gb": "10240",
        "price_per_month": "60.00",
        "plan_type": "DEDICATED",
        "windows": False,
    },
    "116": {
        "VPSPLANID": "116",
        "name": "16384 MB RAM,2x110 GB SSD,20.00 TB BW",
        "vcpu_count": "4",
        "ram": "16384",
        "disk": "110",
        "bandwidth": "20.00",
        "bandwidth_gb": "20480",
        "price_per_month": "120.00",
        "plan_type": "DEDICATED",
        "windows": False,
    },
    "117": {
        "VPSPLANID": "117",
        "name": "24576 MB RAM,3x110 GB SSD,30.00 TB BW",
        "vcpu_count": "6",
        "ram": "24576",
        "disk": "110",
        "bandwidth": "30.00",
        "bandwidth_gb": "30720",
        "price_per_month": "180.00",
        "plan_type": "DEDICATED",
        "windows": False,
    },
    "118": {
        "VPSPLANID": "118",
        "name": "32768 MB RAM,4x110 GB SSD,40.00 TB BW",
        "vcpu_count": "8",
        "ram": "32768",
        "disk": "110",
        "bandwidth": "40.00",
        "bandwidth_gb": "40960",
        "price_per_month": "240.00",
        "plan_type": "DEDICATED",
        "windows": False,
    },
    "400": {
        "VPSPLANID": "400",
        "name": "1024 MB RAM,32 GB SSD,1.00 TB BW",
        "vcpu_count": "1",
        "ram": "1024",
        "disk": "32",
        "bandwidth": "1.00",
        "bandwidth_gb": "1024",
        "price_per_month": "6.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "401": {
        "VPSPLANID": "401",
        "name": "2048 MB RAM,64 GB SSD,2.00 TB BW",
        "vcpu_count": "1",
        "ram": "2048",
        "disk": "64",
        "bandwidth": "2.00",
        "bandwidth_gb": "2048",
        "price_per_month": "12.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "402": {
        "VPSPLANID": "402",
        "name": "4096 MB RAM,128 GB SSD,3.00 TB BW",
        "vcpu_count": "2",
        "ram": "4096",
        "disk": "128",
        "bandwidth": "3.00",
        "bandwidth_gb": "3072",
        "price_per_month": "24.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "403": {
        "VPSPLANID": "403",
        "name": "8192 MB RAM,256 GB SSD,4.00 TB BW",
        "vcpu_count": "3",
        "ram": "8192",
        "disk": "256",
        "bandwidth": "4.00",
        "bandwidth_gb": "4096",
        "price_per_month": "48.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "404": {
        "VPSPLANID": "404",
        "name": "16384 MB RAM,384 GB SSD,5.00 TB BW",
        "vcpu_count": "4",
        "ram": "16384",
        "disk": "384",
        "bandwidth": "5.00",
        "bandwidth_gb": "5120",
        "price_per_month": "96.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "405": {
        "VPSPLANID": "405",
        "name": "32768 MB RAM,512 GB SSD,6.00 TB BW",
        "vcpu_count": "8",
        "ram": "32768",
        "disk": "512",
        "bandwidth": "6.00",
        "bandwidth_gb": "6144",
        "price_per_month": "192.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
    "406": {
        "VPSPLANID": "406",
        "name": "49152 MB RAM,768 GB SSD,8.00 TB BW",
        "vcpu_count": "12",
        "ram": "49152",
        "disk": "768",
        "bandwidth": "8.00",
        "bandwidth_gb": "8192",
        "price_per_month": "256.00",
        "plan_type": "HIGHFREQUENCY",
        "windows": False,
    },
}

class rate_limited:
    """
    Decorator for retrying Vultr calls that are rate-limited.

    :param int sleep: Seconds to sleep after being rate-limited.
    :param int retries: Number of retries.
    """

    def __init__(self, sleep=0.5, retries=1):
        self.sleep = sleep
        self.retries = retries

    def __call__(self, call):
        """
        Run ``call`` method until it's not rate-limited.

        The method is invoked while it returns 503 Service Unavailable or the
        allowed number of retries is reached.

        :param callable call: Method to be decorated.
        """

        def wrapper(*args, **kwargs):
            last_exception = None

            for _ in range(self.retries + 1):
                try:
                    return call(*args, **kwargs)
                except ServiceUnavailableError as e:
                    last_exception = e
                    time.sleep(self.sleep)  # hit by rate limit, let's sleep

            if last_exception:
                raise last_exception  # pylint: disable=raising-bad-type

        update_wrapper(wrapper, call)
        return wrapper

class VultrResponse(JsonResponse):
    def parse_error(self):
        if self.status == httplib.OK:
            body = self.parse_body()
            return body
        elif self.status == httplib.FORBIDDEN:
            raise InvalidCredsError(self.body)
        elif self.status == httplib.SERVICE_UNAVAILABLE:
            raise ServiceUnavailableError(self.body)
        else:
            raise LibcloudError(self.body)

class SSHKey(object):
    def __init__(self, id, name, pub_key):
        self.id = id
        self.name = name
        self.pub_key = pub_key

    def __repr__(self):
        return ("<SSHKey: id=%s, name=%s, pub_key=%s>") % (
            self.id,
            self.name,
            self.pub_key,
        )

class VultrConnection(ConnectionKey):
    """
    Connection class for the Vultr driver.
    """

    host = "api.vultr.com"
    responseCls = VultrResponse
    unauthenticated_endpoints = {  # {action: methods}
        "/v1/app/list": ["GET"],
        "/v1/os/list": ["GET"],
        "/v1/plans/list": ["GET"],
        "/v1/plans/list_vc2": ["GET"],
        "/v1/plans/list_vdc2": ["GET"],
        "/v1/regions/availability": ["GET"],
        "/v1/regions/list": ["GET"],
    }

    def add_default_headers(self, headers):
        """
        Adds ``API-Key`` default header.

        :return: Updated headers.
        :rtype: dict
        """

        if self.require_api_key():
            headers.update({"API-Key": self.key})
        return headers

    def encode_data(self, data):
        return urlencode(data)

    @rate_limited()
    def get(self, url):
        return self.request(url)

    @rate_limited()
    def post(self, url, data):
        headers = {"Content-Type": "application/x-www-form-urlencoded"}
        return self.request(url, data=data, headers=headers, method="POST")

    def require_api_key(self):
        """
        Check whether this call (method + action) must be authenticated.

        :return: True if ``API-Key`` header required, False otherwise.
        :rtype: bool
        """

        try:
            return self.method not in self.unauthenticated_endpoints[self.action]
        except KeyError:
            return True

class VultrNodeDriverHelper(object):
    """
    VultrNode helper class.
    """

    def handle_extra(self, extra_keys, data):
        extra = {}
        for key in extra_keys:
            if key in data:
                extra[key] = data[key]
        return extra

class VultrNodeDriver(NodeDriver):
    type = Provider.VULTR
    name = "Vultr"
    website = "https://www.vultr.com"

    def __new__(
        cls,
        key,
        secret=None,
        secure=True,
        host=None,
        port=None,
        api_version=DEFAULT_API_VERSION,
        region=None,
        **kwargs,
    ):
        if cls is VultrNodeDriver:
            if api_version == "1":
                cls = VultrNodeDriverV1
            elif api_version == "2":
                cls = VultrNodeDriverV2
            else:
                raise NotImplementedError(
                    "No Vultr driver found for API version: %s" % (api_version)
                )
        return super().__new__(cls)

class VultrNodeDriverV1(VultrNodeDriver):
    """
    VultrNode node driver.
    """

    connectionCls = VultrConnection

    NODE_STATE_MAP = {"pending": NodeState.PENDING, "active": NodeState.RUNNING}

    EX_CREATE_YES_NO_ATTRIBUTES = [
        "enable_ipv6",
        "enable_private_network",
        "auto_backups",
        "notify_activate",
        "ddos_protection",
    ]

    EX_CREATE_ID_ATTRIBUTES = {
        "iso_id": "ISOID",
        "script_id": "SCRIPTID",
        "snapshot_id": "SNAPSHOTID",
        "app_id": "APPID",
    }

    EX_CREATE_ATTRIBUTES = [
        "ipxe_chain_url",
        "label",
        "userdata",
        "reserved_ip_v4",
        "hostname",
        "tag",
    ]
    EX_CREATE_ATTRIBUTES.extend(EX_CREATE_YES_NO_ATTRIBUTES)
    EX_CREATE_ATTRIBUTES.extend(EX_CREATE_ID_ATTRIBUTES.keys())

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self._helper = VultrNodeDriverHelper()

    def list_nodes(self):
        return self._list_resources("/v1/server/list", self._to_node)

    def list_key_pairs(self):
        """
        List all the available SSH keys.
        :return: Available SSH keys.
        :rtype: ``list`` of :class:`SSHKey`
        """
        return self._list_resources("/v1/sshkey/list", self._to_ssh_key)

    def create_key_pair(self, name, public_key=""):
        """
        Create a new SSH key.
        :param name: Name of the new SSH key
        :type name: ``str``

        :key public_key: Public part of the new SSH key
        :type name: ``str``

        :return: True on success
        :rtype: ``bool``
        """
        params = {"name": name, "ssh_key": public_key}
        res = self.connection.post("/v1/sshkey/create", params)
        return res.status == httplib.OK

    def delete_key_pair(self, key_pair):
        """
        Delete an SSH key.
        :param key_pair: The SSH key to delete
        :type key_pair: :class:`SSHKey`

        :return: True on success
        :rtype: ``bool``
        """
        params = {"SSHKEYID": key_pair.id}
        res = self.connection.post("/v1/sshkey/destroy", params)
        return res.status == httplib.OK

    def list_locations(self):
        return self._list_resources("/v1/regions/list", self._to_location)

    def list_sizes(self):
        return self._list_resources("/v1/plans/list", self._to_size)

    def list_images(self):
        return self._list_resources("/v1/os/list", self._to_image)

    # pylint: disable=too-many-locals
    def create_node(
        self, name, size, image, location, ex_ssh_key_ids=None, ex_create_attr=None
    ):
        """
        Create a node

        :param name: Name for the new node
        :type name: ``str``

        :param size: Size of the new node
        :type size: :class:`NodeSize`

        :param image: Image for the new node
        :type image: :class:`NodeImage`

        :param location: Location of the new node
        :type location: :class:`NodeLocation`

        :param ex_ssh_key_ids: IDs of the SSH keys to initialize
        :type ex_sshkeyid: ``list`` of ``str``

        :param ex_create_attr: Extra attributes for node creation
        :type ex_create_attr: ``dict``

        The `ex_create_attr` parameter can include the following dictionary
        key and value pairs:

        * `ipxe_chain_url`: ``str`` for specifying URL to boot via IPXE
        * `iso_id`: ``str`` the ID of a specific ISO to mount,
          only meaningful with the `Custom` `NodeImage`
        * `script_id`: ``int`` ID of a startup script to execute on boot,
          only meaningful when the `NodeImage` is not `Custom`
        * 'snapshot_id`: ``str`` Snapshot ID to restore for the initial
          installation, only meaningful with the `Snapshot` `NodeImage`
        * `enable_ipv6`: ``bool`` Whether an IPv6 subnet should be assigned
        * `enable_private_network`: ``bool`` Whether private networking
          support should be added
        * `label`: ``str`` Text label to be shown in the control panel
        * `auto_backups`: ``bool`` Whether automatic backups should be enabled
        * `app_id`: ``int`` App ID to launch if launching an application,
          only meaningful when the `NodeImage` is `Application`
        * `userdata`: ``str`` Base64 encoded cloud-init user-data
        * `notify_activate`: ``bool`` Whether an activation email should be
          sent when the server is ready
        * `ddos_protection`: ``bool`` Whether DDOS protection should be enabled
        * `reserved_ip_v4`: ``str`` IP address of the floating IP to use as
          the main IP of this server
        * `hostname`: ``str`` The hostname to assign to this server
        * `tag`: ``str`` The tag to assign to this server

        :return: The newly created node.
        :rtype: :class:`Node`

        """
        params = {
            "DCID": location.id,
            "VPSPLANID": size.id,
            "OSID": image.id,
            "label": name,
        }

        if ex_ssh_key_ids is not None:
            params["SSHKEYID"] = ",".join(ex_ssh_key_ids)

        ex_create_attr = ex_create_attr or {}
        for key, value in ex_create_attr.items():
            if key in self.EX_CREATE_ATTRIBUTES:
                if key in self.EX_CREATE_YES_NO_ATTRIBUTES:
                    params[key] = "yes" if value else "no"
                else:
                    if key in self.EX_CREATE_ID_ATTRIBUTES:
                        key = self.EX_CREATE_ID_ATTRIBUTES[key]
                    params[key] = value

        result = self.connection.post("/v1/server/create", params)
        if result.status != httplib.OK:
            return False

        subid = result.object["SUBID"]

        retry_count = 3
        created_node = None

        for _ in range(retry_count):
            try:
                nodes = self.list_nodes()
                created_node = [n for n in nodes if n.id == subid][0]
            except IndexError:
                time.sleep(1)
            else:
                break

        return created_node

    def reboot_node(self, node):
        params = {"SUBID": node.id}
        res = self.connection.post("/v1/server/reboot", params)

        return res.status == httplib.OK

    def destroy_node(self, node):
        params = {"SUBID": node.id}
        res = self.connection.post("/v1/server/destroy", params)

        return res.status == httplib.OK

    def _list_resources(self, url, tranform_func):
        data = self.connection.get(url).object
        sorted_key = sorted(data)
        return [tranform_func(data[key]) for key in sorted_key]

    def _to_node(self, data):
        if "status" in data:
            state = self.NODE_STATE_MAP.get(data["status"], NodeState.UNKNOWN)
            if state == NodeState.RUNNING and data["power_status"] != "running":
                state = NodeState.STOPPED
        else:
            state = NodeState.UNKNOWN

        if "main_ip" in data and data["main_ip"] is not None:
            public_ips = [data["main_ip"]]
        else:
            public_ips = []
        # simple check that we have ip address in value
        if len(data["internal_ip"]) > 0:
            private_ips = [data["internal_ip"]]
        else:
            private_ips = []
        created_at = parse_date(data["date_created"])

        # response ordering
        extra_keys = [
            "location",  # Location name
            "default_password",
            "pending_charges",
            "cost_per_month",
            "current_bandwidth_gb",
            "allowed_bandwidth_gb",
            "netmask_v4",
            "gateway_v4",
            "power_status",
            "server_state",
            "v6_networks",
            # TODO: Does we really need kvm_url?
            "kvm_url",
            "auto_backups",
            "tag",
            # "OSID",  # Operating system to use. See v1/os/list.
            "APPID",
            "FIREWALLGROUPID",
        ]
        extra = self._helper.handle_extra(extra_keys, data)

        resolve_data = VULTR_COMPUTE_INSTANCE_IMAGES.get(data["OSID"])
        if resolve_data:
            image = self._to_image(resolve_data)
        else:
            image = None

        resolve_data = VULTR_COMPUTE_INSTANCE_SIZES.get(data["VPSPLANID"])
        if resolve_data:
            size = self._to_size(resolve_data)
        else:
            size = None

        # resolve_data = VULTR_COMPUTE_INSTANCE_LOCATIONS.get(data['DCID'])
        # if resolve_data:
        #     location = self._to_location(resolve_data)
        # extra['location'] = location

        node = Node(
            id=data["SUBID"],
            name=data["label"],
            state=state,
            public_ips=public_ips,
            private_ips=private_ips,
            image=image,
            size=size,
            extra=extra,
            created_at=created_at,
            driver=self,
        )

        return node

    def _to_location(self, data):
        extra_keys = [
            "continent",
            "state",
            "ddos_protection",
            "block_storage",
            "regioncode",
        ]
        extra = self._helper.handle_extra(extra_keys, data)

        return NodeLocation(
            id=data["DCID"],
            name=data["name"],
            country=data["country"],
            extra=extra,
            driver=self,
        )

    def _to_size(self, data):
        extra_keys = [
            "vcpu_count",
            "plan_type",
            "available_locations",
        ]
        extra = self._helper.handle_extra(extra_keys, data)

        # backward compatibility
        if extra.get("vcpu_count").isdigit():
            extra["vcpu_count"] = int(extra["vcpu_count"])

        ram = int(data["ram"])
        disk = int(data["disk"])
        # NodeSize accepted int instead float
        bandwidth = int(float(data["bandwidth"]))
        price = float(data["price_per_month"])
        return NodeSize(
            id=data["VPSPLANID"],
            name=data["name"],
            ram=ram,
            disk=disk,
            bandwidth=bandwidth,
            price=price,
            extra=extra,
            driver=self,
        )

    def _to_image(self, data):
        extra_keys = ["arch", "family"]
        extra = self._helper.handle_extra(extra_keys, data)
        return NodeImage(id=data["OSID"], name=data["name"], extra=extra, driver=self)

    def _to_ssh_key(self, data):
        return SSHKey(id=data["SSHKEYID"], name=data["name"], pub_key=data["ssh_key"])

class VultrNodeDriverV2(VultrNodeDriver):
    """
    Vultr API v2 NodeDriver.
    """

    connectionCls = VultrConnectionV2
    NODE_STATE_MAP = {
        "active": NodeState.RUNNING,
        "halted": NodeState.STOPPED,
        "rebooting": NodeState.REBOOTING,
        "resizing": NodeState.RECONFIGURING,
        "pending": NodeState.PENDING,
    }

    VOLUME_STATE_MAP = {
        "active": StorageVolumeState.AVAILABLE,
        "pending": StorageVolumeState.CREATING,
    }

    SNAPSHOT_STATE_MAP = {
        "complete": VolumeSnapshotState.AVAILABLE,
        "pending": VolumeSnapshotState.CREATING,
    }

    def list_nodes(self, ex_list_bare_metals: bool = True) -> List[Node]:
        """List all nodes.

        :keyword ex_list_bare_metals: Whether to fetch bare metal nodes.
        :type    ex_list_bare_metals: ``bool``

        :return:  list of node objects
        :rtype: ``list`` of :class: `Node`
        """
        data = self._paginated_request("/v2/instances", "instances")
        nodes = [self._to_node(item) for item in data]

        if ex_list_bare_metals:
            nodes += self.ex_list_bare_metal_nodes()
        return nodes

    def create_node(
        self,
        name: str,
        size: NodeSize,
        location: NodeLocation,
        image: Optional[NodeImage] = None,
        ex_ssh_key_ids: Optional[List[str]] = None,
        ex_private_network_ids: Optional[List[str]] = None,
        ex_snapshot: Union[VultrNodeSnapshot, str, None] = None,
        ex_enable_ipv6: bool = False,
        ex_backups: bool = False,
        ex_userdata: Optional[str] = None,
        ex_ddos_protection: bool = False,
        ex_enable_private_network: bool = False,
        ex_ipxe_chain_url: Optional[str] = None,
        ex_iso_id: Optional[str] = None,
        ex_script_id: Optional[str] = None,
        ex_image_id: Optional[str] = None,
        ex_activation_email: bool = False,
        ex_hostname: Optional[str] = None,
        ex_tag: Optional[str] = None,
        ex_firewall_group_id: Optional[str] = None,
        ex_reserved_ipv4: Optional[str] = None,
        ex_persistent_pxe: bool = False,
    ) -> Node:
        """Create a new node.

        :param name: The new node's name.
        :type name: ``str``

        :param size: The size to use to create the node.
        :type size: :class: `NodeSize`

        :param location: The location to provision the node.
        :type location: :class: `NodeLocation`

        :keyword image:  The image to use to provision the node.
        :type    image:  :class: `NodeImage`

        :keyword ex_ssh_key_ids: List of SSH keys to install on this node.
        :type    ex_ssh_key_ids: ``list`` of ``str``

        :keyword ex_private_network_ids: The network ids to attach to node.
                                         This parameter takes precedence over
                                         ex_enable_private_network (VPS only)
        :type    ex_private_network_ids: ``list`` of ``str``

        :keyword ex_snapshot: The snapshot to use when deploying the node.
                                 Mutually exclusive with image,
        :type    ex_snapshot: :class: `VultrNodeSnapshot` or ``str``

        :keyword ex_enable_ipv6: Wheteher to enable IPv6.
        :type    ex_enable_ipv6: ``bool``

        :keyword ex_backups: Enable automatic backups for the node. (VPS only)
        :type    ex_backups: ``bool``

        :keyword ex_userdata: String containing user data
        :type    ex_userdata: ``str``

        :keyword ex_ddos_protection: Enable DDoS protection (VPS only)
        :type    ex_ddos_protection: ``bool``

        :keyword ex_enable_private_network: Enable private networking.
                                            Mutually exclusive with
                                             ex_private_network_ids.
                                            (VPS only)
        :type    ex_enable_private_network: ``bool``

        :keyword ex_ipxe_chain_url: The URL location of the iPXE chainloader
                                    (VPS only)
        :type    ex_ipxe_chain_url: ``str``

        :keyword ex_iso_id: The ISO id to use when deploying this node.
                            (VPS only)
        :type    ex_iso_id: ``str``

        :keyword ex_script_id: The startup script id to use when deploying
                               this node.
        :type    ex_script_id: ``str``

        :keyword ex_image_id: The Application image_id to use when deploying
                              this node.
        :type    ex_image_id: ``str``

        :keyword ex_activation_email: Notify by email after deployment.
        :type    ex_activation_email: ``bool``

        :keyword ex_hostname: The hostname to use when deploying this node.
        :type    ex_hostname: ``str``

        :keyword ex_tag: The user-supplied tag.
        :type    ex_tag: ``str``

        :keyword ex_firewall_group_id: The Firewall Group id to attach to
                                       this node. (VPS only)
        :type    ex_firewall_group_id: ``str``

        :keyword ex_reserved_ipv4: Id of the floating IP to use as the
                                   main IP of this node.
        :type    ex_reserved_ipv4: ``str``

        :keyword ex_persistent_pxe: Enable persistent PXE (Bare Metal only)
        :type    ex_persistent_pxe: ``bool``
        """
        data = {
            "label": name,
            "region": location.id,
            "plan": size.id,
            "enable_ipv6": ex_enable_ipv6,
            "activation_email": ex_activation_email,
        }

        if image:
            data["os_id"] = image.id

        if ex_ssh_key_ids:
            data["sshkey_id"] = ex_ssh_key_ids

        if ex_snapshot:
            try:
                data["snapshot_id"] = ex_snapshot.id
            except AttributeError:
                data["snapshot_id"] = ex_snapshot

        if ex_userdata:
            data["user_data"] = base64.b64encode(bytes(ex_userdata, "utf-8")).decode(
                "utf-8"
            )

        if ex_script_id:
            data["script_id"] = ex_script_id

        if ex_image_id:
            data["image_id"] = ex_image_id

        if ex_hostname:
            data["hostname"] = ex_hostname

        if ex_reserved_ipv4:
            data["reserved_ipv4"] = ex_reserved_ipv4

        if ex_tag:
            data["tag"] = ex_tag

        if self._is_bare_metal(size):
            if ex_persistent_pxe:
                data["persistent_pxe"] = ex_persistent_pxe
            resp = self.connection.request(
                "/v2/bare-metals", data=json.dumps(data), method="POST"
            )
            return self._to_node(resp.object["bare_metal"])
        else:
            if ex_private_network_ids:
                data["attach_private_network"] = ex_private_network_ids

            if ex_enable_private_network:
                data["enable_private_network"] = ex_enable_private_network

            if ex_ipxe_chain_url:
                data["ipxe_chain_url"] = ex_ipxe_chain_url

            if ex_iso_id:
                data["iso_id"] = ex_iso_id

            if ex_ddos_protection:
                data["ddos_protection"] = ex_ddos_protection

            if ex_firewall_group_id:
                data["firewall_group_id"] = ex_firewall_group_id

            if ex_backups:
                data["backups"] = "enabled" if ex_backups is True else "disabled"

            resp = self.connection.request(
                "/v2/instances", data=json.dumps(data), method="POST"
            )
            return self._to_node(resp.object["instance"])

    def reboot_node(self, node: Node) -> bool:
        """Reboot the given node.

        :param node: The node to be rebooted.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        if self._is_bare_metal(node.size):
            return self.ex_reboot_bare_metal_node(node)

        resp = self.connection.request(
            "/v2/instances/%s/reboot" % node.id, method="POST"
        )

        return resp.success()

    def start_node(self, node: Node) -> bool:
        """Start the given node.

        :param node: The node to be started.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        if self._is_bare_metal(node.size):
            return self.ex_start_bare_metal_node(node)

        resp = self.connection.request(
            "/v2/instances/%s/start" % node.id, method="POST"
        )

        return resp.success()

    def stop_node(self, node: Node) -> bool:
        """Stop the given node.

        :param node: The node to be stopped.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        if self._is_bare_metal(node.size):
            return self.ex_stop_bare_metal_node(node)

        return self.ex_stop_nodes([node])

    def destroy_node(self, node: Node) -> bool:
        """Destroy the given node.

        :param node: The node to be destroyed.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        if self._is_bare_metal(node.size):
            return self.ex_destroy_bare_metal_node(node)

        resp = self.connection.request("/v2/instances/%s" % node.id, method="DELETE")

        return resp.success()

    def list_sizes(self, ex_list_bare_metals: bool = True) -> List[NodeSize]:
        """List available node sizes.

        :keyword ex_list_bare_metals: Whether to fetch bare metal sizes.
        :type    ex_list_bare_metals: ``bool``

        :rtype: ``list`` of :class: `NodeSize`
        """
        data = self._paginated_request("/v2/plans", "plans")
        sizes = [self._to_size(item) for item in data]

        if ex_list_bare_metals:
            sizes += self.ex_list_bare_metal_sizes()
        return sizes

    def list_images(self) -> List[NodeImage]:
        """List available node images.

        :rtype: ``list`` of :class: `NodeImage`
        """
        data = self._paginated_request("/v2/os", "os")
        return [self._to_image(item) for item in data]

    def list_locations(self) -> List[NodeLocation]:
        """List available node locations.

        :rtype: ``list`` of :class: `NodeLocation`
        """
        data = self._paginated_request("/v2/regions", "regions")
        return [self._to_location(item) for item in data]

    def list_volumes(self) -> List[StorageVolume]:
        """List storage volumes.

        :rtype: ``list`` of :class:`StorageVolume`
        """
        data = self._paginated_request("/v2/blocks", "blocks")
        return [self._to_volume(item) for item in data]

    def create_volume(
        self,
        size: int,
        name: str,
        location: Union[NodeLocation, str],
    ) -> StorageVolume:
        """Create a new volume.

        :param size: Size of the volume in gigabytes.\
        Size may range between 10 and 10000.
        :type size: ``int``

        :param name: Name of the volume to be created.
        :type name: ``str``

        :param location: Which data center to create the volume in.
        :type location: :class:`NodeLocation` or ``str``

        :return: The newly created volume.
        :rtype: :class:`StorageVolume`
        """

        data = {
            "label": name,
            "size_gb": size,
        }
        try:
            data["region"] = location.id
        except AttributeError:
            data["region"] = location

        resp = self.connection.request(
            "/v2/blocks", data=json.dumps(data), method="POST"
        )
        return self._to_volume(resp.object["block"])

    def attach_volume(
        self,
        node: Node,
        volume: StorageVolume,
        ex_live: bool = True,
    ) -> bool:
        """Attaches volume to node.

        :param node: Node to attach volume to.
        :type node: :class:`Node`

        :param volume: Volume to attach.
        :type volume: :class:`StorageVolume`

        :param ex_live: Attach the volume without restarting the node.
        :type ex_live: ``bool``

        :rytpe: ``bool``
        """

        data = {
            "instance_id": node.id,
            "live": ex_live,
        }
        resp = self.connection.request(
            "/v2/blocks/%s/attach" % volume.id, data=json.dumps(data), method="POST"
        )

        return resp.success()

    def detach_volume(
        self,
        volume: StorageVolume,
        ex_live: bool = True,
    ) -> bool:
        """Detaches a volume from a node.

        :param volume: Volume to be detached
        :type volume: :class:`StorageVolume`

        :param ex_live: Detach the volume without restarting the node.
        :type ex_live: ``bool``

        :rtype: ``bool``
        """
        data = {"live": ex_live}

        resp = self.connection.request(
            "/v2/blocks/%s/detach" % volume.id, data=json.dumps(data), method="POST"
        )

        return resp.success()

    def destroy_volume(self, volume: StorageVolume) -> bool:
        """Destroys a storage volume.

        :param volume: Volume to be destroyed
        :type  volume: :class:`StorageVolume`

        :rtype: ``bool``
        """

        resp = self.connection.request("/v2/blocks/%s" % volume.id, method="DELETE")

        return resp.success()

    def list_key_pairs(self) -> List[KeyPair]:
        """List all the available SSH key pair objects.

        :rtype: ``list`` of :class:`KeyPair`
        """
        data = self._paginated_request("/v2/ssh-keys", "ssh_keys")
        return [self._to_key_pair(item) for item in data]

    def get_key_pair(self, key_id: str) -> KeyPair:
        """Retrieve a single key pair.

        :param key_id: ID of the key pair to retrieve.
        :type  key_id: ``str``

        :rtype: :class: `KeyPair`
        """
        resp = self.connection.request("/v2/ssh-keys/%s" % key_id)
        return self._to_key_pair(resp.object["ssh_key"])

    def import_key_pair_from_string(self, name: str, key_material: str) -> KeyPair:
        """Import a new public key from string.

        :param name: Key pair name.
        :type  name: ``str``

        :param key_material: Public key material.
        :type  key_material: ``str``

        :rtype: :class: `KeyPair`
        """
        data = {
            "name": name,
            "ssh_key": key_material,
        }
        resp = self.connection.request(
            "/v2/ssh-keys", data=json.dumps(data), method="POST"
        )
        return self._to_key_pair(resp.object["ssh_key"])

    def delete_key_pair(self, key_pair: KeyPair) -> bool:
        """Delete existing key pair.

        :param key_pair: The key pair object to delete.
        :type key_pair: :class:`.KeyPair`

        :rtype: ``bool``
        """

        resp = self.connection.request(
            "/v2/ssh-keys/%s" % key_pair.extra["id"], method="DELETE"
        )

        return resp.success()

    def ex_list_bare_metal_nodes(self) -> List[Node]:
        """List all bare metal nodes.

        :return:  list of node objects
        :rtype: ``list`` of :class: `Node`
        """
        data = self._paginated_request("/v2/bare-metals", "bare_metals")
        return [self._to_node(item) for item in data]

    def ex_reboot_bare_metal_node(self, node: Node) -> bool:
        """Reboot the given bare metal node.

        :param node: The bare metal node to be rebooted.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        resp = self.connection.request(
            "/v2/bare-metals/%s/reboot" % node.id, method="POST"
        )

        return resp.success()

    def ex_resize_node(self, node: Node, size: NodeSize) -> bool:
        """Change size for the given node, only applicable for VPS nodes.

        :param node: The node to be resized.
        :type node: :class: `Node`

        :param size: The new size.
        :type size: :class: `NodeSize`
        """
        data = {"plan": size.id}
        resp = self.connection.request(
            "/v2/instances/%s" % node.id, data=json.dumps(data), method="PATCH"
        )
        return self._to_node(resp.object["instance"])

    def ex_start_bare_metal_node(self, node: Node) -> bool:
        """Start the given bare metal node.

        :param node: The bare metal node to be started.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        resp = self.connection.request(
            "/v2/bare-metals/%s/start" % node.id, method="POST"
        )

        return resp.success()

    def ex_stop_bare_metal_node(self, node: Node) -> bool:
        """Stop the given bare metal node.

        :param node: The bare metal node to be stopped.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        resp = self.connection.request(
            "/v2/bare-metals/%s/halt" % node.id, method="POST"
        )

        return resp.success()

    def ex_destroy_bare_metal_node(self, node: Node) -> bool:
        """Destroy the given bare metal node.

        :param node: The bare metal node to be destroyed.
        :type node: :class: `Node`

        :rtype: ``bool``
        """
        resp = self.connection.request("/v2/bare-metals/%s" % node.id, method="DELETE")

        return resp.success()

    def ex_get_node(self, node_id: str) -> Node:
        """Retrieve a node object.

        :param node_id: ID of the node to retrieve.
        :type snapshot_id: ``str``

        :rtype: :class: `Node`
        """
        resp = self.connection.request("/v2/instances/%s" % node_id)
        return self._to_node(resp.object["instance"])

    def ex_stop_nodes(self, nodes: List[Node]) -> bool:
        """Stops all the nodes given.

        : param nodes: A list of the nodes to stop.
        : type node: ``list`` of: class `Node`

        : rtype: ``bool``
        """

        data = {"instance_ids": [node.id for node in nodes]}
        resp = self.connection.request(
            "/v2/instances/halt", data=json.dumps(data), method="POST"
        )

        return resp.success()

    def ex_list_bare_metal_sizes(self) -> List[NodeSize]:
        """List bare metal sizes.

        :rtype: ``list`` of :class: `NodeSize`
        """
        data = self._paginated_request("/v2/plans-metal", "plans_metal")
        return [self._to_size(item) for item in data]

    def ex_list_snapshots(self) -> List[VultrNodeSnapshot]:
        """List node snapshots.

        :rtype: ``list`` of :class: `VultrNodeSnapshot`
        """
        data = self._paginated_request("/v2/snapshots", "snapshots")
        return [self._to_snapshot(item) for item in data]

    def ex_get_snapshot(self, snapshot_id: str) -> VultrNodeSnapshot:
        """Retrieve a snapshot.

        :param snapshot_id: ID of the snapshot to retrieve.
        :type snapshot_id: ``str``

        :rtype: :class: `VultrNodeSnapshot`
        """
        resp = self.connection.request("/v2/snapshots/%s" % snapshot_id)
        return self._to_snapshot(resp.object["snapshot"])

    def ex_create_snapshot(
        self, node: Node, description: Optional[str] = None
    ) -> VultrNodeSnapshot:
        """Create snapshot from a node.

        :param node: Node to create the snapshot from.
        :type node: :class: `Node`

        :keyword description: A description of the snapshot.
        :type    description: ``str``

        :rtype: :class: `VultrNodeSnapshot`
        """
        data = {
            "instance_id": node.id,
        }
        if description:
            data["description"] = description

        resp = self.connection.request(
            "/v2/snapshots", data=json.dumps(data), method="POST"
        )

        return self._to_snapshot(resp.object["snapshot"])

    def ex_delete_snapshot(self, snapshot: VultrNodeSnapshot) -> bool:
        """Delete the given snapshot.

        :param snapshot: The snapshot to delete.
        :type node: :class:`VultrNodeSnapshot`

        :rtype: ``bool``
        """

        resp = self.connection.request(
            "/v2/snapshots/%s" % snapshot.id, method="DELETE"
        )

        return resp.success()

    def ex_list_networks(self) -> List[VultrNetwork]:
        """List all private networks.

        :rtype: ``list`` of :class: `VultrNetwork`
        """

        data = self._paginated_request("/v2/private-networks", "networks")
        return [self._to_network(item) for item in data]

    def ex_create_network(
        self,
        cidr_block: str,
        location: Union[NodeLocation, str],
        description: Optional[str] = None,
    ) -> VultrNetwork:
        """Create a private network.

        :param cidr_block: The CIDR block assigned to the network.
        :type  cidr_block: ``str``

        :param location: The location to create the network.
        :type  location: :class: `NodeLocation` or ``str``

        :keyword description: A description of the private network.
        :type    description: ``str``

        :rtype: :class: `VultrNetwork`
        """
        subnet, subnet_mask = cidr_block.split("/")
        data = {
            "v4_subnet": subnet,
            "v4_subnet_mask": int(subnet_mask),
        }

        try:
            data["region"] = location.id
        except AttributeError:
            data["region"] = location

        if description:
            data["description"] = description

        resp = self.connection.request(
            "/v2/private-networks", data=json.dumps(data), method="POST"
        )

        return self._to_network(resp.object["network"])

    def ex_get_network(self, network_id: str) -> VultrNetwork:
        """Retrieve a private network.

        :param network_id: ID of the network to retrieve.
        :type network_id: ``str``

        :rtype: :class: `VultrNetwork`
        """

        resp = self.connection.request("/v2/private-networks/%s" % network_id)
        return self._to_network(resp.object["network"])

    def ex_destroy_network(self, network: VultrNetwork) -> bool:
        """Delete a private network.

        :param network: The network to destroy.
        :type  network: :class: `VultrNetwork`

        :rtype: ``bool``
        """
        resp = self.connection.request(
            "/v2/private-networks/%s" % network.id, method="DELETE"
        )

        return resp.success()

    def ex_list_available_sizes_for_location(
        self,
        location: NodeLocation,
    ) -> List[str]:
        """Get a list of available sizes for the given location.

        :param location: The location to get available sizes for.
        :type location: :class: `NodeLocation`

        :return:  A list of available size IDs for the given location.
        :rtype: ``list`` of ``str``
        """
        resp = self.connection.request("/v2/regions/%s/availability" % location.id)
        return resp.object["available_plans"]

    def ex_get_volume(self, volume_id: str) -> StorageVolume:
        """Retrieve a single volume.

        :param volume_id: The ID of the volume to fetch.
        :type volume_id: ``str``

        :rtype :class: `StorageVolume`
        :return: StorageVolume instance on success.
        """
        resp = self.connection.request("/v2/blocks/%s" % volume_id)

        return self._to_volume(resp.object["block"])

    def ex_resize_volume(self, volume: StorageVolume, size: int) -> bool:
        """Resize a volume.

        :param volume: The volume to resize.
        :type volume: :class:`StorageVolume`

        :param size: The new volume size in GBs.\
        Size may range between 10 and 10000.
        :type size: ``int``

        :rtype: ``bool``
        """
        data = {
            "label": volume.name,
            "size_gb": size,
        }

        resp = self.connection.request(
            "/v2/blocks/%s" % volume.id, data=json.dumps(data), method="PATCH"
        )
        return resp.success()

    def _is_bare_metal(self, size: Union[NodeSize, str]) -> bool:
        try:
            size_id = size.id
        except AttributeError:
            size_id = size

        return size_id.startswith("vbm")

    def _to_node(self, data: Dict[str, Any]) -> Node:
        id_ = data["id"]
        name = data["label"]
        public_ips = data["main_ip"].split() + data["v6_main_ip"].split()
        size = data["plan"]
        image = str(data["os_id"])
        created_at = data["date_created"]
        is_bare_metal = self._is_bare_metal(size)
        extra = {
            "location": data["region"],
            "ram": data["ram"],
            "disk": data["disk"],
            "netmask_v4": data["netmask_v4"],
            "gateway_v4": data["gateway_v4"],
            "v6_network": data["v6_network"],
            "v6_network_size": data["v6_network_size"],
            "app_id": data["app_id"],
            "image_id": data["image_id"],
            "features": data["features"],
            "tag": data["tag"],
            "os": data["os"],
            "is_bare_metal": is_bare_metal,
        }
        if is_bare_metal:
            state = self._get_node_state(data["status"])
            extra["cpu_count"] = data["cpu_count"]
            extra["mac_address"] = data["mac_address"]
            private_ips = None
        else:
            state = self._get_node_state(
                data["status"], power_state=data["power_status"]
            )
            extra["vcpu_count"] = data["vcpu_count"]
            extra["allowed_bandwidth"] = data["allowed_bandwidth"]
            extra["power_status"] = data["power_status"]
            extra["server_status"] = data["server_status"]
            extra["firewall_group_id"] = data["firewall_group_id"]
            private_ips = data["internal_ip"].split()

        return Node(
            id=id_,
            name=name,
            state=state,
            public_ips=public_ips,
            private_ips=private_ips,
            driver=self,
            size=size,
            image=image,
            extra=extra,
            created_at=created_at,
        )

    def _to_volume(self, data: Dict[str, Any]) -> StorageVolume:
        id_ = data["id"]
        name = data["label"]
        size = data["size_gb"]
        try:
            state = self.VOLUME_STATE_MAP[data["status"]]
        except KeyError:
            state = StorageVolumeState.UNKNOWN
        extra = {
            "date_created": data["date_created"],
            "cost": data["cost"],
            "location": data["region"],
            "attached_to_instance": data["attached_to_instance"],
            "mount_id": data["mount_id"],
        }
        return StorageVolume(
            id=id_, name=name, size=size, driver=self, state=state, extra=extra
        )

    def _get_node_state(
        self,
        state: str,
        power_state: Optional[str] = None,
    ) -> NodeState:
        try:
            state = self.NODE_STATE_MAP[state]
        except KeyError:
            state = NodeState.UNKNOWN

        if power_state is None:
            return state

        if state == NodeState.RUNNING and power_state != "running":
            state = NodeState.STOPPED
        return state

    def _to_key_pair(self, data: Dict[str, Any]) -> KeyPair:
        name = data["name"]
        public_key = data["ssh_key"]
        # requires cryptography module
        try:
            fingerprint = get_pubkey_openssh_fingerprint(public_key)
        except RuntimeError:
            fingerprint = None
        extra = {
            "id": data["id"],
            "date_created": data["date_created"],
        }
        return KeyPair(
            name=name,
            public_key=public_key,
            fingerprint=fingerprint,
            driver=self,
            extra=extra,
        )

    def _to_location(self, data: Dict[str, Any]) -> NodeLocation:
        id_ = data["id"]
        name = data["city"]
        country = data["country"]
        extra = {
            "continent": data["continent"],
            "option": data["options"],
        }
        return NodeLocation(
            id=id_, name=name, country=country, driver=self, extra=extra
        )

    def _to_image(self, data: Dict[str, Any]) -> NodeImage:
        id_ = data["id"]
        name = data["name"]
        extra = {
            "arch": data["arch"],
            "family": data["family"],
        }
        return NodeImage(id=id_, name=name, driver=self, extra=extra)

    def _to_size(self, data: Dict[str, Any]) -> NodeSize:
        id_ = data["id"]
        ram = data["ram"]
        disk = data["disk"]
        bandwidth = data["bandwidth"]
        price = data["monthly_cost"]
        is_bare_metal = self._is_bare_metal(id_)
        extra = {
            "locations": data["locations"],
            "type": data["type"],
            "disk_count": data["disk_count"],
            "is_bare_metal": is_bare_metal,
        }

        # VPS and bare metal sizes have different fields
        if is_bare_metal is False:
            extra["vcpu_count"] = data["vcpu_count"]
        else:
            extra["cpu_count"] = data["cpu_count"]
            extra["cpu_model"] = data["cpu_model"]
            extra["cpu_threads"] = data["cpu_threads"]

        return NodeSize(
            id=id_,
            name=id_,
            ram=ram,
            disk=disk,
            bandwidth=bandwidth,
            price=price,
            driver=self,
            extra=extra,
        )

    def _to_network(self, data: Dict[str, Any]) -> VultrNetwork:
        id_ = data["id"]
        cidr_block = "%s/%s" % (data["v4_subnet"], data["v4_subnet_mask"])
        location = data["region"]
        extra = {
            "description": data["description"],
            "date_created": data["date_created"],
        }
        return VultrNetwork(
            id=id_, cidr_block=cidr_block, location=location, extra=extra
        )

    def _to_snapshot(self, data: Dict[str, Any]) -> VultrNodeSnapshot:
        id_ = data["id"]
        created = data["date_created"]
        # Size is returned in bytes, convert to GBs
        size = data["size"] / 1024 / 1024 / 1024
        try:
            state = self.SNAPSHOT_STATE_MAP[data["status"]]
        except KeyError:
            state = VolumeSnapshotState.UNKNOWN
        extra = {
            "description": data["description"],
            "os_id": data["os_id"],
            "app_id": data["app_id"],
        }
        return VultrNodeSnapshot(
            id=id_, size=size, created=created, state=state, extra=extra, driver=self
        )

    def _paginated_request(
        self, url: str, key: str, params: Optional[Dict[str, Any]] = None
    ) -> List[Any]:
        """Perform multiple calls to get the full list of items when
        the API responses are paginated.

        :param url: API endpoint
        :type url: ``str``

        :param key: Result object key
        :type key: ``str``

        :param params: Request parameters
        :type params: ``dict``

        :return: ``list`` of API response objects
        :rtype: ``list``
        """
        params = params if params is not None else {}
        resp = self.connection.request(url, params=params).object
        data = list(resp.get(key, []))
        objects = data
        while True:
            next_page = resp["meta"]["links"]["next"]
            if next_page:
                params["cursor"] = next_page
                resp = self.connection.request(url, params=params).object
                data = list(resp.get(key, []))
                objects.extend(data)
            else:
                return objects


text:
<?php

namespace App\Libs;

class Core {

    /**
     * Save instance
     * @var \App\Libs\Core
     */
    private static $instance;

    /**
     * Instance name
     * @var string
     */
    private $name = 'default';

    /**
     * Gets instance
     * @return \App\Libs\Core
     */
    public static function getInstance() {

        if (!isset(self::$instance)) {
            $object = __CLASS__;
            self::$instance = new $object;
        }

        return self::$instance;
    }

    /**
     * Constructor
     */
    private function __construct() {

    }

    /**
     * Sets instance name
     * @param string $name Instance name
     */
    public function setName($name = 'default') {
        $this->name = $name;
    }

    /**
     * Gets instance name
     * @return string
     */
    public function getName() {
        return $this->name;
    }

    /**
     * Get Slimpower instance
     * @return \SlimPower\Slim\Slim
     */
    public function getSlimInstance() {
        $app = \SlimPower\Slim\Slim::getInstance($this->name);

        if (is_null($app)) {
            return $this->getApp();
        }

        return $app;
    }

    /**
     * Configure logger
     * @param \SlimPower\Slim\Slim $app Slimpower instance
     */
    private function configureLogger(\SlimPower\Slim\Slim $app) {
        $app->hook('slim.after', function () use ($app) {
            $request = $app->request;
            $response = $app->response;

            $app->log->debug('');
            $app->log->debug('------------- ' . date('Y-m-d H:i:s') . ' -------------');
            $app->log->debug('Request path: ' . $request->getPathInfo());
            $app->log->debug('Response status: ' . $response->getStatus());
            $app->log->debug('Method: ' . $request->getMethod());
            $app->log->debug('IP: ' . $request->getIp());

            if (preg_match('/application\/json/', $response->header('Content-Type'))) {
                $app->log->debug('DATA: ' . $response->getBody());
            }
        });
    }

    /**
     * Get LogWriter instance
     * @param string $logFile Log file.
     * @return \Slim\LogWriter LogWriter instance
     */
    private function getLogWriterInstance($logFile) {
        $logDir = dirname($logFile);

        if (!file_exists($logDir)) {
            $oldmask = umask(0);
            mkdir($logDir, 0777, TRUE);
            umask($oldmask);
        }

        $logWriter = new \Slim\LogWriter(fopen($logFile, 'a+'));
        return $logWriter;
    }

    /**
     * Gets new Slimpower instance
     * @return \SlimPower\Slim\Slim
     */
    private function getApp() {
        $logWriter = $this->getLogWriterInstance(LOG_FILE);

        $app = new \SlimPower\Slim\Slim(array(
            'mode' => APP_ENV,
            'log.level' => LOG_LEVEL,
            'log.writer' => $logWriter));

        $app->setName($this->name);

        $this->configureLogger($app);

        return $app;
    }

}

redpajama_set_name: RedPajamaGithub


text:
<?xml version="1.0" encoding="utf-8"?>
<android.support.design.widget.CoordinatorLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context = "com.app.prashant.monolith.fragments.ImageDetailFragment">

    <com.app.prashant.monolith.helper.TouchImageView
        android:id="@+id/image"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:scaleType="centerCrop"
        android:transitionName="@string/transition_gallery_photo"
        android:contentDescription="@string/gallery_image_desc" />

    <android.support.v7.widget.Toolbar
        android:id="@+id/detail_toolbar"
        android:layout_marginTop="@dimen/detail_toolbar_margin"
        android:layout_width="match_parent"
        android:layout_height="?attr/actionBarSize"
        app:contentInsetStart="@dimen/activity_horizontal_margin"
        app:popupTheme="@style/ThemeOverlay.AppCompat.Light"/>

    <android.support.design.widget.FloatingActionButton
        android:id="@+id/fab"
        android:contentDescription="@string/fab"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        app:pressedTranslationZ="@dimen/fab_press_translation_z"
        android:layout_marginEnd="@dimen/fab_margin"
        android:layout_marginBottom="@dimen/gallery_detail_fab_margin"
        app:fabSize="normal"
        android:src="@drawable/ic_more_vertical"
        android:layout_gravity="bottom|end" />

    <com.hlab.fabrevealmenu.view.FABRevealMenu
        android:id="@+id/fabMenu"
        android:contentDescription="@string/fab_menu"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_centerInParent="true"
        app:animateItems="true"
        app:menuBackgroundColor="@color/accent"
        app:menuDirection="left"
        app:menuRes="@menu/image_fab_menu"
        app:menuTitleTextColor="@color/colorWhite"
        app:showOverlay="true"
        app:showTitle="true" />

</android.support.design.widget.CoordinatorLayout>


text:
using namespace std;

namespace
{
constexpr char kDelimChar = '=';
}  // namespace

namespace platform
{
StringStorageBase::StringStorageBase(string const & path) : m_path(path)
{
  try
  {
    LOG(LINFO, ("Settings path:", m_path));
    ReaderStreamBuf buffer(make_unique<FileReader>(m_path));
    istream stream(&buffer);

    string line;
    while (getline(stream, line))
    {
      if (line.empty())
        continue;

      size_t const delimPos = line.find(kDelimChar);
      if (delimPos == string::npos)
        continue;

      string const key = line.substr(0, delimPos);
      string const value = line.substr(delimPos + 1);
      if (!key.empty() && !value.empty())
        m_values[key] = value;
    }
  }
  catch (RootException const & ex)
  {
    LOG(LWARNING, ("Loading settings:", ex.Msg()));
  }
}

void StringStorageBase::Save() const
{
  try
  {
    FileWriter file(m_path);
    for (auto const & value : m_values)
    {
      string line(value.first);
      line += kDelimChar;
      line += value.second;
      line += '\n';
      file.Write(line.data(), line.size());
    }
  }
  catch (RootException const & ex)
  {
    // Ignore all settings saving exceptions.
    LOG(LWARNING, ("Saving settings:", ex.Msg()));
  }
}

void StringStorageBase::Clear()
{
  lock_guard<mutex> guard(m_mutex);
  m_values.clear();
  Save();
}

bool StringStorageBase::GetValue(string const & key, string & outValue) const
{
  lock_guard<mutex> guard(m_mutex);

  auto const found = m_values.find(key);
  if (found == m_values.end())
    return false;

  outValue = found->second;
  return true;
}

void StringStorageBase::SetValue(string const & key, string && value)
{
  lock_guard<mutex> guard(m_mutex);

  m_values[key] = move(value);
  Save();
}

void StringStorageBase::DeleteKeyAndValue(string const & key)
{
  lock_guard<mutex> guard(m_mutex);

  auto const found = m_values.find(key);
  if (found != m_values.end())
  {
    m_values.erase(found);
    Save();
  }
}
}  // namespace platform


text:
package at.borkowski.spicej.proxy;

import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import at.borkowski.spicej.Streams;
import at.borkowski.spicej.rt.DelayCalculator;
import at.borkowski.spicej.rt.RateCalculator;
import at.borkowski.spicej.rt.RealTimeTickSource;
import at.borkowski.spicej.rt.RateCalculator.Result;

/**
 * A proxy provider for TCP connections allowing for upstream and downstream
 * rate limitation. This proxy listens for connections on a local port and
 * forwards data to and from a connection to a remote port upon local
 * connection. Upstream and downstream rate limitations are possible.
 */
// TODO test this (coverage!)
public class SocketProxy implements Runnable {
   final int localPort, remotePort;
   final String remoteHost;
   final Float rateUp, rateDown, delayUp, delayDown;

   private ServerSocket listener;

   /**
    * The buffer size used for socket connections if delaying is added.
    */
   public static final int BUFFER_SIZE = 100 * 1024;

   /**
    * Creates a proxy and binds to the local port.
    *
    * @param localPort
    *           the local port to listen on
    * @param remoteHost
    *           the remote host to connect to
    * @param remotePort
    *           the remote port to connect to
    * @param rateUp
    *           the upstream rate limitation to establish, or null
    *           for no limit
    * @param rateDown
    *           the downstream rate limitation to establish, or
    *           null for no limit
    * @param delayUp
    *           the delay to add to the uplink stream, or null for
    *           no delay
    * @param delayDown
    *           the delay to add to the downlink stream, or null
    *           for no delay
    */
   public SocketProxy(int localPort, String remoteHost, int remotePort, Float rateUp, Float rateDown, Float delayUp, Float delayDown) {
      this.localPort = localPort;
      this.remoteHost = remoteHost;
      this.remotePort = remotePort;
      this.rateUp = rateUp;
      this.rateDown = rateDown;
      this.delayUp = delayUp;
      this.delayDown = delayDown;
   }

   private static InputStream delay(InputStream inputStream, Float delay) {
      if (delay == null || delay * 1000000 < 1)
         return inputStream;

      DelayCalculator.Result calculation = DelayCalculator.calculate((long) (1000000D * delay));
      return Streams.addDelay(inputStream, new RealTimeTickSource(calculation.getTickNanosecondsInterval(), true), calculation.getDelay(), BUFFER_SIZE);
   }

   private static InputStream rate(InputStream inputStream, Float rate) {
      if (rate == null)
         return inputStream;

      Result calculation = RateCalculator.calculate(rate);
      return Streams.limitRate(inputStream, new RealTimeTickSource(calculation.getTickNanosecondsInterval(), true), calculation.getBytesPerTick(), calculation.getPrescale());
   }

   /**
    * Initializes the proxy provider. This method must be called before the
    * actual use and is required for testability reasons.
    *
    * @throws IOException
    *            If the initialization fails.
    */
   public void initialize() throws IOException {
      if (listener != null)
         throw new IllegalStateException("already initialized");
      listener = new ServerSocket(localPort);
   }

   @Override
   public void run() {
      while (true) {
         try {
            Socket client = listener.accept();
            try {
               Socket server = new Socket(remoteHost, remotePort);
               Thread connector = new Thread(new Connector(client, server));
               connector.setDaemon(true);
               connector.start();
            } catch (Exception ignore) {
               ignore.printStackTrace();
               try {
                  client.close();
               } catch (Exception ignore2) {}
            }
         } catch (IOException e) {
            e.printStackTrace();
         }
      }
   }

   class Connector implements Runnable {
      private final Socket client, server;

      public Connector(Socket client, Socket server) {
         this.client = client;
         this.server = server;
      }

      @Override
      public void run() {
         StreamGobbler a = null, b = null;
         try {
            a = new StreamGobbler(delay(rate(client.getInputStream(), rateUp), delayUp), server.getOutputStream());
            b = new StreamGobbler(delay(rate(server.getInputStream(), rateDown), delayDown), client.getOutputStream());

            Thread t = new Thread(a);
            t.setDaemon(true);
            t.start();

            t = new Thread(b);
            t.setDaemon(true);
            t.start();

            a.waitFor();
            b.waitFor();
         } catch (SocketException ignore) {
            /*
             * unfortunately we can't distinguish between "socket closed" and other exceptions.
             * "socket closed" occurs because we have to close the socket while the other gobbler is
             * still running
             */
         } catch (Throwable t) {
            t.printStackTrace();
         } finally {
            a.close();
            b.close();
            try {
               client.close();
            } catch (Exception ignore) {}
            try {
               server.close();
            } catch (Exception ignore) {}
         }
      }

   }
}


text:
package org.neo4j.driver.internal;

import org.neo4j.driver.exceptions.ClientException;
import org.neo4j.driver.internal.messaging.v44.BoltProtocolV44;
import org.neo4j.driver.internal.spi.Connection;

public class ImpersonationUtil {
    public static final String IMPERSONATION_UNSUPPORTED_ERROR_MESSAGE =
            "Detected connection that does not support impersonation, please make sure to have all servers running 4.4 version or above and communicating"
                    + " over Bolt version 4.4 or above when using impersonation feature";

    public static Connection ensureImpersonationSupport(Connection connection, String impersonatedUser) {
        if (impersonatedUser != null && !supportsImpersonation(connection)) {
            throw new ClientException(IMPERSONATION_UNSUPPORTED_ERROR_MESSAGE);
        }
        return connection;
    }

    private static boolean supportsImpersonation(Connection connection) {
        return connection.protocol().version().compareTo(BoltProtocolV44.VERSION) >= 0;
    }
}


text:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/REC-html401/strict.dtd">
<!--
   Created by torstein@opera.com
-->
<html>
   <head>
      <title>Screen Object Test</title>
      <script type="text/javascript" src="../regression-lib/testbase.js"></script>
      <script type="text/javascript" src="../testconfig.js"></script>
      <script type="text/javascript" src="scripts/js_screen.js"></script>
   </head>
   <body>
      <script type="text/javascript">
        main( self.screen );
      </script>
   </body>
</html>


text:
'use strict'

const rule = require('../rules/no-size')
const RuleTester = require('eslint').RuleTester

const error = 'Prefer length to $.size'

const ruleTester = new RuleTester()
ruleTester.run('no-size', rule, {
  valid: ['size()', '[].size()', 'div.size()', 'div.size'],
  invalid: [
    {
      code: '$("div").size()',
      errors: [{message: error, type: 'CallExpression'}]
    },
    {
      code: '$div.size()',
      errors: [{message: error, type: 'CallExpression'}]
    },
    {
      code: '$("div").first().size()',
      errors: [{message: error, type: 'CallExpression'}]
    },
    {
      code: '$("div").append($("input").size())',
      errors: [{message: error, type: 'CallExpression'}]
    }
  ]
})


text:
ACCEPTED

#### According to
The Catalogue of Life, 3rd January 2011

#### Published in
null

#### Original name
Hedyotis santapaui B.V.Shetty & Vivek.

### Remarks
null


text:
package com.roche.sequencing.bioinformatics.common.utils.bed;

import java.awt.Color;

public class RGB {
	private final int red;
	private final int green;
	private final int blue;

	public RGB(int red, int green, int blue) {
		super();
		this.red = red;
		this.green = green;
		this.blue = blue;
	}

	public RGB(String commaSeparatedRgbValues) {
		String[] splitRgb = commaSeparatedRgbValues.split(",");
		if (splitRgb.length != 3) {
			throw new IllegalStateException("The provided value for the itemRgb[" + commaSeparatedRgbValues + "] is not a valid comma separated RGB value.");
		}
		try {
			this.red = Integer.parseInt(splitRgb[0]);
			this.green = Integer.parseInt(splitRgb[1]);
			this.blue = Integer.parseInt(splitRgb[2]);
		} catch (NumberFormatException e) {
			throw new IllegalStateException("The provided value for the itemRgb[" + commaSeparatedRgbValues + "] is not a valid comma separated RGB value.");
		}
	}

	public int getRed() {
		return red;
	}

	public int getGreen() {
		return green;
	}

	public int getBlue() {
		return blue;
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result + blue;
		result = prime * result + green;
		result = prime * result + red;
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		RGB other = (RGB) obj;
		if (blue != other.blue)
			return false;
		if (green != other.green)
			return false;
		if (red != other.red)
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "RGB [red=" + red + ", green=" + green + ", blue=" + blue + "]";
	}

	public Color getColor() {
		return new Color(red, green, blue);
	}

}


text:
// Copyright (c) Microsoft.  All Rights Reserved.  Licensed under the Apache License, Version 2.0.  See License.txt in the project root for license information.

namespace Microsoft.CodeAnalysis.CSharp.Syntax
{
    public partial class IdentifierNameSyntax
    {
        internal override string ErrorDisplayName()
        {
            return Identifier.ValueText;
        }
    }
}


text:
require 5.005;

use strict;

package Finance::Quote::TSP;

use vars qw($VERSION $TSP_URL $TSP_MAIN_URL %TSP_FUND_COLUMNS %TSP_FUND_NAMES);

use LWP::UserAgent;
use HTTP::Request::Common;
use HTML::TableExtract;

$VERSION = '0.2';

# URLs of where to obtain information

$TSP_URL = 'http://www.tsp.gov/rates/share-prices.html';
$TSP_MAIN_URL=("http://www.tsp.gov");

%TSP_FUND_COLUMNS = (
    TSPL2040FUND => "L 2040",
    TSPL2030FUND => "L 2030",
    TSPL2020FUND => "L 2020",
    TSPL2010FUND => "L 2010",
    TSPLINCOMEFUND => "L INCOME",
    TSPGFUND => "G FUND",
    TSPFFUND => "F FUND",
    TSPCFUND => "C FUND",
    TSPSFUND => "S FUND",
    TSPIFUND => "I FUND" );

%TSP_FUND_NAMES = (
    TSPL2040 => 'Lifecycle 2040 Fund',
    TSPL2030 => 'Lifecycle 2030 Fund',
    TSPL2020 => 'Lifecycle 2020 Fund',
    TSPL2010 => 'Lifecycle 2010 Fund',
    TSPLINCOME => 'Lifecycle Income Fund',
    TSPGFUND => 'Government Securities Investment Fund',
    TSPFFUND => 'Fixed Income Index Investment Fund',
    TSPCFUND => 'Common Stock Index Investment Fund',
    TSPSFUND => 'Small Capitalization Stock Index Investment Fund',
    TSPIFUND => 'International Stock Index Investment Fund' );

sub methods { return (tsp => \&tsp) }

{
	my @labels = qw/name nav date isodate currency method/;

	sub labels { return (tsp => \@labels); }
}

# ==============================================================================
sub tsp {
	my $quoter = shift;
	my @symbols = @_;

	# Make sure symbols are requested
	##CAN exit more gracefully - add later##

	return unless @symbols;

	# Local Variables
	my(%info, %fundrows);
	my($ua, $reply, $row, $te);

	$ua = $quoter->user_agent;
	$reply = $ua->request(GET $TSP_URL);
	return unless ($reply->is_success);
	$te = new HTML::TableExtract( headers =>
		["Date", values %TSP_FUND_COLUMNS] );

	$te->parse($reply->content);

	# First row is newest data, older data follows, maybe there
	# should be some way to get it?
	$row = ($te->rows())[0];

	# Make a hash that maps the order the columns are in
	for(my $i=1; my $key = each %TSP_FUND_COLUMNS ; $i++) {
	    $fundrows{$key} = $i;
	}

	foreach (@symbols) {
	    # Ignore case when looking up the data.  Preserve case
	    # when storing the symbol name in the info array.
	    my $tmp = uc $_;
	    $tmp = uc sprintf("TSP%sfund", substr($tmp,0,1))
	      if (index("GFCSI", substr($tmp,0,1)) >= 0);
		if (index("LINCOME", substr($tmp,0,7)) >= 0)
		{
			$tmp = uc sprintf("TSP%sfund", substr($tmp,0,7));
		} elsif (index("L", substr($tmp,0,1)) >= 0) {
			$tmp = uc sprintf("TSP%sfund", substr($tmp,0,5));
		}

	    if(exists $fundrows{$tmp}) {
		$info{$_, 'success'} = 1;

		$info{$_, 'method'} = 'tsp';
		$info{$_, 'currency'} = 'USD';
		$info{$_, 'source'} = $TSP_MAIN_URL;
		$info{$_, 'symbol'} = $_;
		$info{$_, 'name'} = $TSP_FUND_NAMES{$tmp};
		($info{$_, 'nav'} = $$row[$fundrows{$tmp}]) =~ s/[^0-9]*([0-9.,]+).*/$1/s;
		$info{$_, 'last'} = $info{$_, 'nav'};
		$quoter->store_date(\%info, $_, {usdate => $$row[0]});
	    } else {
		$info{$_, 'success'} = 0;
		$info{$_, 'errormsg'} = "Fund name unknown";
	    }
	}
	return %info if wantarray;
	return \%info;
}
1;

=head1 NAME

Finance::Quote::TSP - Obtain fund prices for US Federal Government Thrift Savings Plan

=head1 SYNOPSIS

    use Finance::Quote;

    $q = Finance::Quote->new;

    %info = Finance::Quote->fetch("tsp","c"); #get value of C "Common Stock Index Investment" Fund

=head1 DESCRIPTION

This module fetches fund information from the "Thrift Savings Plan"
homepage http://www.tsp.gov.

=head1 LABELS RETURNED

The following labels may be returned by Finance::Quote::TSP :
name nav date currency method

=head1 SEE ALSO

Thrift Savings Plan, http://www.tsp.gov

=cut


text:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">

    <modelVersion>4.0.0</modelVersion>

    <groupId>com.devskiller.friendly-id</groupId>
    <artifactId>spring-boot-customized</artifactId>
    <version>1.1.1-SNAPSHOT</version>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.2.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.devskiller.friendly-id</groupId>
            <artifactId>friendly-id-spring-boot-starter</artifactId>
            <version>${project.version}</version>
        </dependency>

        <dependency>
            <groupId>com.fasterxml.jackson.module</groupId>
            <artifactId>jackson-module-parameter-names</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <scope>provided</scope>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
            <plugin>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <parameters>true</parameters>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-deploy-plugin</artifactId>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.jacoco</groupId>
                <artifactId>jacoco-maven-plugin</artifactId>
                <version>0.8.5</version>
                <configuration>
                    <skip>true</skip>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>


text:
package info.bitrich.xchangestream.cexio.dto;

import com.fasterxml.jackson.annotation.JsonProperty;
import java.math.BigDecimal;
import java.util.Date;

public class CexioWebSocketTransaction {

  private final String id;
  private final String d;
  private final String c;
  private final BigDecimal a;
  private final BigDecimal ds;
  private final BigDecimal cs;
  private final String user;
  private final String symbol;
  private final String symbol2;
  private final BigDecimal amount;
  private final Long buy;
  private final Long order;
  private final Long sell;
  private final BigDecimal price;
  private final String type;
  private final Date time;
  private final BigDecimal balance;
  private final BigDecimal feeAmount;

  public CexioWebSocketTransaction(
      @JsonProperty("id") String id,
      @JsonProperty("d") String d,
      @JsonProperty("c") String c,
      @JsonProperty("a") BigDecimal a,
      @JsonProperty("ds") BigDecimal ds,
      @JsonProperty("cs") BigDecimal cs,
      @JsonProperty("user") String user,
      @JsonProperty("symbol") String symbol,
      @JsonProperty("symbol2") String symbol2,
      @JsonProperty("amount") BigDecimal amount,
      @JsonProperty("order") Long order,
      @JsonProperty("buy") Long buy,
      @JsonProperty("sell") Long sell,
      @JsonProperty("price") BigDecimal price,
      @JsonProperty("type") String type,
      @JsonProperty("time") Date time,
      @JsonProperty("balance") BigDecimal balance,
      @JsonProperty("fee_amount") BigDecimal feeAmount) {
    this.id = id;
    this.d = d;
    this.c = c;
    this.a = a;
    this.ds = ds;
    this.cs = cs;
    this.user = user;
    this.symbol = symbol;
    this.symbol2 = symbol2;
    this.amount = amount;
    this.buy = buy;
    this.order = order;
    this.sell = sell;
    this.price = price;
    this.type = type;
    this.time = time;
    this.balance = balance;
    this.feeAmount = feeAmount;
  }

  public String getId() {
    return id;
  }

  public String getD() {
    return d;
  }

  public String getC() {
    return c;
  }

  public BigDecimal getA() {
    return a;
  }

  public BigDecimal getDs() {
    return ds;
  }

  public BigDecimal getCs() {
    return cs;
  }

  public String getUser() {
    return user;
  }

  public String getSymbol() {
    return symbol;
  }

  public String getSymbol2() {
    return symbol2;
  }

  public BigDecimal getAmount() {
    return amount;
  }

  public Long getBuy() {
    return buy;
  }

  public Long getOrder() {
    return order;
  }

  public Long getSell() {
    return sell;
  }

  public BigDecimal getPrice() {
    return price;
  }

  public String getType() {
    return type;
  }

  public Date getTime() {
    return time;
  }

  public BigDecimal getBalance() {
    return balance;
  }

  public BigDecimal getFeeAmount() {
    return feeAmount;
  }

  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (!(o instanceof CexioWebSocketTransaction)) return false;

    CexioWebSocketTransaction that = (CexioWebSocketTransaction) o;

    if (id != null ? !id.equals(that.id) : that.id != null) return false;
    if (d != null ? !d.equals(that.d) : that.d != null) return false;
    if (c != null ? !c.equals(that.c) : that.c != null) return false;
    if (user != null ? !user.equals(that.user) : that.user != null) return false;
    if (symbol != null ? !symbol.equals(that.symbol) : that.symbol != null) return false;
    if (symbol2 != null ? !symbol2.equals(that.symbol2) : that.symbol2 != null) return false;
    if (buy != null ? !buy.equals(that.buy) : that.buy != null) return false;
    if (order != null ? !order.equals(that.order) : that.order != null) return false;
    if (sell != null ? !sell.equals(that.sell) : that.sell != null) return false;
    if (type != null ? !type.equals(that.type) : that.type != null) return false;
    if (time != null ? !time.equals(that.time) : that.time != null) return false;

    if (a != null ? a.compareTo(that.a) != 0 : that.a != null) return false;
    if (ds != null ? ds.compareTo(that.ds) != 0 : that.ds != null) return false;
    if (cs != null ? cs.compareTo(that.cs) != 0 : that.cs != null) return false;
    if (amount != null ? amount.compareTo(that.amount) != 0 : that.amount != null) return false;
    if (price != null ? price.compareTo(that.price) != 0 : that.price != null) return false;
    if (balance != null ? balance.compareTo(that.balance) != 0 : that.balance != null) return false;

    return feeAmount != null ? feeAmount.compareTo(that.feeAmount) == 0 : that.feeAmount == null;
  }

  @Override
  public int hashCode() {
    int result = id != null ? id.hashCode() : 0;
    result = 31 * result + (d != null ? d.hashCode() : 0);
    result = 31 * result + (c != null ? c.hashCode() : 0);
    result = 31 * result + (a != null ? a.hashCode() : 0);
    result = 31 * result + (ds != null ? ds.hashCode() : 0);
    result = 31 * result + (cs != null ? cs.hashCode() : 0);
    result = 31 * result + (user != null ? user.hashCode() : 0);
    result = 31 * result + (symbol != null ? symbol.hashCode() : 0);
    result = 31 * result + (symbol2 != null ? symbol2.hashCode() : 0);
    result = 31 * result + (amount != null ? amount.hashCode() : 0);
    result = 31 * result + (buy != null ? buy.hashCode() : 0);
    result = 31 * result + (order != null ? order.hashCode() : 0);
    result = 31 * result + (sell != null ? sell.hashCode() : 0);
    result = 31 * result + (price != null ? price.hashCode() : 0);
    result = 31 * result + (type != null ? type.hashCode() : 0);
    result = 31 * result + (time != null ? time.hashCode() : 0);
    result = 31 * result + (balance != null ? balance.hashCode() : 0);
    result = 31 * result + (feeAmount != null ? feeAmount.hashCode() : 0);
    return result;
  }

  @Override
  public String toString() {
    final StringBuffer buffer = new StringBuffer("{");
    buffer.append("id='").append(id).append('\'');
    buffer.append(", d='").append(d).append('\'');
    buffer.append(", c='").append(c).append('\'');
    buffer.append(", a=").append(a);
    buffer.append(", ds=").append(ds);
    buffer.append(", cs=").append(cs);
    buffer.append(", user='").append(user).append('\'');
    buffer.append(", symbol='").append(symbol).append('\'');
    buffer.append(", symbol2='").append(symbol2).append('\'');
    buffer.append(", amount=").append(amount);
    buffer.append(", buy=").append(buy);
    buffer.append(", order=").append(order);
    buffer.append(", sell=").append(sell);
    buffer.append(", price=").append(price);
    buffer.append(", type='").append(type).append('\'');
    buffer.append(", time=").append(time);
    buffer.append(", balance=").append(balance);
    buffer.append(", feeAmount=").append(feeAmount);
    buffer.append('}');
    return buffer.toString();
  }
}


text:
require_relative 'cluster_onsite_worker_delegate'
require_relative 'cluster_remote_worker_delegate'

class ClusterWorkerDelegate

  def install(record)
    # blank on purpose
  end

  def self.create_delegate(sm_record, cluster_facade)
    if sm_record.onsite_monitoring
      ClusterOnsiteWorkerDelegate.new(cluster_facade.scheduler)
    else
      delegate = ClusterRemoteWorkerDelegate.new(cluster_facade.scheduler)
      delegate.cluster_facade = cluster_facade
      delegate
    end
  end

end


text:
<!DOCTYPE html>

		<meta charset="utf-8">

		<meta name="description" content="An infinitely hypnotic canvas animation" />
		<meta name="author" content="Hakim El Hattab" />

		<meta http-equiv="X-UA-Compatible" content="chrome=1">

		<title>Hypnos</title>

		<link href='https://fonts.googleapis.com/css?family=Molengo' rel='stylesheet' type='text/css'>

Hypnos by @hakimel / http://hakim.se

			<canvas></canvas>


text:
from nose.tools import *
from dateutil.parser import parse as time_parse
import yawhois

class TestWhoisNicFrReResponseThrottled(object):

    def setUp(self):
        fixture_path = "spec/fixtures/responses/whois.nic.fr/re/response_throttled.txt"
        host         = "whois.nic.fr"
        part         = yawhois.record.Part(open(fixture_path, "r").read(), host)
        self.record  = yawhois.record.Record(None, [part])

    def test_response_throttled(self):
        eq_(self.record.response_throttled, True)


text:
var __extends = (this && this.__extends) || (function () {
    var extendStatics = Object.setPrototypeOf ||
        ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
        function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
    return function (d, b) {
        extendStatics(d, b);
        function __() { this.constructor = d; }
        d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
    };
})();
import { CompositeRule } from './CompositeRule';
import { IsNotNullOrUndefined } from './IsNotNullOrUndefined';
import { Min } from './Min';
import { Max } from './Max';
/**
 * Use this rule to determine if the specified target is within the specified range (start and end) values.
 *
 * The range values are inclusive.
 *
 * Ex: 1 is within 1 and 3. The target is valid.
 * Ex: 2 is within 1 and 3. The target is valid.
 * Ex: 0 is not within 1 and 3. The target is not valid.
 * Ex: 4 is not within 1 and 3. The target is not valid.
 */
var /**
 * Use this rule to determine if the specified target is within the specified range (start and end) values.
 *
 * The range values are inclusive.
 *
 * Ex: 1 is within 1 and 3. The target is valid.
 * Ex: 2 is within 1 and 3. The target is valid.
 * Ex: 0 is not within 1 and 3. The target is not valid.
 * Ex: 4 is not within 1 and 3. The target is not valid.
 */
Range = (function (_super) {
    __extends(Range, _super);
    /**
     * Constructor for the [Range] rule.
     * @param name: The name of the rule.
     * @param message: A message to display if the rule is violated.
     * @param target: The target object that the rules will be applied to.
     * @param start: The start range value - the lowest allowed boundary value.
     * @param end: The end range value - the highest allowed boundary value.
     * @param isDisplayable: (Optional) Indicates if the rule violation may be displayed or visible to the caller or client. Default is [false].
     */
    function Range(name, message, target, start, end, isDisplayable) {
        if (isDisplayable === void 0) { isDisplayable = false; }
        var _this = _super.call(this, name, message, isDisplayable) || this;
        _this.target = target;
        _this.start = start;
        _this.end = end;
        _this.isDisplayable = isDisplayable;
        _this.rules.push(new IsNotNullOrUndefined('TargetIsNotNull', 'The target is null or undefined.', _this.target));
        if (_this.target != null) {
            _this.rules.push(new Min('MinValue', 'The value must be equal to or greater than the start range value.', _this.target, _this.start));
            _this.rules.push(new Max('MaxValue', 'The value must be equal to or less than the end range value.', _this.target, _this.end));
        }
        return _this;
    }
    return Range;
}(CompositeRule));
/**
 * Use this rule to determine if the specified target is within the specified range (start and end) values.
 *
 * The range values are inclusive.
 *
 * Ex: 1 is within 1 and 3. The target is valid.
 * Ex: 2 is within 1 and 3. The target is valid.
 * Ex: 0 is not within 1 and 3. The target is not valid.
 * Ex: 4 is not within 1 and 3. The target is not valid.
 */
export { Range };
//# sourceMappingURL=Range.js.map


text:
package com.tinkerpop.rexster.server;

/**
 * Interface for the various "servers" that Rexster exposes.
 *
 * @author Stephen Mallette (http://stephen.genoprime.com)
 */
public interface RexsterServer {
    void stop() throws Exception;

    void start(final RexsterApplication application) throws Exception ;
}


text:
package hu.unideb.inf.rft.neuban.persistence.entities;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import javax.persistence.*;
import java.io.Serializable;

/**
 * Super entity for the database entities.
 *
 * @author Erdei Krisztián
 * @param <ID> Generated ID
 */
@NoArgsConstructor
@AllArgsConstructor
@Data
@MappedSuperclass
public abstract class SuperEntity<ID extends Serializable> implements Serializable {

	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private ID id;
}


text:
.. ==================================================
.. FOR YOUR INFORMATION
.. --------------------------------------------------
.. -*- coding: utf-8 -*- with BOM.

.. include:: Includes.txt

.. _start:

=============================================================
Calendar
=============================================================

.. only:: html

	:Classification:
		kd_calendar

	:Version:
		|release|

	:Language:
		en

	:Description:
		Extension to handle calendar events. Can handle google calendar by google api.

	:Keywords:
		comma,separated,list,of,keywords

	:Copyright:
		2016

	:Author:
		Kevin Ditscheid

	:Email:
		kevinditscheid@gmail.com

	:License:
		This document is published under the Open Content License
		available from http://www.opencontent.org/opl.shtml

	:Rendered:
		|today|

	The content of this document is related to TYPO3,
	a GNU/GPL CMS/Framework available from `www.typo3.org <http://www.typo3.org/>`_.

	**Table of Contents**

.. toctree::
	:maxdepth: 3
	:titlesonly:

	Introduction/Index
	User/Index
	Administrator/Index
	Configuration/Index
	Developer/Index
	KnownProblems/Index
	ToDoList/Index
	ChangeLog/Index
	Links


text:
namespace ClosedXML_Examples
{
    public interface IXLExample
    {
        void Create(string filePath);
    }
}