<commit_before>from __future__ import unicode_literals

from django.conf.urls import patterns, include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin

from mezzanine.core.views import direct_to_template

admin.autodiscover()

# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.

urlpatterns = i18n_patterns("",
    # Change the admin prefix here to use an alternate URL for the
    # admin interface, which would be marginally more secure.
    ("^admin/", include(admin.site.urls)),
)

urlpatterns += patterns('',

    # We don't want to presume how your homepage works, so here are a
    # few patterns you can use to set it up.

    # HOMEPAGE AS STATIC TEMPLATE
    # ---------------------------
    # This pattern simply loads the index.html template. It isn't
    # commented out like the others, so it's the default. You only need
    # one homepage pattern, so if you use a different one, comment this
    # one out.

    url("^$", direct_to_template, {"template": "index.html"}, name="home"),

    # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
    # ---------------------------------------------
    # This pattern gives us a normal ``Page`` object, so that your
    # homepage can be managed via the page tree in the admin. If you
    # use this pattern, you'll need to create a page in the page tree,
    # and specify its URL (in the Meta Data section) as "/", which
    # is the value used below in the ``{"slug": "/"}`` part.
    # Also note that the normal rule of adding a custom
    # template per page with the template name using the page's slug
    # doesn't apply here, since we can't have a template called
    # "/.html" - so for this case, the template "pages/index.html"
    # should be used if you want to customize the homepage's template.

    # url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),

    # HOMEPAGE FOR A BLOG-ONLY SITE
    # -----------------------------
    # This pattern points the homepage to the blog post listing page,
    # and is useful for sites that are primarily blogs. If you use this
    # pattern, you'll also need to set BLOG_SLUG = "" in your
    # ``settings.py`` module, and delete the blog page object from the
    # page tree in the admin if it was installed.

    # url("^$", "mezzanine.blog.views.blog_post_list", name="home"),

    # MEZZANINE'S URLS
    # ----------------
    # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
    # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
    # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
    # WILL NEVER BE MATCHED!

    # If you'd like more granular control over the patterns in
    # ``mezzanine.urls``, go right ahead and take the parts you want
    # from it, and use them directly below instead of using
    # ``mezzanine.urls``.
    ("^", include("mezzanine.urls")),

    # MOUNTING MEZZANINE UNDER A PREFIX
    # ---------------------------------
    # You can also mount all of Mezzanine's urlpatterns under a
    # URL prefix if desired. When doing this, you need to define the
    # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
    # SITE_PREFIX = "my/site/prefix"
    # For convenience, and to avoid repeating the prefix, use the
    # commented out pattern below (commenting out the one above of course)
    # which will make use of the ``SITE_PREFIX`` setting. Make sure to
    # add the import ``from django.conf import settings`` to the top
    # of this file as well.
    # Note that for any of the various homepage patterns above, you'll
    # need to use the ``SITE_PREFIX`` setting as well.

    # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
    url(r'^i18n/', include('django.conf.urls.i18n')),

)

# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"
<commit_msg>Sitemap added<commit_after>from __future__ import unicode_literals

from django.conf.urls import patterns, include, url
from django.conf.urls.i18n import i18n_patterns
from django.contrib import admin

from mezzanine.core.views import direct_to_template

from django.contrib.sitemaps import GenericSitemap
from mezzanine.blog.models import BlogPost
from mezzanine.pages.models import RichTextPage

admin.autodiscover()

# Sitemaps
# Define information to be published in dictionaries
blog_dict = {
    'queryset': BlogPost.objects.published(),
    'date_field': 'created',
}
page_dict = {
    'queryset': RichTextPage.objects.published(),
}

sitemaps = {
    'pages': GenericSitemap(page_dict, priority=0.6),
    'blog': GenericSitemap(blog_dict, priority=0.6),
}

# Add the urlpatterns for any custom Django applications here.
# You can also change the ``home`` view to add your own functionality
# to the project's homepage.

urlpatterns = patterns("",
    # Change the admin prefix here to use an alternate URL for the
    # admin interface, which would be marginally more secure.
    ("^admin/", include(admin.site.urls)),
    (r'^sitemap\.xml$', 'django.contrib.sitemaps.views.sitemap', {'sitemaps': sitemaps}),
)

urlpatterns += patterns('',

    # We don't want to presume how your homepage works, so here are a
    # few patterns you can use to set it up.

    # HOMEPAGE AS STATIC TEMPLATE
    # ---------------------------
    # This pattern simply loads the index.html template. It isn't
    # commented out like the others, so it's the default. You only need
    # one homepage pattern, so if you use a different one, comment this
    # one out.

    url("^$", direct_to_template, {"template": "index.html"}, name="home"),

    # HOMEPAGE AS AN EDITABLE PAGE IN THE PAGE TREE
    # ---------------------------------------------
    # This pattern gives us a normal ``Page`` object, so that your
    # homepage can be managed via the page tree in the admin. If you
    # use this pattern, you'll need to create a page in the page tree,
    # and specify its URL (in the Meta Data section) as "/", which
    # is the value used below in the ``{"slug": "/"}`` part.
    # Also note that the normal rule of adding a custom
    # template per page with the template name using the page's slug
    # doesn't apply here, since we can't have a template called
    # "/.html" - so for this case, the template "pages/index.html"
    # should be used if you want to customize the homepage's template.

    # url("^$", "mezzanine.pages.views.page", {"slug": "/"}, name="home"),

    # HOMEPAGE FOR A BLOG-ONLY SITE
    # -----------------------------
    # This pattern points the homepage to the blog post listing page,
    # and is useful for sites that are primarily blogs. If you use this
    # pattern, you'll also need to set BLOG_SLUG = "" in your
    # ``settings.py`` module, and delete the blog page object from the
    # page tree in the admin if it was installed.

    # url("^$", "mezzanine.blog.views.blog_post_list", name="home"),

    # MEZZANINE'S URLS
    # ----------------
    # ADD YOUR OWN URLPATTERNS *ABOVE* THE LINE BELOW.
    # ``mezzanine.urls`` INCLUDES A *CATCH ALL* PATTERN
    # FOR PAGES, SO URLPATTERNS ADDED BELOW ``mezzanine.urls``
    # WILL NEVER BE MATCHED!

    # If you'd like more granular control over the patterns in
    # ``mezzanine.urls``, go right ahead and take the parts you want
    # from it, and use them directly below instead of using
    # ``mezzanine.urls``.
    ("^", include("mezzanine.urls")),

    # MOUNTING MEZZANINE UNDER A PREFIX
    # ---------------------------------
    # You can also mount all of Mezzanine's urlpatterns under a
    # URL prefix if desired. When doing this, you need to define the
    # ``SITE_PREFIX`` setting, which will contain the prefix. Eg:
    # SITE_PREFIX = "my/site/prefix"
    # For convenience, and to avoid repeating the prefix, use the
    # commented out pattern below (commenting out the one above of course)
    # which will make use of the ``SITE_PREFIX`` setting. Make sure to
    # add the import ``from django.conf import settings`` to the top
    # of this file as well.
    # Note that for any of the various homepage patterns above, you'll
    # need to use the ``SITE_PREFIX`` setting as well.

    # ("^%s/" % settings.SITE_PREFIX, include("mezzanine.urls"))
    url(r'^i18n/', include('django.conf.urls.i18n')),

)

# Adds ``STATIC_URL`` to the context of error pages, so that error
# pages can use JS, CSS and images.
handler404 = "mezzanine.core.views.page_not_found"
handler500 = "mezzanine.core.views.server_error"
<|endoftext|>


<commit_before>import commands
import tempfile
import pexpect
import logging
import signal
import killableprocess, commands
import sys, os
import urlparse

import windmill

logger = logging.getLogger(__name__)

"""
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -getwebproxy "AirPort"                                          [14:12]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Enabled: No
Server: localhost
Port: 4444
Authenticated Proxy Enabled: 0
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -setwebproxystate "AirPort" on                                  [14:12]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -getwebproxy "AirPort"                                          [14:13]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Enabled: Yes
Server: localhost
Port: 4444
Authenticated Proxy Enabled: 0
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ whoami                                                                         [14:13]
Usage: networksetup -setwebproxy <networkservice> <domain> <port number> <authenticated> <username> <password>
mikeal
"""

