<commit_before>"""
mapping.py

A module for handling code mappings.
Note that this module has state.

:copyright: (c) 2013 by Christoffer Fink.
:license: MIT. See LICENSE for details.
"""
import importlib

__all__ = ('getType', 'Mapping', 'CodeMapping', )

mappings = {}
types = {}

def __load(typeString):
    """
    Return the type referred to by a string naming the type, including any
    package and module names.
    While the use of plain built-in type names ('int') is discouraged
    ('builtins.int' should be used instead), both cases are supported.

    This is a low level helper function. It does not do any caching, so it
    will always import modules.
    This function is as pure as a function that interacts with the file
    system can be.
    """
    typeName = typeString
    moduleName = 'builtins'
    modEnd = typeString.rfind('.')

    if modEnd != -1:
        moduleName = typeString[:modEnd]
        typeName = typeString[modEnd+1:]

    module = importlib.import_module(moduleName)
    return module.__dict__[typeName]

def getType(typeString):
    """
    Return a type referred to by a string. Modules will be imported as
    necessary. Redundant imports are avoided by caching the results.
    """
    if typeString not in types:
        types[typeString] = __load(typeString)
    return types[typeString]

# If we're serious about supporting parameter names with spaces, then
# they should be removed or replaced here. Otherwise the accessor will be
# absolutely illegal and useless.
def getAccessor(paramId, prefix):
    """
    Returns the parameter ID with a prefix attached. This function is
    almost silly, but it does strip the parameter ID to the relative
    part, which means that this function can handle absolute IDs.
    """
    # TODO:
    # Pull this out and make a general utility function out of it.
    index = paramId.rfind('.')
    if index != -1:
        paramId = paramId[index + 1:]
    return prefix + paramId

def getDefaultSetter(paramId, prefix='set'):
    """
    Uses getAccessor with a default prefix of 'set'.
    """
    return getAccessor(paramId, prefix)

def getDefaultGetter(paramId, prefix='get'):
    """
    Uses getAccessor with a default prefix of 'get'.
    """
    return getAccessor(paramId, prefix)

class Mapping:
    def __init__(self, id, type, constructor=None, set=None, get=None):
        self.id = id
        self.type = type
        self.constructor = constructor
        self.setter = set or getDefaultSetter(id)
        self.getter = get or getDefaultGetter(id)

        if constructor is not None:
            self.dep = tuple(constructor.split())
        else:
            self.dep = ()

    def getId(self):
        return self.id

    def getType(self):
        return self.type

    def getTypeName(self):
        return self.type

    def getDependencies(self):
        return self.dep

    def getConstructor(self):
        return self.constructor

    def getSetter(self):
        return self.setter

    def getGetter(self):
        return self.getter

    def getParameters(self):
        return {
            'id': self.id, 'type': self.type, 'constructor': self.constructor,
            'set': self.setter, 'get': self.getter,
        }

    @staticmethod
    def makeDirect(paramId, mapping):
        params = mapping.getParameters()
        params['id'] = paramId
        return Mapping(**params)

class CodeMapping:
    """
    Objects of this class act as databases of code mappings.
    The class uses a bit of internal magic to simplify handling of the
    different mappings, but the original information should still be
    reproducible.
    """
    def __init__(self, paramMappings, mappingTypes):
        """
        Regular mappings (corresponding to a "Mapping" element) and
        mapping types (corresponding to a "MappingType" element) are
        handled separately to make it possible to accurately export the
        object to XML if needed.
        """
        self.__paramMappings = paramMappings
        self.__mappingTypes = mappingTypes

        types = {m.getId(): m for m in mappingTypes}

        # Update the mapping so that every parameter is associated to a mapping.
        # If the type matches one of the mapping types, then a new mapping is
        # created. The same type and initialization information is used, but
        # now it is directly mapped from a parameter ID.
        self.__mappings = {m.getId(): m for m in paramMappings}
        self.__mappings.update({
            m.getId(): Mapping.makeDirect(m.getId(), types[m.getTypeName()])
            for m in paramMappings if m.getTypeName() in types
        })

    # Always returns a full/direct mapping.
    def getMapping(self, id):
        return self.__mappings[id]
<commit_msg>Cleaned up mapping module<commit_after>"""
mapping.py

A module for handling code mappings.
Note that this module has state.

:copyright: (c) 2013 by Christoffer Fink.
:license: MIT. See LICENSE for details.
"""
import importlib
from inputpy.q import SETTER_PREFIX
from inputpy.q import GETTER_PREFIX
import inputpy.util as util

__all__ = ('getType', 'Mapping', 'CodeMapping', )

types = {}

def __load(typeString):
    """
    Return the type referred to by a string naming the type, including any
    package and module names.
    While the use of plain built-in type names ('int') is discouraged
    ('builtins.int' should be used instead), both cases are supported.

    This is a low level helper function. It does not do any caching, so it
    will always import modules.
    This function is as pure as a function that interacts with the file
    system can be.
    """
    typeName = typeString
    moduleName = 'builtins'
    modEnd = typeString.rfind('.')

    if modEnd != -1:
        moduleName = typeString[:modEnd]
        typeName = typeString[modEnd+1:]

    module = importlib.import_module(moduleName)
    return module.__dict__[typeName]

def getType(typeString):
    """
    Return a type referred to by a string. Modules will be imported as
    necessary. Redundant imports are avoided by caching the results.
    """
    if typeString not in types:
        types[typeString] = __load(typeString)
    return types[typeString]

# If we're serious about supporting parameter names with spaces, then
# they should be removed or replaced here. Otherwise the accessor will be
# absolutely illegal and useless.
def getDefaultSetter(paramId, prefix=SETTER_PREFIX):
    """
    Return the name of the default setter for this parameter ID.
    A prefix can optionally be specified.
    """
    return prefix + util.relative(paramId)

def getDefaultGetter(paramId, prefix=GETTER_PREFIX):
    """
    Return the name of the default getter for this parameter ID.
    A prefix can optionally be specified.
    """
    return prefix + util.relative(paramId)

class Mapping:
    def __init__(self, id, type, constructor=None, set=None, get=None):
        self.id = id
        self.type = type
        self.constructor = constructor
        self.setter = set or getDefaultSetter(id)
        self.getter = get or getDefaultGetter(id)

        if constructor is not None:
            self.dep = tuple(constructor.split())
        else:
            self.dep = ()

    def getId(self):
        return self.id

    def getType(self):
        return self.type

    def getTypeName(self):
        return self.type

    def getDependencies(self):
        return self.dep

    def getConstructor(self):
        return self.constructor

    def getSetter(self):
        return self.setter

    def getGetter(self):
        return self.getter

    def getParameters(self):
        return {
            'id': self.id, 'type': self.type, 'constructor': self.constructor,
            'set': self.setter, 'get': self.getter,
        }

    @staticmethod
    def makeDirect(paramId, mapping):
        params = mapping.getParameters()
        params['id'] = paramId
        return Mapping(**params)

class CodeMapping:
    """
    Objects of this class act as databases of code mappings.
    The class uses a bit of internal magic to simplify handling of the
    different mappings, but the original information should still be
    reproducible.
    """
    def __init__(self, paramMappings, mappingTypes):
        """
        Regular mappings (corresponding to a "Mapping" element) and
        mapping types (corresponding to a "MappingType" element) are
        handled separately to make it possible to accurately export the
        object to XML if needed.
        """
        self.__paramMappings = paramMappings
        self.__mappingTypes = mappingTypes

        types = {m.getId(): m for m in mappingTypes}

        # Update the mapping so that every parameter is associated to a mapping.
        # If the type matches one of the mapping types, then a new mapping is
        # created. The same type and initialization information is used, but
        # now it is directly mapped from a parameter ID.
        self.__mappings = {m.getId(): m for m in paramMappings}
        self.__mappings.update({
            m.getId(): Mapping.makeDirect(m.getId(), types[m.getTypeName()])
            for m in paramMappings if m.getTypeName() in types
        })

    # Always returns a full/direct mapping.
    def getMapping(self, id):
        return self.__mappings[id]
<|endoftext|>


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

import datetime
import logging
import os
import re
from urllib.parse import urljoin

from utils import utils, inspector

