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

import base64
import logging
import os
import httplib2
import configparser
import time
import urllib
from datetime import date, timedelta
from functools import wraps

from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials

# Fix 'six' import errors in OS X
import platform
if platform.system() == "Darwin":
    import sys
    sys.path.insert(1, '/Library/Python/2.7/site-packages')

# Print logging to console
# logging.getLogger().setLevel(logging.INFO)

RUNNING_ON_GAE = 'SERVER_SOFTWARE' in os.environ

# Load our configuration
THIS_PATH = os.path.dirname(os.path.realpath(__file__))

_CONFIG = configparser.ConfigParser()
_CONFIG.read(THIS_PATH + "/secrets.cfg")

GA_DOMAIN = _CONFIG.get('google', 'domain')
SERVICE_ACCOUNT = _CONFIG.get('google', 'serviceAccount')
SERVICE_ACCOUNT_KEY = _CONFIG.get('google', 'serviceAccountKey')
ADMIN_TO_IMPERSONATE = _CONFIG.get('google', 'adminToImpersonate')
GA_BLACKLISTED_USERS = _CONFIG.get('google', 'blacklistedUsers')
GA_SKIP_USERS = _CONFIG.get('google', 'skipUsers')
RETENTION_DAYS = _CONFIG.getint('google', 'retentionPeriodInDays')
CAN_SEND_MAIL = _CONFIG.getboolean('google', 'canSendMail')

# Grab the service account .pem or .p12 private key
with open(THIS_PATH + "/" + SERVICE_ACCOUNT_KEY, 'rb') as f:
    SERVICE_SECRET_KEY = f.read()

# Bare-bones (one value) handling of pretty output for CRON vs GAE
class gae_print_handler():
    def __init__(self):
        self.buffer = []

    def write(self, message):
        if RUNNING_ON_GAE:
            self.buffer.append(message)
        else:
            print(message)

    def clear(self):
        self.buffer = []

OUTPUT_BUFFER = gae_print_handler()

# Retry decorator
# Adapted from http://googleadsdeveloper.blogspot.com/2014/09/decorating-your-python-dfp-api.html
def retry(func):
    @wraps(func)
    def function_to_retry(*args, **kwargs):
        tries = 4
        delay = 1
        while tries > 1:
            try:
                return func(*args, **kwargs)
            except Exception, e:
                print('%s, Retrying in %d seconds...' % (str(e), delay))
                time.sleep(delay)
                tries -= 1
                delay *= 2
        return func(*args, **kwargs)
    return function_to_retry

def getDirectoryService(user_to_impersonate):
    """Build and returns a Directory service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user.
    Returns:
      Directory service object.
    """
    assert(user_to_impersonate.endswith(GA_DOMAIN))
    assert(user_to_impersonate not in GA_BLACKLISTED_USERS)

    credentials = SignedJwtAssertionCredentials(
        SERVICE_ACCOUNT,
        SERVICE_SECRET_KEY,
        sub=user_to_impersonate,
        scope=['https://www.googleapis.com/auth/admin.directory.user.readonly']
    )

    http = httplib2.Http()
    http = credentials.authorize(http)

    return build('admin', 'directory_v1', http=http)

def getGmailService(user_to_impersonate):
    """Build and returns a Gmail service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user.
    Returns:
      Gmail service object.
    """
    assert(user_to_impersonate.endswith(GA_DOMAIN))
    assert(user_to_impersonate not in GA_BLACKLISTED_USERS)

    credentials = SignedJwtAssertionCredentials(
        SERVICE_ACCOUNT,
        SERVICE_SECRET_KEY,
        sub=user_to_impersonate,
        scope=['https://www.googleapis.com/auth/gmail.readonly',
               'https://www.googleapis.com/auth/gmail.compose']
    )

    http = httplib2.Http()
    http = credentials.authorize(http)

    return build('gmail', 'v1', http=http)

def getAllUsers(directory_service):
    """
    Get a list of all users on the domain

    Via API manual at https://developers.google.com/admin-sdk/directory/v1/reference/#Users

    :param directory_service: A directory service object
    :return: A dictionary of {primaryEmail: givenName}
    """
    OUTPUT_BUFFER.write('Listing all users at %s' % (GA_DOMAIN))
    all_users = []
    page_token = None
    params = {'domain': GA_DOMAIN, 'viewType': 'domain_public'}

    while True:
        try:
            if page_token:
                params['pageToken'] = page_token
            current_page = retry(directory_service.users().list(**params).execute)()

            all_users.extend(current_page['users'])
            page_token = current_page.get('nextPageToken')
            if not page_token:
                break
        except errors.HttpError as error:
            logging.error('An error occurred: %s' % error)
            break

    email_and_name = {}
    for user in all_users:
        if str(user['primaryEmail']) not in GA_SKIP_USERS:
            email_and_name[user['primaryEmail']] = user['name']['givenName']
        else:
            OUTPUT_BUFFER.write('Skipped user: %s' % (user['primaryEmail']))

    OUTPUT_BUFFER.write('Found %d users in domain.' % (len(email_and_name)))
    return email_and_name

def sendWarningMessage(gmail_service, retention_period_in_days, user_email, user_name,
                       message_count, subjects, before_date, suggest_date):
    """
    Send a warning email to a user who has mail that may be deleted.
    """
    # TODO: Clean up this mess.
    logging.debug('Sending message to %s' % user_email)
    subject = "[%s] Warning: Some very old emails will be trashed" % (user_name)

    body = [
        "Your email address (%s) is set to keep messages for %s days (%.4g years).\n" % (user_email, retention_period_in_days, retention_period_in_days / float(365)),
        "You have at least %s messages from before %s that will be trashed over the next month.\n" % (message_count, before_date),
        "Some of the ancient emails to be removed include:\n\n> %s\n\n" % (subjects),
        "You can see the full list of messages at: https://mail.google.com/a/%s/#search/%s\n" % (GA_DOMAIN, urllib.quote_plus('before:%s' % before_date)),
        "Thanks,", "Domain Administrator\n\n",
        "P.S. You'll receive a message like this every Monday if you have extremely old emails -- they really slow down your mailbox!",
        "Want to clean up now? Try deleting some of these messages: https://mail.google.com/a/%s/#search/%s\n" % (GA_DOMAIN, urllib.quote_plus('before:%s' % suggest_date))
    ]

    body = '\n'.join(body)

    message = 'From: %s\nTo: %s\nSubject: %s\n\n%s' % (user_email, user_email, subject, body)
    encoded_message = base64.urlsafe_b64encode(message)
    params = {'userId': user_email, 'body': {'raw': encoded_message}}

    try:
        sent_message = retry(gmail_service.users().messages().send(**params).execute)()
        OUTPUT_BUFFER.write('Sent message, ID: %s' % sent_message['id'])
    except errors.HttpError, error:
        logging.error('An error occurred: %s' % error)

def run(send_mail=False, retention_period_in_days=RETENTION_DAYS):
    """
    Look up users, and email a warning if they have super old emails.
    """
    OUTPUT_BUFFER.clear()
    # There's a "warning" period of "hey, this will get deleted"
    # And a "suggest" period of "why not clean out this other old stuff, too?"
    date_before = date.today() - timedelta(days=(retention_period_in_days - 97))  # Subtract 30 for a warning period
    suggest_before = date.today() - timedelta(days=(retention_period_in_days - (365 * 2)))  # Subtract 365*2 for a suggestion email period
    date_string_before = date_before.strftime('%Y/%m/%d')
    suggest_string_before = suggest_before.strftime('%Y/%m/%d')

    directory_service = getDirectoryService(ADMIN_TO_IMPERSONATE)
    all_users = getAllUsers(directory_service)

    OUTPUT_BUFFER.write('Retention set to: %d days' % (retention_period_in_days))
    OUTPUT_BUFFER.write('Before string is: %s' % (date_string_before))
    OUTPUT_BUFFER.write('Sending mail: %s' % (send_mail and CAN_SEND_MAIL))

    OUTPUT_BUFFER.write('Looping over users...\n')
    for email, firstName in all_users.iteritems():
        gmail_service = getGmailService(email)

        params = {'userId': email, 'q': 'before:%s' % date_string_before}

        one_page = retry(gmail_service.users().threads().list(**params).execute)()

        size_estimate = one_page['resultSizeEstimate']
        if 'threads' in one_page:
            size_estimate = max(size_estimate, len(one_page['threads']))

        if size_estimate > 0:
            OUTPUT_BUFFER.write('User: %s (%s)' % (email, size_estimate))

            # Cap size to 10
            one_page['threads'] = one_page['threads'][:10]

            thread_params = {'userId': email, 'format': 'metadata',
                             'fields': 'messages/payload/headers', 'metadataHeaders': 'subject'}

            subject_list = []
            for thread in one_page['threads']:
                thread_params['id'] = thread['id']
                one_thread = retry(gmail_service.users().threads().get(**thread_params).execute)()
                first_subject = one_thread['messages'][0]['payload']['headers'][0]['value']
                safer_subject = first_subject.encode('ascii', 'ignore')
                if safer_subject is not "":
                    subject_list.append(safer_subject)
                    OUTPUT_BUFFER.write('\t' + safer_subject)

            if send_mail and CAN_SEND_MAIL:
                sendWarningMessage(gmail_service, retention_period_in_days, email, firstName, size_estimate,
                                   '\n> '.join(subject_list), date_string_before, suggest_string_before)
            OUTPUT_BUFFER.write('')

    OUTPUT_BUFFER.write('Done.')
    return OUTPUT_BUFFER.buffer

