<commit_before># -*- coding: UTF-8 -*-
""" Create coupons for speakers:

    Talk     - 25%
    Training - 100%

    Write the created coupons as CSV data to stdout. The script makes
    sure that no duplicate coupons are created. If you want a coupon
    to get recreated, deleted it in the database first and then run
    the script.

    Use --dry-run to test drive the script.

"""
import string
import random
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError
from django.db import transaction

from conference import models as cmodels
from assopy.models import Coupon

### Globals

# From cmodels.TALK_TYPES
TALK_TYPE_TALK = 's'
TALK_TYPE_TRAINING = 't'

# Discounts
SPEAKER_DISCOUNT = '25%'
TRAINING_DISCOUNT = '100%'

# Coupon prefix (3 letters)
COUPON_PREFIX = {
    'speaker': 'SPK',
    'trainer': 'TRN',
    }

###

class Command(BaseCommand):

    option_list = BaseCommand.option_list + (
        make_option('--dry-run',
                    action='store_true',
                    dest='dry_run',
                    help='Do everything except create the coupons',
                    ),
    )

    # Dry run ?
    dry_run = False

    @transaction.commit_on_success
    def handle(self, *args, **options):

        self.dry_run = options.get('dry_run', False)

        try:
            conference = cmodels.Conference.objects.get(code=args[0])
        except IndexError:
            raise CommandError('conference missing')

        # Find speakers eligible for coupons
        speakers = {}
        qs = cmodels.TalkSpeaker.objects\
            .filter(talk__conference=conference.code, talk__status='accepted')\
            .select_related('talk', 'speaker__user')
        for row in qs:
            if row.talk.type not in (TALK_TYPE_TALK,
                                     TALK_TYPE_TRAINING):
                continue
            if row.speaker_id not in speakers:
                entry = {
                    'spk': row.speaker,
                    'title': row.talk.title,
                    'duration': row.talk.duration,
                    'discount': SPEAKER_DISCOUNT,
                    'type': 'speaker',
                    }
                speakers[row.speaker_id] = entry
            else:
                entry = speakers[row.speaker_id]
            # Override discount with 'training' for trainings; this
            # means that someone who does both a talk and training,
            # will get a training discount
            if row.talk.type == TALK_TYPE_TRAINING:
                entry['discount'] = TRAINING_DISCOUNT
                entry['type'] = 'trainer'
                entry['title'] = row.talk.title
                entry['duration'] = row.talk.duration

        # Valid fares (conference fares only)
        fares = cmodels.Fare.objects\
            .filter(conference=conference.code,
                    ticket_type='conference')

        # Get set of existing codes
        codes = set(c['code'] for c in Coupon.objects\
            .filter(conference=conference.code)\
            .values('code'))

        # Get coupon emails of already issued coupons
        existing_coupon_emails = set(
            c['user__user__email']
            for c in Coupon.objects\
            .filter(conference=conference.code)\
            .select_related('user')\
            .values('user__user__email', 'code')
            if (c['code'].startswith(tuple(COUPON_PREFIX.values()))
                and c['user__user__email'])
            )

        # Create coupons
        data = []
        for sid, entry in speakers.items():

            # Get coupon data
            type = entry['type']
            user = entry['spk'].user
            value = entry['discount']

            # Check if we have already issued a coupon
            if user.email in existing_coupon_emails:
                continue

            # Determine a new code
            coupon_prefix = COUPON_PREFIX[type]
            while True:
                # Codes: SPK-RANDOM
                code = (coupon_prefix + '-'
                        + ''.join(random.sample(string.uppercase, 6)))
                if code not in codes:
                    codes.add(code)
                    break

            # Build CSV data
            name = u'%s %s' % (user.first_name, user.last_name)
            data_row = (
                user.email,
                name,
                entry['type'],
                code,
                value,
                entry['title'],
                entry['duration'],
                )

            # Create coupon
            c = Coupon(conference=conference)
            c.code = code
            c.user = user.assopy_user
            c.max_usage = 1
            c.items_per_usage = 1
            c.value = value
            c.description = '[%s] %s discount' % (
                conference, entry['type'])
            if not self.dry_run:
                c.save()
                c.fares = fares
            data.append(data_row)

        # Output CSV data, UTF-8 encoded
        data.insert(0, (
            # Header
            'email', 'name', 'type', 'code', 'discount', 'title', 'duration'))
        for row in data:
            csv_data = (u'"%s"' % (unicode(x).replace(u'"', u'""'))
                        for x in row)
            print (u','.join(csv_data).encode('utf-8'))