# http://www.eeoc.gov/eeoc/oig/index.cfm
archive = 2003

# options:
#   standard since/year options for a year range to fetch from.
#
# Notes for IG's web team:
#

REPORTS_URL = "http://www.eeoc.gov/eeoc/oig/"

REPORT_PUBLISHED_MAP = {
  '2005-02-amr': datetime.datetime(2005, 1, 1),
  '2005-03-prop': datetime.datetime(2005, 9, 1),
  '2005-08-mgt': datetime.datetime(2005, 10, 27),
  'nccrep': datetime.datetime(2006, 6, 29),
}

def run(options):
  year_range = inspector.year_range(options, archive)

  # Pull the reports
  doc = utils.beautifulsoup_from_url(REPORTS_URL)
  semiannual_report_results, other_results = doc.select("table tr")[1].select("td")

  if not semiannual_report_results:
    raise inspector.NoReportsFoundError("EEOC (semiannual reports)")
  if not other_results:
    raise inspector.NoReportsFoundError("EEOC (other reports)")

  merge_items(semiannual_report_results)
  merge_items(other_results)

  for result in semiannual_report_results.select("li"):
    report = semiannual_report_from(result, year_range, title_prefix="Semiannual Report - ")
    if report:
      inspector.save_report(report)

  for result in other_results.select("li"):
    report = report_from(result, year_range)
    if report:
      inspector.save_report(report)

def semiannual_report_from(result, year_range, title_prefix=None):
  link = result.find("a")
  report_url = urljoin(REPORTS_URL, link.get('href'))
  report_filename = report_url.split("/")[-1]
  report_id, _ = os.path.splitext(report_filename)

  published_on_text = link.text.split("-")[-1].strip()
  published_on = datetime.datetime.strptime(published_on_text, '%B %d, %Y')

  title = link.text
  if title_prefix:
    title = "{}{}".format(title_prefix, title)

  if published_on.year not in year_range:
    logging.debug("[%s] Skipping, not in requested range." % report_url)
    return

  report = {
    'inspector': "eeoc",
    'inspector_url': "http://www.eeoc.gov/eeoc/oig/",
    'agency': "eeoc",
    'agency_name': "Equal Employment Opportunity Commission",
    'report_id': report_id,
    'url': report_url,
    'title': title,
    'published_on': datetime.datetime.strftime(published_on, "%Y-%m-%d"),
  }

  return report

def report_from(result, year_range):
  link = result.find("a")
  report_url = urljoin(REPORTS_URL, link.get('href'))
  report_filename = report_url.split("/")[-1]
  report_id, _ = os.path.splitext(report_filename)

  if report_id in REPORT_PUBLISHED_MAP:
    published_on = REPORT_PUBLISHED_MAP[report_id]
  else:
    try:
      published_on_text = "-".join(re.search('\((\w+) (\d+),?\s(\d{4})\)', result.text).groups())
      published_on = datetime.datetime.strptime(published_on_text, '%B-%d-%Y')
    except AttributeError:
      try:
        published_on_text = "-".join(re.search('\((\w+)\s(\d{4})\)', result.text).groups())
        published_on = datetime.datetime.strptime(published_on_text, '%B-%Y')
      except AttributeError:
        published_on_text = "-".join(re.search('(\w+) (\d+),?\s(\d{4})', result.text).groups())
        published_on = datetime.datetime.strptime(published_on_text, '%B-%d-%Y')

  title = link.text

  if published_on.year not in year_range:
    logging.debug("[%s] Skipping, not in requested range." % report_url)
    return

  report = {
    'inspector': "eeoc",
    'inspector_url': "http://www.eeoc.gov/eeoc/oig/",
    'agency': "eeoc",
    'agency_name': "Equal Employment Opportunity Commission",
    'report_id': report_id,
    'url': report_url,
    'title': title,
    'published_on': datetime.datetime.strftime(published_on, "%Y-%m-%d"),
  }
  return report

def merge_items(parent):
  '''This function loops through all the <li> tags in a subtree of a document,
  checks if two neighboring items each contain one link to the same href,
  and if they do, merges them together into one <li> with one <a> tag.'''

  items = parent.find_all("li")
  for i in range(len(items) - 2, -1, -1):
    first_item = items[i]
    second_item = items[i+1]

    first_links = first_item.find_all("a")
    if len(first_links) != 1:
      continue
    second_links = second_item.find_all("a")
    if len(second_links) != 1:
      continue
    first_link = first_links[0]
    second_link = second_links[0]

    if first_link.get("href") != second_link.get("href"):
      continue

    # Transplant the contents of the second link into the end of the first link
    first_link.append(" ")
    while second_link.contents:
      temp = second_link.contents[0].extract()
      first_link.append(temp)

    # Discard the now-empty second link
    second_link.extract()

    # Transplant everything else inside the <li> to the end of the first <li>
    while second_item.contents:
      temp = second_item.contents[0].extract()
      first_item.append(temp)

    # Discard the now-empty list item
    second_item.extract()