if __name__ == "__main__":
    OUTPUT_BUFFER.write('Running...')
    run(send_mail=True)
    OUTPUT_BUFFER.write('Done.')
<commit_msg>A temporarily more aggressive window.<commit_after>#!/usr/bin/env python

import base64
import logging
import os
import httplib2
import configparser
import time
import urllib
from datetime import date, timedelta
from functools import wraps

from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import SignedJwtAssertionCredentials

# Fix 'six' import errors in OS X
import platform
if platform.system() == "Darwin":
    import sys
    sys.path.insert(1, '/Library/Python/2.7/site-packages')

# Print logging to console
# logging.getLogger().setLevel(logging.INFO)

RUNNING_ON_GAE = 'SERVER_SOFTWARE' in os.environ

# Load our configuration
THIS_PATH = os.path.dirname(os.path.realpath(__file__))

_CONFIG = configparser.ConfigParser()
_CONFIG.read(THIS_PATH + "/secrets.cfg")

GA_DOMAIN = _CONFIG.get('google', 'domain')
SERVICE_ACCOUNT = _CONFIG.get('google', 'serviceAccount')
SERVICE_ACCOUNT_KEY = _CONFIG.get('google', 'serviceAccountKey')
ADMIN_TO_IMPERSONATE = _CONFIG.get('google', 'adminToImpersonate')
GA_BLACKLISTED_USERS = _CONFIG.get('google', 'blacklistedUsers')
GA_SKIP_USERS = _CONFIG.get('google', 'skipUsers')
RETENTION_DAYS = _CONFIG.getint('google', 'retentionPeriodInDays')
CAN_SEND_MAIL = _CONFIG.getboolean('google', 'canSendMail')

# Grab the service account .pem or .p12 private key
with open(THIS_PATH + "/" + SERVICE_ACCOUNT_KEY, 'rb') as f:
    SERVICE_SECRET_KEY = f.read()

# Bare-bones (one value) handling of pretty output for CRON vs GAE
class gae_print_handler():
    def __init__(self):
        self.buffer = []

    def write(self, message):
        if RUNNING_ON_GAE:
            self.buffer.append(message)
        else:
            print(message)

    def clear(self):
        self.buffer = []

OUTPUT_BUFFER = gae_print_handler()

# Retry decorator
# Adapted from http://googleadsdeveloper.blogspot.com/2014/09/decorating-your-python-dfp-api.html
def retry(func):
    @wraps(func)
    def function_to_retry(*args, **kwargs):
        tries = 4
        delay = 1
        while tries > 1:
            try:
                return func(*args, **kwargs)
            except Exception, e:
                print('%s, Retrying in %d seconds...' % (str(e), delay))
                time.sleep(delay)
                tries -= 1
                delay *= 2
        return func(*args, **kwargs)
    return function_to_retry

def getDirectoryService(user_to_impersonate):
    """Build and returns a Directory service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user.
    Returns:
      Directory service object.
    """
    assert(user_to_impersonate.endswith(GA_DOMAIN))
    assert(user_to_impersonate not in GA_BLACKLISTED_USERS)

    credentials = SignedJwtAssertionCredentials(
        SERVICE_ACCOUNT,
        SERVICE_SECRET_KEY,
        sub=user_to_impersonate,
        scope=['https://www.googleapis.com/auth/admin.directory.user.readonly']
    )

    http = httplib2.Http()
    http = credentials.authorize(http)

    return build('admin', 'directory_v1', http=http)

def getGmailService(user_to_impersonate):
    """Build and returns a Gmail service object authorized with the service accounts
    that act on behalf of the given user.

    Args:
      user_email: The email of the user.
    Returns:
      Gmail service object.
    """
    assert(user_to_impersonate.endswith(GA_DOMAIN))
    assert(user_to_impersonate not in GA_BLACKLISTED_USERS)

    credentials = SignedJwtAssertionCredentials(
        SERVICE_ACCOUNT,
        SERVICE_SECRET_KEY,
        sub=user_to_impersonate,
        scope=['https://www.googleapis.com/auth/gmail.readonly',
               'https://www.googleapis.com/auth/gmail.compose']
    )

    http = httplib2.Http()
    http = credentials.authorize(http)

    return build('gmail', 'v1', http=http)

def getAllUsers(directory_service):
    """
    Get a list of all users on the domain

    Via API manual at https://developers.google.com/admin-sdk/directory/v1/reference/#Users

    :param directory_service: A directory service object
    :return: A dictionary of {primaryEmail: givenName}
    """
    OUTPUT_BUFFER.write('Listing all users at %s' % (GA_DOMAIN))
    all_users = []
    page_token = None
    params = {'domain': GA_DOMAIN, 'viewType': 'domain_public'}

    while True:
        try:
            if page_token:
                params['pageToken'] = page_token
            current_page = retry(directory_service.users().list(**params).execute)()

            all_users.extend(current_page['users'])
            page_token = current_page.get('nextPageToken')
            if not page_token:
                break
        except errors.HttpError as error:
            logging.error('An error occurred: %s' % error)
            break

    email_and_name = {}
    for user in all_users:
        if str(user['primaryEmail']) not in GA_SKIP_USERS:
            email_and_name[user['primaryEmail']] = user['name']['givenName']
        else:
            OUTPUT_BUFFER.write('Skipped user: %s' % (user['primaryEmail']))

    OUTPUT_BUFFER.write('Found %d users in domain.' % (len(email_and_name)))
    return email_and_name

def sendWarningMessage(gmail_service, retention_period_in_days, user_email, user_name,
                       message_count, subjects, before_date, suggest_date):
    """
    Send a warning email to a user who has mail that may be deleted.
    """
    # TODO: Clean up this mess.
    logging.debug('Sending message to %s' % user_email)
    subject = "[%s] Warning: Some very old emails will be trashed" % (user_name)

    body = [
        "Your email address (%s) is set to keep messages for %s days (%.4g years).\n" % (user_email, retention_period_in_days, retention_period_in_days / float(365)),
        "You have at least %s messages from before %s that will be trashed over the next month.\n" % (message_count, before_date),
        "Some of the ancient emails to be removed include:\n\n> %s\n\n" % (subjects),
        "You can see the full list of messages at: https://mail.google.com/a/%s/#search/%s\n" % (GA_DOMAIN, urllib.quote_plus('before:%s' % before_date)),
        "Thanks,", "Domain Administrator\n\n",
        "P.S. You'll receive a message like this every Monday if you have extremely old emails -- they really slow down your mailbox!",
        "Want to clean up now? Try deleting some of these messages: https://mail.google.com/a/%s/#search/%s\n" % (GA_DOMAIN, urllib.quote_plus('before:%s' % suggest_date))
    ]

    body = '\n'.join(body)

    message = 'From: %s\nTo: %s\nSubject: %s\n\n%s' % (user_email, user_email, subject, body)
    encoded_message = base64.urlsafe_b64encode(message)
    params = {'userId': user_email, 'body': {'raw': encoded_message}}

    try:
        sent_message = retry(gmail_service.users().messages().send(**params).execute)()
        OUTPUT_BUFFER.write('Sent message, ID: %s' % sent_message['id'])
    except errors.HttpError, error:
        logging.error('An error occurred: %s' % error)