<commit_msg>Add note about sponsored talks.<commit_after># -*- coding: UTF-8 -*-
""" Create coupons for speakers:

    Talk     - 25%
    Training - 100%

    Write the created coupons as CSV data to stdout. The script makes
    sure that no duplicate coupons are created. If you want a coupon
    to get recreated, deleted it in the database first and then run
    the script.

    Use --dry-run to test drive the script.

    WARNING: This script will create coupons for all speakers,
    including ones which are giving sponsored talks.

"""
import string
import random
from optparse import make_option

from django.core.management.base import BaseCommand, CommandError
from django.db import transaction

from conference import models as cmodels
from assopy.models import Coupon

### Globals

# From cmodels.TALK_TYPES
TALK_TYPE_TALK = 's'
TALK_TYPE_TRAINING = 't'

# Discounts
SPEAKER_DISCOUNT = '25%'
TRAINING_DISCOUNT = '100%'

# Coupon prefix (3 letters)
COUPON_PREFIX = {
    'speaker': 'SPK',
    'trainer': 'TRN',
    }

###

class Command(BaseCommand):

    option_list = BaseCommand.option_list + (
        make_option('--dry-run',
                    action='store_true',
                    dest='dry_run',
                    help='Do everything except create the coupons',
                    ),
    )

    # Dry run ?
    dry_run = False

    @transaction.commit_on_success
    def handle(self, *args, **options):

        self.dry_run = options.get('dry_run', False)

        try:
            conference = cmodels.Conference.objects.get(code=args[0])
        except IndexError:
            raise CommandError('conference missing')

        # Find speakers eligible for coupons
        speakers = {}
        qs = cmodels.TalkSpeaker.objects\
            .filter(talk__conference=conference.code, talk__status='accepted')\
            .select_related('talk', 'speaker__user')
        for row in qs:
            if row.talk.type not in (TALK_TYPE_TALK,
                                     TALK_TYPE_TRAINING):
                continue
            if row.speaker_id not in speakers:
                entry = {
                    'spk': row.speaker,
                    'title': row.talk.title,
                    'duration': row.talk.duration,
                    'discount': SPEAKER_DISCOUNT,
                    'type': 'speaker',
                    }
                speakers[row.speaker_id] = entry
            else:
                entry = speakers[row.speaker_id]
            # Override discount with 'training' for trainings; this
            # means that someone who does both a talk and training,
            # will get a training discount
            if row.talk.type == TALK_TYPE_TRAINING:
                entry['discount'] = TRAINING_DISCOUNT
                entry['type'] = 'trainer'
                entry['title'] = row.talk.title
                entry['duration'] = row.talk.duration

        # Valid fares (conference fares only)
        fares = cmodels.Fare.objects\
            .filter(conference=conference.code,
                    ticket_type='conference')

        # Get set of existing codes
        codes = set(c['code'] for c in Coupon.objects\
            .filter(conference=conference.code)\
            .values('code'))

        # Get coupon emails of already issued coupons
        existing_coupon_emails = set(
            c['user__user__email']
            for c in Coupon.objects\
            .filter(conference=conference.code)\
            .select_related('user')\
            .values('user__user__email', 'code')
            if (c['code'].startswith(tuple(COUPON_PREFIX.values()))
                and c['user__user__email'])
            )

        # Create coupons
        data = []
        for sid, entry in speakers.items():

            # Get coupon data
            type = entry['type']
            user = entry['spk'].user
            value = entry['discount']

            # Check if we have already issued a coupon
            if user.email in existing_coupon_emails:
                continue

            # Determine a new code
            coupon_prefix = COUPON_PREFIX[type]
            while True:
                # Codes: SPK-RANDOM
                code = (coupon_prefix + '-'
                        + ''.join(random.sample(string.uppercase, 6)))
                if code not in codes:
                    codes.add(code)
                    break

            # Build CSV data
            name = u'%s %s' % (user.first_name, user.last_name)
            data_row = (
                user.email,
                name,
                entry['type'],
                code,
                value,
                entry['title'],
                entry['duration'],
                )

            # Create coupon
            c = Coupon(conference=conference)
            c.code = code
            c.user = user.assopy_user
            c.max_usage = 1
            c.items_per_usage = 1
            c.value = value
            c.description = '[%s] %s discount' % (
                conference, entry['type'])
            if not self.dry_run:
                c.save()
                c.fares = fares
            data.append(data_row)

        # Output CSV data, UTF-8 encoded
        data.insert(0, (
            # Header
            'email', 'name', 'type', 'code', 'discount', 'title', 'duration'))
        for row in data:
            csv_data = (u'"%s"' % (unicode(x).replace(u'"', u'""'))
                        for x in row)
            print (u','.join(csv_data).encode('utf-8'))