html_redirection = """
<html>
  <head>
    <script type="text/javascript">
    var i = function(){
    	window.location = "http://{replace}/windmill-serv/start.html";
    }
    </script>
 </head>
  <body onload="i();">
  </body>
<html>"""

def find_default_interface_name():
    interface = [ s for s in commands.getoutput('netstat -nr').splitlines() if (
                  s.startswith('default') )
                 ][0].split()[-1] # split lines of the command, find default, last value in line is interface

    interfaces = commands.getoutput(windmill.settings['NETWORKSETUP_BINARY']+' -listnetworkserviceorder').split('\n\n')
    for line in interfaces:
        if not line.startswith('(') and line.find('(1)') is not -1:
            line = '(1)'+line.split('(1)')[-1]
        if line.find('Device: '+interface) is not -1:
            interface_name = ' '.join(line.splitlines()[0].split()[1:])

    return interface_name

class Safari(object):

	def __init__(self):
	    self.netsetup_binary = windmill.settings['NETWORKSETUP_BINARY']
	    self.safari_binary = windmill.settings['SAFARI_BINARY']
	    self.test_url = windmill.settings['TEST_URL']

	def start(self):
	    # Set local Proxy
	    interface_name = find_default_interface_name()
	    uri = urlparse.urlparse(self.test_url)
	    set_proxy_command = ' '.join([ self.netsetup_binary,
	                                   '-setwebproxy',
	                                   '"'+interface_name+'"',
	                                   'localhost',
	                                   str(windmill.settings['SERVER_HTTP_PORT'])
	                                 ])
	    commands.getoutput(set_proxy_command)
	    enable_proxy_command = ' '.join([ self.netsetup_binary,
	                                      '-setwebproxystate',
	                                      '"'+interface_name+'"',
	                                      'on'
	                                    ])
	    commands.getoutput(enable_proxy_command)

	    redirection_page = tempfile.mktemp(suffix='.html')
	    f = open(redirection_page, 'w')
	    f.write(html_redirection.replace('{replace}', uri.netloc+uri.path))
	    f.flush() ; f.close()
	    print self.safari_binary, redirection_page
	    self.p_handle = killableprocess.runCommand([self.safari_binary, redirection_page])
	    logger.info([self.safari_binary, redirection_page])
	    self.interface_name = interface_name

	def kill(self, kill_signal=None):
	    commands.getoutput(' '.join([self.netsetup_binary, '-setwebproxystate', '"'+self.interface_name+'"', 'off']))
	    try:
	        self.p_handle.kill(group=True)
	    except:
	        logger.error('Cannot kill Safari')

	def stop(self):
	    commands.getoutput(' '.join([self.netsetup_binary, '-setwebproxystate', '"'+self.interface_name+'"', 'off']))
	    self.kill(signal.SIGTERM)

	def is_alive(self):
	    if self.p_handle.poll() is None:
	        return False
	    return True

# def ipfw_configure_global_proxy():
#
#   if commands.getoutput('whoami') == 'root':
#       assert commands.getoutput('ipfw add 00017 allow ip from any 32000-34000 to any 80')==\
#                                 '00017 allow ip from any 32000-34000 to any dst-port 80'
#       assert commands.getoutput('ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80')==\
#                                 '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#       print 'is root'
#   else:
#       if SUDO_PASS is not None:
#           cmd =  'echo "spawn sudo ipfw add 00017 allow ip from any 32000-34000 to any 80 \n\rexpect \"Password:\" \n\rsend \"%s\" " | expect' % SUDO_PASS
#           commands.getoutput(cmd)
#           cmd = 'sudo ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#           assert commands.getoutput(cmd) == '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#
# def ipfw_remove_transparent_proxy():
#
#   if commands.getoutput('whoami') == 'root':
#       assert commands.getoutput('ipfw add 00017 allow ip from any 32000-34000 to any 80')==\
#                                 '00017 allow ip from any 32000-34000 to any dst-port 80'
#       assert commands.getoutput('ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80')==\
#                                 '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#       print 'is root'
#   else:
#       if SUDO_PASS is not None:
#           cmd =  'echo "spawn sudo ipfw delete 00017 \n\rexpect \"Password:\" \n\rsend \"%s\" " | expect' % SUDO_PASS
#           commands.getoutput(cmd)
#           cmd = 'sudo ipfw delete'
#           assert commands.getoutput(cmd) == ''<commit_msg>We don't actually use pexcpect anymore.<commit_after>import commands
import tempfile
import logging
import signal
import killableprocess, commands
import sys, os
import urlparse

import windmill

logger = logging.getLogger(__name__)

"""
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -getwebproxy "AirPort"                                          [14:12]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Enabled: No
Server: localhost
Port: 4444
Authenticated Proxy Enabled: 0
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -setwebproxystate "AirPort" on                                  [14:12]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ ./networksetup -getwebproxy "AirPort"                                          [14:13]
cp: /Library/Preferences/SystemConfiguration/preferences.plist.old: Permission denied
Enabled: Yes
Server: localhost
Port: 4444
Authenticated Proxy Enabled: 0
Colossus:/System/Library/CoreServices/RemoteManagement/ARDAgent.app/Contents/Support mikeal$ whoami                                                                         [14:13]
Usage: networksetup -setwebproxy <networkservice> <domain> <port number> <authenticated> <username> <password>
mikeal
"""

html_redirection = """
<html>
  <head>
    <script type="text/javascript">
    var i = function(){
    	window.location = "http://{replace}/windmill-serv/start.html";
    }
    </script>
 </head>
  <body onload="i();">
  </body>
<html>"""

def find_default_interface_name():
    interface = [ s for s in commands.getoutput('netstat -nr').splitlines() if (
                  s.startswith('default') )
                 ][0].split()[-1] # split lines of the command, find default, last value in line is interface

    interfaces = commands.getoutput(windmill.settings['NETWORKSETUP_BINARY']+' -listnetworkserviceorder').split('\n\n')
    for line in interfaces:
        if not line.startswith('(') and line.find('(1)') is not -1:
            line = '(1)'+line.split('(1)')[-1]
        if line.find('Device: '+interface) is not -1:
            interface_name = ' '.join(line.splitlines()[0].split()[1:])

    return interface_name

class Safari(object):

	def __init__(self):
	    self.netsetup_binary = windmill.settings['NETWORKSETUP_BINARY']
	    self.safari_binary = windmill.settings['SAFARI_BINARY']
	    self.test_url = windmill.settings['TEST_URL']

	def start(self):
	    # Set local Proxy
	    interface_name = find_default_interface_name()
	    uri = urlparse.urlparse(self.test_url)
	    set_proxy_command = ' '.join([ self.netsetup_binary,
	                                   '-setwebproxy',
	                                   '"'+interface_name+'"',
	                                   'localhost',
	                                   str(windmill.settings['SERVER_HTTP_PORT'])
	                                 ])
	    commands.getoutput(set_proxy_command)
	    enable_proxy_command = ' '.join([ self.netsetup_binary,
	                                      '-setwebproxystate',
	                                      '"'+interface_name+'"',
	                                      'on'
	                                    ])
	    commands.getoutput(enable_proxy_command)

	    redirection_page = tempfile.mktemp(suffix='.html')
	    f = open(redirection_page, 'w')
	    f.write(html_redirection.replace('{replace}', uri.netloc+uri.path))
	    f.flush() ; f.close()
	    print self.safari_binary, redirection_page
	    self.p_handle = killableprocess.runCommand([self.safari_binary, redirection_page])
	    logger.info([self.safari_binary, redirection_page])
	    self.interface_name = interface_name

	def kill(self, kill_signal=None):
	    commands.getoutput(' '.join([self.netsetup_binary, '-setwebproxystate', '"'+self.interface_name+'"', 'off']))
	    try:
	        self.p_handle.kill(group=True)
	    except:
	        logger.error('Cannot kill Safari')

	def stop(self):
	    commands.getoutput(' '.join([self.netsetup_binary, '-setwebproxystate', '"'+self.interface_name+'"', 'off']))
	    self.kill(signal.SIGTERM)

	def is_alive(self):
	    if self.p_handle.poll() is None:
	        return False
	    return True