def run(send_mail=False, retention_period_in_days=RETENTION_DAYS):
    """
    Look up users, and email a warning if they have super old emails.
    """
    OUTPUT_BUFFER.clear()
    # There's a "warning" period of "hey, this will get deleted"
    # And a "suggest" period of "why not clean out this other old stuff, too?"
    warn_window = 187  # Subtract this for a warning period
    date_before = date.today() - timedelta(days=(retention_period_in_days - warn_window))  # e.g. subtract 30 d.
    suggest_before = date.today() - timedelta(days=(retention_period_in_days - (365 * 2)))  # Subtract 365*2 for a suggestion email period
    date_string_before = date_before.strftime('%Y/%m/%d')
    suggest_string_before = suggest_before.strftime('%Y/%m/%d')

    directory_service = getDirectoryService(ADMIN_TO_IMPERSONATE)
    all_users = getAllUsers(directory_service)

    OUTPUT_BUFFER.write('Retention set to: %d days' % (retention_period_in_days))
    OUTPUT_BUFFER.write('Before string is: %d days (%s)' % (warn_window, date_string_before))
    OUTPUT_BUFFER.write('Sending mail: %s' % (send_mail and CAN_SEND_MAIL))

    OUTPUT_BUFFER.write('Looping over users...\n')
    for email, firstName in all_users.iteritems():
        gmail_service = getGmailService(email)

        params = {'userId': email, 'q': 'before:%s' % date_string_before}

        one_page = retry(gmail_service.users().threads().list(**params).execute)()

        size_estimate = one_page['resultSizeEstimate']
        if 'threads' in one_page:
            size_estimate = max(size_estimate, len(one_page['threads']))

        if size_estimate > 0:
            OUTPUT_BUFFER.write('User: %s (%s)' % (email, size_estimate))

            # Cap size to 10
            one_page['threads'] = one_page['threads'][:10]

            thread_params = {'userId': email, 'format': 'metadata',
                             'fields': 'messages/payload/headers', 'metadataHeaders': 'subject'}

            subject_list = []
            for thread in one_page['threads']:
                thread_params['id'] = thread['id']
                one_thread = retry(gmail_service.users().threads().get(**thread_params).execute)()
                first_subject = one_thread['messages'][0]['payload']['headers'][0]['value']
                safer_subject = first_subject.encode('ascii', 'ignore')
                if safer_subject is not "":
                    subject_list.append(safer_subject)
                    OUTPUT_BUFFER.write('\t' + safer_subject)

            if send_mail and CAN_SEND_MAIL:
                sendWarningMessage(gmail_service, retention_period_in_days, email, firstName, size_estimate,
                                   '\n> '.join(subject_list), date_string_before, suggest_string_before)
            OUTPUT_BUFFER.write('')

    OUTPUT_BUFFER.write('Done.')
    return OUTPUT_BUFFER.buffer

if __name__ == "__main__":
    OUTPUT_BUFFER.write('Running...')
    run(send_mail=True)
    OUTPUT_BUFFER.write('Done.')
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
===========================
Benchmark plots
===========================

M. Mosteiro Romero  script development          31.08.16

"""
from __future__ import division

import os

import matplotlib.pyplot as plt
import pandas as pd
from geopandas import GeoDataFrame as gpdf

from cea import inputlocator

__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"

def benchmark(locator_list, output_file):
    """
    Algorithm to print graphs in PDF concerning the 2000 Watt society benchmark for different scenarios.

    Parameters
    ----------
    :param locator: a list of InputLocator instances set to each scenario to be computed. The first element in
    the array is always considered as the baseline for the comparison.
    :type locator: list
    :param output_file: the filename (pdf) to save the results as.
    :type output_file: str

    Side effects
    -------
    The following file is created by this script:
    - ouput_file: .pdf
        Plot of the embodied and operational emissions and primary energy demand
    """

    # setup: the labels and colors for the graphs are defined
    color_palette = ['g', 'r', 'y', 'c', 'b', 'm', 'k']
    legend = []
    graphs = ['embodied', 'operation', 'mobility', 'total']
    old_fields = ['nre_pen_GJ', 'ghg_ton', 'nre_pen_MJm2', 'ghg_kgm2']
    old_prefix = ['E_', 'O_', 'M_']
    fields = ['_GJ', '_ton', '_MJm2', '_kgm2']
    new_cols = {}
    # prepare a dictionary to contain the results for the maximum primary energy demand and emissions in the comparison
    # these are later used to set the scale of the axes of the plots
    scenario_max = {}
    for i in range(4):
        for j in range(3):
            new_cols[old_prefix[j] + old_fields[i]] = graphs[j] + fields[i]
        scenario_max[graphs[i] + fields[2]] = scenario_max[graphs[i] + fields[3]] = 0

    # calculate target values based on the baseline case
    targets = calc_benchmark_targets(locator_list[0])
    # calculate current values based on the baseline case
    values_today = calc_benchmark_today(locator_list[0])

    # start graphs
    fig, (ax1, ax2, ax3, ax4, ax5, ax6) = plt.subplots(6, figsize=(16, 12))
    fig.text(0.07, 0.5, 'Greenhouse Gas Emissions [kg CO$_2$-eq/m$^2$-yr]', va='center', rotation='vertical')
    fig.text(0.375, 0.04, 'Non-Renewable Primary Energy Demand [MJ/m$^2$-yr]', ha='center')
    ax3.axis('off')
    ax6.axis('off')
    axes = [1, 2, 4, 5]

    # run for each locator (i.e., for each scenario)
    for n in range(len(locator_list)):
        locator = locator_list[n]
        scenario_name = os.path.basename(locator.scenario_path)

        # get embodied and operation PEN and GHG for each building from CSV files
        demand = pd.read_csv(locator.get_total_demand())
        df_buildings = pd.read_csv(locator.get_lca_embodied()).merge\
            (pd.read_csv(locator.get_lca_operation()),on = 'Name').merge\
            (pd.read_csv(locator.get_lca_mobility()),on = 'Name')
        df_buildings = df_buildings.rename(columns=new_cols)

        for i in range(4):
            col_list = [graphs[0] + fields[i], graphs[1] + fields[i], graphs[2] + fields[i]]
            df_buildings[graphs[3] + fields[i]] = df_buildings[col_list].sum(axis=1)

        # calculate total results for entire scenario
        df_scenario = df_buildings.drop('Name',axis=1).sum(axis=0)
        for graph in graphs:
            for j in range(2):
                df_scenario[graph + fields[j+2]] = df_scenario[graph + fields[j]] / df_scenario['GFA_m2'] * 1000
                if scenario_max[graph + fields[j+2]] < df_scenario[graph + fields[j+2]]:
                    scenario_max[graph + fields[j+2]] = df_scenario[graph + fields[j+2]]

        # plot scenario results
        for i in range(len(graphs)):
            plt.subplot(2, 3, axes[i])
            plt.plot(df_buildings[graphs[i]+fields[2]], df_buildings[graphs[i]+fields[3]],'o', color = color_palette[n])
            plt.plot(df_scenario[graphs[i]+fields[2]], df_scenario[graphs[i]+fields[3]], 'o', color = color_palette[n],
                     markersize = 15)
        legend.extend([scenario_name, scenario_name+' total'])

    # complete graphs
    plt.plot()
    for i in range(len(graphs)):
        # plot today and target values
        plt.subplot(2, 3, axes[i])
        plt.plot([0,targets[graphs[i] + fields[2]],targets[graphs[i] + fields[2]]],
                 [targets[graphs[i] + fields[3]],targets[graphs[i] + fields[3]],0], color='k')
        plt.plot([0, values_today[graphs[i] + fields[2]], values_today[graphs[i] + fields[2]]],
                 [values_today[graphs[i] + fields[3]], values_today[graphs[i] + fields[3]], 0], '--', color='k')
        # set axis limits
        if values_today[graphs[i] + fields[2]] > df_scenario[graphs[i] + fields[2]]:
            plt.axis([0, values_today[graphs[i] + fields[2]] * 1.2, 0, values_today[graphs[i] + fields[3]] * 1.2])
        else:
            plt.axis([0, scenario_max[graphs[i] + fields[2]] * 1.2, 0, values_today[graphs[i] + fields[3]] *
                      scenario_max[graphs[i] + fields[2]] / values_today[graphs[i] + fields[2]] * 1.2 ])
        # plot title
        plt.title(graphs[i])

    legend.extend(['Benchmark targets','Present day values'])
    legend_y = 1.2 + 0.05 * (len(locator_list) - 2)
    plt.legend(legend, bbox_to_anchor=(1.3, legend_y , 0.8, 0.102), loc=0, ncol=1 , mode="expand", borderaxespad=0,numpoints=1)

    # save to disk
    plt.savefig(output_file)
    plt.clf()
    plt.close()

def calc_benchmark_targets(locator):
    '''
    This function calculates the embodied, operation, mobility and total targets (ghg_kgm2 and pen_MJm2) for all
    buildings in a scenario.

    The target values for the Swiss case for each type of occupancy are based on the following sources:
        -   Swiss Society of Engineers and Architects (SIA), "SIA Efficiency Path 2040" (2011):
            'MULTI_RES', 'SINGLE_RES', 'SCHOOL', 'OFFICE'
        -   Kellenberger, D. et al. "Arealentwicklung fur die 2000-Watt gesellschaft: Leitfaden und Fallbeispiele" (2012):
            'HOTEL', 'RETAIL', 'FOODSTORE', 'RESTAURANT'
        -   Calculated based on "SIA Effizienzpfad: Bestimmung der Ziel- und Richtwerte mit dem Top-Down Approach" (2010):
            'HOSPITAL', 'INDUSTRY'
    Due to lack of sources, the following target values are, as of yet, undefined:
        'GYM', 'SWIMMING', 'SERVERROOM', 'COOLROOM'

    Parameters
    ----------
    :param locator: an InputLocator instance set to the scenario to compute
    :type locator: InputLocator

    Return
    ------
    :returns target: dict containing pen_MJm2 and ghg_kgm2 target values
    :rtype target: dict
    '''

    # local files
    demand = pd.read_csv(locator.get_total_demand())
    prop_occupancy = gpdf.from_file(locator.get_building_occupancy()).drop('geometry', axis=1)
    data_benchmark = locator.get_data_benchmark()
    occupancy = prop_occupancy.merge(demand,on='Name')

    categories = ['embodied', 'operation', 'mobility', 'total']
    suffix = ['_GJ', '_ton','_MJm2', '_kgm2']
    targets = {}
    area_study = 0

    factors = pd.read_excel(data_benchmark, sheetname=categories[0])
    for i in range(len(factors['code'])):
        if factors['code'][i] in occupancy:
            if factors['PEN'][i] > 0 and factors['CO2'][i] > 0:
                area_study += (occupancy['GFA_m2'] * occupancy[factors['code'][i]]).sum()

    for category in categories:
        factors = pd.read_excel(data_benchmark, sheetname = category)
        vt = factors['code']
        pt = factors['PEN']
        gt = factors['CO2']

        for j in range(len(suffix)):
            targets[category + suffix[j]] = 0
        for i in range(len(vt)):
            targets[category+suffix[0]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * pt[i]).sum() / 1000
            targets[category+suffix[1]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * gt[i]).sum() / 1000
        targets[category + suffix[2]] += targets[category+suffix[0]] / area_study * 1000
        targets[category + suffix[3]] += targets[category + suffix[1]] / area_study * 1000

    return targets

def calc_benchmark_today(locator):
    '''
    This function calculates the embodied, operation, mobility and total targets (ghg_kgm2 and pen_MJm2)
    for the area for the current national trend.

    The current values for the Swiss case for each type of occupancy are based on the following sources:
        -   Swiss Society of Engineers and Architects (SIA), "SIA Efficiency Path 2040" (2011):
            'MULTI_RES', 'SINGLE_RES', 'SCHOOL', 'OFFICE'
        -   Kellenberger, D. et al. "Arealentwicklung fur die 2000-Watt gesellschaft: Leitfaden und Fallbeispiele" (2012):
            'HOTEL', 'RETAIL', 'FOODSTORE', 'RESTAURANT'
        -   Calculated based on "SIA Effizienzpfad: Bestimmung der Ziel- und Richtwerte mit dem Top-Down Approach" (2010):
            'HOSPITAL', 'INDUSTRY'
    Due to lack of sources, the following target values are, as of yet, undefined:
        'GYM', 'SWIMMING', 'SERVERROOM', 'COOLROOM'

    Parameters
    ----------
    :param locator: an InputLocator instance set to the scenario to compute
    :type locator: InputLocator

    Return
    ------
    :returns target: dict containing pen_MJm2 and ghg_kgm2 target values
    :rtype target: dict
    '''

    # local files
    demand = pd.read_csv(locator.get_total_demand())
    prop_occupancy = gpdf.from_file(locator.get_building_occupancy()).drop('geometry', axis=1)
    data_benchmark_today = locator.get_data_benchmark_today()
    occupancy = prop_occupancy.merge(demand, on='Name')

    fields = ['Name', 'pen_GJ', 'ghg_ton', 'pen_MJm2', 'ghg_kgm2']
    categories = ['embodied', 'operation', 'mobility', 'total']
    suffix = ['_GJ', '_ton', '_MJm2', '_kgm2']
    values_today = {}
    area_study = 0

    factors = pd.read_excel(data_benchmark_today, sheetname=categories[0])
    for i in range(len(factors['code'])):
        if factors['code'][i] in occupancy:
            if factors['PEN'][i] > 0 and factors['CO2'][i] > 0:
                area_study += (occupancy['GFA_m2'] * occupancy[factors['code'][i]]).sum()

    for category in categories:
        factors = pd.read_excel(data_benchmark_today, sheetname=category)
        vt = factors['code']
        pt = factors['PEN']
        gt = factors['CO2']

        for j in range(len(suffix)):
            values_today[category + suffix[j]] = 0
        for i in range(len(vt)):
            values_today[category + suffix[0]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * pt[i]).sum() / 1000
            values_today[category + suffix[1]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * gt[i]).sum() / 1000
        values_today[category + suffix[2]] += values_today[category + suffix[0]] / area_study * 1000
        values_today[category + suffix[3]] += values_today[category + suffix[1]] / area_study * 1000

    return values_today

def test_benchmark():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case-zug\baseline')
    locator_list = [locator, locator, locator, locator]
    output_file = os.path.expandvars(r'%TEMP%\test_benchmark.pdf')
    benchmark(locator_list=locator_list, output_file=output_file)
    print 'test_benchmark() succeeded'

def test_benchmark_targets():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case-zug\baseline')
    calc_benchmark_targets(locator)

if __name__ == '__main__':
    test_benchmark()

<commit_msg>Author credit<commit_after># -*- coding: utf-8 -*-
"""
===========================
Benchmark plots
===========================