<|endoftext|>


<commit_before>"""interpret event traces as test activity

this file serves as an example for the xunitgen module

event traces are similar/compatible with those produced by uu.spdr

https://github.com/uucidl/uu.spdr
"""
from argparse import ArgumentParser

import os
import re

from socket import gethostname

from xunitgen import EventReceiver, toxml

def parse_trace(line):
    main_re = r'^TT01 ([0-9]+) ([0-9]+) ([0-9]+) ("(?:[^\\"]|\\.)*") ("(?:[^\\"]|\\.)*") ("[A-Z]")(.*)$'
    match = re.match(main_re, line)
    if match:
        def get(i):
            return match.group(i)

        def unquote_str(string):
            return eval(string)

        trace = dict(
            ts=int(get(1)),
            pid=int(get(2)),
            tid=int(get(3)),
            cat=unquote_str(get(4)),
            name=unquote_str(get(5)),
            ph=unquote_str(get(6)),
            args={},
        )

        arg_str = get(7)
        if arg_str:
            for match in re.finditer(r' ("(?:[^\\"]|\\.)*") ((?:"(?:[^\\"]|\\.)*")|(?:[0-9]+\.[0-9]*)|(?:[0-9]+))', arg_str):
                name = unquote_str(get(1))
                value_str = get(2)
                if re.match(r'^"(?:[^\\"]|\\.)*"$', value_str):
                    value = unquote_str(value_str)
                elif re.match(r'^[0-9]+\.[0-9]*$', value_str):
                    value = float(value_str)
                elif re.match(r'^[0-9]+$', value_str):
                    value = int(value_str)

                trace['args'][name] = value

            if not trace['args']:
                raise Exception('Could not parse args %r' % arg_str)

        return trace

    raise Exception('Could not parse %r' % line)

def gather_test_results(traces):
    MICROS_TO_S = 1000000.0
    receiver = EventReceiver()

    for trace in traces:
        ts_seconds = trace['ts'] / MICROS_TO_S
        if trace['cat'] == 'test':
            if trace['ph'] == 'E' and receiver.current_case.name == trace['name']:
                receiver.end_case(trace['name'], ts_seconds)
            elif trace['ph'] == 'B' and receiver.current_case is None:
                receiver.begin_case(
                    trace['name'], ts_seconds, os.path.splitext(
                        trace['args']['filename'])[0].replace(os.sep, '.')
                )
            elif trace['ph'] == 'I' and trace['name'] == 'failure':
                receiver.failure(trace['args'][
                                 'reason'], trace['args']['lineno'])

    return receiver.results()

def main():
    parser = ArgumentParser()
    parser.add_argument("dst_xunit_file")
    parser.add_argument("src_trace_log")

    args = parser.parse_args()

    with open(args.src_trace_log) as file:
        def parse_line(line_i, line):
            try:
                return parse_trace(line)
            except Exception as e:
                raise Exception('%s:%d: error: %r' % (
                    args.src_trace_log, i, e))

        test_results = gather_test_results(
            [parse_line(i, line) for i, line in enumerate(file.readlines())]
        )

    with open(args.dst_xunit_file, 'w') as file:
        file.write(tostring(test_results, gethostname()))

if __name__ == "__main__":
    main()
<commit_msg>modernize event_traces example<commit_after>"""interpret event traces as test activity

this file serves as an example for the xunitgen module

event traces are similar/compatible with those produced by uu.spdr

https://github.com/uucidl/uu.spdr
"""
from argparse import ArgumentParser

import os
import re

from socket import gethostname

from xunitgen import XunitDestination, EventReceiver, toxml