# def ipfw_configure_global_proxy():
#
#   if commands.getoutput('whoami') == 'root':
#       assert commands.getoutput('ipfw add 00017 allow ip from any 32000-34000 to any 80')==\
#                                 '00017 allow ip from any 32000-34000 to any dst-port 80'
#       assert commands.getoutput('ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80')==\
#                                 '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#       print 'is root'
#   else:
#       if SUDO_PASS is not None:
#           cmd =  'echo "spawn sudo ipfw add 00017 allow ip from any 32000-34000 to any 80 \n\rexpect \"Password:\" \n\rsend \"%s\" " | expect' % SUDO_PASS
#           commands.getoutput(cmd)
#           cmd = 'sudo ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#           assert commands.getoutput(cmd) == '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#
# def ipfw_remove_transparent_proxy():
#
#   if commands.getoutput('whoami') == 'root':
#       assert commands.getoutput('ipfw add 00017 allow ip from any 32000-34000 to any 80')==\
#                                 '00017 allow ip from any 32000-34000 to any dst-port 80'
#       assert commands.getoutput('ipfw add 00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80')==\
#                                 '00019 fwd 127.0.0.1,4444 tcp from any to any dst-port 80'
#       print 'is root'
#   else:
#       if SUDO_PASS is not None:
#           cmd =  'echo "spawn sudo ipfw delete 00017 \n\rexpect \"Password:\" \n\rsend \"%s\" " | expect' % SUDO_PASS
#           commands.getoutput(cmd)
#           cmd = 'sudo ipfw delete'
#           assert commands.getoutput(cmd) == ''<|endoftext|>


<commit_before>"""Place of record for the package version"""

__version__ = "1.0.110"
__rpm_version__ = "WILL_BE_SET_BY_RPM_BUILD"
__git_hash__ = "WILL_BE_SET_BY_EGG_BUILD"
<commit_msg>version bump<commit_after>"""Place of record for the package version"""

__version__ = "1.0.111"
__rpm_version__ = "WILL_BE_SET_BY_RPM_BUILD"
__git_hash__ = "WILL_BE_SET_BY_EGG_BUILD"
<|endoftext|>


<commit_before>###
### Script name: Send invoices
### Description: Sends a batch of invoices specified by id.
### Version: 1.0
### Author: Jimmy Bergman
###
### Parameters:
### invoice_ids - Array of invoice ID:s to send
###    example: [System.Guid("5332eba0-b55d-44a4-a94a-a960a4f25d04"), System.Guid("0a019a00-562a-4ae4-acff-6a1607021255")]

import System

invoice_ids = [System.Guid("5332eba0-b55d-44a4-a94a-a960a4f25d04"), System.Guid("0a019a00-562a-4ae4-acff-6a1607021255")]

billingApi.SendInvoices(System.Array[System.Guid](invoice_ids), None)

print str(len(invoice_ids)) + " invoices sent"<commit_msg>Fixed SendInvoices version<commit_after>###
### Script name: Send invoices
### Description: Sends a batch of invoices specified by id.
### Version: 1.1
### Author: Jimmy Bergman
###
### Parameters:
### invoice_ids - Array of invoice ID:s to send
###    example: [ "5332eba0-f6aa-4b57-a340-9c141f9d252f", "0a019a00-6c62-49f7-a251-d04829beaff8" ]

import System

billingApi.SendInvoices(System.Array[System.Guid](map(System.Guid,invoice_ids)), None)

print str(len(invoice_ids)) + " invoices sent"<|endoftext|>


<commit_before>"""private_base will be populated from puppet and placed in this directory"""

import logging

import dj_database_url

import private_base as private

ADMINS = ()

DATABASES = {}
DATABASES['default'] = dj_database_url.parse(private.DATABASES_DEFAULT_URL)
DATABASES['default']['ENGINE'] = 'django.db.backends.mysql'
DATABASES['default']['OPTIONS'] = {'init_command': 'SET storage_engine=InnoDB'}

DEBUG = False
DEBUG_PROPAGATE_EXCEPTIONS = False

HMAC_KEYS = private.HMAC_KEYS

LOG_LEVEL = logging.DEBUG

SECRET_KEY = private.SECRET_KEY

SENTRY_DSN = private.SENTRY_DSN

STATSD_HOST = private.STATSD_HOST
STATSD_PORT = private.STATSD_PORT
STATSD_PREFIX = private.STATSD_PREFIX

SYSLOG_TAG = 'http_app_payments_dev'
TEMPLATE_DEBUG = DEBUG

# Solitude specific settings.
AES_KEYS = private.AES_KEYS

CLEANSED_SETTINGS_ACCESS = True
CLIENT_JWT_KEYS = private.CLIENT_JWT_KEYS

PAYPAL_PROXY = private.PAYPAL_PROXY
PAYPAL_URL_WHITELIST = ('https://marketplace-dev.allizom.org',)

BANGO_PROXY = private.BANGO_PROXY
<commit_msg>Revert "proxy on again"<commit_after>"""private_base will be populated from puppet and placed in this directory"""

import logging

import dj_database_url

import private_base as private

ADMINS = ()

DATABASES = {}
DATABASES['default'] = dj_database_url.parse(private.DATABASES_DEFAULT_URL)
DATABASES['default']['ENGINE'] = 'django.db.backends.mysql'
DATABASES['default']['OPTIONS'] = {'init_command': 'SET storage_engine=InnoDB'}

DEBUG = False
DEBUG_PROPAGATE_EXCEPTIONS = False

HMAC_KEYS = private.HMAC_KEYS

LOG_LEVEL = logging.DEBUG

SECRET_KEY = private.SECRET_KEY

SENTRY_DSN = private.SENTRY_DSN

STATSD_HOST = private.STATSD_HOST
STATSD_PORT = private.STATSD_PORT
STATSD_PREFIX = private.STATSD_PREFIX

SYSLOG_TAG = 'http_app_payments_dev'
TEMPLATE_DEBUG = DEBUG

# Solitude specific settings.
AES_KEYS = private.AES_KEYS

CLEANSED_SETTINGS_ACCESS = True
CLIENT_JWT_KEYS = private.CLIENT_JWT_KEYS

PAYPAL_PROXY = private.PAYPAL_PROXY
PAYPAL_URL_WHITELIST = ('https://marketplace-dev.allizom.org',)

# Swap these around when bug 831576 is fixed.
# Speak to Bango directly.
BANGO_ENV = 'test'
BANGO_AUTH = private.BANGO_AUTH
# Use the proxy.
#BANGO_PROXY = private.BANGO_PROXY
<|endoftext|>


<commit_before>"""
Support for editable text, a part of a diagram item, i.e. name of named
item, guard of flow item, etc.
"""

from gaphor.diagram.style import Style
from gaphor.diagram.style import ALIGN_CENTER, ALIGN_TOP
import gaphor.diagram.font as font

from gaphas.geometry import distance_rectangle_point, Rectangle
from gaphas.util import text_extents, text_align, text_multiline, \
    text_set_font

def swap(list, el1, el2):
    """
    Swap two elements on the list.
    """
    i1 = list.index(el1)
    i2 = list.index(el2)
    list[i1] = el2
    list[i2] = el1