M. Mosteiro Romero  script development          31.08.16

"""
from __future__ import division

import os

import matplotlib.pyplot as plt
import pandas as pd
from geopandas import GeoDataFrame as gpdf

from cea import inputlocator

__author__ = "Martin Mosteiro Romero"
__copyright__ = "Copyright 2016, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Martin Mosteiro Romero"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"

def benchmark(locator_list, output_file):
    """
    Algorithm to print graphs in PDF concerning the 2000 Watt society benchmark for different scenarios.

    Parameters
    ----------
    :param locator: a list of InputLocator instances set to each scenario to be computed. The first element in
    the array is always considered as the baseline for the comparison.
    :type locator: list
    :param output_file: the filename (pdf) to save the results as.
    :type output_file: str

    Side effects
    -------
    The following file is created by this script:
    - ouput_file: .pdf
        Plot of the embodied and operational emissions and primary energy demand
    """

    # setup: the labels and colors for the graphs are defined
    color_palette = ['g', 'r', 'y', 'c', 'b', 'm', 'k']
    legend = []
    graphs = ['embodied', 'operation', 'mobility', 'total']
    old_fields = ['nre_pen_GJ', 'ghg_ton', 'nre_pen_MJm2', 'ghg_kgm2']
    old_prefix = ['E_', 'O_', 'M_']
    fields = ['_GJ', '_ton', '_MJm2', '_kgm2']
    new_cols = {}
    # prepare a dictionary to contain the results for the maximum primary energy demand and emissions in the comparison
    # these are later used to set the scale of the axes of the plots
    scenario_max = {}
    for i in range(4):
        for j in range(3):
            new_cols[old_prefix[j] + old_fields[i]] = graphs[j] + fields[i]
        scenario_max[graphs[i] + fields[2]] = scenario_max[graphs[i] + fields[3]] = 0

    # calculate target values based on the baseline case
    targets = calc_benchmark_targets(locator_list[0])
    # calculate current values based on the baseline case
    values_today = calc_benchmark_today(locator_list[0])

    # start graphs
    fig, (ax1, ax2, ax3, ax4, ax5, ax6) = plt.subplots(6, figsize=(16, 12))
    fig.text(0.07, 0.5, 'Greenhouse Gas Emissions [kg CO$_2$-eq/m$^2$-yr]', va='center', rotation='vertical')
    fig.text(0.375, 0.04, 'Non-Renewable Primary Energy Demand [MJ/m$^2$-yr]', ha='center')
    ax3.axis('off')
    ax6.axis('off')
    axes = [1, 2, 4, 5]

    # run for each locator (i.e., for each scenario)
    for n in range(len(locator_list)):
        locator = locator_list[n]
        scenario_name = os.path.basename(locator.scenario_path)

        # get embodied and operation PEN and GHG for each building from CSV files
        demand = pd.read_csv(locator.get_total_demand())
        df_buildings = pd.read_csv(locator.get_lca_embodied()).merge\
            (pd.read_csv(locator.get_lca_operation()),on = 'Name').merge\
            (pd.read_csv(locator.get_lca_mobility()),on = 'Name')
        df_buildings = df_buildings.rename(columns=new_cols)

        for i in range(4):
            col_list = [graphs[0] + fields[i], graphs[1] + fields[i], graphs[2] + fields[i]]
            df_buildings[graphs[3] + fields[i]] = df_buildings[col_list].sum(axis=1)

        # calculate total results for entire scenario
        df_scenario = df_buildings.drop('Name',axis=1).sum(axis=0)
        for graph in graphs:
            for j in range(2):
                df_scenario[graph + fields[j+2]] = df_scenario[graph + fields[j]] / df_scenario['GFA_m2'] * 1000
                if scenario_max[graph + fields[j+2]] < df_scenario[graph + fields[j+2]]:
                    scenario_max[graph + fields[j+2]] = df_scenario[graph + fields[j+2]]

        # plot scenario results
        for i in range(len(graphs)):
            plt.subplot(2, 3, axes[i])
            plt.plot(df_buildings[graphs[i]+fields[2]], df_buildings[graphs[i]+fields[3]],'o', color = color_palette[n])
            plt.plot(df_scenario[graphs[i]+fields[2]], df_scenario[graphs[i]+fields[3]], 'o', color = color_palette[n],
                     markersize = 15)
        legend.extend([scenario_name, scenario_name+' total'])

    # complete graphs
    plt.plot()
    for i in range(len(graphs)):
        # plot today and target values
        plt.subplot(2, 3, axes[i])
        plt.plot([0,targets[graphs[i] + fields[2]],targets[graphs[i] + fields[2]]],
                 [targets[graphs[i] + fields[3]],targets[graphs[i] + fields[3]],0], color='k')
        plt.plot([0, values_today[graphs[i] + fields[2]], values_today[graphs[i] + fields[2]]],
                 [values_today[graphs[i] + fields[3]], values_today[graphs[i] + fields[3]], 0], '--', color='k')
        # set axis limits
        if values_today[graphs[i] + fields[2]] > df_scenario[graphs[i] + fields[2]]:
            plt.axis([0, values_today[graphs[i] + fields[2]] * 1.2, 0, values_today[graphs[i] + fields[3]] * 1.2])
        else:
            plt.axis([0, scenario_max[graphs[i] + fields[2]] * 1.2, 0, values_today[graphs[i] + fields[3]] *
                      scenario_max[graphs[i] + fields[2]] / values_today[graphs[i] + fields[2]] * 1.2 ])
        # plot title
        plt.title(graphs[i])

    legend.extend(['Benchmark targets','Present day values'])
    legend_y = 1.2 + 0.05 * (len(locator_list) - 2)
    plt.legend(legend, bbox_to_anchor=(1.3, legend_y , 0.8, 0.102), loc=0, ncol=1 , mode="expand", borderaxespad=0,numpoints=1)

    # save to disk
    plt.savefig(output_file)
    plt.clf()
    plt.close()

def calc_benchmark_targets(locator):
    '''
    This function calculates the embodied, operation, mobility and total targets (ghg_kgm2 and pen_MJm2) for all
    buildings in a scenario.

    The target values for the Swiss case for each type of occupancy are based on the following sources:
        -   Swiss Society of Engineers and Architects (SIA), "SIA Efficiency Path 2040" (2011):
            'MULTI_RES', 'SINGLE_RES', 'SCHOOL', 'OFFICE'
        -   Kellenberger, D. et al. "Arealentwicklung fur die 2000-Watt gesellschaft: Leitfaden und Fallbeispiele" (2012):
            'HOTEL', 'RETAIL', 'FOODSTORE', 'RESTAURANT'
        -   Calculated based on "SIA Effizienzpfad: Bestimmung der Ziel- und Richtwerte mit dem Top-Down Approach" (2010):
            'HOSPITAL', 'INDUSTRY'
    Due to lack of sources, the following target values are, as of yet, undefined:
        'GYM', 'SWIMMING', 'SERVERROOM', 'COOLROOM'

    Parameters
    ----------
    :param locator: an InputLocator instance set to the scenario to compute
    :type locator: InputLocator

    Return
    ------
    :returns target: dict containing pen_MJm2 and ghg_kgm2 target values
    :rtype target: dict
    '''

    # local files
    demand = pd.read_csv(locator.get_total_demand())
    prop_occupancy = gpdf.from_file(locator.get_building_occupancy()).drop('geometry', axis=1)
    data_benchmark = locator.get_data_benchmark()
    occupancy = prop_occupancy.merge(demand,on='Name')

    categories = ['embodied', 'operation', 'mobility', 'total']
    suffix = ['_GJ', '_ton','_MJm2', '_kgm2']
    targets = {}
    area_study = 0

    factors = pd.read_excel(data_benchmark, sheetname=categories[0])
    for i in range(len(factors['code'])):
        if factors['code'][i] in occupancy:
            if factors['PEN'][i] > 0 and factors['CO2'][i] > 0:
                area_study += (occupancy['GFA_m2'] * occupancy[factors['code'][i]]).sum()

    for category in categories:
        factors = pd.read_excel(data_benchmark, sheetname = category)
        vt = factors['code']
        pt = factors['PEN']
        gt = factors['CO2']

        for j in range(len(suffix)):
            targets[category + suffix[j]] = 0
        for i in range(len(vt)):
            targets[category+suffix[0]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * pt[i]).sum() / 1000
            targets[category+suffix[1]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * gt[i]).sum() / 1000
        targets[category + suffix[2]] += targets[category+suffix[0]] / area_study * 1000
        targets[category + suffix[3]] += targets[category + suffix[1]] / area_study * 1000

    return targets

def calc_benchmark_today(locator):
    '''
    This function calculates the embodied, operation, mobility and total targets (ghg_kgm2 and pen_MJm2)
    for the area for the current national trend.

    The current values for the Swiss case for each type of occupancy are based on the following sources:
        -   Swiss Society of Engineers and Architects (SIA), "SIA Efficiency Path 2040" (2011):
            'MULTI_RES', 'SINGLE_RES', 'SCHOOL', 'OFFICE'
        -   Kellenberger, D. et al. "Arealentwicklung fur die 2000-Watt gesellschaft: Leitfaden und Fallbeispiele" (2012):
            'HOTEL', 'RETAIL', 'FOODSTORE', 'RESTAURANT'
        -   Calculated based on "SIA Effizienzpfad: Bestimmung der Ziel- und Richtwerte mit dem Top-Down Approach" (2010):
            'HOSPITAL', 'INDUSTRY'
    Due to lack of sources, the following target values are, as of yet, undefined:
        'GYM', 'SWIMMING', 'SERVERROOM', 'COOLROOM'

    Parameters
    ----------
    :param locator: an InputLocator instance set to the scenario to compute
    :type locator: InputLocator

    Return
    ------
    :returns target: dict containing pen_MJm2 and ghg_kgm2 target values
    :rtype target: dict
    '''

    # local files
    demand = pd.read_csv(locator.get_total_demand())
    prop_occupancy = gpdf.from_file(locator.get_building_occupancy()).drop('geometry', axis=1)
    data_benchmark_today = locator.get_data_benchmark_today()
    occupancy = prop_occupancy.merge(demand, on='Name')

    fields = ['Name', 'pen_GJ', 'ghg_ton', 'pen_MJm2', 'ghg_kgm2']
    categories = ['embodied', 'operation', 'mobility', 'total']
    suffix = ['_GJ', '_ton', '_MJm2', '_kgm2']
    values_today = {}
    area_study = 0

    factors = pd.read_excel(data_benchmark_today, sheetname=categories[0])
    for i in range(len(factors['code'])):
        if factors['code'][i] in occupancy:
            if factors['PEN'][i] > 0 and factors['CO2'][i] > 0:
                area_study += (occupancy['GFA_m2'] * occupancy[factors['code'][i]]).sum()

    for category in categories:
        factors = pd.read_excel(data_benchmark_today, sheetname=category)
        vt = factors['code']
        pt = factors['PEN']
        gt = factors['CO2']

        for j in range(len(suffix)):
            values_today[category + suffix[j]] = 0
        for i in range(len(vt)):
            values_today[category + suffix[0]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * pt[i]).sum() / 1000
            values_today[category + suffix[1]] += (occupancy['GFA_m2'] * occupancy[vt[i]] * gt[i]).sum() / 1000
        values_today[category + suffix[2]] += values_today[category + suffix[0]] / area_study * 1000
        values_today[category + suffix[3]] += values_today[category + suffix[1]] / area_study * 1000

    return values_today

def test_benchmark():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case-zug\baseline')
    locator_list = [locator, locator, locator, locator]
    output_file = os.path.expandvars(r'%TEMP%\test_benchmark.pdf')
    benchmark(locator_list=locator_list, output_file=output_file)
    print 'test_benchmark() succeeded'

def test_benchmark_targets():
    locator = inputlocator.InputLocator(scenario_path=r'C:\reference-case-zug\baseline')
    calc_benchmark_targets(locator)

if __name__ == '__main__':
    test_benchmark()

<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst') as readme_file:
    readme = readme_file.read()

with open('HISTORY.rst') as history_file:
    history = history_file.read()

setup(
    name='django_excel_tools',
    version='0.2.3',
    description="Common function when working with excel.",
    long_description=readme + '\n\n' + history,
    author="Khemanorak Khath",
    author_email='khath.khemanorak@gmail.com',
    url='https://github.com/NorakGithub/django_excel_tools',
    packages=find_packages(include=['django_excel_tools']),
    include_package_data=True,
    license="MIT license",
    zip_safe=False,
    keywords='django, excel, tools',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        "Programming Language :: Python :: 2",
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
    ]
)
<commit_msg>Update version number to 0.2.4<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""The setup script."""