def parse_trace(line):
    main_re = r'^TT01 ([0-9]+) ([0-9]+) ([0-9]+) ("(?:[^\\"]|\\.)*") ("(?:[^\\"]|\\.)*") ("[A-Z]")(.*)$'
    match = re.match(main_re, line)
    if match:
        def get(i):
            return match.group(i)

        def unquote_str(string):
            return eval(string)

        trace = dict(
            ts=int(get(1)),
            pid=int(get(2)),
            tid=int(get(3)),
            cat=unquote_str(get(4)),
            name=unquote_str(get(5)),
            ph=unquote_str(get(6)),
            args={},
        )

        arg_str = get(7)
        if arg_str:
            for match in re.finditer(r' ("(?:[^\\"]|\\.)*") ((?:"(?:[^\\"]|\\.)*")|(?:[0-9]+\.[0-9]*)|(?:[0-9]+))', arg_str):
                name = unquote_str(get(1))
                value_str = get(2)
                if re.match(r'^"(?:[^\\"]|\\.)*"$', value_str):
                    value = unquote_str(value_str)
                elif re.match(r'^[0-9]+\.[0-9]*$', value_str):
                    value = float(value_str)
                elif re.match(r'^[0-9]+$', value_str):
                    value = int(value_str)

                trace['args'][name] = value

            if not trace['args']:
                raise Exception('Could not parse args %r' % arg_str)

        return trace

    raise Exception('Could not parse %r' % line)

def gather_test_results(traces):
    MICROS_TO_S = 1000000.0
    receiver = EventReceiver()

    for trace in traces:
        ts_seconds = trace['ts'] / MICROS_TO_S
        if trace['cat'] == 'test':
            if trace['ph'] == 'E' and receiver.current_case.name == trace['name']:
                receiver.end_case(trace['name'], ts_seconds)
            elif trace['ph'] == 'B' and receiver.current_case is None:
                receiver.begin_case(
                    trace['name'], ts_seconds, os.path.splitext(
                        trace['args']['filename'])[0].replace(os.sep, '.')
                )
            elif trace['ph'] == 'I' and trace['name'] == 'failure':
                receiver.failure(trace['args'][
                                 'reason'], trace['args']['lineno'])

    return receiver.results()

def main():
    parser = ArgumentParser()
    parser.add_argument("dst_xunit_file")
    parser.add_argument("src_trace_log")

    args = parser.parse_args()

    destination = XunitDestination(os.path.dirname(os.path.abspath(args.dst_xunit_file)))
    xml_filepath = os.path.splitext(os.path.basename(args.dst_xunit_file))[0]
    with open(args.src_trace_log) as file:
        def parse_line(line_i, line):
            try:
                return parse_trace(line)
            except Exception as e:
                raise Exception('%s:%d: error: %r' % (
                    args.src_trace_log, i, e))

        test_results = gather_test_results(
            [parse_line(i, line) for i, line in enumerate(file.readlines())]
        )

    destination.write_reports(xml_filepath, 'testsuite', test_results)

if __name__ == "__main__":
    main()
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Local development settings.

Copyright 2011-2012 Plexical. See LICENCE for permissions.
"""
import os

from starter.settings import *

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ENV = 'dev'

ADMINS = (
    ('Foo Bar', 'foo@example.com'),
)

MANAGERS = ADMINS

"""
This server's own opinion of it's name.
"""
INSTANCE_URL = 'http://localhost:8000'

ADMINS = (
    ('Jacob Oscarson', 'jacob@plexical.com'),
)

MANAGERS = ADMINS

DATABASES = {
    'default': {
        # 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': path(PROJECT_DIR, '..', 'var', 'dev.db'),
    }
}

# SPATIALITE_LIBRARY_PATH = '/Library/Frameworks/SQLite3.framework/SQLite3'

"""
Absolute filesystem path to the directory that will hold user-uploaded files.
Example: `"/home/media/media.lawrence.com/`
"""
MEDIA_ROOT = path(PROJECT_DIR, '..', 'static', 'media')

STATIC_ROOT = path(PROJECT_DIR, 'static')

STATICFILES_DIRS = (
    path(PROJECT_DIR, '..', 'static'),
)

"""
Make this unique, and don't share it with anybody.
"""
SECRET_KEY = 'my-supersecret-developer-key'

"""
Per environment specific apps.
Relevant place to put development environment specific installed apps.
"""
INSTALLED_APPS = BASE_INSTALLED_APPS + (
    'django_pytest',
    'werkzeug_debugger_runserver'
)

TEST_RUNNER = 'django_pytest.test_runner.run_tests'
<commit_msg>Removed extra ADMINS setting<commit_after># -*- coding: utf-8 -*-
"""
Local development settings.