class EditableTextSupport(object):
    """
    Editable text support to allow display and edit text parts of a diagram
    item.

    Attributes:
     - _texts:       list of diagram item text elements
     - _text_groups: grouping information of text elements (None - ungrouped)
    """
    def __init__(self):
        self._texts = []
        self._text_groups = { None: [] }
        self._text_groups_sizes = {}

    def postload(self):
        super(EditableTextSupport, self).postload()

    def texts(self):
        """
        Return list of diagram item text elements.
        """
        return self._texts

    def add_text(self, attr, style=None, pattern=None, visible=None,
            editable=False, font=font.FONT):
        """
        Create and add a text element.

        For parameters description and more information see TextElement
        class documentation.

        If style information contains 'text-align-group' data, then text
        element is grouped.

        Returns created text element.
        """
        txt = TextElement(attr, style=style, pattern=pattern,
                visible=visible, editable=editable, font=font)
        self._texts.append(txt)

        # try to group text element
        gname = style and style.get('text-align-group') or None
        if gname not in self._text_groups:
            self._text_groups[gname] = []
        group = self._text_groups[gname]
        group.append(txt)

        return txt

    def remove_text(self, txt):
        """
        Remove a text element from diagram item.

        Parameters:
        - txt: text to be removed
        """
        # remove from align group
        style = txt.style
        if style and hasattr(style, 'text_align_group'):
            gname = style.text_align_group
        else:
            gname = None

        group = self._text_groups[gname]
        group.remove(txt)

        # remove text element from diagram item
        self._texts.remove(txt)

    def swap_texts(self, txt1, txt2):
        """
        Swap two text elements.
        """
        swap(self._texts, txt1, txt2)

        style = txt1.style
        if style and hasattr(style, 'text_align_group'):
            gname = style.text_align_group
        else:
            gname = None

        group = self._text_groups[gname]
        swap(group, txt1, txt2)

    def _get_visible_texts(self, texts):
        """
        Get list of visible texts.
        """
        return [txt for txt in texts if txt.is_visible()]

    def _get_text_groups(self):
        """
        Get text groups.
        """
        tg = self._text_groups
        groups = self._text_groups
        return ((name, tg[name]) for name in groups if name)

    def _set_text_sizes(self, context, texts):
        """
        Calculate size for every text in the list.

        Parameters:
         - context: cairo context
         - texts:   list of texts
        """
        cr = context.cairo
        for txt in texts:
            extents = text_extents(cr, txt.text, font=txt.font, multiline=True)
            txt.bounds.width, txt.bounds.height = extents

    def _set_text_group_size(self, context, name, texts):
        """
        Calculate size of a group.

        Parameters:
         - context: cairo context
         - name:    group name
         - texts:   list of group texts
        """
        cr = context.cairo

        texts = self._get_visible_texts(texts)

        if not texts:
            self._text_groups_sizes[name] = (0, 0)
            return

        # find maximum width and total height
        width = max(txt.bounds.width for txt in texts)
        height = sum(txt.bounds.height for txt in texts)
        self._text_groups_sizes[name] = width, height

    def pre_update(self, context):
        """
        Calculate sizes of text elements and text groups.
        """
        cr = context.cairo

        # calculate sizes of text groups
        for name, texts in self._get_text_groups():
            self._set_text_sizes(context, texts)
            self._set_text_group_size(context, name, texts)

        # calculate sizes of ungrouped texts
        texts = self._text_groups[None]
        texts = self._get_visible_texts(texts)
        self._set_text_sizes(context, texts)

    def _text_group_align(self, context, name, texts):
        """
        Align group of text elements making vertical stack of strings.

        Parameters:
         - context: cairo context
         - name:    group name
         - texts:   list of group texts
        """
        cr = context.cairo

        texts = self._get_visible_texts(texts)

        if not texts:
            return

        # align according to style of last text in the group
        style = texts[-1]._style
        extents = self._text_groups_sizes[name]
        x, y = self.text_align(extents, style.text_align,
                style.text_padding, style.text_outside)

        # stack texts
        dy = 0
        dw = extents[0]
        for txt in texts:
            bounds = txt.bounds
            width, height = bounds.width, bounds.height
            hint = self._get_text_align_hint(cr, txt)
            # center stacked texts
            if hint:
                txt.bounds.x = x + dw / 2.0 - hint
            else:
                txt.bounds.x = x + (dw - width) / 2.0
            txt.bounds.y = y + dy
            dy += height

    def _get_text_align_hint(self, cr, txt):
        """
        Calculate hint value for text element. Currently, hint value is
        calculated only for text elements, which style contains
        ``text-align-str`` style property.
        """
        hint = 0
        style = txt.style
        if style.text_align_str:
            chunks = txt.text.split(style.text_align_str)
            if len(chunks) > 1:
                hint, _ = text_extents(cr, chunks[0], font=txt.font)
        return hint

    def post_update(self, context):
        """
        Calculate position and sizes of all text elements of a diagram
        item.
        """
        cr = context.cairo

        # align groups of text elements
        for name, texts in self._get_text_groups():
            assert name in self._text_groups_sizes, 'No text group "%s"' % name
            self._text_group_align(context, name, texts)

        # align ungrouped text elements
        texts = self._get_visible_texts(self._text_groups[None])
        for txt in texts:
            style = txt._style
            extents = txt.bounds.width, txt.bounds.height
            x, y = self.text_align(extents, style.text_align,
                    style.text_padding, style.text_outside)

            bounds = txt.bounds # fixme: gaphor rectangle problem
            width, height = bounds.width, bounds.height # fixme: gaphor rectangle problem
            txt.bounds.x = x
            txt.bounds.y = y

    def point(self, x, y):
        """
        Return the distance to the nearest editable and visible text
        element.
        """
        def distances():
            yield 10000.0
            for txt in self._texts:
                if txt.is_visible() and txt.editable:
                    yield distance_rectangle_point(txt.bounds, (x, y))
        return min(distances())

    def draw(self, context):
        """
        Draw all text elements of a diagram item.
        """
        cr = context.cairo
        cr.save()
        for txt in self._get_visible_texts(self._texts):
            bounds = txt.bounds
            x, y = bounds.x, bounds.y
            width, height = bounds.width, bounds.height

            if self.subject:
                text_set_font(cr, txt.font)
                text_multiline(cr, x, y, txt.text)
                cr.stroke()

            if self.subject and txt.editable \
                    and (context.hovered or context.focused):

                width = max(15, width)
                height = max(10, height)
                cr.set_line_width(0.5)
                cr.rectangle(x, y, width, height)
                cr.stroke()

        cr.restore()

class TextElement(object):
    """
    Representation of an editable text, which is part of a diagram item.

    Text element is aligned according to style information.

    It also displays and allows to edit value of an attribute of UML
    class (DiagramItem.subject). Attribute name can be recursive, all
    below attribute names are valid:
     - name (named item name)
     - guard.value (flow item guard)

    Attributes and properties:
     - attr:     name of displayed and edited UML class attribute
     - bounds:   text bounds
     - _style:   text style (i.e. align information, padding)
     - text:     rendered string to be displayed
     - pattern:  print pattern of text
     - editable: True if text should be editable
     - font:     text font

    See also EditableTextSupport.add_text.
    """

    bounds = property(lambda self: self._bounds)

    def __init__(self, attr, style=None, pattern=None, visible=None,
            editable=False, font=font.FONT_NAME):
        """
        Create new text element with bounds (0, 0, 10, 10) and empty text.

        Parameters:
         - visible: function, which evaluates to True/False if text should
                    be visible
        """
        super(TextElement, self).__init__()

        self._bounds = Rectangle(0, 0, width=10, height=0)

        # create default style for a text element
        self._style = Style()
        self._style.add('text-padding', (2, 2, 2, 2))
        self._style.add('text-align', (ALIGN_CENTER, ALIGN_TOP))
        self._style.add('text-outside', False)
        self._style.add('text-align-str', None)
        if style:
            self._style.update(style)

        self.attr = attr
        self._text = ''

        if visible:
            self.is_visible = visible

        if pattern:
            self._pattern = pattern
        else:
            self._pattern = '%s'

        self.editable = editable
        self.font = font

    def _set_text(self, value):
        """
        Render text value using pattern.
        """
        self._text = value and self._pattern % value or ''

    text = property(lambda s: s._text, _set_text)

    style = property(lambda s: s._style)

    def is_visible(self):
        """
        Display text by default.
        """
        return True