from setuptools import setup, find_packages

with open('README.rst') as readme_file:
    readme = readme_file.read()

with open('HISTORY.rst') as history_file:
    history = history_file.read()

setup(
    name='django_excel_tools',
    version='0.2.4',
    description="Common function when working with excel.",
    long_description=readme + '\n\n' + history,
    author="Khemanorak Khath",
    author_email='khath.khemanorak@gmail.com',
    url='https://github.com/NorakGithub/django_excel_tools',
    packages=find_packages(include=['django_excel_tools']),
    include_package_data=True,
    license="MIT license",
    zip_safe=False,
    keywords='django, excel, tools',
    classifiers=[
        'Development Status :: 2 - Pre-Alpha',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Natural Language :: English',
        "Programming Language :: Python :: 2",
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
    ]
)
<|endoftext|>


<commit_before>"""
This file implements the ``cea`` command line interface script. Basically, it uses the first argument passed to
it to look up a module to import in ``cli.config``, imports that and then calls the ``main`` function on that module.

The rest of the command line arguments are passed to the ``cea.config.Configuration`` object for processing.
"""

import sys
import os
import importlib
import ConfigParser
import cea.config

def main(config=None):
    if not config:
        config = cea.config.Configuration()

    cli_config = get_cli_config()

    # handle arguments
    args = sys.argv[1:]  # drop the script name from the arguments
    if not len(args) or args[0].lower() == '--help':
        print_help(config, cli_config, args[1:])
        sys.exit(1)
    script_name = args.pop(0)
    option_list = cli_config.get('config', script_name).split()
    config.apply_command_line_args(args, option_list)

    # save the updates to the configuration file (re-running the same tool will result in the
    # same parameters being set)
    config.save(cea.config.CEA_CONFIG)

    print_script_configuration(config, script_name, option_list)

    module_path = cli_config.get('scripts', script_name)
    script_module = importlib.import_module(module_path)
    script_module.main(config)