Copyright 2011-2012 Plexical. See LICENCE for permissions.
"""
import os

from starter.settings import *

DEBUG = True
TEMPLATE_DEBUG = DEBUG

ENV = 'dev'

ADMINS = (
    ('Foo Bar', 'foo@example.com'),
)

MANAGERS = ADMINS

"""
This server's own opinion of it's name.
"""
INSTANCE_URL = 'http://localhost:8000'

MANAGERS = ADMINS

DATABASES = {
    'default': {
        # 'ENGINE': 'django.contrib.gis.db.backends.spatialite',
        'ENGINE': 'django.db.backends.sqlite3',
        'NAME': path(PROJECT_DIR, '..', 'var', 'dev.db'),
    }
}

# SPATIALITE_LIBRARY_PATH = '/Library/Frameworks/SQLite3.framework/SQLite3'

"""
Absolute filesystem path to the directory that will hold user-uploaded files.
Example: `"/home/media/media.lawrence.com/`
"""
MEDIA_ROOT = path(PROJECT_DIR, '..', 'static', 'media')

STATIC_ROOT = path(PROJECT_DIR, 'static')

STATICFILES_DIRS = (
    path(PROJECT_DIR, '..', 'static'),
)

"""
Make this unique, and don't share it with anybody.
"""
SECRET_KEY = 'my-supersecret-developer-key'

"""
Per environment specific apps.
Relevant place to put development environment specific installed apps.
"""
INSTALLED_APPS = BASE_INSTALLED_APPS + (
    'django_pytest',
    'werkzeug_debugger_runserver'
)

TEST_RUNNER = 'django_pytest.test_runner.run_tests'
<|endoftext|>


<commit_before>#!/usr/bin/env python
# __BEGIN_LICENSE__
# Copyright (c) 2015, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All rights reserved.
#
# The xGDS platform is licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# __END_LICENSE__

"""
This bootstrap script does the first stage of prep work for a Django
site that consists of multiple apps pulled in from separate repos via
git submodules.  The script does just enough so that our subsequent
Django management commands will work -- they need Django to be installed
and minimally configured, and they need the apps to be present
and linked into the right place relative to the PYTHONPATH.