utils.run(run) if (__name__ == "__main__") else None
<commit_msg>[eeoc] Update for new site (#300)<commit_after>#!/usr/bin/env python

import datetime
import logging
from urllib.parse import urljoin

from utils import utils, inspector, admin

# https://oig.eeoc.gov/
archive = 1995

# options:
#   standard since/year options for a year range to fetch from.
#
# Notes for IG's web team:
#   - include all reports from old site (https://www.eeoc.gov/eeoc/oig/)
#   - some old reports could be run through an OCR maybe
#   - include full publication dates in HTML

AUDIT_REPORTS_URL = "https://oig.eeoc.gov/reports/audits"
CONGRESSIONAL_REPORTS_URL = "https://oig.eeoc.gov/reports/semi-annual"
REPORT_URLS = [
  ("audit", AUDIT_REPORTS_URL),
  ("congress", CONGRESSIONAL_REPORTS_URL),
]
INSPECTOR_URL = "https://oig.eeoc.gov/"

REPORT_PUBLISHED_MAP = {
  "1995-005-atr": datetime.datetime(1995, 7, 1),
  "1997-005-ape": datetime.datetime(1998, 6, 1),
  "1999-008-impr": datetime.datetime(1999, 10, 1),
  "1999-019-impr": datetime.datetime(1999, 10, 1),
  "2001-019-aic": datetime.datetime(2002, 9, 1),
  "2002-013-fin": datetime.datetime(2003, 12, 22),
  "2003-001-amr": datetime.datetime(2004, 9, 1),
  "2003-004-amr": datetime.datetime(2004, 1, 1),
  "2003-004-fin": datetime.datetime(2004, 11, 1),
  "2003-005-mis": datetime.datetime(2005, 9, 30),
  "2003-015-amr": datetime.datetime(2002, 10, 1),
  "2005-002-amr": datetime.datetime(2006, 7, 1),
  "2005-003-prop": datetime.datetime(2005, 5, 1),
  "2005-008-mgt": datetime.datetime(2005, 10, 1),
  "2006-002-fin": datetime.datetime(2006, 10, 1),
  "2006-007-amr": datetime.datetime(2007, 2, 1),
  "2007-003-amr": datetime.datetime(2007, 4, 1),
  "2007-007-adv": datetime.datetime(2009, 4, 24),
  "2007-011-rfpe": datetime.datetime(2008, 1, 1),
  "2007-012-amr": datetime.datetime(2008, 3, 27),
  "2008-003-amr": datetime.datetime(2008, 9, 26),
  "2008-006-fin": datetime.datetime(2008, 10, 1),
  "2008-012-aep": datetime.datetime(2008, 9, 30),
  "2009-004-fin": datetime.datetime(2009, 11, 13),
  "2010-009-aep": datetime.datetime(2011, 3, 10),
  "2011-001-aep": datetime.datetime(2011, 7, 15),
  "2011-002-aep": datetime.datetime(2011, 9, 30),
  "2011-002-fin": datetime.datetime(2011, 11, 11),
  "2011-005-fism": datetime.datetime(2011, 11, 21),
  "2011-apr-sep": datetime.datetime(2011, 11, 1),
  "2011-oct-mar": datetime.datetime(2011, 4, 30),
  "2012-001-fin": datetime.datetime(2012, 11, 15),
  "2012-003-fism": datetime.datetime(2012, 9, 1),
  "2012-008-purc": datetime.datetime(2013, 3, 26),
  "2012-009-rev": datetime.datetime(2013, 4, 9),
  "2012-010-pmev": datetime.datetime(2013, 3, 19),
  "2012-apr-sep": datetime.datetime(2012, 11, 1),
  "2012-oct-mar": datetime.datetime(2012, 4, 30),
  "2013-001-fin": datetime.datetime(2013, 12, 12),
  "2013-003-caro": datetime.datetime(2014, 9, 23),
  "2013-005-fism": datetime.datetime(2013, 12, 5),
  "2013-008-psa": datetime.datetime(2014, 9, 15),
  "2013-apr-sep": datetime.datetime(2013, 11, 6),
  "2013-oct-mar": datetime.datetime(2013, 4, 30),
  "2014-001-fin": datetime.datetime(2014, 11, 17),
  "2014-003-oe": datetime.datetime(2015, 5, 1),
  "2014-008-eoig": datetime.datetime(2014, 12, 16),
  "2014-apr-sep": datetime.datetime(2014, 10, 31),
  "2014-oct-mar-0": datetime.datetime(2014, 4, 30),
  "2015-001-fin": datetime.datetime(2015, 12, 16),
  "2015-001-iper": datetime.datetime(2015, 5, 13),
  "2015-001-lit": datetime.datetime(2016, 6, 1),
  "2015-003-eoig": datetime.datetime(2015, 12, 9),
  "2015-apr-sep": datetime.datetime(2015, 11, 1),
  "2015-oct-mar": datetime.datetime(2015, 4, 30),
  "2016-0004-aoig": datetime.datetime(2016, 5, 11),
  "2016-001-aoig": datetime.datetime(2016, 11, 15),
  "2016-008-eoig": datetime.datetime(2017, 1, 4),
  "2016-012-aep": datetime.datetime(2016, 9, 30),
  "2016-apr-sep": datetime.datetime(2016, 11, 1),
  "2016-oct-mar": datetime.datetime(2016, 5, 1),
}

def run(options):
  year_range = inspector.year_range(options, archive)

  # Pull the reports
  for report_type, report_url in REPORT_URLS:
      doc = utils.beautifulsoup_from_url(report_url)
      results = doc.select("tbody tr > td:nth-of-type(1) a") or doc.select(".views-more-link")
      for result in results:
        report = report_from(result, year_range, report_type)
        if report:
          inspector.save_report(report)

def report_from(result, year_range, report_type):
  path = result.get("href")
  html_report_url = urljoin(INSPECTOR_URL, path)
  html_report = utils.beautifulsoup_from_url(html_report_url)
  report_id = path.split('/')[-1]
  title = html_report.find("span", {"property": "dc:title"})['content']
  fiscal_year = fiscal_year_parse(html_report)

  links = html_report.select(".file a")
  hrefs = filter_links(links)
  if len(hrefs) > 1:
    raise Exception("Found multiple links on {}:\n{}".format(html_report_url,
                                                             hrefs))
  if len(hrefs) == 0:
    raise Exception("Found no links on {}".format(html_report_url))
  pdf_report_url = hrefs[0]

  if report_id in REPORT_PUBLISHED_MAP:
    published_on = REPORT_PUBLISHED_MAP[report_id]
  else:
    admin.log_no_date("eeoc", report_id, title, pdf_report_url)

  if fiscal_year not in year_range:
    logging.debug("[%s] Skipping, not in requested range." % pdf_report_url)
    return

  report = {
    'inspector': "eeoc",
    'inspector_url': INSPECTOR_URL,
    'agency': "eeoc",
    'agency_name': "Equal Employment Opportunity Commission",
    'report_id': report_id,
    'url': pdf_report_url,
    'title': title,
    'type': report_type,
    'published_on': datetime.datetime.strftime(published_on, "%Y-%m-%d"),
  }

  return report

def fiscal_year_parse(html_report):
  fiscal_year_text = (html_report
                      .find(class_="field-name-field-fiscal-year")
                      .find(class_="field-item")
                      .get_text())
  return int(fiscal_year_text)

def filter_links(links):
  return [link["href"] for link in links
          if ("Trans_Rept" not in link.text and
              "Transmittal" not in link.text)]

utils.run(run) if (__name__ == "__main__") else None
<|endoftext|>


<commit_before><commit_msg>query by site and analyte now for manages connection<commit_after><|endoftext|>


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

from __future__ import print_function

import argparse
import codecs
import epitran.vector

def main(code, space, infile):
    vec = epitran.vector.VectorWithIPASpace(code, space)
    with codecs.open(infile, 'r', 'utf-8') as f:
        for line in f:
            fields = line.split('\t')
            if len(fields) > 1:
                word = fields[0]
                cat, case, orth, phon, vec = vec.word_to_pfvecter(word)
                print("Category: {}".format(cat))
                print("Case: {}".format(case))
                print("Orthographic: {}".format(orth))
                print("Phonetic: {}".format(phon))
                print("Vector: {}".format(vec))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--code', help='Script code.')
    parser.add_argument('-s', '--space', help='Space.')
    parser.add_argument('-i', '--infile', help='Input file.')
    args = parser.parse_args()
    main(args.code, args.space, args.infile)
<commit_msg>Corrected logical flaws<commit_after>#!/usr/bin/env python

from __future__ import print_function

import argparse
import codecs
import epitran.vector

def main(code, space, infile):
    vec = epitran.vector.VectorWithIPASpace(code, space)
    with codecs.open(infile, 'r', 'utf-8') as f:
        for line in f:
            fields = line.split('\t')
            if len(fields) > 1:
                word = fields[0]
                print(u"WORD: {}".format(word))
                segs = vec.word_to_pfvecter(word)
                print(segs)
                for record in segs:
                    cat, case, orth, phon, id_, vector = record
                    print(u"Category: {}".format(cat))
                    print(u"Case: {}".format(case))
                    print(u"Orthographic: {}".format(orth))
                    print(u"Phonetic: {}".format(phon))
                    print(u"Vector: {}".format(vector))

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('-c', '--code', help='Script code.')
    parser.add_argument('-s', '--space', help='Space.')
    parser.add_argument('-i', '--infile', help='Input file.')
    args = parser.parse_args()
    main(args.code, args.space, args.infile)
<|endoftext|>


<commit_before>"""Helper methods for dealing with Cloud Datastore's Protobuf API."""
import calendar
from datetime import datetime, timedelta

from google.protobuf.internal.type_checkers import Int64ValueChecker
import pytz

from gcloud.datastore.key import Key

check_int64_value = Int64ValueChecker().CheckValue

def get_protobuf_attribute_and_value(val):
    """Given a value, return the protobuf attribute name and proper value.

    The Protobuf API uses different attribute names
    based on value types rather than inferring the type.
    This method simply determines the proper attribute name
    based on the type of the value provided
    and returns the attribute name
    as well as a properly formatted value.

    Certain value types need to be coerced into a different type (such as a
    `datetime.datetime` into an integer timestamp, or a
    `gcloud.datastore.key.Key` into a Protobuf representation.
    This method handles that for you.

    For example:

    >>> get_protobuf_attribute_and_value(1234)
    ('integer_value', 1234)
    >>> get_protobuf_attribute_and_value('my_string')
    ('string_value', 'my_string')

    :type val: `datetime.datetime`, :class:`gcloud.datastore.key.Key`,
               bool, float, integer, string
    :param val: The value to be scrutinized.

    :returns: A tuple of the attribute name and proper value type.
    """

    if isinstance(val, datetime):
        name = 'timestamp_microseconds'
        # If the datetime is naive (no timezone), consider that it was
        # intended to be UTC and replace the tzinfo to that effect.
        if not val.tzinfo:
            val = val.replace(tzinfo=pytz.utc)
        # Regardless of what timezone is on the value, convert it to UTC.
        val = val.astimezone(pytz.utc)
        # Convert the datetime to a microsecond timestamp.
        value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond
    elif isinstance(val, Key):
        name, value = 'key', val.to_protobuf()
    elif isinstance(val, bool):
        name, value = 'boolean', val
    elif isinstance(val, float):
        name, value = 'double', val
    elif isinstance(val, (int, long)):
        check_int64_value(val)  # This will raise an exception if invalid.
        name, value = 'integer', val
    elif isinstance(val, basestring):
        name, value = 'string', val

    return name + '_value', value

def get_value_from_protobuf(pb):
    """Given a protobuf for a Property, get the correct value.

    The Cloud Datastore Protobuf API returns a Property Protobuf
    which has one value set and the rest blank.
    This method retrieves the the one value provided.

    Some work is done to coerce the return value into a more useful type
    (particularly in the case of a timestamp value, or a key value).

    :type pb: :class:`gcloud.datastore.datastore_v1_pb2.Property`
    :param pb: The Property Protobuf.

    :returns: The value provided by the Protobuf.
    """

    if pb.value.HasField('timestamp_microseconds_value'):
        microseconds = pb.value.timestamp_microseconds_value
        naive = (datetime.utcfromtimestamp(0) +
                 timedelta(microseconds=microseconds))
        return naive.replace(tzinfo=pytz.utc)

    elif pb.value.HasField('key_value'):
        return Key.from_protobuf(pb.value.key_value)

    elif pb.value.HasField('boolean_value'):
        return pb.value.boolean_value

    elif pb.value.HasField('double_value'):
        return pb.value.double_value

    elif pb.value.HasField('integer_value'):
        return pb.value.integer_value

    elif pb.value.HasField('string_value'):
        return pb.value.string_value

    else:
        return None
<commit_msg>Updated naming of global variable to follow PEP8.<commit_after>"""Helper methods for dealing with Cloud Datastore's Protobuf API."""
import calendar
from datetime import datetime, timedelta

from google.protobuf.internal.type_checkers import Int64ValueChecker
import pytz

from gcloud.datastore.key import Key

INT_VALUE_CHECKER = Int64ValueChecker()

def get_protobuf_attribute_and_value(val):
    """Given a value, return the protobuf attribute name and proper value.

    The Protobuf API uses different attribute names
    based on value types rather than inferring the type.
    This method simply determines the proper attribute name
    based on the type of the value provided
    and returns the attribute name
    as well as a properly formatted value.

    Certain value types need to be coerced into a different type (such as a
    `datetime.datetime` into an integer timestamp, or a
    `gcloud.datastore.key.Key` into a Protobuf representation.
    This method handles that for you.

    For example:

    >>> get_protobuf_attribute_and_value(1234)
    ('integer_value', 1234)
    >>> get_protobuf_attribute_and_value('my_string')
    ('string_value', 'my_string')

    :type val: `datetime.datetime`, :class:`gcloud.datastore.key.Key`,
               bool, float, integer, string
    :param val: The value to be scrutinized.

    :returns: A tuple of the attribute name and proper value type.
    """

    if isinstance(val, datetime):
        name = 'timestamp_microseconds'
        # If the datetime is naive (no timezone), consider that it was
        # intended to be UTC and replace the tzinfo to that effect.
        if not val.tzinfo:
            val = val.replace(tzinfo=pytz.utc)
        # Regardless of what timezone is on the value, convert it to UTC.
        val = val.astimezone(pytz.utc)
        # Convert the datetime to a microsecond timestamp.
        value = long(calendar.timegm(val.timetuple()) * 1e6) + val.microsecond
    elif isinstance(val, Key):
        name, value = 'key', val.to_protobuf()
    elif isinstance(val, bool):
        name, value = 'boolean', val
    elif isinstance(val, float):
        name, value = 'double', val
    elif isinstance(val, (int, long)):
        INT_VALUE_CHECKER.CheckValue(val)  # This will raise an exception if invalid.
        name, value = 'integer', val
    elif isinstance(val, basestring):
        name, value = 'string', val

    return name + '_value', value

def get_value_from_protobuf(pb):
    """Given a protobuf for a Property, get the correct value.

    The Cloud Datastore Protobuf API returns a Property Protobuf
    which has one value set and the rest blank.
    This method retrieves the the one value provided.

    Some work is done to coerce the return value into a more useful type
    (particularly in the case of a timestamp value, or a key value).

    :type pb: :class:`gcloud.datastore.datastore_v1_pb2.Property`
    :param pb: The Property Protobuf.

    :returns: The value provided by the Protobuf.
    """

    if pb.value.HasField('timestamp_microseconds_value'):
        microseconds = pb.value.timestamp_microseconds_value
        naive = (datetime.utcfromtimestamp(0) +
                 timedelta(microseconds=microseconds))
        return naive.replace(tzinfo=pytz.utc)

    elif pb.value.HasField('key_value'):
        return Key.from_protobuf(pb.value.key_value)

    elif pb.value.HasField('boolean_value'):
        return pb.value.boolean_value

    elif pb.value.HasField('double_value'):
        return pb.value.double_value

    elif pb.value.HasField('integer_value'):
        return pb.value.integer_value

    elif pb.value.HasField('string_value'):
        return pb.value.string_value

    else:
        return None
<|endoftext|>


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

"""Client for interacting with the `Google Stackdriver Monitoring API (V3)`_.

Example::

    >>> from gcloud import monitoring
    >>> client = monitoring.Client()
    >>> query = client.query(minutes=5)
    >>> print(query.as_dataframe())  # Requires pandas.

At present, the client supports querying of time series, metric descriptors,
and monitored resource descriptors.

.. _Google Stackdriver Monitoring API (V3):
    https://cloud.google.com/monitoring/api/v3/
"""

import datetime

from gcloud.client import JSONClient
from gcloud.monitoring.connection import Connection
from gcloud.monitoring.group import Group
from gcloud.monitoring.metric import Metric
from gcloud.monitoring.metric import MetricDescriptor
from gcloud.monitoring.metric import MetricKind
from gcloud.monitoring.metric import ValueType
from gcloud.monitoring.query import Query
from gcloud.monitoring.resource import Resource
from gcloud.monitoring.resource import ResourceDescriptor
from gcloud.monitoring.timeseries import Point
from gcloud.monitoring.timeseries import TimeSeries

_UTCNOW = datetime.datetime.utcnow  # To be replaced by tests.

class Client(JSONClient):
    """Client to bundle configuration needed for API requests.

    :type project: string
    :param project: The target project. If not passed, falls back to the
                    default inferred from the environment.

    :type credentials: :class:`oauth2client.client.OAuth2Credentials` or
                       :class:`NoneType`
    :param credentials: The OAuth2 Credentials to use for the connection
                        owned by this client. If not passed (and if no ``http``
                        object is passed), falls back to the default inferred
                        from the environment.

    :type http: :class:`httplib2.Http` or class that defines ``request()``
    :param http: An optional HTTP object to make requests. If not passed, an
                 ``http`` object is created that is bound to the
                 ``credentials`` for the current object.
    """

    _connection_class = Connection

    def query(self,
              metric_type=Query.DEFAULT_METRIC_TYPE,
              end_time=None,
              days=0, hours=0, minutes=0):
        """Construct a query object for retrieving metric data.

        Example::

            >>> query = client.query(minutes=5)
            >>> print(query.as_dataframe())  # Requires pandas.

        :type metric_type: string
        :param metric_type: The metric type name. The default value is
            :data:`Query.DEFAULT_METRIC_TYPE
            <gcloud.monitoring.query.Query.DEFAULT_METRIC_TYPE>`,
            but please note that this default value is provided only for
            demonstration purposes and is subject to change. See the
            `supported metrics`_.

        :type end_time: :class:`datetime.datetime` or None
        :param end_time: The end time (inclusive) of the time interval
            for which results should be returned, as a datetime object.
            The default is the start of the current minute.

            The start time (exclusive) is determined by combining the
            values of  ``days``, ``hours``, and ``minutes``, and
            subtracting the resulting duration from the end time.

            It is also allowed to omit the end time and duration here,
            in which case
            :meth:`~gcloud.monitoring.query.Query.select_interval`
            must be called before the query is executed.

        :type days: integer
        :param days: The number of days in the time interval.

        :type hours: integer
        :param hours: The number of hours in the time interval.

        :type minutes: integer
        :param minutes: The number of minutes in the time interval.

        :rtype: :class:`~gcloud.monitoring.query.Query`
        :returns: The query object.

        :raises: :exc:`ValueError` if ``end_time`` is specified but
            ``days``, ``hours``, and ``minutes`` are all zero.
            If you really want to specify a point in time, use
            :meth:`~gcloud.monitoring.query.Query.select_interval`.

        .. _supported metrics: https://cloud.google.com/monitoring/api/metrics
        """
        return Query(self, metric_type,
                     end_time=end_time,
                     days=days, hours=hours, minutes=minutes)

    def metric_descriptor(self, type_,
                          metric_kind=MetricKind.METRIC_KIND_UNSPECIFIED,
                          value_type=ValueType.VALUE_TYPE_UNSPECIFIED,
                          labels=(), unit='', description='', display_name=''):
        """Construct a metric descriptor object.

        Metric descriptors specify the schema for a particular metric type.

        This factory method is used most often in conjunction with the metric
        descriptor :meth:`~gcloud.monitoring.metric.MetricDescriptor.create`
        method to define custom metrics::

            >>> descriptor = client.metric_descriptor(
            ...     'custom.googleapis.com/my_metric',
            ...     metric_kind=MetricKind.GAUGE,
            ...     value_type=ValueType.DOUBLE,
            ...     description='This is a simple example of a custom metric.')
            >>> descriptor.create()

        Here is an example where the custom metric is parameterized by a
        metric label::

            >>> label = LabelDescriptor('response_code', LabelValueType.INT64,
            ...                         description='HTTP status code')
            >>> descriptor = client.metric_descriptor(
            ...     'custom.googleapis.com/my_app/response_count',
            ...     metric_kind=MetricKind.CUMULATIVE,
            ...     value_type=ValueType.INT64,
            ...     labels=[label],
            ...     description='Cumulative count of HTTP responses.')
            >>> descriptor.create()

        :type type_: string
        :param type_:
            The metric type including a DNS name prefix. For example:
            ``"custom.googleapis.com/my_metric"``

        :type metric_kind: string
        :param metric_kind:
            The kind of measurement. It must be one of
            :data:`MetricKind.GAUGE`, :data:`MetricKind.DELTA`,
            or :data:`MetricKind.CUMULATIVE`.
            See :class:`~gcloud.monitoring.metric.MetricKind`.

        :type value_type: string
        :param value_type:
            The value type of the metric. It must be one of
            :data:`ValueType.BOOL`, :data:`ValueType.INT64`,
            :data:`ValueType.DOUBLE`, :data:`ValueType.STRING`,
            or :data:`ValueType.DISTRIBUTION`.
            See :class:`ValueType`.

        :type labels: list of :class:`~gcloud.monitoring.label.LabelDescriptor`
        :param labels:
            A sequence of zero or more label descriptors specifying the labels
            used to identify a specific instance of this metric.

        :type unit: string
        :param unit: An optional unit in which the metric value is reported.

        :type description: string
        :param description: An optional detailed description of the metric.

        :type display_name: string
        :param display_name: An optional concise name for the metric.

        :rtype: :class:`MetricDescriptor`
        :returns: The metric descriptor created with the passed-in arguments.
        """
        return MetricDescriptor(
            self, type_,
            metric_kind=metric_kind,
            value_type=value_type,
            labels=labels,
            unit=unit,
            description=description,
            display_name=display_name,
        )

    @staticmethod
    def metric(type_, labels):
        """Factory for constructing metric objects.

        :class:`~gcloud.monitoring.metric.Metric` objects are typically
        created to write custom metric values. The type should match the
        metric type specified in the
        :class:`~gcloud.monitoring.metric.MetricDescriptor` used to
        create the custom metric::

             >>> metric = client.metric('custom.googleapis.com/my_metric',
             ...                        labels={
             ...                            'status': 'successful',
             ...                         })

        :type type_: string
        :param type_: The metric type name.

        :type labels: dict
        :param labels: A mapping from label names to values for all labels
                       enumerated in the associated
                       :class:`~gcloud.monitoring.metric.MetricDescriptor`.

        :rtype: :class:`~gcloud.monitoring.metric.Metric`
        :returns: The metric object.
        """
        return Metric(type=type_, labels=labels)

    @staticmethod
    def resource(type_, labels):
        """Factory for constructing monitored resource objects.

        A monitored resource object (
        :class:`~gcloud.monitoring.resource.Resource`) is
        typically used to create a
        :class:`~gcloud.monitoring.timeseries.TimeSeries` object.

        For a list of possible monitored resource types and their associated
        labels, see:

        https://cloud.google.com/monitoring/api/resources

        :type type_: string
        :param type_: The monitored resource type name.

        :type labels: dict
        :param labels: A mapping from label names to values for all labels
                       enumerated in the associated
                       :class:`~gcloud.monitoring.resource.ResourceDescriptor`,
                       except that ``project_id`` can and should be omitted
                       when writing time series data.

        :rtype: :class:`~gcloud.monitoring.resource.Resource`
        :returns: A monitored resource object.
        """
        return Resource(type_, labels)

    @staticmethod
    def time_series(metric, resource, value,
                    end_time=None, start_time=None):
        """Construct a time series object for a single data point.

        .. note::

           While :class:`~gcloud.monitoring.timeseries.TimeSeries` objects
           returned by the API typically have multiple data points,
           :class:`~gcloud.monitoring.timeseries.TimeSeries` objects
           sent to the API must have at most one point.

        For example::

            >>> timeseries = client.time_series(metric, resource, 1.23,
            ...                                 end_time=end)

        For more information, see:

        https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries

        :type metric: :class:`~gcloud.monitoring.metric.Metric`
        :param metric: A :class:`~gcloud.monitoring.metric.Metric` object.

        :type resource: :class:`~gcloud.monitoring.resource.Resource`
        :param resource: A :class:`~gcloud.monitoring.resource.Resource`
                         object.

        :type value: bool, int, string, or float
        :param value:
            The value of the data point to create for the
            :class:`~gcloud.monitoring.timeseries.TimeSeries`.

            .. note::

               The Python type of the value will determine the
               `class`:ValueType: sent to the API, which must match the value
               type specified in the metric descriptor. For example, a Python
               float will be sent to the API as a :data:`ValueType.DOUBLE`.

        :type end_time: :class:`~datetime.datetime`
        :param end_time:
            The end time for the point to be included in the time series.
            Assumed to be UTC if no time zone information is present.
            Defaults to the current time, as obtained by calling
            :meth:`datetime.datetime.utcnow`.

        :type start_time: :class:`~datetime.datetime`
        :param start_time:
            The start time for the point to be included in the time series.
            Assumed to be UTC if no time zone information is present
            Defaults to None. If the start time is unspecified,
            the API interprets the start time to be the same as the end time.

        :rtype: :class:`~gcloud.monitoring.timeseries.TimeSeries`
        :returns: A time series object.
        """
        if end_time is None:
            end_time = _UTCNOW()
        point = Point(value=value, start_time=start_time, end_time=end_time)
        return TimeSeries(metric=metric, resource=resource, metric_kind=None,
                          value_type=None, points=[point])

    def fetch_metric_descriptor(self, metric_type):
        """Look up a metric descriptor by type.

        Example::

            >>> METRIC = 'compute.googleapis.com/instance/cpu/utilization'
            >>> print(client.fetch_metric_descriptor(METRIC))

        :type metric_type: string
        :param metric_type: The metric type name.

        :rtype: :class:`~gcloud.monitoring.metric.MetricDescriptor`
        :returns: The metric descriptor instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the metric descriptor
            is not found.
        """
        return MetricDescriptor._fetch(self, metric_type)

    def list_metric_descriptors(self, filter_string=None, type_prefix=None):
        """List all metric descriptors for the project.

        Examples::

            >>> for descriptor in client.list_metric_descriptors():
            ...     print(descriptor.type)

            >>> for descriptor in client.list_metric_descriptors(
            ...         type_prefix='custom.'):
            ...     print(descriptor.type)

        :type filter_string: string or None
        :param filter_string:
            An optional filter expression describing the metric descriptors
            to be returned. See the `filter documentation`_.

        :type type_prefix: string or None
        :param type_prefix: An optional prefix constraining the selected
            metric types. This adds ``metric.type = starts_with("<prefix>")``
            to the filter.

        :rtype: list of :class:`~gcloud.monitoring.metric.MetricDescriptor`
        :returns: A list of metric descriptor instances.

        .. _filter documentation:
            https://cloud.google.com/monitoring/api/v3/filters
        """
        return MetricDescriptor._list(self, filter_string,
                                      type_prefix=type_prefix)

    def fetch_resource_descriptor(self, resource_type):
        """Look up a monitored resource descriptor by type.

        Example::

            >>> print(client.fetch_resource_descriptor('gce_instance'))

        :type resource_type: string
        :param resource_type: The resource type name.

        :rtype: :class:`~gcloud.monitoring.resource.ResourceDescriptor`
        :returns: The resource descriptor instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the resource descriptor
            is not found.
        """
        return ResourceDescriptor._fetch(self, resource_type)

    def list_resource_descriptors(self, filter_string=None):
        """List all monitored resource descriptors for the project.

        Example::

            >>> for descriptor in client.list_resource_descriptors():
            ...     print(descriptor.type)

        :type filter_string: string or None
        :param filter_string:
            An optional filter expression describing the resource descriptors
            to be returned. See the `filter documentation`_.

        :rtype: list of :class:`~gcloud.monitoring.resource.ResourceDescriptor`
        :returns: A list of resource descriptor instances.

        .. _filter documentation:
            https://cloud.google.com/monitoring/api/v3/filters
        """
        return ResourceDescriptor._list(self, filter_string)

    def group(self, group_id=None, display_name=None, parent_id=None,
              filter_string=None, is_cluster=False):
        """Factory constructor for group object.

        .. note::
          This will not make an HTTP request; it simply instantiates
          a group object owned by this client.

        :type group_id: string or None
        :param group_id: The ID of the group.

        :type display_name: string or None
        :param display_name:
            A user-assigned name for this group, used only for display
            purposes.

        :type parent_id: string or None
        :param parent_id:
            The ID of the group's parent, if it has one.

        :type filter_string: string or None
        :param filter_string:
            The filter string used to determine which monitored resources
            belong to this group.

        :type is_cluster: boolean
        :param is_cluster:
            If true, the members of this group are considered to be a cluster.
            The system can perform additional analysis on groups that are
            clusters.

        :rtype: :class:`Group`
        :returns: The group created with the passed-in arguments.

        :raises:
            :exc:`ValueError` if both ``group_id`` and ``name`` are specified.
        """
        return Group(
            self,
            group_id=group_id,
            display_name=display_name,
            parent_id=parent_id,
            filter_string=filter_string,
            is_cluster=is_cluster,
        )

    def fetch_group(self, group_id):
        """Fetch a group from the API based on it's ID.

        Example::

            >>> try:
            >>>     group = client.fetch_group('1234')
            >>> except gcloud.exceptions.NotFound:
            >>>     print('That group does not exist!')

        :type group_id: string
        :param group_id: The ID of the group.

        :rtype: :class:`~gcloud.monitoring.group.Group`
        :returns: The group instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the group is not found.
        """
        return Group._fetch(self, group_id)

    def list_groups(self):
        """List all groups for the project.

        Example::

            >>> for group in client.list_groups():
            ...     print((group.display_name, group.name))

        :rtype: list of :class:`~gcloud.monitoring.group.Group`
        :returns: A list of group instances.
        """
        return Group._list(self)
<commit_msg>Fix ValueType link<commit_after># Copyright 2016 Google Inc. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Client for interacting with the `Google Stackdriver Monitoring API (V3)`_.

Example::

    >>> from gcloud import monitoring
    >>> client = monitoring.Client()
    >>> query = client.query(minutes=5)
    >>> print(query.as_dataframe())  # Requires pandas.

At present, the client supports querying of time series, metric descriptors,
and monitored resource descriptors.

.. _Google Stackdriver Monitoring API (V3):
    https://cloud.google.com/monitoring/api/v3/
"""

import datetime

from gcloud.client import JSONClient
from gcloud.monitoring.connection import Connection
from gcloud.monitoring.group import Group
from gcloud.monitoring.metric import Metric
from gcloud.monitoring.metric import MetricDescriptor
from gcloud.monitoring.metric import MetricKind
from gcloud.monitoring.metric import ValueType
from gcloud.monitoring.query import Query
from gcloud.monitoring.resource import Resource
from gcloud.monitoring.resource import ResourceDescriptor
from gcloud.monitoring.timeseries import Point
from gcloud.monitoring.timeseries import TimeSeries

_UTCNOW = datetime.datetime.utcnow  # To be replaced by tests.

class Client(JSONClient):
    """Client to bundle configuration needed for API requests.

    :type project: string
    :param project: The target project. If not passed, falls back to the
                    default inferred from the environment.

    :type credentials: :class:`oauth2client.client.OAuth2Credentials` or
                       :class:`NoneType`
    :param credentials: The OAuth2 Credentials to use for the connection
                        owned by this client. If not passed (and if no ``http``
                        object is passed), falls back to the default inferred
                        from the environment.

    :type http: :class:`httplib2.Http` or class that defines ``request()``
    :param http: An optional HTTP object to make requests. If not passed, an
                 ``http`` object is created that is bound to the
                 ``credentials`` for the current object.
    """

    _connection_class = Connection

    def query(self,
              metric_type=Query.DEFAULT_METRIC_TYPE,
              end_time=None,
              days=0, hours=0, minutes=0):
        """Construct a query object for retrieving metric data.

        Example::

            >>> query = client.query(minutes=5)
            >>> print(query.as_dataframe())  # Requires pandas.

        :type metric_type: string
        :param metric_type: The metric type name. The default value is
            :data:`Query.DEFAULT_METRIC_TYPE
            <gcloud.monitoring.query.Query.DEFAULT_METRIC_TYPE>`,
            but please note that this default value is provided only for
            demonstration purposes and is subject to change. See the
            `supported metrics`_.

        :type end_time: :class:`datetime.datetime` or None
        :param end_time: The end time (inclusive) of the time interval
            for which results should be returned, as a datetime object.
            The default is the start of the current minute.

            The start time (exclusive) is determined by combining the
            values of  ``days``, ``hours``, and ``minutes``, and
            subtracting the resulting duration from the end time.

            It is also allowed to omit the end time and duration here,
            in which case
            :meth:`~gcloud.monitoring.query.Query.select_interval`
            must be called before the query is executed.

        :type days: integer
        :param days: The number of days in the time interval.

        :type hours: integer
        :param hours: The number of hours in the time interval.

        :type minutes: integer
        :param minutes: The number of minutes in the time interval.

        :rtype: :class:`~gcloud.monitoring.query.Query`
        :returns: The query object.

        :raises: :exc:`ValueError` if ``end_time`` is specified but
            ``days``, ``hours``, and ``minutes`` are all zero.
            If you really want to specify a point in time, use
            :meth:`~gcloud.monitoring.query.Query.select_interval`.

        .. _supported metrics: https://cloud.google.com/monitoring/api/metrics
        """
        return Query(self, metric_type,
                     end_time=end_time,
                     days=days, hours=hours, minutes=minutes)

    def metric_descriptor(self, type_,
                          metric_kind=MetricKind.METRIC_KIND_UNSPECIFIED,
                          value_type=ValueType.VALUE_TYPE_UNSPECIFIED,
                          labels=(), unit='', description='', display_name=''):
        """Construct a metric descriptor object.

        Metric descriptors specify the schema for a particular metric type.

        This factory method is used most often in conjunction with the metric
        descriptor :meth:`~gcloud.monitoring.metric.MetricDescriptor.create`
        method to define custom metrics::

            >>> descriptor = client.metric_descriptor(
            ...     'custom.googleapis.com/my_metric',
            ...     metric_kind=MetricKind.GAUGE,
            ...     value_type=ValueType.DOUBLE,
            ...     description='This is a simple example of a custom metric.')
            >>> descriptor.create()

        Here is an example where the custom metric is parameterized by a
        metric label::

            >>> label = LabelDescriptor('response_code', LabelValueType.INT64,
            ...                         description='HTTP status code')
            >>> descriptor = client.metric_descriptor(
            ...     'custom.googleapis.com/my_app/response_count',
            ...     metric_kind=MetricKind.CUMULATIVE,
            ...     value_type=ValueType.INT64,
            ...     labels=[label],
            ...     description='Cumulative count of HTTP responses.')
            >>> descriptor.create()

        :type type_: string
        :param type_:
            The metric type including a DNS name prefix. For example:
            ``"custom.googleapis.com/my_metric"``

        :type metric_kind: string
        :param metric_kind:
            The kind of measurement. It must be one of
            :data:`MetricKind.GAUGE`, :data:`MetricKind.DELTA`,
            or :data:`MetricKind.CUMULATIVE`.
            See :class:`~gcloud.monitoring.metric.MetricKind`.

        :type value_type: string
        :param value_type:
            The value type of the metric. It must be one of
            :data:`ValueType.BOOL`, :data:`ValueType.INT64`,
            :data:`ValueType.DOUBLE`, :data:`ValueType.STRING`,
            or :data:`ValueType.DISTRIBUTION`.
            See :class:`ValueType`.

        :type labels: list of :class:`~gcloud.monitoring.label.LabelDescriptor`
        :param labels:
            A sequence of zero or more label descriptors specifying the labels
            used to identify a specific instance of this metric.

        :type unit: string
        :param unit: An optional unit in which the metric value is reported.

        :type description: string
        :param description: An optional detailed description of the metric.

        :type display_name: string
        :param display_name: An optional concise name for the metric.

        :rtype: :class:`MetricDescriptor`
        :returns: The metric descriptor created with the passed-in arguments.
        """
        return MetricDescriptor(
            self, type_,
            metric_kind=metric_kind,
            value_type=value_type,
            labels=labels,
            unit=unit,
            description=description,
            display_name=display_name,
        )

    @staticmethod
    def metric(type_, labels):
        """Factory for constructing metric objects.

        :class:`~gcloud.monitoring.metric.Metric` objects are typically
        created to write custom metric values. The type should match the
        metric type specified in the
        :class:`~gcloud.monitoring.metric.MetricDescriptor` used to
        create the custom metric::

             >>> metric = client.metric('custom.googleapis.com/my_metric',
             ...                        labels={
             ...                            'status': 'successful',
             ...                         })

        :type type_: string
        :param type_: The metric type name.

        :type labels: dict
        :param labels: A mapping from label names to values for all labels
                       enumerated in the associated
                       :class:`~gcloud.monitoring.metric.MetricDescriptor`.

        :rtype: :class:`~gcloud.monitoring.metric.Metric`
        :returns: The metric object.
        """
        return Metric(type=type_, labels=labels)

    @staticmethod
    def resource(type_, labels):
        """Factory for constructing monitored resource objects.

        A monitored resource object (
        :class:`~gcloud.monitoring.resource.Resource`) is
        typically used to create a
        :class:`~gcloud.monitoring.timeseries.TimeSeries` object.

        For a list of possible monitored resource types and their associated
        labels, see:

        https://cloud.google.com/monitoring/api/resources

        :type type_: string
        :param type_: The monitored resource type name.

        :type labels: dict
        :param labels: A mapping from label names to values for all labels
                       enumerated in the associated
                       :class:`~gcloud.monitoring.resource.ResourceDescriptor`,
                       except that ``project_id`` can and should be omitted
                       when writing time series data.

        :rtype: :class:`~gcloud.monitoring.resource.Resource`
        :returns: A monitored resource object.
        """
        return Resource(type_, labels)

    @staticmethod
    def time_series(metric, resource, value,
                    end_time=None, start_time=None):
        """Construct a time series object for a single data point.

        .. note::

           While :class:`~gcloud.monitoring.timeseries.TimeSeries` objects
           returned by the API typically have multiple data points,
           :class:`~gcloud.monitoring.timeseries.TimeSeries` objects
           sent to the API must have at most one point.

        For example::

            >>> timeseries = client.time_series(metric, resource, 1.23,
            ...                                 end_time=end)

        For more information, see:

        https://cloud.google.com/monitoring/api/ref_v3/rest/v3/TimeSeries

        :type metric: :class:`~gcloud.monitoring.metric.Metric`
        :param metric: A :class:`~gcloud.monitoring.metric.Metric` object.

        :type resource: :class:`~gcloud.monitoring.resource.Resource`
        :param resource: A :class:`~gcloud.monitoring.resource.Resource`
                         object.

        :type value: bool, int, string, or float
        :param value:
            The value of the data point to create for the
            :class:`~gcloud.monitoring.timeseries.TimeSeries`.

            .. note::

               The Python type of the value will determine the
               :class:`~ValueType` sent to the API, which must match the value
               type specified in the metric descriptor. For example, a Python
               float will be sent to the API as a :data:`ValueType.DOUBLE`.

        :type end_time: :class:`~datetime.datetime`
        :param end_time:
            The end time for the point to be included in the time series.
            Assumed to be UTC if no time zone information is present.
            Defaults to the current time, as obtained by calling
            :meth:`datetime.datetime.utcnow`.

        :type start_time: :class:`~datetime.datetime`
        :param start_time:
            The start time for the point to be included in the time series.
            Assumed to be UTC if no time zone information is present
            Defaults to None. If the start time is unspecified,
            the API interprets the start time to be the same as the end time.

        :rtype: :class:`~gcloud.monitoring.timeseries.TimeSeries`
        :returns: A time series object.
        """
        if end_time is None:
            end_time = _UTCNOW()
        point = Point(value=value, start_time=start_time, end_time=end_time)
        return TimeSeries(metric=metric, resource=resource, metric_kind=None,
                          value_type=None, points=[point])

    def fetch_metric_descriptor(self, metric_type):
        """Look up a metric descriptor by type.

        Example::

            >>> METRIC = 'compute.googleapis.com/instance/cpu/utilization'
            >>> print(client.fetch_metric_descriptor(METRIC))

        :type metric_type: string
        :param metric_type: The metric type name.

        :rtype: :class:`~gcloud.monitoring.metric.MetricDescriptor`
        :returns: The metric descriptor instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the metric descriptor
            is not found.
        """
        return MetricDescriptor._fetch(self, metric_type)

    def list_metric_descriptors(self, filter_string=None, type_prefix=None):
        """List all metric descriptors for the project.

        Examples::

            >>> for descriptor in client.list_metric_descriptors():
            ...     print(descriptor.type)

            >>> for descriptor in client.list_metric_descriptors(
            ...         type_prefix='custom.'):
            ...     print(descriptor.type)

        :type filter_string: string or None
        :param filter_string:
            An optional filter expression describing the metric descriptors
            to be returned. See the `filter documentation`_.

        :type type_prefix: string or None
        :param type_prefix: An optional prefix constraining the selected
            metric types. This adds ``metric.type = starts_with("<prefix>")``
            to the filter.

        :rtype: list of :class:`~gcloud.monitoring.metric.MetricDescriptor`
        :returns: A list of metric descriptor instances.

        .. _filter documentation:
            https://cloud.google.com/monitoring/api/v3/filters
        """
        return MetricDescriptor._list(self, filter_string,
                                      type_prefix=type_prefix)

    def fetch_resource_descriptor(self, resource_type):
        """Look up a monitored resource descriptor by type.

        Example::

            >>> print(client.fetch_resource_descriptor('gce_instance'))

        :type resource_type: string
        :param resource_type: The resource type name.

        :rtype: :class:`~gcloud.monitoring.resource.ResourceDescriptor`
        :returns: The resource descriptor instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the resource descriptor
            is not found.
        """
        return ResourceDescriptor._fetch(self, resource_type)

    def list_resource_descriptors(self, filter_string=None):
        """List all monitored resource descriptors for the project.

        Example::

            >>> for descriptor in client.list_resource_descriptors():
            ...     print(descriptor.type)

        :type filter_string: string or None
        :param filter_string:
            An optional filter expression describing the resource descriptors
            to be returned. See the `filter documentation`_.

        :rtype: list of :class:`~gcloud.monitoring.resource.ResourceDescriptor`
        :returns: A list of resource descriptor instances.

        .. _filter documentation:
            https://cloud.google.com/monitoring/api/v3/filters
        """
        return ResourceDescriptor._list(self, filter_string)

    def group(self, group_id=None, display_name=None, parent_id=None,
              filter_string=None, is_cluster=False):
        """Factory constructor for group object.

        .. note::
          This will not make an HTTP request; it simply instantiates
          a group object owned by this client.

        :type group_id: string or None
        :param group_id: The ID of the group.

        :type display_name: string or None
        :param display_name:
            A user-assigned name for this group, used only for display
            purposes.

        :type parent_id: string or None
        :param parent_id:
            The ID of the group's parent, if it has one.

        :type filter_string: string or None
        :param filter_string:
            The filter string used to determine which monitored resources
            belong to this group.

        :type is_cluster: boolean
        :param is_cluster:
            If true, the members of this group are considered to be a cluster.
            The system can perform additional analysis on groups that are
            clusters.

        :rtype: :class:`Group`
        :returns: The group created with the passed-in arguments.

        :raises:
            :exc:`ValueError` if both ``group_id`` and ``name`` are specified.
        """
        return Group(
            self,
            group_id=group_id,
            display_name=display_name,
            parent_id=parent_id,
            filter_string=filter_string,
            is_cluster=is_cluster,
        )

    def fetch_group(self, group_id):
        """Fetch a group from the API based on it's ID.

        Example::

            >>> try:
            >>>     group = client.fetch_group('1234')
            >>> except gcloud.exceptions.NotFound:
            >>>     print('That group does not exist!')

        :type group_id: string
        :param group_id: The ID of the group.

        :rtype: :class:`~gcloud.monitoring.group.Group`
        :returns: The group instance.

        :raises: :class:`gcloud.exceptions.NotFound` if the group is not found.
        """
        return Group._fetch(self, group_id)

    def list_groups(self):
        """List all groups for the project.

        Example::

            >>> for group in client.list_groups():
            ...     print((group.display_name, group.name))

        :rtype: list of :class:`~gcloud.monitoring.group.Group`
        :returns: A list of group instances.
        """
        return Group._list(self)
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# Copyright (c) 2013 by Pablo Martín <goinnn@gmail.com>
#
# This software is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this software.  If not, see <http://www.gnu.org/licenses/>.

# This file originally was in this repository:
# <https://github.com/goinnn/Kate-plugins/tree/master/kate_plugins/pyte_plugins/djte_plugins/block_plugins.py>

import kate
import re

from libkatepate.text import insertText
from django_settings import (KATE_ACTIONS,
                             _TEMPLATE_TAGS_CLOSE,
                             DEFAULT_TEMPLATE_TAGS_CLOSE)

str_blank = "(?:\ |\t|\n)*"

@kate.action(**KATE_ACTIONS['closeTemplateTag'])
def closeTemplateTag():
    """Close the last templatetag open"""
    django_utils_conf = kate.configuration.root.get('django_utils', {})
    template_tags_close = django_utils_conf.get(_TEMPLATE_TAGS_CLOSE, DEFAULT_TEMPLATE_TAGS_CLOSE).split(",")
    template_tags_close = [tag.strip() for tag in template_tags_close]
    template_tags = '|'.join(template_tags_close)
    pattern_tag_open = re.compile("(.)*{%%%(espaces)s(%(tags)s)%(espaces)s(.)*%(espaces)s%%}(.)*" % {'espaces': str_blank, 'tags': template_tags})
    pattern_tag_close = re.compile("(.)*{%%%(espaces)send(%(tags)s)%(espaces)s%(espaces)s%%}(.)*" % {'espaces': str_blank, 'tags': template_tags})
    tag_closes = {}
    currentDocument = kate.activeDocument()
    view = currentDocument.activeView()
    currentPosition = view.cursorPosition()
    currentLine = currentPosition.line()
    tag = ''
    while currentLine >= 0:
        text = currentDocument.line(currentLine)
        match_open = pattern_tag_open.match(text)
        if match_open:
            tag_name = match_open.groups()[1]
            if tag_name in tag_closes:
                tag_closes[tag_name] -= 1
                if tag_closes[tag_name] == 0:
                    del tag_closes[tag_name]
            elif not tag_closes:
                tag = match_open.groups()[1]
                break
        else:
            match_close = pattern_tag_close.match(text)
            if match_close:
                tag_name = match_close.groups()[1]
                tag_closes[tag_name] = tag_closes.get(tag_name, 0) + 1
        currentLine = currentLine - 1
    insertText("{%% end%s %%}" % tag)

@kate.action(**KATE_ACTIONS['createBlock'])
def createBlock():
    """Insert the tag block/endblock. The name of the block will be the text selected"""
    currentDocument = kate.activeDocument()
    view = currentDocument.activeView()
    source = view.selectionText()
    try:
        block_type, block_source = source.split("#")
    except ValueError:
        block_type = 'block'
        block_source = source
    view.removeSelectionText()
    insertText("{%% %(block_type)s %(block_source)s %%}XXX{%% end%(block_type)s %%}" %
               {'block_type': block_type, 'block_source': block_source})

# kate: space-indent on; indent-width 4;
<commit_msg>Fix a little error, change XXX to TEXT_TO_CHANGE<commit_after># -*- coding: utf-8 -*-
# Copyright (c) 2013 by Pablo Martín <goinnn@gmail.com>
#
# This software is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This software is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with this software.  If not, see <http://www.gnu.org/licenses/>.

# This file originally was in this repository:
# <https://github.com/goinnn/Kate-plugins/tree/master/kate_plugins/pyte_plugins/djte_plugins/block_plugins.py>

import kate
import re

from libkatepate.text import insertText, TEXT_TO_CHANGE
from django_settings import (KATE_ACTIONS,
                             _TEMPLATE_TAGS_CLOSE,
                             DEFAULT_TEMPLATE_TAGS_CLOSE)

str_blank = "(?:\ |\t|\n)*"

@kate.action(**KATE_ACTIONS['closeTemplateTag'])
def closeTemplateTag():
    """Close the last templatetag open"""
    django_utils_conf = kate.configuration.root.get('django_utils', {})
    template_tags_close = django_utils_conf.get(_TEMPLATE_TAGS_CLOSE, DEFAULT_TEMPLATE_TAGS_CLOSE).split(",")
    template_tags_close = [tag.strip() for tag in template_tags_close]
    template_tags = '|'.join(template_tags_close)
    pattern_tag_open = re.compile("(.)*{%%%(espaces)s(%(tags)s)%(espaces)s(.)*%(espaces)s%%}(.)*" % {'espaces': str_blank, 'tags': template_tags})
    pattern_tag_close = re.compile("(.)*{%%%(espaces)send(%(tags)s)%(espaces)s%(espaces)s%%}(.)*" % {'espaces': str_blank, 'tags': template_tags})
    tag_closes = {}
    currentDocument = kate.activeDocument()
    view = currentDocument.activeView()
    currentPosition = view.cursorPosition()
    currentLine = currentPosition.line()
    tag = ''
    while currentLine >= 0:
        text = currentDocument.line(currentLine)
        match_open = pattern_tag_open.match(text)
        if match_open:
            tag_name = match_open.groups()[1]
            if tag_name in tag_closes:
                tag_closes[tag_name] -= 1
                if tag_closes[tag_name] == 0:
                    del tag_closes[tag_name]
            elif not tag_closes:
                tag = match_open.groups()[1]
                break
        else:
            match_close = pattern_tag_close.match(text)
            if match_close:
                tag_name = match_close.groups()[1]
                tag_closes[tag_name] = tag_closes.get(tag_name, 0) + 1
        currentLine = currentLine - 1
    insertText("{%% end%s %%}" % tag)

@kate.action(**KATE_ACTIONS['createBlock'])
def createBlock():
    """Insert the tag block/endblock. The name of the block will be the text selected"""
    currentDocument = kate.activeDocument()
    view = currentDocument.activeView()
    source = view.selectionText()
    try:
        block_type, block_source = source.split("#")
    except ValueError:
        block_type = 'block'
        block_source = source
    view.removeSelectionText()
    insertText("{%% %(block_type)s %(block_source)s %%}%(cursor)s{%% end%(block_type)s %%}" %
               {'block_type': block_type,
                'block_source': block_source,
                'cursor': TEXT_TO_CHANGE})

# kate: space-indent on; indent-width 4;
<|endoftext|>