def print_script_configuration(config, script_name, option_list):
    """
    Print a list of script parameters being used for this run of the tool. Historically, each tool
    was responsible for printing their own parameters, but that requires manually keeping track of these
    parameters.
    """
    print("Running `cea %(script_name)s` with the following parameters:" % locals())
    for section, parameter in config.matching_parameters(option_list):
        section_name = section.name
        parameter_name = parameter.name
        parameter_value = parameter.get()
        print("- %(section_name)s:%(parameter_name)s = %(parameter_value)s" % locals())

def get_cli_config():
    """Return a ConfigParser object for the ``cli.config`` file used to configure the scripts known to the
    ``cea`` command line interface and the parameters accepted by each script"""

    cli_config = ConfigParser.SafeConfigParser()
    cli_config.read(os.path.join(os.path.dirname(__file__), 'cli.config'))
    return cli_config

def print_help(config, cli_config, remaining_args):
    """Print out the help message for the ``cea`` command line interface"""
    if remaining_args:
        script_name = remaining_args[0]
        try:
            module_path = cli_config.get('scripts', script_name)
            option_list = cli_config.get('config', script_name).split()
        except:
            print("Invalid value for SCRIPT.")
            print_valid_script_names(cli_config)
            return
        script_module = importlib.import_module(module_path)
        print(script_module.__doc__)
        print("")
        print("OPTIONS for %s:" % script_name)
        for _, parameter in config.matching_parameters(option_list):
            print("--%s: %s" % (parameter.name, parameter.get()))
            print("    %s" % parameter.help)
    else:
        print("usage: cea SCRIPT [OPTIONS]")
        print("       to run a specific script")
        print("usage: cea --help SCRIPT")
        print("       to get additional help specific to a script")
        print_valid_script_names(cli_config)

def print_valid_script_names(cli_config):
    import textwrap
    print("")
    print(textwrap.fill("SCRIPT can be one of: %s" % ', '.join(sorted(cli_config.options('scripts'))),
                        subsequent_indent='    ', break_on_hyphens=False))

if __name__ == '__main__':
    main(cea.config.Configuration())<commit_msg>small change to trigger the jenkins<commit_after>"""
This file implements the ``cea`` command line interface script. Basically, it uses the first argument passed to
it to look up a module to import in ``cli.config``, imports that and then calls the ``main`` function on that module.

The rest of the command line arguments are passed to the ``cea.config.Configuration`` object for processing.
"""

import sys
import os
import importlib
import ConfigParser
import cea.config

__author__ = "Daren Thomas"
__copyright__ = "Copyright 2017, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Daren Thomas"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"

def main(config=None):
    if not config:
        config = cea.config.Configuration()

    cli_config = get_cli_config()

    # handle arguments
    args = sys.argv[1:]  # drop the script name from the arguments
    if not len(args) or args[0].lower() == '--help':
        print_help(config, cli_config, args[1:])
        sys.exit(1)
    script_name = args.pop(0)
    option_list = cli_config.get('config', script_name).split()
    config.apply_command_line_args(args, option_list)

    # save the updates to the configuration file (re-running the same tool will result in the
    # same parameters being set)
    config.save(cea.config.CEA_CONFIG)

    print_script_configuration(config, script_name, option_list)

    module_path = cli_config.get('scripts', script_name)
    script_module = importlib.import_module(module_path)
    script_module.main(config)

def print_script_configuration(config, script_name, option_list):
    """
    Print a list of script parameters being used for this run of the tool. Historically, each tool
    was responsible for printing their own parameters, but that requires manually keeping track of these
    parameters.
    """
    print("Running `cea %(script_name)s` with the following parameters:" % locals())
    for section, parameter in config.matching_parameters(option_list):
        section_name = section.name
        parameter_name = parameter.name
        parameter_value = parameter.get()
        print("- %(section_name)s:%(parameter_name)s = %(parameter_value)s" % locals())

def get_cli_config():
    """Return a ConfigParser object for the ``cli.config`` file used to configure the scripts known to the
    ``cea`` command line interface and the parameters accepted by each script"""

    cli_config = ConfigParser.SafeConfigParser()
    cli_config.read(os.path.join(os.path.dirname(__file__), 'cli.config'))
    return cli_config

def print_help(config, cli_config, remaining_args):
    """Print out the help message for the ``cea`` command line interface"""
    if remaining_args:
        script_name = remaining_args[0]
        try:
            module_path = cli_config.get('scripts', script_name)
            option_list = cli_config.get('config', script_name).split()
        except:
            print("Invalid value for SCRIPT.")
            print_valid_script_names(cli_config)
            return
        script_module = importlib.import_module(module_path)
        print(script_module.__doc__)
        print("")
        print("OPTIONS for %s:" % script_name)
        for _, parameter in config.matching_parameters(option_list):
            print("--%s: %s" % (parameter.name, parameter.get()))
            print("    %s" % parameter.help)
    else:
        print("usage: cea SCRIPT [OPTIONS]")
        print("       to run a specific script")
        print("usage: cea --help SCRIPT")
        print("       to get additional help specific to a script")
        print_valid_script_names(cli_config)

def print_valid_script_names(cli_config):
    import textwrap
    print("")
    print(textwrap.fill("SCRIPT can be one of: %s" % ', '.join(sorted(cli_config.options('scripts'))),
                        subsequent_indent='    ', break_on_hyphens=False))

if __name__ == '__main__':
    main(cea.config.Configuration())<|endoftext|>


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

import os
from setuptools import find_packages, setup

setup(
    name='django-unload',
    version='0.3.3',
    url="https://github.com/Styria-Digital/django-unload",
    author='Styria Digital Services',
    description='Remove unused custom Django template tags and filters',
    long_description=open(
            os.path.join(os.path.dirname(__file__), 'README.rst')
    ).read(),
    license='MIT',
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    keywords='django template tag filter',
    install_requires=[
        'django>=1.8, <1.9',
        'tabulate==0.7.5',
    ],
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Environment :: Web Environment',
        'Framework :: Django',
        'Framework :: Django :: 1.8',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
    ],
)
<commit_msg>List extra dependencies for development and testing<commit_after>#!/usr/bin/env python