This script is intended to be generic across sites.  Please don't put
any site-specific customizations in here.  If you need to modify it,
please check your changes into
geocamDjangoSiteSkeleton/skel/bin/bootstrap.py so other sites can
benefit.  Normally we would put code like this in geocamUtil, but the
whole reason we need a bootstrap step is to make sure things like
geocamUtil are available...
"""

import os
import sys
from glob import glob
import logging
from random import choice

DEFAULT_SITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SOURCEME_NAME = 'sourceme.sh'
SETTINGS_NAME = 'settings.py'
STATUS_PATH_TEMPLATE = 'build/management/bootstrap/%sStatus.txt'

ACTIONS = (dict(name='gitInitSubmodules',
                desc="init and update submodules",
                confirm=True),
           dict(name='linkSubmodules',
                desc='link submodules into apps directory',
                confirm=True),
           dict(name='installDjango',
                desc='install Django',
                confirm=True,
                needed='needDjango'),
           dict(name='genSourceme',
                needed='needSourceme'),
           dict(name='genSettings',
                needed='needSettings'),
           )
ACTION_DICT = dict([(a['name'], a) for a in ACTIONS])

def getConfirmation(opts, actionStr):
    if opts.yes:
        sys.stdout.write(actionStr + '? [Y/n] ')
        print 'y'
        return True
    else:
        while 1:
            sys.stdout.write(actionStr + '? [Y/n] ')
            response = raw_input().strip().lower()
            if not response:
                return True
            elif response == 'y':
                return True
            elif response == 'n':
                return False

def dosys(cmd, continueOnError=False):
    if cmd.startswith('sudo'):
        # force print before user gets password prompt
        print 'running: ' + cmd
    else:
        logging.info('running: ' + cmd)
    ret = os.system(cmd)
    if ret != 0:
        if continueOnError:
            logging.warning('warning: command returned non-zero return value %d' % ret)
        else:
            logging.error('error: command returned non-zero return value %d' % ret)
            sys.exit(1)

def writeFileMakeDir(path, text):
    theDir = os.path.dirname(path)
    if not os.path.exists(theDir):
        os.makedirs(theDir)
    f = file(path, 'w')
    f.write(text + '\n')
    f.close()

def fillTemplate(inputFile, outputFile, context):
    from django.template import Template, Context
    from django.conf import settings
    if not settings.configured:
        settings.configure()
    tmpl = Template(file(inputFile, 'r').read())
    text = tmpl.render(Context(context))
    file(outputFile, 'w').write(text)

######################################################################
# ACTION DEFINITIONS

def gitInitSubmodules(opts):
    dosys('git submodule init')
    dosys('git submodule update')

def linkSubmodules(opts):
    if not os.path.exists('apps'):
        os.mkdir('apps')
    # assumes each submodule app has a models dir or a models.py file
    submoduleAppDirs = [os.path.dirname(d) for d in glob('submodules/*/*/models*')]
    for src in submoduleAppDirs:
        appName = os.path.basename(src)
        relativeSrc = '../%s' % src
        dst = 'apps/%s' % appName
        if os.path.lexists(dst):
            logging.debug('  %s -> %s skipped (already exists)' % (dst, relativeSrc))
        else:
            logging.debug('  %s -> %s' % (dst, relativeSrc))
            os.symlink(relativeSrc, dst)

def needDjango(opts):
    try:
        import django
    except ImportError:
        return True
    return False

def installDjango(opts):
    needSudo = 'VIRTUALENV' not in os.environ
    if needSudo:
        sudoStr = 'sudo '
    else:
        sudoStr = ''
    dosys('%spip install django' % sudoStr)

def needSourceme(opts):
    return not os.path.exists(SOURCEME_NAME)

def genSourceme(opts):
    logging.info('generating %s' % SOURCEME_NAME)

    fillTemplate('management/templates/%s' % SOURCEME_NAME,
                 SOURCEME_NAME,
                 dict(virtualEnvDir=os.environ.get('VIRTUALENV', None),
                      parentDir=os.path.dirname(os.path.abspath(os.getcwd())),
                      appsDir=os.path.abspath('apps')
                      ))

def needSettings(opts):
    return not os.path.exists(SETTINGS_NAME)

def genSettings(opts):
    logging.info('generating %s' % SETTINGS_NAME)

    secretKey = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])

    fillTemplate('management/templates/%s' % SETTINGS_NAME,
                 SETTINGS_NAME,
                 dict(secretKey=secretKey))

def needAction(opts, action):
    statusFile = STATUS_PATH_TEMPLATE % action['name']
    if os.path.exists(statusFile):
        return file(statusFile, 'r').read().strip()
    else:
        return False

######################################################################
# TOP-LEVEL CODE

def doAction(opts, action):
    # check if we need to do the action
    neededName = action.get('needed', None)
    if neededName:
        # special check function defined for this action
        neededFunc = globals()[neededName]
        actionIsNeeded = neededFunc(opts)
        if not actionIsNeeded:
            logging.info('skipping step %s, not needed' % action['name'])
            return
    else:
        # standard check function
        status = needAction(opts, action)
        if status:
            logging.info('skipping step %s, status is %s' % (action['name'], status))
            return

    # confirm with user
    if 'confirm' in action and not getConfirmation(opts, action['desc']):
        writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'UNWANTED')
        return

    # do the action
    actionFunc = globals()[action['name']]
    actionFunc(opts)

    # mark completion (unless special check function is defined)
    if not neededName:
        writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'DONE')

def doit(opts, args):
    os.chdir(opts.siteDir)
    if os.path.exists('build/management/bootstrap/bootstrapStatus.txt'):
        sys.exit(0)
    print 'bootstrapping...'

    logging.basicConfig(level=(logging.WARNING - opts.verbose * 10),
                        format='%(message)s')

    if args:
        for arg in args:
            if arg not in ACTION_DICT:
                print >>sys.stderr, 'ERROR: there is no action %s' % arg
                print >>sys.stderr, 'available actions are: %s' % (' '.join([a['name'] for a in ACTIONS]))
                sys.exit(1)
        actions = [ACTION_DICT[arg] for arg in args]
    else:
        actions = ACTIONS

    logging.info('working in %s' % os.getcwd())
    for action in actions:
        doAction(opts, action)

    # mark overall completion
    writeFileMakeDir(STATUS_PATH_TEMPLATE % 'bootstrap', 'DONE')

    print '\nnow "source sourceme.sh" before running manage.py again'
    sys.exit(1)

def main():
    import optparse
    parser = optparse.OptionParser('usage: %prog [action1 action2 ...]')
    parser.add_option('-y', '--yes',
                      action='store_true', default=False,
                      help='Automatically answer yes to all confirmation questions')
    parser.add_option('-s', '--siteDir',
                      default=DEFAULT_SITE_DIR,
                      help='Site directory to work in [%default]')
    parser.add_option('-v', '--verbose',
                      action='count', default=0,
                      help='Increase verbosity, can specify multiple times')
    opts, args = parser.parse_args()
    doit(opts, args)

if __name__ == '__main__':
    main()
<commit_msg>call bootstrap with puppet option to suppress output<commit_after>#!/usr/bin/env python
# __BEGIN_LICENSE__
# Copyright (c) 2015, United States Government, as represented by the
# Administrator of the National Aeronautics and Space Administration.
# All rights reserved.
#
# The xGDS platform is licensed under the Apache License, Version 2.0
# (the "License"); you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
# http://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software distributed
# under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
# CONDITIONS OF ANY KIND, either express or implied. See the License for the
# specific language governing permissions and limitations under the License.
# __END_LICENSE__

"""
This bootstrap script does the first stage of prep work for a Django
site that consists of multiple apps pulled in from separate repos via
git submodules.  The script does just enough so that our subsequent
Django management commands will work -- they need Django to be installed
and minimally configured, and they need the apps to be present
and linked into the right place relative to the PYTHONPATH.