# vim:sw=4:et:ai
<commit_msg>- speed up splitting text a bit when aligning on string<commit_after>"""
Support for editable text, a part of a diagram item, i.e. name of named
item, guard of flow item, etc.
"""

from gaphor.diagram.style import Style
from gaphor.diagram.style import ALIGN_CENTER, ALIGN_TOP
import gaphor.diagram.font as font

from gaphas.geometry import distance_rectangle_point, Rectangle
from gaphas.util import text_extents, text_align, text_multiline, \
    text_set_font

def swap(list, el1, el2):
    """
    Swap two elements on the list.
    """
    i1 = list.index(el1)
    i2 = list.index(el2)
    list[i1] = el2
    list[i2] = el1

class EditableTextSupport(object):
    """
    Editable text support to allow display and edit text parts of a diagram
    item.

    Attributes:
     - _texts:       list of diagram item text elements
     - _text_groups: grouping information of text elements (None - ungrouped)
    """
    def __init__(self):
        self._texts = []
        self._text_groups = { None: [] }
        self._text_groups_sizes = {}

    def postload(self):
        super(EditableTextSupport, self).postload()

    def texts(self):
        """
        Return list of diagram item text elements.
        """
        return self._texts

    def add_text(self, attr, style=None, pattern=None, visible=None,
            editable=False, font=font.FONT):
        """
        Create and add a text element.

        For parameters description and more information see TextElement
        class documentation.

        If style information contains 'text-align-group' data, then text
        element is grouped.

        Returns created text element.
        """
        txt = TextElement(attr, style=style, pattern=pattern,
                visible=visible, editable=editable, font=font)
        self._texts.append(txt)

        # try to group text element
        gname = style and style.get('text-align-group') or None
        if gname not in self._text_groups:
            self._text_groups[gname] = []
        group = self._text_groups[gname]
        group.append(txt)

        return txt

    def remove_text(self, txt):
        """
        Remove a text element from diagram item.

        Parameters:
        - txt: text to be removed
        """
        # remove from align group
        style = txt.style
        if style and hasattr(style, 'text_align_group'):
            gname = style.text_align_group
        else:
            gname = None

        group = self._text_groups[gname]
        group.remove(txt)

        # remove text element from diagram item
        self._texts.remove(txt)

    def swap_texts(self, txt1, txt2):
        """
        Swap two text elements.
        """
        swap(self._texts, txt1, txt2)

        style = txt1.style
        if style and hasattr(style, 'text_align_group'):
            gname = style.text_align_group
        else:
            gname = None

        group = self._text_groups[gname]
        swap(group, txt1, txt2)

    def _get_visible_texts(self, texts):
        """
        Get list of visible texts.
        """
        return [txt for txt in texts if txt.is_visible()]

    def _get_text_groups(self):
        """
        Get text groups.
        """
        tg = self._text_groups
        groups = self._text_groups
        return ((name, tg[name]) for name in groups if name)

    def _set_text_sizes(self, context, texts):
        """
        Calculate size for every text in the list.

        Parameters:
         - context: cairo context
         - texts:   list of texts
        """
        cr = context.cairo
        for txt in texts:
            extents = text_extents(cr, txt.text, font=txt.font, multiline=True)
            txt.bounds.width, txt.bounds.height = extents

    def _set_text_group_size(self, context, name, texts):
        """
        Calculate size of a group.

        Parameters:
         - context: cairo context
         - name:    group name
         - texts:   list of group texts
        """
        cr = context.cairo

        texts = self._get_visible_texts(texts)

        if not texts:
            self._text_groups_sizes[name] = (0, 0)
            return

        # find maximum width and total height
        width = max(txt.bounds.width for txt in texts)
        height = sum(txt.bounds.height for txt in texts)
        self._text_groups_sizes[name] = width, height

    def pre_update(self, context):
        """
        Calculate sizes of text elements and text groups.
        """
        cr = context.cairo

        # calculate sizes of text groups
        for name, texts in self._get_text_groups():
            self._set_text_sizes(context, texts)
            self._set_text_group_size(context, name, texts)

        # calculate sizes of ungrouped texts
        texts = self._text_groups[None]
        texts = self._get_visible_texts(texts)
        self._set_text_sizes(context, texts)

    def _text_group_align(self, context, name, texts):
        """
        Align group of text elements making vertical stack of strings.

        Parameters:
         - context: cairo context
         - name:    group name
         - texts:   list of group texts
        """
        cr = context.cairo

        texts = self._get_visible_texts(texts)

        if not texts:
            return

        # align according to style of last text in the group
        style = texts[-1]._style
        extents = self._text_groups_sizes[name]
        x, y = self.text_align(extents, style.text_align,
                style.text_padding, style.text_outside)

        # stack texts
        dy = 0
        dw = extents[0]
        for txt in texts:
            bounds = txt.bounds
            width, height = bounds.width, bounds.height
            hint = self._get_text_align_hint(cr, txt)
            # center stacked texts
            if hint:
                txt.bounds.x = x + dw / 2.0 - hint
            else:
                txt.bounds.x = x + (dw - width) / 2.0
            txt.bounds.y = y + dy
            dy += height

    def _get_text_align_hint(self, cr, txt):
        """
        Calculate hint value for text element. Currently, hint value is
        calculated only for text elements, which style contains
        ``text-align-str`` style property.
        """
        hint = 0
        style = txt.style
        if style.text_align_str:
            chunks = txt.text.split(style.text_align_str, 1)
            if len(chunks) > 1:
                hint, _ = text_extents(cr, chunks[0], font=txt.font)
        return hint

    def post_update(self, context):
        """
        Calculate position and sizes of all text elements of a diagram
        item.
        """
        cr = context.cairo

        # align groups of text elements
        for name, texts in self._get_text_groups():
            assert name in self._text_groups_sizes, 'No text group "%s"' % name
            self._text_group_align(context, name, texts)

        # align ungrouped text elements
        texts = self._get_visible_texts(self._text_groups[None])
        for txt in texts:
            style = txt._style
            extents = txt.bounds.width, txt.bounds.height
            x, y = self.text_align(extents, style.text_align,
                    style.text_padding, style.text_outside)

            bounds = txt.bounds # fixme: gaphor rectangle problem
            width, height = bounds.width, bounds.height # fixme: gaphor rectangle problem
            txt.bounds.x = x
            txt.bounds.y = y

    def point(self, x, y):
        """
        Return the distance to the nearest editable and visible text
        element.
        """
        def distances():
            yield 10000.0
            for txt in self._texts:
                if txt.is_visible() and txt.editable:
                    yield distance_rectangle_point(txt.bounds, (x, y))
        return min(distances())

    def draw(self, context):
        """
        Draw all text elements of a diagram item.
        """
        cr = context.cairo
        cr.save()
        for txt in self._get_visible_texts(self._texts):
            bounds = txt.bounds
            x, y = bounds.x, bounds.y
            width, height = bounds.width, bounds.height

            if self.subject:
                text_set_font(cr, txt.font)
                text_multiline(cr, x, y, txt.text)
                cr.stroke()

            if self.subject and txt.editable \
                    and (context.hovered or context.focused):

                width = max(15, width)
                height = max(10, height)
                cr.set_line_width(0.5)
                cr.rectangle(x, y, width, height)
                cr.stroke()

        cr.restore()