import os
from setuptools import find_packages, setup

setup(
    name='django-unload',
    version='0.3.3',
    url="https://github.com/Styria-Digital/django-unload",
    author='Styria Digital Services',
    description='Remove unused custom Django template tags and filters',
    long_description=open(
            os.path.join(os.path.dirname(__file__), 'README.rst')
    ).read(),
    license='MIT',
    packages=find_packages(),
    include_package_data=True,
    zip_safe=False,
    keywords='django template tag filter',
    install_requires=[
        'django>=1.8, <1.9',
        'tabulate==0.7.5',
    ],
    extras_require={
        'dev': [
            'autopep8==1.3.3',
            'flake8==3.4.1',
            'ipdb==0.10.3',
        ],
        'test': [
            'coverage==4.4.1',
            'pytest==3.2.3',
            'pytest-cov==2.5.1',
            'pytest-django==3.1.2',
            'pytest-runner==2.12.1',
            'pytest-sugar==0.9.0',
            'tox==2.9.1'
        ],
    },
    classifiers=[
        'Development Status :: 3 - Alpha',
        'Environment :: Web Environment',
        'Framework :: Django',
        'Framework :: Django :: 1.8',
        'Framework :: Django :: 1.11',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: MIT License',
        'Operating System :: OS Independent',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.4',
        'Programming Language :: Python :: 3.5',
        'Topic :: Internet :: WWW/HTTP :: Dynamic Content',
    ],
)
<|endoftext|>


<commit_before>"""
Tests to make sure the schemas.yml file is structurally sound.
"""

import unittest

import cea.config
import cea.inputlocator
import cea.scripts

__author__ = "Daren Thomas"
__copyright__ = "Copyright 2017, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Daren Thomas", "Jimeno A. Fonseca"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"

class TestSchemas(unittest.TestCase):

    def test_all_locator_methods_described(self):
        schemas = cea.scripts.schemas()
        config = cea.config.Configuration()
        locator = cea.inputlocator.InputLocator(config.scenario)

        for method in self.extract_locator_methods(locator):
            self.assertIn(method, schemas.keys())

        self.assertEqual(True, False)

    def extract_locator_methods(self, locator):
        """Return the list of locator methods that point to files"""
        ignore = {"ensure_parent_folder_exists"}
        for m in dir(locator):
            if not callable(getattr(locator, m)):
                # normal attributes (fields) are not locator methods
                continue
            if m.startswith("_"):
                # these are private methods, ignore
                continue
            if m in ignore:
                # keep a list of special methods to ignore
                continue
            if m.endswith("_folder"):
                # not interested in folders
                continue
            yield m

if __name__ == '__main__':
    unittest.main()
<commit_msg>Update test_schemas.py<commit_after>"""
Tests to make sure the schemas.yml file is structurally sound.
"""

import unittest

import cea.config
import cea.inputlocator
import cea.scripts

__author__ = "Daren Thomas"
__copyright__ = "Copyright 2017, Architecture and Building Systems - ETH Zurich"
__credits__ = ["Daren Thomas", "Jimeno A. Fonseca"]
__license__ = "MIT"
__version__ = "0.1"
__maintainer__ = "Daren Thomas"
__email__ = "cea@arch.ethz.ch"
__status__ = "Production"

class TestSchemas(unittest.TestCase):

    def test_all_locator_methods_described(self):
        schemas = cea.scripts.schemas()
        config = cea.config.Configuration()
        locator = cea.inputlocator.InputLocator(config.scenario)

        for method in self.extract_locator_methods(locator):
            self.assertIn(method, schemas.keys())

        self.assertEqual(True, False)

    def extract_locator_methods(self, locator):
        """Return the list of locator methods that point to files"""
        ignore = {
            "ensure_parent_folder_exists",
            "get_optimization_network_all_individuals_results_file",  # TODO: remove this when we know how
            "get_optimization_network_generation_individuals_results_file",  # TODO: remove this when we know how
            "get_optimization_network_individual_results_file",  # TODO: remove this when we know how
            "get_optimization_network_layout_costs_file",  # TODO: remove this when we know how
        }
        for m in dir(locator):
            if not callable(getattr(locator, m)):
                # normal attributes (fields) are not locator methods
                continue
            if m.startswith("_"):
                # these are private methods, ignore
                continue
            if m in ignore:
                # keep a list of special methods to ignore
                continue
            if m.endswith("_folder"):
                # not interested in folders
                continue
            yield m

if __name__ == '__main__':
    unittest.main()
<|endoftext|>


<commit_before>from setuptools import setup, find_packages
import os

here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.md')).read()
NEWS = open(os.path.join(here, 'NEWS.txt')).read()

version = '0.4'

install_requires = [
    # List your project dependencies here.
    # For more details, see:
    # http://packages.python.org/distribute/setuptools.html#declaring-dependencies
    'lxml', 'networkx'
    ]

setup(name='dgd2cmdi',
    version=version,
    description="XSLT transformation for cmdi resources of the AGD",
    long_description=README + '\n\n' + NEWS,
    classifiers=[
      # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
    ],
    keywords='xslt python xml',
    author='Florian Kuhn',
    author_email='kuhn@ids-mannheim.de',
    url='www.ids-mannheim.de',
    license='Apache v2',
    package_data={'samples': ['/samples/example_resources.yml'], 'data': ['../data/*']},
    include_package_data= True,
    packages=find_packages('src'),
    package_dir = {'': 'src'},
    zip_safe=False,
    install_requires=install_requires,
    entry_points={
        'console_scripts':
            ['dgd2cmdi = dgd2cmdi.dgd2cmdi:main',
             'dgd_trans = dgd2cmdi.dgd2cmdi_trans:main']
    }
)
<commit_msg>removed old entrypoint<commit_after>from setuptools import setup, find_packages
import os

here = os.path.abspath(os.path.dirname(__file__))
README = open(os.path.join(here, 'README.md')).read()
NEWS = open(os.path.join(here, 'NEWS.txt')).read()

version = '0.4'

install_requires = [
    # List your project dependencies here.
    # For more details, see:
    # http://packages.python.org/distribute/setuptools.html#declaring-dependencies
    'lxml', 'networkx'
    ]

setup(name='dgd2cmdi',
    version=version,
    description="XSLT transformation for cmdi resources of the AGD",
    long_description=README + '\n\n' + NEWS,
    classifiers=[
      # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
    ],
    keywords='xslt python xml',
    author='Florian Kuhn',
    author_email='kuhn@ids-mannheim.de',
    url='www.ids-mannheim.de',
    license='Apache v2',
    package_data={'samples': ['/samples/resources.yml'], 'data': ['../data/*']},
    include_package_data= True,
    packages=find_packages('src'),
    package_dir = {'': 'src'},
    zip_safe=False,
    install_requires=install_requires,
    entry_points={
        'console_scripts':
            ['dgd2cmdi = dgd2cmdi.dgd2cmdi:main'
             ]
    }
)
<|endoftext|>


<commit_before>"""Views for the ``unshorten`` app."""
import json

from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views.generic import View

from unshorten.backend import RateLimit
from unshorten.decorators import api_auth
from unshorten.utils import unshorten_url