This script is intended to be generic across sites.  Please don't put
any site-specific customizations in here.  If you need to modify it,
please check your changes into
geocamDjangoSiteSkeleton/skel/bin/bootstrap.py so other sites can
benefit.  Normally we would put code like this in geocamUtil, but the
whole reason we need a bootstrap step is to make sure things like
geocamUtil are available...
"""

import os
import sys
from glob import glob
import logging
from random import choice

DEFAULT_SITE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

SOURCEME_NAME = 'sourceme.sh'
SETTINGS_NAME = 'settings.py'
STATUS_PATH_TEMPLATE = 'build/management/bootstrap/%sStatus.txt'

ACTIONS = (dict(name='gitInitSubmodules',
                desc="init and update submodules",
                confirm=True),
           dict(name='linkSubmodules',
                desc='link submodules into apps directory',
                confirm=True),
           dict(name='installDjango',
                desc='install Django',
                confirm=True,
                needed='needDjango'),
           dict(name='genSourceme',
                needed='needSourceme'),
           dict(name='genSettings',
                needed='needSettings'),
           )
ACTION_DICT = dict([(a['name'], a) for a in ACTIONS])

def getConfirmation(opts, actionStr):
    if opts.yes:
        sys.stdout.write(actionStr + '? [Y/n] ')
        print 'y'
        return True
    else:
        while 1:
            sys.stdout.write(actionStr + '? [Y/n] ')
            response = raw_input().strip().lower()
            if not response:
                return True
            elif response == 'y':
                return True
            elif response == 'n':
                return False

def dosys(cmd, continueOnError=False):
    if cmd.startswith('sudo'):
        # force print before user gets password prompt
        print 'running: ' + cmd
    else:
        logging.info('running: ' + cmd)
    ret = os.system(cmd)
    if ret != 0:
        if continueOnError:
            logging.warning('warning: command returned non-zero return value %d' % ret)
        else:
            logging.error('error: command returned non-zero return value %d' % ret)
            sys.exit(1)

def writeFileMakeDir(path, text):
    theDir = os.path.dirname(path)
    if not os.path.exists(theDir):
        os.makedirs(theDir)
    f = file(path, 'w')
    f.write(text + '\n')
    f.close()

def fillTemplate(inputFile, outputFile, context):
    from django.template import Template, Context
    from django.conf import settings
    if not settings.configured:
        settings.configure()
    tmpl = Template(file(inputFile, 'r').read())
    text = tmpl.render(Context(context))
    file(outputFile, 'w').write(text)

######################################################################
# ACTION DEFINITIONS

def gitInitSubmodules(opts):
    dosys('git submodule init')
    dosys('git submodule update')

def linkSubmodules(opts):
    if not os.path.exists('apps'):
        os.mkdir('apps')
    # assumes each submodule app has a models dir or a models.py file
    submoduleAppDirs = [os.path.dirname(d) for d in glob('submodules/*/*/models*')]
    for src in submoduleAppDirs:
        appName = os.path.basename(src)
        relativeSrc = '../%s' % src
        dst = 'apps/%s' % appName
        if os.path.lexists(dst):
            logging.debug('  %s -> %s skipped (already exists)' % (dst, relativeSrc))
        else:
            logging.debug('  %s -> %s' % (dst, relativeSrc))
            os.symlink(relativeSrc, dst)

def needDjango(opts):
    try:
        import django
    except ImportError:
        return True
    return False

def installDjango(opts):
    needSudo = 'VIRTUALENV' not in os.environ
    if needSudo:
        sudoStr = 'sudo '
    else:
        sudoStr = ''
    dosys('%spip install django' % sudoStr)

def needSourceme(opts):
    return not os.path.exists(SOURCEME_NAME)

def genSourceme(opts):
    logging.info('generating %s' % SOURCEME_NAME)

    fillTemplate('management/templates/%s' % SOURCEME_NAME,
                 SOURCEME_NAME,
                 dict(virtualEnvDir=os.environ.get('VIRTUALENV', None),
                      parentDir=os.path.dirname(os.path.abspath(os.getcwd())),
                      appsDir=os.path.abspath('apps')
                      ))

def needSettings(opts):
    return not os.path.exists(SETTINGS_NAME)

def genSettings(opts):
    logging.info('generating %s' % SETTINGS_NAME)

    secretKey = ''.join([choice('abcdefghijklmnopqrstuvwxyz0123456789!@#$%^&*(-_=+)') for i in range(50)])

    fillTemplate('management/templates/%s' % SETTINGS_NAME,
                 SETTINGS_NAME,
                 dict(secretKey=secretKey))

def needAction(opts, action):
    statusFile = STATUS_PATH_TEMPLATE % action['name']
    if os.path.exists(statusFile):
        return file(statusFile, 'r').read().strip()
    else:
        return False

######################################################################
# TOP-LEVEL CODE

def doAction(opts, action):
    # check if we need to do the action
    neededName = action.get('needed', None)
    if neededName:
        # special check function defined for this action
        neededFunc = globals()[neededName]
        actionIsNeeded = neededFunc(opts)
        if not actionIsNeeded:
            logging.info('skipping step %s, not needed' % action['name'])
            return
    else:
        # standard check function
        status = needAction(opts, action)
        if status:
            logging.info('skipping step %s, status is %s' % (action['name'], status))
            return

    # confirm with user
    if 'confirm' in action and not getConfirmation(opts, action['desc']):
        writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'UNWANTED')
        return

    # do the action
    actionFunc = globals()[action['name']]
    actionFunc(opts)

    # mark completion (unless special check function is defined)
    if not neededName:
        writeFileMakeDir(STATUS_PATH_TEMPLATE % action['name'], 'DONE')

def doit(opts, args):
    os.chdir(opts.siteDir)
    if os.path.exists('build/management/bootstrap/bootstrapStatus.txt'):
        sys.exit(0)
    print 'bootstrapping...'

    logging.basicConfig(level=(logging.WARNING - opts.verbose * 10),
                        format='%(message)s')

    if args:
        for arg in args:
            if arg not in ACTION_DICT:
                print >>sys.stderr, 'ERROR: there is no action %s' % arg
                print >>sys.stderr, 'available actions are: %s' % (' '.join([a['name'] for a in ACTIONS]))
                sys.exit(1)
        actions = [ACTION_DICT[arg] for arg in args]
    else:
        actions = ACTIONS

    logging.info('working in %s' % os.getcwd())
    for action in actions:
        doAction(opts, action)

    # mark overall completion
    writeFileMakeDir(STATUS_PATH_TEMPLATE % 'bootstrap', 'DONE')

    if not opts.puppet:
        print '\nnow "source sourceme.sh" before running manage.py again'
    sys.exit(1)

def main():
    import optparse
    parser = optparse.OptionParser('usage: %prog [action1 action2 ...]')
    parser.add_option('-y', '--yes',
                      action='store_true', default=False,
                      help='Automatically answer yes to all confirmation questions')
    parser.add_option('-s', '--siteDir',
                      default=DEFAULT_SITE_DIR,
                      help='Site directory to work in [%default]')
    parser.add_option('-v', '--verbose',
                      action='count', default=0,
                      help='Increase verbosity, can specify multiple times')
    parser.add_option('-p', '--puppet',
                      action='store_true', default=False,
                      help='Pass this when calling from puppet to disable exit printout')
    opts, args = parser.parse_args()
    doit(opts, args)

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