class TextElement(object):
    """
    Representation of an editable text, which is part of a diagram item.

    Text element is aligned according to style information.

    It also displays and allows to edit value of an attribute of UML
    class (DiagramItem.subject). Attribute name can be recursive, all
    below attribute names are valid:
     - name (named item name)
     - guard.value (flow item guard)

    Attributes and properties:
     - attr:     name of displayed and edited UML class attribute
     - bounds:   text bounds
     - _style:   text style (i.e. align information, padding)
     - text:     rendered string to be displayed
     - pattern:  print pattern of text
     - editable: True if text should be editable
     - font:     text font

    See also EditableTextSupport.add_text.
    """

    bounds = property(lambda self: self._bounds)

    def __init__(self, attr, style=None, pattern=None, visible=None,
            editable=False, font=font.FONT_NAME):
        """
        Create new text element with bounds (0, 0, 10, 10) and empty text.

        Parameters:
         - visible: function, which evaluates to True/False if text should
                    be visible
        """
        super(TextElement, self).__init__()

        self._bounds = Rectangle(0, 0, width=10, height=0)

        # create default style for a text element
        self._style = Style()
        self._style.add('text-padding', (2, 2, 2, 2))
        self._style.add('text-align', (ALIGN_CENTER, ALIGN_TOP))
        self._style.add('text-outside', False)
        self._style.add('text-align-str', None)
        if style:
            self._style.update(style)

        self.attr = attr
        self._text = ''

        if visible:
            self.is_visible = visible

        if pattern:
            self._pattern = pattern
        else:
            self._pattern = '%s'

        self.editable = editable
        self.font = font

    def _set_text(self, value):
        """
        Render text value using pattern.
        """
        self._text = value and self._pattern % value or ''

    text = property(lambda s: s._text, _set_text)

    style = property(lambda s: s._style)

    def is_visible(self):
        """
        Display text by default.
        """
        return True

# vim:sw=4:et:ai
<|endoftext|>


<commit_before>import pickle
import unittest

from basicstruct import BasicStruct

class Foo(BasicStruct):
    __slots__ = ('x', 'y')