class UnshortenAPIView(View):
    """API view to handle the unshortening."""
    @method_decorator(api_auth)
    def dispatch(self, request, *args, **kwargs):
        self.rate_limit = RateLimit(request)
        # checking if rate limit is exceeded
        if self.rate_limit.is_rate_limit_exceeded():
            raise PermissionDenied
        self.short_url = request.GET.get('url')
        return super(UnshortenAPIView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        if not self.short_url:
            return HttpResponse(json.dumps(None))

        self.rate_limit.log_api_call()
        long_url = unshorten_url(self.short_url)
        return HttpResponse(json.dumps({'long_url': long_url}))
<commit_msg>Allowed posting to API.<commit_after>"""Views for the ``unshorten`` app."""
import json

from django.core.exceptions import PermissionDenied
from django.http import HttpResponse
from django.utils.decorators import method_decorator
from django.views.generic import View

from unshorten.backend import RateLimit
from unshorten.decorators import api_auth
from unshorten.utils import unshorten_url

class UnshortenAPIView(View):
    """API view to handle the unshortening."""
    @method_decorator(api_auth)
    def dispatch(self, request, *args, **kwargs):
        self.rate_limit = RateLimit(request)
        # checking if rate limit is exceeded
        if self.rate_limit.is_rate_limit_exceeded():
            raise PermissionDenied
        self.short_url = request.GET.get('url')
        return super(UnshortenAPIView, self).dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        if not self.short_url:
            return HttpResponse(json.dumps(None))

        self.rate_limit.log_api_call()
        long_url = unshorten_url(self.short_url)
        return HttpResponse(json.dumps({'long_url': long_url}))

    def post(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)
<|endoftext|>


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

from setuptools import setup

setup(name='tap-mysql',
      version='0.4.0',
      description='Singer.io tap for extracting data from MySQL',
      author='Stitch',
      url='https://singer.io',
      classifiers=['Programming Language :: Python :: 3 :: Only'],
      py_modules=['tap_mysql'],
      install_requires=[
          'attrs==16.3.0',
          'pendulum==1.2.0',
          'singer-python==1.9.1',
          'PyMySQL==0.7.11',
      ],
      entry_points='''
          [console_scripts]
          tap-mysql=tap_mysql:main
      ''',
      packages=['tap_mysql'],
)
<commit_msg>bump version to 0.5.0<commit_after>#!/usr/bin/env python

from setuptools import setup

setup(name='tap-mysql',
      version='0.5.0',
      description='Singer.io tap for extracting data from MySQL',
      author='Stitch',
      url='https://singer.io',
      classifiers=['Programming Language :: Python :: 3 :: Only'],
      py_modules=['tap_mysql'],
      install_requires=[
          'attrs==16.3.0',
          'pendulum==1.2.0',
          'singer-python==1.9.1',
          'PyMySQL==0.7.11',
      ],
      entry_points='''
          [console_scripts]
          tap-mysql=tap_mysql:main
      ''',
      packages=['tap_mysql'],
)
<|endoftext|>


<commit_before>import os

from django.conf import settings

from .base import FunctionalTest

class PostFileUploadTest(FunctionalTest):
    def test_file_upload(self):
        self.browser.get(self.live_server_url)
        self.move_to_default_board()

        # 지훈이는 첨부파일을 추가하여 새 게시글을 작성하기 위해 글 쓰기 버튼을 누른다.
        self.click_create_post_button()

        # 글 쓰기 페이지로 이동한다.
        self.assertRegex(self.browser.current_url, '.+/default/new/')

        # 제목과 내용을 입력한다.
        titlebox = self.browser.find_element_by_id('id_post_title')
        titlebox.send_keys('Title of This Post')

        contentbox = self.get_contentbox()
        contentbox.send_keys('Content of This Post')
        self.browser.switch_to.default_content()

        # 하단에 파일을 업로드 할 수 있는 버튼을 클릭하여 파일을 추가한다.
        fileuploadbox = self.browser.find_elements_by_tag_name('input')[2]
        fileuploadbox.send_keys(os.path.join(settings.BASE_DIR, 'test_file/test.txt'))

        # 하단의 등록 버튼을 누르면 글 작성이 완료되고 게시글 목록으로 돌아간다.
        self.click_submit_button()
        self.assertRegex(self.browser.current_url, '.+/default/')

        # 첨부파일 업로드가 잘 되었는지 확인하기 위해 방금 작성한 게시글을 클릭한다.
        table = self.browser.find_element_by_id('id_post_list_table')

        rows = table.find_elements_by_css_selector('tbody > tr > td > a')
        rows[0].click()

        # 'test.txt'라는 이름의 첨부파일이 표시된다.
        uploaded_file = self.browser.find_element_by_id('id_uploaded_file')
        self.assertEqual(uploaded_file.text, 'test.txt')

        # 테스트에 사용했던 파일을 제거한다.
        saved_test_file_name = os.path.join(settings.BASE_DIR, 'file/test.txt')
        if os.path.isfile(saved_test_file_name):
            os.remove(saved_test_file_name)
<commit_msg>Move removing test file to tearDown method in FT<commit_after>import os

from django.conf import settings

from .base import FunctionalTest

class PostFileUploadTest(FunctionalTest):
    def tearDown(self):
        # 테스트에 사용했던 'test.txt'파일이 존재하면 제거한다.
        saved_test_file_name = os.path.join(settings.BASE_DIR, 'file/test.txt')
        if os.path.isfile(saved_test_file_name):
            os.remove(saved_test_file_name)
        super().tearDown()

    def test_file_upload(self):
        self.browser.get(self.live_server_url)
        self.move_to_default_board()

        # 지훈이는 첨부파일을 추가하여 새 게시글을 작성하기 위해 글 쓰기 버튼을 누른다.
        self.click_create_post_button()

        # 글 쓰기 페이지로 이동한다.
        self.assertRegex(self.browser.current_url, '.+/default/new/')

        # 제목과 내용을 입력한다.
        titlebox = self.browser.find_element_by_id('id_post_title')
        titlebox.send_keys('Title of This Post')

        contentbox = self.get_contentbox()
        contentbox.send_keys('Content of This Post')
        self.browser.switch_to.default_content()

        # 하단에 파일을 업로드 할 수 있는 버튼을 클릭하여 파일을 추가한다.
        fileuploadbox = self.browser.find_elements_by_tag_name('input')[2]
        fileuploadbox.send_keys(os.path.join(settings.BASE_DIR, 'test_file/test.txt'))

        # 하단의 등록 버튼을 누르면 글 작성이 완료되고 게시글 목록으로 돌아간다.
        self.click_submit_button()
        self.assertRegex(self.browser.current_url, '.+/default/')

        # 첨부파일 업로드가 잘 되었는지 확인하기 위해 방금 작성한 게시글을 클릭한다.
        table = self.browser.find_element_by_id('id_post_list_table')

        rows = table.find_elements_by_css_selector('tbody > tr > td > a')
        rows[0].click()

        # 'test.txt'라는 이름의 첨부파일이 표시된다.
        uploaded_file = self.browser.find_element_by_id('id_uploaded_file')
        self.assertEqual(uploaded_file.text, 'test.txt')
<|endoftext|>


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

from distutils.core import setup
import os

from mama_cas import __version__ as version

def read_file(filename):
    """
    Utility function to read a provided filename.
    """
    return open(os.path.join(os.path.dirname(__file__), filename)).read()

packages = [
    'mama_cas',
    'mama_cas.management',
    'mama_cas.management.commands',
    'mama_cas.tests'
]

package_data = {
    '': ['LICENSE', 'README.rst'],
    'mama_cas': ['templates/mama_cas/*.html', 'templates/mama_cas/*.xml']
}

setup(
    name='django-mama-cas',
    version=version,
    description='A CAS server single sign-on application for Django',
    long_description=read_file('README.rst'),
    author='Jason Bittel',
    author_email='jason.bittel@gmail.com',
    url='http://github.com/jbittel/django-mama-cas',
    download_url='http://github.com/jbittel/django-mama-cas/downloads',
    package_dir={'mama_cas': 'mama_cas'},
    packages=packages,
    package_data=package_data,
    license='BSD',
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: Web Environment',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Topic :: System :: Systems Administration :: Authentication/Directory',
        'Topic :: Software Development :: Libraries :: Python Modules',
    ],
    keywords=['django', 'cas', 'single sign-on', 'authentication', 'auth'],
    install_requires=['requests == 1.1.0'],
)
<commit_msg>Update setup URLs to HTTPS<commit_after>#!/usr/bin/env python

from distutils.core import setup
import os

from mama_cas import __version__ as version

def read_file(filename):
    """
    Utility function to read a provided filename.
    """
    return open(os.path.join(os.path.dirname(__file__), filename)).read()

packages = [
    'mama_cas',
    'mama_cas.management',
    'mama_cas.management.commands',
    'mama_cas.tests',
]

package_data = {
    '': ['LICENSE', 'README.rst'],
    'mama_cas': ['templates/mama_cas/*.html', 'templates/mama_cas/*.xml']
}

setup(
    name='django-mama-cas',
    version=version,
    description='A CAS server single sign-on application for Django',
    long_description=read_file('README.rst'),
    author='Jason Bittel',
    author_email='jason.bittel@gmail.com',
    url='https://github.com/jbittel/django-mama-cas',
    download_url='https://github.com/jbittel/django-mama-cas/downloads',
    package_dir={'mama_cas': 'mama_cas'},
    packages=packages,
    package_data=package_data,
    license='BSD',
    classifiers=[
        'Development Status :: 4 - Beta',
        'Environment :: Web Environment',
        'Programming Language :: Python',
        'Programming Language :: Python :: 2.6',
        'Programming Language :: Python :: 2.7',
        'Programming Language :: Python :: 3',
        'Programming Language :: Python :: 3.3',
        'Framework :: Django',
        'Intended Audience :: Developers',
        'License :: OSI Approved :: BSD License',
        'Operating System :: OS Independent',
        'Topic :: System :: Systems Administration :: Authentication/Directory',
        'Topic :: Software Development :: Libraries :: Python Modules',
    ],
    keywords=['django', 'cas', 'single sign-on', 'authentication', 'auth'],
    install_requires=['requests == 1.1.0'],
)
<|endoftext|>