class MyTestCase(unittest.TestCase):
    def test_attribute_access(self):
        f = Foo(2, 'blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_attribute_access_with_kwargs(self):
        f = Foo(x=2, y='blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_attribute_access_partly_kwargs(self):
        f = Foo(2, y='blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_comparisons(self):
        small = Foo(1, 'irreleant')
        medium = Foo(2, 5)
        another_medium = Foo(2, 5)
        large = Foo(2, 15)

        self.assertEqual(medium, another_medium)

        self.assertTrue(small < medium)
        self.assertTrue(small < large)
        self.assertTrue(small <= medium)
        self.assertTrue(small <= large)
        self.assertTrue(medium < large)
        self.assertTrue(medium <= another_medium)
        self.assertTrue(another_medium <= medium)

        self.assertTrue(medium > small)
        self.assertTrue(large > small)
        self.assertTrue(medium >= small)
        self.assertTrue(large >= medium)
        self.assertTrue(large > medium)
        self.assertTrue(medium >= another_medium)
        self.assertTrue(another_medium >= medium)

    def test_repr(self):
        f = Foo(1, 'irrelevant')
        self.assertEqual(repr(f), "Foo(x=1, y='irrelevant')")

    def test_pickle(self):
        f = Foo(1, 'irrelevant')
        self.assertEqual(f, pickle.loads(pickle.dumps(f)))

if __name__ == '__main__':
    unittest.main()
<commit_msg>More tests!<commit_after>import pickle
import unittest

from basicstruct import BasicStruct

class Foo(BasicStruct):
    __slots__ = ('x', 'y')

class MyTestCase(unittest.TestCase):
    def test_attribute_access(self):
        f = Foo(2, 'blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_attribute_access_with_kwargs(self):
        f = Foo(x=2, y='blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_attribute_access_partly_kwargs(self):
        f = Foo(2, y='blah')
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, 'blah')

    def test_attribute_access_missing_values(self):
        f = Foo(2)
        self.assertEqual(f.x, 2)
        self.assertEqual(f.y, None)

    def test_attribute_access_missing_values_partial_kwargs(self):
        f = Foo(y=2)
        self.assertEqual(f.x, None)
        self.assertEqual(f.y, 2)

    def test_comparisons(self):
        small = Foo(1, 'irreleant')
        medium = Foo(2, 5)
        another_medium = Foo(2, 5)
        large = Foo(2, 15)

        self.assertEqual(medium, another_medium)

        self.assertTrue(small < medium)
        self.assertTrue(small < large)
        self.assertTrue(small <= medium)
        self.assertTrue(small <= large)
        self.assertTrue(medium < large)
        self.assertTrue(medium <= another_medium)
        self.assertTrue(another_medium <= medium)

        self.assertTrue(medium > small)
        self.assertTrue(large > small)
        self.assertTrue(medium >= small)
        self.assertTrue(large >= medium)
        self.assertTrue(large > medium)
        self.assertTrue(medium >= another_medium)
        self.assertTrue(another_medium >= medium)

        self.assertTrue(small != medium)
        self.assertTrue(medium != small)
        self.assertTrue(medium != large)
        self.assertTrue(large != medium)

    def test_repr(self):
        f = Foo(1, 'irrelevant')
        self.assertEqual(repr(f), "Foo(x=1, y='irrelevant')")

    def test_pickle(self):
        f = Foo(1, 'irrelevant')
        self.assertEqual(f, pickle.loads(pickle.dumps(f)))

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


<commit_before>"""
The ``modelchain`` module contains functions and classes of the
windpowerlib. This module makes it easy to get started with the windpowerlib
and demonstrates standard ways to use the library.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import logging
from windpowerlib import wind_speed, density, power_output

class ModelChain(object):
    r"""Model to determine the output of a wind turbine

    Parameters
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'p_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.

    Attributes
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'p_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    power_output : pandas.Series
        Electrical power output of the wind turbine in W.

    Examples
    --------
    >>> from windpowerlib import modelchain
    >>> from windpowerlib import wind_turbine
    >>> enerconE126 = {
    ...    'hub_height': 135,
    ...    'd_rotor': 127,
    ...    'wind_conv_type': 'ENERCON E 126 7500'}
    >>> e126 = wind_turbine.WindTurbine(**enerconE126)
    >>> modelchain_data = {'rho_model': 'ideal_gas',
    ...    'temperature_model': 'interpolation'}
    >>> e126_md = modelchain.ModelChain(e126, **modelchain_data)
    >>> print(e126.d_rotor)
    127

    """

    def __init__(self, wind_turbine,
                 obstacle_height=0,
                 wind_model='logarithmic',
                 rho_model='barometric',
                 temperature_model='gradient',
                 power_output_model='p_values',
                 density_corr=False,
                 hellman_exp=None):

        self.wind_turbine = wind_turbine
        self.obstacle_height = obstacle_height
        self.wind_model = wind_model
        self.rho_model = rho_model
        self.temperature_model = temperature_model
        self.power_output_model = power_output_model
        self.density_corr = density_corr
        self.hellman_exp = hellman_exp
        self.power_output = None

    def rho_hub(self, weather, data_height):
        r"""
        Calculates the density of air at hub height.

        The density is calculated using the method specified by the parameter
        `rho_model`. Previous to the calculation of density the temperature at
        hub height is calculated using the method specified by the parameter
        `temperature_model`.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with timeseries for temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally the temperature `temp_air_2` in K at a different height
            for interpolation.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        rho_hub : pandas.Series or array
            Density of air in kg/m³ at hub height.

        """
        # Check if temperature data is at hub height.
        if 'temp_air_2' not in weather:
            weather['temp_air_2'] = None
            data_height['temp_air_2'] = None
        if data_height['temp_air'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (at hub height).')
            temp_hub = weather['temp_air']
        elif data_height['temp_air_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (2) (at hub height).')
            temp_hub = weather['temp_air_2']
        # Calculation of temperature in K at hub height.
        elif self.temperature_model == 'gradient':
            logging.debug('Calculating temperature using a temp. gradient.')
            temp_hub = density.temperature_gradient(
                weather['temp_air'], data_height['temp_air'],
                self.wind_turbine.hub_height)
        elif self.temperature_model == 'interpolation':
            logging.debug('Calculating temperature using interpolation.')
            temp_hub = density.temperature_interpol(
                weather['temp_air'], weather['temp_air_2'],
                data_height['temp_air'], data_height['temp_air_2'],
                self.wind_turbine.hub_height)
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.temperature_model) + "`temperature_model` " +
                             "must be 'gradient' or 'interpolation'.")
        # Calculation of density in kg/m³ at hub height
        if self.rho_model == 'barometric':
            logging.debug('Calculating density using barometric height eq.')
            rho_hub = density.rho_barometric(weather['pressure'],
                                             data_height['pressure'],
                                             self.wind_turbine.hub_height,
                                             temp_hub)
        elif self.rho_model == 'ideal_gas':
            logging.debug('Calculating density using ideal gas equation.')
            rho_hub = density.rho_ideal_gas(weather['pressure'],
                                            data_height['pressure'],
                                            self.wind_turbine.hub_height,
                                            temp_hub)
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.rho_model) + "`rho_model` " +
                             "must be 'barometric' or 'ideal_gas'.")
        return rho_hub

    def v_wind_hub(self, weather, data_height):
        r"""
        Calculates the wind speed at hub height.

        The method specified by the parameter `wind_model` is used.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s and roughness length `z0` in m, as well as
            optionally wind speed `v_wind_2` in m/s at different height.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        v_wind : pandas.Series or array
            Wind speed in m/s at hub height.

        Notes
        -----
        If `weather` contains wind speeds at different heights it is calculated
        with `v_wind` of which data height is closer to hub height.

        """
        # Check if wind speed data is at hub height.
        if 'v_wind_2' not in weather:
            weather['v_wind_2'] = None
            data_height['v_wind_2'] = None
        if data_height['v_wind'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (at hub height).')
            v_wind = weather['v_wind']
        elif data_height['v_wind_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (2) (at hub height).')
            v_wind = weather['v_wind_2']
        # Calculation of wind speed in m/s at hub height.
        elif self.wind_model == 'logarithmic':
            logging.debug('Calculating v_wind using logarithmic wind profile.')
            if weather['v_wind_2'].isnull().all():
                v_wind = wind_speed.logarithmic_wind_profile(
                    weather['v_wind'], data_height['v_wind'],
                    self.wind_turbine.hub_height,
                    weather['z0'], self.obstacle_height)
            else:
                if (abs(data_height['v_wind'] -
                        self.wind_turbine.hub_height) <=
                        abs(data_height['v_wind_2'] -
                            self.wind_turbine.hub_height)):
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind'], data_height['v_wind'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
                else:
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind_2'], data_height['v_wind_2'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
        elif self.wind_model == 'hellman':
            logging.debug('Calculating v_wind using hellman equation.')
            v_wind = wind_speed.v_wind_hellman(
                weather['v_wind'], data_height['v_wind'],
                self.wind_turbine.hub_height,
                self.hellman_exp, weather['z0'])
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.wind_model) + "`wind_model` " +
                             "must be 'logarithmic' or 'hellman'.")
        return v_wind

    def turbine_power_output(self, v_wind, rho_hub):
        r"""
        Calculates the power output of the wind turbine.

        The method specified by the parameter `power_output_model` is used.

        Parameters
        ----------
        v_wind : pandas.Series or array
            Wind speed at hub height in m/s.
        rho_hub : pandas.Series or array
            Density of air at hub height in kg/m³.

        Returns
        -------
        output : pandas.Series
            Electrical power in W of the wind turbine.

        """
        if self.power_output_model == 'cp_values':
            if self.wind_turbine.cp_values is None:
                raise TypeError("Cp values of " +
                                self.wind_turbine.turbine_name +
                                " are missing.")
            if self.density_corr is False:
                logging.debug('Calculating power output using cp curve.')
                output = power_output.cp_curve(v_wind, rho_hub,
                                               self.wind_turbine.d_rotor,
                                               self.wind_turbine.cp_values)
            elif self.density_corr is True:
                logging.debug('Calculating power output using density ' +
                              'corrected cp curve.')
                output = power_output.cp_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.d_rotor,
                    self.wind_turbine.cp_values)
            else:
                raise TypeError("'{0}' is an invalid type.".format(type(
                                self.density_corr)) + "`density_corr` must " +
                                "be Boolean (True or False).")
        elif self.power_output_model == 'p_values':
            if self.wind_turbine.p_values is None:
                raise TypeError("P values of " +
                                self.wind_turbine.turbine_name +
                                " are missing.")
            if self.density_corr is False:
                logging.debug('Calculating power output using power curve.')
                output = power_output.p_curve(self.wind_turbine.p_values,
                                              v_wind)
            elif self.density_corr is True:
                logging.debug('Calculating power output using density ' +
                              'corrected power curve.')
                output = power_output.p_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.p_values)
            else:
                raise TypeError("'{0}' is an invalid type.".format(type(
                                self.density_corr)) + "`density_corr` must " +
                                "be Boolean (True or False).")
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.power_output_model) +
                             "`power_output_model` " +
                             "must be 'cp_values' or 'p_values'.")
        return output

    def run_model(self, weather, data_height):
        r"""
        Runs the model.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s, roughness length `z0` in m, temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally wind speed `v_wind_2` in m/s and temperature
            `temp_air_2` in K at different height for interpolation.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        self

        """
        v_wind = self.v_wind_hub(weather, data_height)
        rho_hub = None if (self.power_output_model == 'p_values' and
                           self.density_corr is False) \
                       else self.rho_hub(weather, data_height)
        self.power_output = self.turbine_power_output(v_wind, rho_hub)
        return self
<commit_msg>Raise error if 'temp_air_2' not in `weather`<commit_after>"""
The ``modelchain`` module contains functions and classes of the
windpowerlib. This module makes it easy to get started with the windpowerlib
and demonstrates standard ways to use the library.

"""

__copyright__ = "Copyright oemof developer group"
__license__ = "GPLv3"

import logging
from windpowerlib import wind_speed, density, power_output

class ModelChain(object):
    r"""Model to determine the output of a wind turbine

    Parameters
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'p_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.

    Attributes
    ----------
    wind_turbine : WindTurbine
        A :class:`~.wind_turbine.WindTurbine` object representing the wind
        turbine.
    obstacle_height : float
        Height of obstacles in the surrounding area of the wind turbine in m.
        Set `obstacle_height` to zero for wide spread obstacles. Default: 0.
    wind_model : string
        Parameter to define which model to use to calculate the wind speed at
        hub height. Valid options are 'logarithmic' and 'hellman'.
        Default: 'logarithmic'.
    rho_model : string
        Parameter to define which model to use to calculate the density of air
        at hub height. Valid options are 'barometric' and 'ideal_gas'.
        Default: 'barometric'.
    temperature_model : string
        Parameter to define which model to use to calculate the temperature at
        hub height. Valid options are 'gradient' and 'interpolation'.
        Default: 'gradient'.
    power_output_model : string
        Parameter to define which model to use to calculate the turbine power
        output. Valid options are 'cp_values' and 'p_values'.
        Default: 'p_values'.
    density_corr : boolean
        If the parameter is True the density corrected power curve is used for
        the calculation of the turbine power output. Default: False.
    hellman_exp : float
        The Hellman exponent, which combines the increase in wind speed due to
        stability of atmospheric conditions and surface roughness into one
        constant. Default: None.
    power_output : pandas.Series
        Electrical power output of the wind turbine in W.

    Examples
    --------
    >>> from windpowerlib import modelchain
    >>> from windpowerlib import wind_turbine
    >>> enerconE126 = {
    ...    'hub_height': 135,
    ...    'd_rotor': 127,
    ...    'wind_conv_type': 'ENERCON E 126 7500'}
    >>> e126 = wind_turbine.WindTurbine(**enerconE126)
    >>> modelchain_data = {'rho_model': 'ideal_gas',
    ...    'temperature_model': 'interpolation'}
    >>> e126_md = modelchain.ModelChain(e126, **modelchain_data)
    >>> print(e126.d_rotor)
    127

    """

    def __init__(self, wind_turbine,
                 obstacle_height=0,
                 wind_model='logarithmic',
                 rho_model='barometric',
                 temperature_model='gradient',
                 power_output_model='p_values',
                 density_corr=False,
                 hellman_exp=None):

        self.wind_turbine = wind_turbine
        self.obstacle_height = obstacle_height
        self.wind_model = wind_model
        self.rho_model = rho_model
        self.temperature_model = temperature_model
        self.power_output_model = power_output_model
        self.density_corr = density_corr
        self.hellman_exp = hellman_exp
        self.power_output = None

    def rho_hub(self, weather, data_height):
        r"""
        Calculates the density of air at hub height.

        The density is calculated using the method specified by the parameter
        `rho_model`. Previous to the calculation of density the temperature at
        hub height is calculated using the method specified by the parameter
        `temperature_model`.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with timeseries for temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally the temperature `temp_air_2` in K at a different height
            for interpolation.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        rho_hub : pandas.Series or array
            Density of air in kg/m³ at hub height.

        """
        # Check if temperature data is at hub height.
        if 'temp_air_2' not in weather:
            weather['temp_air_2'] = None
            data_height['temp_air_2'] = None
        if data_height['temp_air'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (at hub height).')
            temp_hub = weather['temp_air']
        elif data_height['temp_air_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given temperature (2) (at hub height).')
            temp_hub = weather['temp_air_2']
        # Calculation of temperature in K at hub height.
        elif self.temperature_model == 'gradient':
            logging.debug('Calculating temperature using a temp. gradient.')
            temp_hub = density.temperature_gradient(
                weather['temp_air'], data_height['temp_air'],
                self.wind_turbine.hub_height)
        elif self.temperature_model == 'interpolation':
            try:
                logging.debug('Calculating temperature using interpolation.')
                temp_hub = density.temperature_interpol(
                    weather['temp_air'], weather['temp_air_2'],
                    data_height['temp_air'], data_height['temp_air_2'],
                    self.wind_turbine.hub_height)
            except TypeError:
                raise KeyError("No 'temp_air_2' in `weather`, but needed " +
                               "for interpolation.")
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.temperature_model) + "`temperature_model` " +
                             "must be 'gradient' or 'interpolation'.")
        # Calculation of density in kg/m³ at hub height
        if self.rho_model == 'barometric':
            logging.debug('Calculating density using barometric height eq.')
            rho_hub = density.rho_barometric(weather['pressure'],
                                             data_height['pressure'],
                                             self.wind_turbine.hub_height,
                                             temp_hub)
        elif self.rho_model == 'ideal_gas':
            logging.debug('Calculating density using ideal gas equation.')
            rho_hub = density.rho_ideal_gas(weather['pressure'],
                                            data_height['pressure'],
                                            self.wind_turbine.hub_height,
                                            temp_hub)
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.rho_model) + "`rho_model` " +
                             "must be 'barometric' or 'ideal_gas'.")
        return rho_hub

    def v_wind_hub(self, weather, data_height):
        r"""
        Calculates the wind speed at hub height.

        The method specified by the parameter `wind_model` is used.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s and roughness length `z0` in m, as well as
            optionally wind speed `v_wind_2` in m/s at different height.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        v_wind : pandas.Series or array
            Wind speed in m/s at hub height.

        Notes
        -----
        If `weather` contains wind speeds at different heights it is calculated
        with `v_wind` of which data height is closer to hub height.

        """
        # Check if wind speed data is at hub height.
        if 'v_wind_2' not in weather:
            weather['v_wind_2'] = None
            data_height['v_wind_2'] = None
        if data_height['v_wind'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (at hub height).')
            v_wind = weather['v_wind']
        elif data_height['v_wind_2'] == self.wind_turbine.hub_height:
            logging.debug('Using given wind speed (2) (at hub height).')
            v_wind = weather['v_wind_2']
        # Calculation of wind speed in m/s at hub height.
        elif self.wind_model == 'logarithmic':
            logging.debug('Calculating v_wind using logarithmic wind profile.')
            if weather['v_wind_2'].isnull().all():
                v_wind = wind_speed.logarithmic_wind_profile(
                    weather['v_wind'], data_height['v_wind'],
                    self.wind_turbine.hub_height,
                    weather['z0'], self.obstacle_height)
            else:
                if (abs(data_height['v_wind'] -
                        self.wind_turbine.hub_height) <=
                        abs(data_height['v_wind_2'] -
                            self.wind_turbine.hub_height)):
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind'], data_height['v_wind'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
                else:
                    v_wind = wind_speed.logarithmic_wind_profile(
                        weather['v_wind_2'], data_height['v_wind_2'],
                        self.wind_turbine.hub_height, weather['z0'],
                        self.obstacle_height)
        elif self.wind_model == 'hellman':
            logging.debug('Calculating v_wind using hellman equation.')
            v_wind = wind_speed.v_wind_hellman(
                weather['v_wind'], data_height['v_wind'],
                self.wind_turbine.hub_height,
                self.hellman_exp, weather['z0'])
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.wind_model) + "`wind_model` " +
                             "must be 'logarithmic' or 'hellman'.")
        return v_wind

    def turbine_power_output(self, v_wind, rho_hub):
        r"""
        Calculates the power output of the wind turbine.

        The method specified by the parameter `power_output_model` is used.

        Parameters
        ----------
        v_wind : pandas.Series or array
            Wind speed at hub height in m/s.
        rho_hub : pandas.Series or array
            Density of air at hub height in kg/m³.

        Returns
        -------
        output : pandas.Series
            Electrical power in W of the wind turbine.

        """
        if self.power_output_model == 'cp_values':
            if self.wind_turbine.cp_values is None:
                raise TypeError("Cp values of " +
                                self.wind_turbine.turbine_name +
                                " are missing.")
            if self.density_corr is False:
                logging.debug('Calculating power output using cp curve.')
                output = power_output.cp_curve(v_wind, rho_hub,
                                               self.wind_turbine.d_rotor,
                                               self.wind_turbine.cp_values)
            elif self.density_corr is True:
                logging.debug('Calculating power output using density ' +
                              'corrected cp curve.')
                output = power_output.cp_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.d_rotor,
                    self.wind_turbine.cp_values)
            else:
                raise TypeError("'{0}' is an invalid type.".format(type(
                                self.density_corr)) + "`density_corr` must " +
                                "be Boolean (True or False).")
        elif self.power_output_model == 'p_values':
            if self.wind_turbine.p_values is None:
                raise TypeError("P values of " +
                                self.wind_turbine.turbine_name +
                                " are missing.")
            if self.density_corr is False:
                logging.debug('Calculating power output using power curve.')
                output = power_output.p_curve(self.wind_turbine.p_values,
                                              v_wind)
            elif self.density_corr is True:
                logging.debug('Calculating power output using density ' +
                              'corrected power curve.')
                output = power_output.p_curve_density_corr(
                    v_wind, rho_hub, self.wind_turbine.p_values)
            else:
                raise TypeError("'{0}' is an invalid type.".format(type(
                                self.density_corr)) + "`density_corr` must " +
                                "be Boolean (True or False).")
        else:
            raise ValueError("'{0}' is an invalid value.".format(
                             self.power_output_model) +
                             "`power_output_model` " +
                             "must be 'cp_values' or 'p_values'.")
        return output

    def run_model(self, weather, data_height):
        r"""
        Runs the model.

        Parameters
        ----------
        weather : DataFrame or Dictionary
            Containing columns or keys with the timeseries for wind speed
            `v_wind` in m/s, roughness length `z0` in m, temperature
            `temp_air` in K and pressure `pressure` in Pa, as well as
            optionally wind speed `v_wind_2` in m/s and temperature
            `temp_air_2` in K at different height for interpolation.
            If a Dictionary is used the data inside the dictionary has to be of
            the types pandas.Series or numpy.array.
        data_height : DataFrame or Dictionary
            Containing columns or keys with the heights in m for which the
            corresponding parameters in `weather` apply.

        Returns
        -------
        self

        """
        v_wind = self.v_wind_hub(weather, data_height)
        rho_hub = None if (self.power_output_model == 'p_values' and
                           self.density_corr is False) \
                       else self.rho_hub(weather, data_height)
        self.power_output = self.turbine_power_output(v_wind, rho_hub)
        return self
<|endoftext|>