<commit_before>import csv
import json
import datetime

from optparse import make_option

from django.utils import timezone
from django.db import transaction
from django.core.management.base import BaseCommand

from schools.models import (
    School, BoundaryType, DiseInfo)
from stories.models import (
    Question, Questiongroup, QuestionType,
    QuestiongroupQuestions, Source, UserType,
    Story, Answer)

class Command(BaseCommand):
    args = "<path to file>"
    help = """Parse and store the Community Feedback V2 data

    ./manage.py fetchcommunityv2 --file=path/to/file"""

    option_list = BaseCommand.option_list + (
        make_option('--file',
                    help='Path to the csv file'),
        make_option('--format',
                    help='Which format to use - Hosakote/v2/GKA1/GKA2'),
    )

    @transaction.atomic
    def handle(self, *args, **options):
        file_name = options.get('file', None)
        if not file_name:
            print "Please specify a filename with the --file argument"
            return

        csv_format = options.get('format', None)
        if not csv_format or csv_format not in ['Hosakote', 'v2', 'GKA1', 'GKA2']:
            print "Please specify a formate with the --format argument [Hosakote/v2/GKA]"
            return

        source = Source.objects.get_or_create(name="community")[0]
        question_group = Questiongroup.objects.get_or_create(version=2, source=source)[0]
        user_types = {
            'parents': UserType.PARENTS,
            'cbo member': UserType.CBO_MEMBER,
            'local leader': UserType.LOCAL_LEADER,
            'elcted/local leader': UserType.LOCAL_LEADER,
            'sdmc member': UserType.SDMC_MEMBER,
            'educated youth': UserType.EDUCATED_YOUTH,
        }
        UserType.objects.get_or_create(name=UserType.PARENTS)
        UserType.objects.get_or_create(name=UserType.CBO_MEMBER)
        UserType.objects.get_or_create(name=UserType.SDMC_MEMBER)
        UserType.objects.get_or_create(name=UserType.LOCAL_LEADER)
        UserType.objects.get_or_create(name=UserType.EDUCATED_YOUTH)

        num_to_user_type = {
            '':None,
            '1':'Parents',
            '2':'SDMC Member',
            '3':'Local Leader',
            '4':'CBO Member',
            '5':'Educated youth'
        }

        f = open(file_name, 'r')
        csv_f = csv.reader(f)

        if csv_format == "Hosakote":
            dise_errors = {}
            dise_errors['no_school_code'] = []
            count = -1
        else:
            dise_errors = {}
            dise_errors['no_dise_code'] = []
            dise_errors['no_school_for_dise'] = []
            count = 0

        previous_date = ""

        for row in csv_f:
            # Skip first few rows
            if count in [0, 1, -1]:
                count += 1
                continue

            if csv_format == "v2":
                name = row[6]
                dise_code = row[5]
                accepted_answers = {'Y':'Yes', 'N':'No'}

                if row[7] in ['1', '2', '3', '4', '5']:
                    user_type = self.get_user_type(num_to_user_type[row[7]], user_types)
                else:
                    user_type = self.get_user_type(row[7], user_types)

                previous_date = date_of_visit = self.parse_date(previous_date, row[16])

                try:
                    dise_info = DiseInfo.objects.get(dise_code=dise_code)
                except Exception as ex:
                    dise_errors['no_dise_code'].append(dise_code)
                    continue

                try:
                    school = School.objects.get(dise_info=dise_info)
                except Exception as ex:
                    dise_errors['no_school_for_dise'].append(dise_code)
                    continue

                question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                answer_columns = [8, 9, 10, 11, 12, 13, 14, 15]

            elif csv_format == "Hosakote":
                name = row[13]
                school_id = row[9]
                accepted_answers = {'1':'Yes', '0':'No', '88':'Unknown', '99':'Unknown'}
                user_type = self.get_user_type(num_to_user_type[row[14]], user_types)
                previous_date = date_of_visit = self.parse_date(previous_date, row[11])

                try:
                    school = School.objects.get(id=school_id)
                except Exception as ex:
                    dise_errors['no_school_code'].append(school_id)
                    continue

                question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                answer_columns = [14, 15, 16, 17, 18, 19, 20, 21]

            else:
                name = row[8]
                accepted_answers = {'1':'Yes', '0':'No', '88':'Unknown', '99':'Unknown'}
                user_type = self.get_user_type(num_to_user_type[row[9]], user_types)
                previous_date = date_of_visit = self.parse_date(previous_date, row[18])
                if csv_format == "GKA1":
                    dise_code = row[5]
                else:
                    dise_code = row[7]

                try:
                    dise_info = DiseInfo.objects.get(dise_code=dise_code)
                except Exception as ex:
                    dise_errors['no_dise_code'].append(dise_code)
                    continue

                try:
                    school = School.objects.get(dise_info=dise_info)
                except Exception as ex:
                    dise_errors['no_school_for_dise'].append(dise_code)
                    continue

                question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                answer_columns = [10, 11, 12, 13, 14, 15, 16, 17]

            for answer_column in answer_columns:
                if row[answer_column] in accepted_answers:
                    at_least_one_answer = True
                    break
            else:
                at_least_one_answer = False

            if at_least_one_answer:
                story, created = Story.objects.get_or_create(
                    school=school,
                    name=name,
                    group=question_group,
                    date_of_visit=timezone.make_aware(
                        date_of_visit, timezone.get_current_timezone()
                    ),
                    user_type=user_type,
                )

                for sequence_number, answer_column in zip(question_sequence, answer_columns):
                    if row[answer_column] in accepted_answers:
                        question = Question.objects.get(
                            questiongroup=question_group,
                            questiongroupquestions__sequence=sequence_number,
                        )
                        answer = Answer.objects.get_or_create(
                            story=story,
                            question=question,
                            text=accepted_answers[row[answer_column]],
                        )
        f.close()
        f = open('dise_error.log', 'w')
        f.write(json.dumps(dise_errors, indent = 4))
        f.close()

    def parse_date(self, previous_date,  date):
        if date:
            if date == "99":
                return previous_date
            date, date_is_sane = self.check_date_sanity(date)
            if date_is_sane:
                date_of_visit = datetime.datetime.strptime(
                    date, '%d/%m/%Y'
                )
                return date_of_visit

        return previous_date

    def get_user_type(self, user_type, user_types):
        if user_type:
            return UserType.objects.get(
                name=user_types[user_type.strip().lower()]
            )
        else:
            return None

    def check_date_sanity(self, date):
        if "." in date:
            try:
                day = date.split(".")[0]
                month = date.split(".")[1]
                year = date.split(".")[2]
            except:
                return (date, False)
        elif "//" in date:
            try:
                day = date.split("/")[0]
                month = date.split("/")[2]
                year = date.split("/")[3]
                if len(year) == 2:
                    year = "20"+year
            except:
                # Date format itself will be messed up
                return (date, False)
        else:
            try:
                day = date.split("/")[0]
                month = date.split("/")[1]
                year = date.split("/")[2]
                if len(year) == 2:
                    year = "20"+year
            except:
                # Date format itself will be messed up
                return (date, False)

        if not self.is_day_correct(day):
            return (date, False)

        if not self.is_month_correct(month):
            return (date, False)

        if not self.is_year_correct(year):
            return (date, False)

        date = day+"/"+month+"/"+year
        return (date, True)

    def is_day_correct(self, day):
        return int(day) in range(1,32)

    def is_month_correct(self, month):
        return int(month) in range(1,13)

    def is_year_correct(self, year):
        return (len(year) == 4 and int(year) <= timezone.now().year)
<commit_msg>Adds Hosakote v2<commit_after>import csv
import json
import datetime

from optparse import make_option

from django.utils import timezone
from django.db import transaction
from django.core.management.base import BaseCommand

from schools.models import (
    School, BoundaryType, DiseInfo)
from stories.models import (
    Question, Questiongroup, QuestionType,
    QuestiongroupQuestions, Source, UserType,
    Story, Answer)

class Command(BaseCommand):
    args = "<path to file>"
    help = """Parse and store the Community Feedback V2 data

    ./manage.py fetchcommunityv2 --file=path/to/file"""

    option_list = BaseCommand.option_list + (
        make_option('--file',
                    help='Path to the csv file'),
        make_option('--format',
                    help='Which format to use - Hosakote1/Hosakote2/v2/GKA1/GKA2'),
    )

    @transaction.atomic
    def handle(self, *args, **options):
        file_name = options.get('file', None)
        if not file_name:
            print "Please specify a filename with the --file argument"
            return

        csv_format = options.get('format', None)
        if not csv_format or csv_format not in ['Hosakote1', 'Hosakote2', 'v2', 'GKA1', 'GKA2']:
            print "Please specify a formate with the --format argument [Hosakote/v2/GKA]"
            return

        source = Source.objects.get_or_create(name="community")[0]
        question_group = Questiongroup.objects.get_or_create(version=2, source=source)[0]
        user_types = {
            'parents': UserType.PARENTS,
            'cbo member': UserType.CBO_MEMBER,
            'local leader': UserType.LOCAL_LEADER,
            'elcted/local leader': UserType.LOCAL_LEADER,
            'sdmc member': UserType.SDMC_MEMBER,
            'educated youth': UserType.EDUCATED_YOUTH,
        }
        UserType.objects.get_or_create(name=UserType.PARENTS)
        UserType.objects.get_or_create(name=UserType.CBO_MEMBER)
        UserType.objects.get_or_create(name=UserType.SDMC_MEMBER)
        UserType.objects.get_or_create(name=UserType.LOCAL_LEADER)
        UserType.objects.get_or_create(name=UserType.EDUCATED_YOUTH)

        num_to_user_type = {
            '':None,
            '1':'Parents',
            '2':'SDMC Member',
            '3':'Local Leader',
            '4':'CBO Member',
            '5':'Educated youth'
        }

        f = open(file_name, 'r')
        csv_f = csv.reader(f)

        if csv_format in ["Hosakote1", "Hosakote2"]:
            dise_errors = {}
            dise_errors['no_school_code'] = []
            count = -1
        else:
            dise_errors = {}
            dise_errors['no_dise_code'] = []
            dise_errors['no_school_for_dise'] = []
            count = 0

        previous_date = ""

        for row in csv_f:
            # Skip first few rows
            if count in [0, 1, -1]:
                count += 1
                continue

            if csv_format == "v2":
                name = row[6]
                dise_code = row[5]
                accepted_answers = {'Y':'Yes', 'N':'No'}

                if row[7] in ['1', '2', '3', '4', '5']:
                    user_type = self.get_user_type(num_to_user_type[row[7]], user_types)
                else:
                    user_type = self.get_user_type(row[7], user_types)

                previous_date = date_of_visit = self.parse_date(previous_date, row[16])

                try:
                    dise_info = DiseInfo.objects.get(dise_code=dise_code)
                except Exception as ex:
                    dise_errors['no_dise_code'].append(dise_code)
                    continue

                try:
                    school = School.objects.get(dise_info=dise_info)
                except Exception as ex:
                    dise_errors['no_school_for_dise'].append(dise_code)
                    continue

                question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                answer_columns = [8, 9, 10, 11, 12, 13, 14, 15]

            elif csv_format in ["Hosakote1", "Hosakote2"]:
                if csv_format == "Hosakote1":
                    name = row[13]
                    school_id = row[9]
                    accepted_answers = {'1':'Yes', '0':'No', '88':'Unknown', '99':'Unknown'}
                    user_type = self.get_user_type(num_to_user_type[row[14]], user_types)
                    previous_date = date_of_visit = self.parse_date(previous_date, row[11])

                    try:
                        school = School.objects.get(id=school_id)
                    except Exception as ex:
                        dise_errors['no_school_code'].append(school_id)
                        continue

                    question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                    answer_columns = [14, 15, 16, 17, 18, 19, 20, 21]

                else:
                    users = {
                        'parents': ['parent'],
                        'cbo member': ['cbo member', 'cbo membar'],
                        'local leader': ['elected/ local leader', 'elected- local leader',
                                         'elected/local leader', 'elected-local leader'],
                        'sdmc member': ['sdmc-1', 'sdmc-2', 'sdmc -2', 'sdmc -1'],
                        'educated youth': ['educated youth'],
                    }

                    name = row[10]
                    school_id = row[6]
                    accepted_answers = {'Yes':'Yes', 'No':'No', 'Unaware':'Unknown'}
                    user_type = row[9].strip().lower()
                    for user in users:
                        if user_type in users[user]:
                            user_type = user
                    previous_date = date_of_visit = self.parse_date(previous_date, row[8])

                    try:
                        school = School.objects.get(id=school_id)
                    except Exception as ex:
                        dise_errors['no_school_code'].append(school_id)
                        continue

                    question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                    answer_columns = [11, 14, 17, 20, 23, 26, 29, 32]

                    story, created = Story.objects.get_or_create(
                        school=school,
                        name=name,
                        group=question_group,
                        date_of_visit=timezone.make_aware(
                            date_of_visit, timezone.get_current_timezone()
                        ),
                        user_type=user_type,
                    )

                    answer_text = None
                    for sequence_number, answer_column in zip(question_sequence, answer_columns):
                        for i in range(0, 3):
                            if row[answer_column+i].strip() in accepted_answers:
                                answer_text = row[answer_column+i].strip()
                                break
                        question = Question.objects.get(
                            questiongroup=question_group,
                            questiongroupquestions__sequence=sequence_number,
                        )
                        answer = Answer.objects.get_or_create(
                            story=story,
                            question=question,
                            text=accepted_answers[answer_text],
                        )

                    continue

            else:
                name = row[8]
                accepted_answers = {'1':'Yes', '0':'No', '88':'Unknown', '99':'Unknown'}
                user_type = self.get_user_type(num_to_user_type[row[9]], user_types)
                previous_date = date_of_visit = self.parse_date(previous_date, row[18])
                if csv_format == "GKA1":
                    dise_code = row[5]
                else:
                    dise_code = row[7]

                try:
                    dise_info = DiseInfo.objects.get(dise_code=dise_code)
                except Exception as ex:
                    dise_errors['no_dise_code'].append(dise_code)
                    continue

                try:
                    school = School.objects.get(dise_info=dise_info)
                except Exception as ex:
                    dise_errors['no_school_for_dise'].append(dise_code)
                    continue

                question_sequence = [1, 2, 3, 4, 5, 6, 7, 8]
                answer_columns = [10, 11, 12, 13, 14, 15, 16, 17]

            for answer_column in answer_columns:
                if row[answer_column] in accepted_answers:
                    at_least_one_answer = True
                    break
            else:
                at_least_one_answer = False

            if at_least_one_answer:
                story, created = Story.objects.get_or_create(
                    school=school,
                    name=name,
                    group=question_group,
                    date_of_visit=timezone.make_aware(
                        date_of_visit, timezone.get_current_timezone()
                    ),
                    user_type=user_type,
                )

                for sequence_number, answer_column in zip(question_sequence, answer_columns):
                    if row[answer_column] in accepted_answers:
                        question = Question.objects.get(
                            questiongroup=question_group,
                            questiongroupquestions__sequence=sequence_number,
                        )
                        answer = Answer.objects.get_or_create(
                            story=story,
                            question=question,
                            text=accepted_answers[row[answer_column]],
                        )
        f.close()
        f = open('dise_error.log', 'w')
        f.write(json.dumps(dise_errors, indent = 4))
        f.close()

    def parse_date(self, previous_date,  date):
        if date:
            if date == "99":
                return previous_date
            date, date_is_sane = self.check_date_sanity(date)
            if date_is_sane:
                date_of_visit = datetime.datetime.strptime(
                    date, '%d/%m/%Y'
                )
                return date_of_visit

        return previous_date

    def get_user_type(self, user_type, user_types):
        if user_type:
            return UserType.objects.get(
                name=user_types[user_type.strip().lower()]
            )
        else:
            return None

    def check_date_sanity(self, date):
        if "." in date:
            try:
                day = date.split(".")[0]
                month = date.split(".")[1]
                year = date.split(".")[2]
            except:
                return (date, False)
        elif "//" in date:
            try:
                day = date.split("/")[0]
                month = date.split("/")[2]
                year = date.split("/")[3]
                if len(year) == 2:
                    year = "20"+year
            except:
                # Date format itself will be messed up
                return (date, False)
        else:
            try:
                day = date.split("/")[0]
                month = date.split("/")[1]
                year = date.split("/")[2]
                if len(year) == 2:
                    year = "20"+year
            except:
                # Date format itself will be messed up
                return (date, False)

        if not self.is_day_correct(day):
            return (date, False)

        if not self.is_month_correct(month):
            return (date, False)

        if not self.is_year_correct(year):
            return (date, False)

        date = day+"/"+month+"/"+year
        return (date, True)

    def is_day_correct(self, day):
        return int(day) in range(1,32)

    def is_month_correct(self, month):
        return int(month) in range(1,13)

    def is_year_correct(self, year):
        return (len(year) == 4 and int(year) <= timezone.now().year)
<|endoftext|>


<commit_before>from flask.ext.wtf import Form
from wtforms import SelectField, RadioField
from .models import Presentation, Technical, CoreValues

class PresentationForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Research
    problem_identification = RadioField(u'Problem identification',
                                        choices=[(i, i) for i in range(0, 5)],
                                        coerce=int,
                                        default=0)
    sources_of_information = RadioField(u'Sources of information',
                                        choices=[(i, i) for i in range(0, 5)],
                                        coerce=int,
                                        default=0)
    problem_analysis = RadioField(u'Problem analysis',
                                  choices=[(i, i) for i in range(0, 5)],
                                  coerce=int,
                                  default=0)
    existing_solutions = RadioField(u'Existing solutions',
                                    choices=[(i, i) for i in range(0, 5)],
                                    coerce=int,
                                    default=0)
    # Innovative Solution
    team_solution = RadioField(u'Team solution',
                               choices=[(i, i) for i in range(0, 5)],
                               coerce=int,
                               default=0)
    innovation = RadioField(u'Innovation',
                            choices=[(i, i) for i in range(0, 5)],
                            coerce=int,
                            default=0)
    implementation = RadioField(u'Implementation',
                                choices=[(i, i) for i in range(0, 5)],
                                coerce=int,
                                default=0)
    # Presentation
    sharing = RadioField(u'Sharing',
                         choices=[(i, i) for i in range(0, 5)],
                         coerce=int,
                         default=0)
    creativity = RadioField(u'Creativity',
                            choices=[(i, i) for i in range(0, 5)],
                            coerce=int,
                            default=0)
    effectiveness = RadioField(u'Effectiveness',
                               choices=[(i, i) for i in range(0, 5)],
                               coerce=int,
                               default=0)

    # TODO this code is duplicated in each judging form class, combine?
    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        p = Presentation.query.filter_by(team_id=self.team_id.data).first()
        if p is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True

class CoreValuesForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Inspiration
    discovery = RadioField(u'Discovery',
                           choices=[(i, i) for i in range(0, 5)],
                           coerce=int,
                           default=0)
    team_spirit = RadioField(u'Team Spirit',
                             choices=[(i, i) for i in range(0, 5)],
                             coerce=int,
                             default=0)
    integration = RadioField(u'Inspiration',
                             choices=[(i, i) for i in range(0, 5)],
                             coerce=int,
                             default=0)
    # Teamwork
    effectiveness = RadioField(u'Effectiveness',
                               choices=[(i, i) for i in range(0, 5)],
                               coerce=int,
                               default=0)
    efficiency = RadioField(u'Efficiency',
                            choices=[(i, i) for i in range(0, 5)],
                            coerce=int,
                            default=0)
    kids_do_the_work = RadioField(u'Kids do the work',
                                  choices=[(i, i) for i in range(0, 5)],
                                  coerce=int,
                                  default=0)
    # Gracious Professionalism
    inclusion = RadioField(u'Inclusion',
                           choices=[(i, i) for i in range(0, 5)],
                           coerce=int,
                           default=0)
    respect = RadioField(u'Respect',
                         choices=[(i, i) for i in range(0, 5)],
                         coerce=int,
                         default=0)
    coopertition = RadioField(u'Coopertition',
                              choices=[(i, i) for i in range(0, 5)],
                              coerce=int,
                              default=0)

    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        t = CoreValues.query.filter_by(team_id=self.team_id.data).first()
        if t is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True

class TechnicalForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Mechanical Design
    mechanical_durability = RadioField(u'Mechanical durability',
                                       choices=[(i, i) for i in range(0, 5)],
                                       coerce=int,
                                       default=0)
    mechanical_efficiency = RadioField(u'Mechanical efficiency',
                                       choices=[(i, i) for i in range(0, 5)],
                                       coerce=int,
                                       default=0)
    mechanization = RadioField(u'Mechanization',
                               choices=[(i, i) for i in range(0, 5)],
                               coerce=int,
                               default=0)
    # Programming
    programming_quality = RadioField(u'Programming quality',
                                     choices=[(i, i) for i in range(0, 5)],
                                     coerce=int,
                                     default=0)
    programming_efficiency = RadioField(u'Programming efficiency',
                                        choices=[(i, i) for i in range(0, 5)],
                                        coerce=int,
                                        default=0)
    autonomous_navigation = RadioField(u'Autonomous navigation',
                                       choices=[(i, i) for i in range(0, 5)],
                                       coerce=int,
                                       default=0)
    # Strategy and Innovation
    design_process = RadioField(u'Design process',
                                choices=[(i, i) for i in range(0, 5)],
                                coerce=int,
                                default=0)
    mission_strategy = RadioField(u'Mission strategy',
                                  choices=[(i, i) for i in range(0, 5)],
                                  coerce=int,
                                  default=0)
    innovation = RadioField(u'Innovation',
                            choices=[(i, i) for i in range(0, 5)],
                            coerce=int,
                            default=0)

    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        t = Technical.query.filter_by(team_id=self.team_id.data).first()
        if t is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True
<commit_msg>Change '0' to 'ND' on judging forms.<commit_after>from flask.ext.wtf import Form
from wtforms import SelectField, RadioField
from .models import Presentation, Technical, CoreValues

# Default choices for judging fields
default_choices = [(0, 'ND'), (1, '1'), (2, '2'), (3, '3'), (4, '4')]

class PresentationForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Research
    problem_identification = RadioField(u'Problem identification',
                                        choices=default_choices,
                                        coerce=int,
                                        default=0)
    sources_of_information = RadioField(u'Sources of information',
                                        choices=default_choices,
                                        coerce=int,
                                        default=0)
    problem_analysis = RadioField(u'Problem analysis',
                                  choices=default_choices,
                                  coerce=int,
                                  default=0)
    existing_solutions = RadioField(u'Existing solutions',
                                    choices=default_choices,
                                    coerce=int,
                                    default=0)
    # Innovative Solution
    team_solution = RadioField(u'Team solution',
                               choices=default_choices,
                               coerce=int,
                               default=0)
    innovation = RadioField(u'Innovation',
                            choices=default_choices,
                            coerce=int,
                            default=0)
    implementation = RadioField(u'Implementation',
                                choices=default_choices,
                                coerce=int,
                                default=0)
    # Presentation
    sharing = RadioField(u'Sharing',
                         choices=default_choices,
                         coerce=int,
                         default=0)
    creativity = RadioField(u'Creativity',
                            choices=default_choices,
                            coerce=int,
                            default=0)
    effectiveness = RadioField(u'Effectiveness',
                               choices=default_choices,
                               coerce=int,
                               default=0)

    # TODO this code is duplicated in each judging form class, combine?
    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        p = Presentation.query.filter_by(team_id=self.team_id.data).first()
        if p is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True

class CoreValuesForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Inspiration
    discovery = RadioField(u'Discovery',
                           choices=default_choices,
                           coerce=int,
                           default=0)
    team_spirit = RadioField(u'Team Spirit',
                             choices=default_choices,
                             coerce=int,
                             default=0)
    integration = RadioField(u'Inspiration',
                             choices=default_choices,
                             coerce=int,
                             default=0)
    # Teamwork
    effectiveness = RadioField(u'Effectiveness',
                               choices=default_choices,
                               coerce=int,
                               default=0)
    efficiency = RadioField(u'Efficiency',
                            choices=default_choices,
                            coerce=int,
                            default=0)
    kids_do_the_work = RadioField(u'Kids do the work',
                                  choices=default_choices,
                                  coerce=int,
                                  default=0)
    # Gracious Professionalism
    inclusion = RadioField(u'Inclusion',
                           choices=default_choices,
                           coerce=int,
                           default=0)
    respect = RadioField(u'Respect',
                         choices=default_choices,
                         coerce=int,
                         default=0)
    coopertition = RadioField(u'Coopertition',
                              choices=default_choices,
                              coerce=int,
                              default=0)

    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        t = CoreValues.query.filter_by(team_id=self.team_id.data).first()
        if t is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True

class TechnicalForm(Form):
    team_id = SelectField(u'Team', coerce=int)
    # Mechanical Design
    mechanical_durability = RadioField(u'Mechanical durability',
                                       choices=default_choices,
                                       coerce=int,
                                       default=0)
    mechanical_efficiency = RadioField(u'Mechanical efficiency',
                                       choices=default_choices,
                                       coerce=int,
                                       default=0)
    mechanization = RadioField(u'Mechanization',
                               choices=default_choices,
                               coerce=int,
                               default=0)
    # Programming
    programming_quality = RadioField(u'Programming quality',
                                     choices=default_choices,
                                     coerce=int,
                                     default=0)
    programming_efficiency = RadioField(u'Programming efficiency',
                                        choices=default_choices,
                                        coerce=int,
                                        default=0)
    autonomous_navigation = RadioField(u'Autonomous navigation',
                                       choices=default_choices,
                                       coerce=int,
                                       default=0)
    # Strategy and Innovation
    design_process = RadioField(u'Design process',
                                choices=default_choices,
                                coerce=int,
                                default=0)
    mission_strategy = RadioField(u'Mission strategy',
                                  choices=default_choices,
                                  coerce=int,
                                  default=0)
    innovation = RadioField(u'Innovation',
                            choices=default_choices,
                            coerce=int,
                            default=0)

    def validate(self):
        # Base validation
        rv = Form.validate(self)
        if not rv:
            return False

        # Team-ID fields doesn't exist on an 'edit' form
        if not self.team_id:
            return True

        # New score being entered, check if one already exists for team/ round
        t = Technical.query.filter_by(team_id=self.team_id.data).first()
        if t is not None:
            self.team_id.errors.append("Entry already exists for this team")
            return False

        return True
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
import logging
from iktomi.forms import convs, widgets, Field, FieldSet, FileField

logger = logging.getLogger(__name__)

class FileFieldSetConv(convs.Converter):

    error_inner = 'Error uploading file'
    error_lost = 'Transient file has been lost'
    error_hacking = 'Transient file name is not provided or is incorrect'

    def from_python(self, value):
        return {'transient_name': value.name if value and value.mode == 'transient' else None,
                #'original_name': value and value.original_name,
                'original_name': value.name if value and value.mode == 'transient' else None, # XXX
                'file': value,
                'mode': value.mode if value is not None else 'empty'}

    def _to_python(self, file=None, mode=None,
                   transient_name=None, original_name=None):

        file_manager = self.env.file_manager

        if not self._is_empty(file):
            file = file_manager.create_transient(file.file, file.filename)
        else:
            file = None

        if mode == 'empty':
            if not file and self.required:
                raise convs.ValidationError(self.error_required)

        elif mode == 'transient':
            if not original_name:
                logger.warning('Missing original_name for FileField')
            if not transient_name:
                logger.warning('Missing transient_name for FileField '
                               'in mode "transient"')
                raise convs.ValidationError(self.error_hacking)

            try:
                transient_file = file_manager.get_transient(transient_name)
            except OSError:
                raise convs.ValidationError(self.error_lost)

            if file:
                file_manager.delete(transient_file)
            else:
                file = transient_file

        elif mode == 'existing':
            if not file:
                return self._existing_value

        return file

    def to_python(self, value):
        value = self._to_python(**value)
        #XXX Hack
        self.field.set_raw_value(self.field.form.raw_data,
                                 self.from_python(value))
        return value

def check_file_path(conv, value):
    if value and ('/' in value or '\\' in value or value[0] in '.~'):
        logger.warning('Hacking attempt: submitted temp_name '\
                       'for FileField contains "/"')
        raise convs.ValidationError('Invalid filename')
    return value

class FileFieldSet(FieldSet):
    '''FieldSet aggregating fields required for file upload handling::
    '''

    fields = [
            FileField('file',
                  conv=convs.SimpleFile(),
                  widget=widgets.FileInput()),
            Field('mode',
                  conv=convs.EnumChoice(choices=[('existing', ''),
                                                 ('transient', ''),
                                                 ('empty', '')],
                                        required=True),
                  widget=widgets.HiddenInput),
            Field('transient_name',
                  conv=convs.Char(check_file_path, required=False),
                  widget=widgets.HiddenInput),
            Field('original_name',
                  conv=convs.Char(check_file_path, required=False),
                  widget=widgets.HiddenInput),
        ]

    conv = FileFieldSetConv

    def __init__(self, name, conv=FileFieldSetConv, **kwargs):
        kwargs.setdefault('fields', self.fields)
        FieldSet.__init__(self, name, conv=conv, **kwargs)

    def get_initial(self):
        # Redefine because FieldSet.get_initial returns dict by default,
        # but python value of FileFieldSet is either None, either BaseFile
        # instance.
        return None

<commit_msg>fixed conv setting in FileFieldSet<commit_after># -*- coding: utf-8 -*-
import logging
from iktomi.forms import convs, widgets, Field, FieldSet, FileField

logger = logging.getLogger(__name__)

class FileFieldSetConv(convs.Converter):

    error_inner = 'Error uploading file'
    error_lost = 'Transient file has been lost'
    error_hacking = 'Transient file name is not provided or is incorrect'

    def from_python(self, value):
        return {'transient_name': value.name if value and value.mode == 'transient' else None,
                #'original_name': value and value.original_name,
                'original_name': value.name if value and value.mode == 'transient' else None, # XXX
                'file': value,
                'mode': value.mode if value is not None else 'empty'}

    def _to_python(self, file=None, mode=None,
                   transient_name=None, original_name=None):

        file_manager = self.env.file_manager

        if not self._is_empty(file):
            file = file_manager.create_transient(file.file, file.filename)
        else:
            file = None

        if mode == 'empty':
            if not file and self.required:
                raise convs.ValidationError(self.error_required)

        elif mode == 'transient':
            if not original_name:
                logger.warning('Missing original_name for FileField')
            if not transient_name:
                logger.warning('Missing transient_name for FileField '
                               'in mode "transient"')
                raise convs.ValidationError(self.error_hacking)

            try:
                transient_file = file_manager.get_transient(transient_name)
            except OSError:
                raise convs.ValidationError(self.error_lost)

            if file:
                file_manager.delete(transient_file)
            else:
                file = transient_file

        elif mode == 'existing':
            if not file:
                return self._existing_value

        return file

    def to_python(self, value):
        value = self._to_python(**value)
        #XXX Hack
        self.field.set_raw_value(self.field.form.raw_data,
                                 self.from_python(value))
        return value

def check_file_path(conv, value):
    if value and ('/' in value or '\\' in value or value[0] in '.~'):
        logger.warning('Hacking attempt: submitted temp_name '\
                       'for FileField contains "/"')
        raise convs.ValidationError('Invalid filename')
    return value

class FileFieldSet(FieldSet):
    '''FieldSet aggregating fields required for file upload handling::
    '''

    fields = [
            FileField('file',
                  conv=convs.SimpleFile(),
                  widget=widgets.FileInput()),
            Field('mode',
                  conv=convs.EnumChoice(choices=[('existing', ''),
                                                 ('transient', ''),
                                                 ('empty', '')],
                                        required=True),
                  widget=widgets.HiddenInput),
            Field('transient_name',
                  conv=convs.Char(check_file_path, required=False),
                  widget=widgets.HiddenInput),
            Field('original_name',
                  conv=convs.Char(check_file_path, required=False),
                  widget=widgets.HiddenInput),
        ]

    conv = FileFieldSetConv

    def __init__(self, name, **kwargs):
        kwargs.setdefault('fields', self.fields)
        kwargs.setdefault('conv', self.conv)
        FieldSet.__init__(self, name, **kwargs)

    def get_initial(self):
        # Redefine because FieldSet.get_initial returns dict by default,
        # but python value of FileFieldSet is either None, either BaseFile
        # instance.
        return None

<|endoftext|>


<commit_before>from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import NoArgsCommand, CommandError

from optparse import make_option

class Command(NoArgsCommand):
    help = "Set the user profile settings of every user to the defaults"

    option_list = NoArgsCommand.option_list + (
        make_option('--update-anon-user', dest='update-anon-user',
            default=False, action='store_true',
            help='Update also the profile of the anonymous user'),
        )

    def handle_noargs(self, **options):
        update_anon_user = 'update-anon-user' in options
        for u in User.objects.all():
            # Ignore the anonymous user by default
            if u.id == settings.ANONYMOUS_USER_ID and not update_anon_user:
                continue
            up = u.userprofile
            # Expect user profiles to be there and add all default settings
            up.inverse_mouse_wheel = settings.PROFILE_DEFAULT_INVERSE_MOUSE_WHEEL
            up.show_text_label_tool = settings.PROFILE_SHOW_TEXT_LABEL_TOOL
            up.show_tagging_tool = settings.PROFILE_SHOW_TAGGING_TOOL
            up.show_cropping_tool = settings.PROFILE_SHOW_CROPPING_TOOL
            up.show_segmentation_tool = settings.PROFILE_SHOW_SEGMENTATION_TOOL
            up.show_tracing_tool = settings.PROFILE_SHOW_TRACING_TOOL
            # Save the changes
            up.save()
<commit_msg>Bring user profile defaults management command up to date<commit_after>from django.conf import settings
from django.contrib.auth.models import User
from django.core.management.base import NoArgsCommand, CommandError

from optparse import make_option

class Command(NoArgsCommand):
    help = "Set the user profile settings of every user to the defaults"

    option_list = NoArgsCommand.option_list + (
        make_option('--update-anon-user', dest='update-anon-user',
            default=False, action='store_true',
            help='Update also the profile of the anonymous user'),
        )

    def handle_noargs(self, **options):
        update_anon_user = 'update-anon-user' in options
        for u in User.objects.all():
            # Ignore the anonymous user by default
            if u.id == settings.ANONYMOUS_USER_ID and not update_anon_user:
                continue
            up = u.userprofile
            # Expect user profiles to be there and add all default settings
            up.inverse_mouse_wheel = settings.PROFILE_DEFAULT_INVERSE_MOUSE_WHEEL
            up.independent_ontology_workspace_is_default = \
                settings.PROFILE_INDEPENDENT_ONTOLOGY_WORKSPACE_IS_DEFAULT
            up.show_text_label_tool = settings.PROFILE_SHOW_TEXT_LABEL_TOOL
            up.show_tagging_tool = settings.PROFILE_SHOW_TAGGING_TOOL
            up.show_cropping_tool = settings.PROFILE_SHOW_CROPPING_TOOL
            up.show_segmentation_tool = settings.PROFILE_SHOW_SEGMENTATION_TOOL
            up.show_tracing_tool = settings.PROFILE_SHOW_TRACING_TOOL
            up.show_ontology_tool = settings.PROFILE_SHOW_ONTOLOGY_TOOL
            # Save the changes
            up.save()
<|endoftext|>


<commit_before>"""Common settings and globals."""

VERSION = '0.5.2'

import dj_database_url
from os.path import abspath, basename, dirname, join, normpath
from sys import path

from os import environ

# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured

def get_env_setting(setting):
    """ Get the environment setting or return exception """
    try:
        return environ[setting]
    except KeyError:
        error_msg = "Set the %s env variable" % setting
        raise ImproperlyConfigured(error_msg)

########## PATH CONFIGURATION
# Absolute filesystem path to the Django project directory:
DJANGO_ROOT = dirname(dirname(abspath(__file__)))

# Absolute filesystem path to the top-level project folder:
SITE_ROOT = dirname(DJANGO_ROOT)

# Site name:
SITE_NAME = basename(DJANGO_ROOT)

# Add our project to our pythonpath, this way we don't need to type our project
# name in our dotted import paths:
path.append(DJANGO_ROOT)
########## END PATH CONFIGURATION

########## DEBUG CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = False

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
TEMPLATE_DEBUG = DEBUG
########## END DEBUG CONFIGURATION

########## MANAGER CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
    ('Kit', 'kit.la.t@gmail.com'),
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS
########## END MANAGER CONFIGURATION

########## DATABASE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {}
DATABASES['default'] = dj_database_url.config(
    default='postgres://localhost/are_there_spiders'
)
########## END DATABASE CONFIGURATION

########## GENERAL CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone
TIME_ZONE = 'America/Chicago'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'en-us'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True

LOGIN_REDIRECT_URL = '/'
########## END GENERAL CONFIGURATION

########## MEDIA CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = normpath(join(SITE_ROOT, 'media'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
MEDIA_URL = '/media/'
########## END MEDIA CONFIGURATION

########## STATIC FILE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = normpath(join(SITE_ROOT, 'assets'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
# STATIC_URL = '/static/'

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
#   #std:setting-STATICFILES_DIRS
STATICFILES_DIRS = (
    normpath(join(SITE_ROOT, 'static')),
)

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
#   #staticfiles-finders
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

STATICFILES_STORAGE = 'are_there_spiders.custom_storages.S3PipelineStorage'

AWS_QUERYSTRING_AUTH = False
AWS_ACCESS_KEY_ID = get_env_setting('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = get_env_setting('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = get_env_setting('AWS_STORAGE_BUCKET_NAME')
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
STATIC_URL = S3_URL
ADMIN_MEDIA_PREFIX = S3_URL + 'admin/'

########## END STATIC FILE CONFIGURATION

########## PIPELINE CONFIGURATION
PIPELINE_CSS = {
    'all': {
        'source_filenames': (
            'css/bootstrap.css',
            'css/bootstrap-responsive.css',
            'css/project.css'
        ),
        'output_filename': 'css/all.css',
        'extra_context': {
            'media': 'screen,projection',
        },
    },
}

PIPELINE_JS = {
    'all': {
        'source_filenames': (
            'js/jquery-1.9.1.js',
            'js/bootstrap.js',
            'js/project.js'
        ),
        'output_filename': 'js/all.js',
    }
}
########## END PIPELINE CONFIGURATION

########## SECRET CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Note: This key only used for development and testing.
SECRET_KEY = r"g7!m5v$tyk%*3-l5nw8lwju)lsg#!znrk1nb3&vhx_f$%()9zm"
########## END SECRET CONFIGURATION

########## SITE CONFIGURATION
# Hosts/domain names that are valid for this site
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
    '.aretherespiders.com',
    'aretherespiders.herokuapp.com',
]
########## END SITE CONFIGURATION

########## FIXTURE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/
#   #std:setting-FIXTURE_DIRS
FIXTURE_DIRS = (
    normpath(join(SITE_ROOT, 'fixtures')),
)
########## END FIXTURE CONFIGURATION

########## TEMPLATE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/
#   #template-context-processors
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.request',
    'are_there_spiders.context_processors.login_next',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
TEMPLATE_DIRS = (
    normpath(join(SITE_ROOT, 'templates')),
)
########## END TEMPLATE CONFIGURATION

########## MIDDLEWARE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes
MIDDLEWARE_CLASSES = (
    # Default Django middleware.
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'pipeline.middleware.MinifyHTMLMiddleware',
)
########## END MIDDLEWARE CONFIGURATION

########## URL CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
ROOT_URLCONF = '%s.urls' % SITE_NAME
########## END URL CONFIGURATION

########## APP CONFIGURATION
DJANGO_APPS = (
    # Default Django apps:
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Useful template tags:
    'django.contrib.humanize',
    'django.contrib.markup',

    # Admin panel and documentation:
    'django.contrib.admin',
    # 'django.contrib.admindocs',
)

THIRD_PARTY_APPS = (
    # Database migration helpers:
    'south',
    # Static files but better:
    'pipeline',
    # Tags on models:
    'taggit',
    # Signup:
    'registration',
)

# Apps specific for this project go here.
LOCAL_APPS = (
    'phobias',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
########## END APP CONFIGURATION

########## REGISTRATION CONFIGURATION
ACCOUNT_ACTIVATION_DAYS = 7
REGISTRATION_OPEN = False
DEFAULT_FROM_EMAIL = 'Are there spiders <no-reply@aretherespiders.com>'
########## END REGISTRATION CONFIGURATION

########## LOGGING CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}
########## END LOGGING CONFIGURATION

########## WSGI CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = 'wsgi.application'
########## END WSGI CONFIGURATION

########## PHOBIAS CONFIGURATION
# These settings are REQUIRED.
ARTWORK_PAGINATION_NUMBER = 20
REVIEW_PAGINATION_NUMBER = 20
########## END PHOBIAS CONFIGURATION
<commit_msg>Bumped version.<commit_after>"""Common settings and globals."""

VERSION = '0.5.3'

import dj_database_url
from os.path import abspath, basename, dirname, join, normpath
from sys import path

from os import environ

# Normally you should not import ANYTHING from Django directly
# into your settings, but ImproperlyConfigured is an exception.
from django.core.exceptions import ImproperlyConfigured

def get_env_setting(setting):
    """ Get the environment setting or return exception """
    try:
        return environ[setting]
    except KeyError:
        error_msg = "Set the %s env variable" % setting
        raise ImproperlyConfigured(error_msg)

########## PATH CONFIGURATION
# Absolute filesystem path to the Django project directory:
DJANGO_ROOT = dirname(dirname(abspath(__file__)))

# Absolute filesystem path to the top-level project folder:
SITE_ROOT = dirname(DJANGO_ROOT)

# Site name:
SITE_NAME = basename(DJANGO_ROOT)

# Add our project to our pythonpath, this way we don't need to type our project
# name in our dotted import paths:
path.append(DJANGO_ROOT)
########## END PATH CONFIGURATION

########## DEBUG CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#debug
DEBUG = False

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-debug
TEMPLATE_DEBUG = DEBUG
########## END DEBUG CONFIGURATION

########## MANAGER CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#admins
ADMINS = (
    ('Kit', 'kit.la.t@gmail.com'),
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#managers
MANAGERS = ADMINS
########## END MANAGER CONFIGURATION

########## DATABASE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#databases
DATABASES = {}
DATABASES['default'] = dj_database_url.config(
    default='postgres://localhost/are_there_spiders'
)
########## END DATABASE CONFIGURATION

########## GENERAL CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#time-zone
TIME_ZONE = 'America/Chicago'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#language-code
LANGUAGE_CODE = 'en-us'

# See: https://docs.djangoproject.com/en/dev/ref/settings/#site-id
SITE_ID = 1

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-i18n
USE_I18N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-l10n
USE_L10N = True

# See: https://docs.djangoproject.com/en/dev/ref/settings/#use-tz
USE_TZ = True

LOGIN_REDIRECT_URL = '/'
########## END GENERAL CONFIGURATION

########## MEDIA CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-root
MEDIA_ROOT = normpath(join(SITE_ROOT, 'media'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#media-url
MEDIA_URL = '/media/'
########## END MEDIA CONFIGURATION

########## STATIC FILE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-root
STATIC_ROOT = normpath(join(SITE_ROOT, 'assets'))

# See: https://docs.djangoproject.com/en/dev/ref/settings/#static-url
# STATIC_URL = '/static/'

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
#   #std:setting-STATICFILES_DIRS
STATICFILES_DIRS = (
    normpath(join(SITE_ROOT, 'static')),
)

# See: https://docs.djangoproject.com/en/dev/ref/contrib/staticfiles/
#   #staticfiles-finders
STATICFILES_FINDERS = (
    'django.contrib.staticfiles.finders.FileSystemFinder',
    'django.contrib.staticfiles.finders.AppDirectoriesFinder',
)

STATICFILES_STORAGE = 'are_there_spiders.custom_storages.S3PipelineStorage'

AWS_QUERYSTRING_AUTH = False
AWS_ACCESS_KEY_ID = get_env_setting('AWS_ACCESS_KEY_ID')
AWS_SECRET_ACCESS_KEY = get_env_setting('AWS_SECRET_ACCESS_KEY')
AWS_STORAGE_BUCKET_NAME = get_env_setting('AWS_STORAGE_BUCKET_NAME')
S3_URL = 'http://%s.s3.amazonaws.com/' % AWS_STORAGE_BUCKET_NAME
STATIC_URL = S3_URL
ADMIN_MEDIA_PREFIX = S3_URL + 'admin/'

########## END STATIC FILE CONFIGURATION

########## PIPELINE CONFIGURATION
PIPELINE_CSS = {
    'all': {
        'source_filenames': (
            'css/bootstrap.css',
            'css/bootstrap-responsive.css',
            'css/project.css'
        ),
        'output_filename': 'css/all.css',
        'extra_context': {
            'media': 'screen,projection',
        },
    },
}

PIPELINE_JS = {
    'all': {
        'source_filenames': (
            'js/jquery-1.9.1.js',
            'js/bootstrap.js',
            'js/project.js'
        ),
        'output_filename': 'js/all.js',
    }
}
########## END PIPELINE CONFIGURATION

########## SECRET CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#secret-key
# Note: This key only used for development and testing.
SECRET_KEY = r"g7!m5v$tyk%*3-l5nw8lwju)lsg#!znrk1nb3&vhx_f$%()9zm"
########## END SECRET CONFIGURATION

########## SITE CONFIGURATION
# Hosts/domain names that are valid for this site
# See https://docs.djangoproject.com/en/1.5/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [
    '.aretherespiders.com',
    'aretherespiders.herokuapp.com',
]
########## END SITE CONFIGURATION

########## FIXTURE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/
#   #std:setting-FIXTURE_DIRS
FIXTURE_DIRS = (
    normpath(join(SITE_ROOT, 'fixtures')),
)
########## END FIXTURE CONFIGURATION

########## TEMPLATE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/
#   #template-context-processors
TEMPLATE_CONTEXT_PROCESSORS = (
    'django.contrib.auth.context_processors.auth',
    'django.core.context_processors.debug',
    'django.core.context_processors.i18n',
    'django.core.context_processors.media',
    'django.core.context_processors.static',
    'django.core.context_processors.tz',
    'django.contrib.messages.context_processors.messages',
    'django.core.context_processors.request',
    'are_there_spiders.context_processors.login_next',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-loaders
TEMPLATE_LOADERS = (
    'django.template.loaders.filesystem.Loader',
    'django.template.loaders.app_directories.Loader',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#template-dirs
TEMPLATE_DIRS = (
    normpath(join(SITE_ROOT, 'templates')),
)
########## END TEMPLATE CONFIGURATION

########## MIDDLEWARE CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#middleware-classes
MIDDLEWARE_CLASSES = (
    # Default Django middleware.
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'pipeline.middleware.MinifyHTMLMiddleware',
)
########## END MIDDLEWARE CONFIGURATION

########## URL CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#root-urlconf
ROOT_URLCONF = '%s.urls' % SITE_NAME
########## END URL CONFIGURATION

########## APP CONFIGURATION
DJANGO_APPS = (
    # Default Django apps:
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.sites',
    'django.contrib.messages',
    'django.contrib.staticfiles',

    # Useful template tags:
    'django.contrib.humanize',
    'django.contrib.markup',

    # Admin panel and documentation:
    'django.contrib.admin',
    # 'django.contrib.admindocs',
)

THIRD_PARTY_APPS = (
    # Database migration helpers:
    'south',
    # Static files but better:
    'pipeline',
    # Tags on models:
    'taggit',
    # Signup:
    'registration',
)

# Apps specific for this project go here.
LOCAL_APPS = (
    'phobias',
)

# See: https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
########## END APP CONFIGURATION

########## REGISTRATION CONFIGURATION
ACCOUNT_ACTIVATION_DAYS = 7
REGISTRATION_OPEN = False
DEFAULT_FROM_EMAIL = 'Are there spiders <no-reply@aretherespiders.com>'
########## END REGISTRATION CONFIGURATION

########## LOGGING CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#logging
# A sample logging configuration. The only tangible logging
# performed by this configuration is to send an email to
# the site admins on every HTTP 500 error when DEBUG=False.
# See http://docs.djangoproject.com/en/dev/topics/logging for
# more details on how to customize your logging configuration.
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'filters': {
        'require_debug_false': {
            '()': 'django.utils.log.RequireDebugFalse'
        }
    },
    'handlers': {
        'mail_admins': {
            'level': 'ERROR',
            'filters': ['require_debug_false'],
            'class': 'django.utils.log.AdminEmailHandler'
        }
    },
    'loggers': {
        'django.request': {
            'handlers': ['mail_admins'],
            'level': 'ERROR',
            'propagate': True,
        },
    }
}
########## END LOGGING CONFIGURATION

########## WSGI CONFIGURATION
# See: https://docs.djangoproject.com/en/dev/ref/settings/#wsgi-application
WSGI_APPLICATION = 'wsgi.application'
########## END WSGI CONFIGURATION

########## PHOBIAS CONFIGURATION
# These settings are REQUIRED.
ARTWORK_PAGINATION_NUMBER = 20
REVIEW_PAGINATION_NUMBER = 20
########## END PHOBIAS CONFIGURATION
<|endoftext|>


<commit_before>NPMJS = "NPMJS"

GERRIT = "GERRIT:"

NPM_VERSIONS = {
    "bower": "1.8.8",
    "crisper": "2.0.2",
    "vulcanize": "1.14.8",
}

NPM_SHA1S = {
    "bower": "82544be34a33aeae7efb8bdf9905247b2cffa985",
    "crisper": "7183c58cea33632fb036c91cefd1b43e390d22a2",
    "vulcanize": "679107f251c19ab7539529b1e3fdd40829e6fc63",
}

def _npm_tarball(name):
    return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])

def _npm_binary_impl(ctx):
    """rule to download a NPM archive."""
    name = ctx.name
    version = NPM_VERSIONS[name]
    sha1 = NPM_VERSIONS[name]

    dir = "%s-%s" % (name, version)
    filename = "%s.tgz" % dir
    base = "%s@%s.npm_binary.tgz" % (name, version)
    dest = ctx.path(base)
    repository = ctx.attr.repository
    if repository == GERRIT:
        url = "https://gerrit-maven.storage.googleapis.com/npm-packages/%s" % filename
    elif repository == NPMJS:
        url = "https://registry.npmjs.org/%s/-/%s" % (name, filename)
    else:
        fail("repository %s not in {%s,%s}" % (repository, GERRIT, NPMJS))

    python = ctx.which("python")
    script = ctx.path(ctx.attr._download_script)

    sha1 = NPM_SHA1S[name]
    args = [python, script, "-o", dest, "-u", url, "-v", sha1]
    out = ctx.execute(args)
    if out.return_code:
        fail("failed %s: %s" % (args, out.stderr))
    ctx.file("BUILD", "package(default_visibility=['//visibility:public'])\nfilegroup(name='tarball', srcs=['%s'])" % base, False)

npm_binary = repository_rule(
    attrs = {
        "repository": attr.string(default = NPMJS),
        # Label resolves within repo of the .bzl file.
        "_download_script": attr.label(default = Label("//tools:download_file.py")),
    },
    local = True,
    implementation = _npm_binary_impl,
)

# for use in repo rules.
def _run_npm_binary_str(ctx, tarball, args):
    python_bin = ctx.which("python")
    return " ".join([
        python_bin,
        ctx.path(ctx.attr._run_npm),
        ctx.path(tarball),
    ] + args)

def _bower_archive(ctx):
    """Download a bower package."""
    download_name = "%s__download_bower.zip" % ctx.name
    renamed_name = "%s__renamed.zip" % ctx.name
    version_name = "%s__version.json" % ctx.name

    cmd = [
        ctx.which("python"),
        ctx.path(ctx.attr._download_bower),
        "-b",
        "%s" % _run_npm_binary_str(ctx, ctx.attr._bower_archive, []),
        "-n",
        ctx.name,
        "-p",
        ctx.attr.package,
        "-v",
        ctx.attr.version,
        "-s",
        ctx.attr.sha1,
        "-o",
        download_name,
    ]

    out = ctx.execute(cmd)
    if out.return_code:
        fail("failed %s: %s" % (" ".join(cmd), out.stderr))

    _bash(ctx, " && ".join([
        "TMP=$(mktemp -d || mktemp -d -t bazel-tmp)",
        "TZ=UTC",
        "export UTC",
        "cd $TMP",
        "mkdir bower_components",
        "cd bower_components",
        "unzip %s" % ctx.path(download_name),
        "cd ..",
        "find . -exec touch -t 198001010000 '{}' ';'",
        "zip -Xr %s bower_components" % renamed_name,
        "cd ..",
        "rm -rf ${TMP}",
    ]))

    dep_version = ctx.attr.semver if ctx.attr.semver else ctx.attr.version
    ctx.file(
        version_name,
        '"%s":"%s#%s"' % (ctx.name, ctx.attr.package, dep_version),
    )
    ctx.file(
        "BUILD",
        "\n".join([
            "package(default_visibility=['//visibility:public'])",
            "filegroup(name = 'zipfile', srcs = ['%s'], )" % download_name,
            "filegroup(name = 'version_json', srcs = ['%s'], visibility=['//visibility:public'])" % version_name,
        ]),
        False,
    )

def _bash(ctx, cmd):
    cmd_list = ["bash", "-c", cmd]
    out = ctx.execute(cmd_list)
    if out.return_code:
        fail("failed %s: %s" % (" ".join(cmd_list), out.stderr))

bower_archive = repository_rule(
    _bower_archive,
    attrs = {
        "package": attr.string(mandatory = True),
        "semver": attr.string(),
        "sha1": attr.string(mandatory = True),
        "version": attr.string(mandatory = True),
        "_bower_archive": attr.label(default = Label("@bower//:%s" % _npm_tarball("bower"))),
        "_download_bower": attr.label(default = Label("//tools/js:download_bower.py")),
        "_run_npm": attr.label(default = Label("//tools/js:run_npm_binary.py")),
    },
)

def _bower_component_impl(ctx):
    transitive_zipfiles = depset(
        direct = [ctx.file.zipfile],
        transitive = [d.transitive_zipfiles for d in ctx.attr.deps],
    )

    transitive_licenses = depset(
        direct = [ctx.file.license],
        transitive = [d.transitive_licenses for d in ctx.attr.deps],
    )

    transitive_versions = depset(
        direct = ctx.files.version_json,
        transitive = [d.transitive_versions for d in ctx.attr.deps],
    )

    return struct(
        transitive_zipfiles = transitive_zipfiles,
        transitive_versions = transitive_versions,
        transitive_licenses = transitive_licenses,
    )

_common_attrs = {
    "deps": attr.label_list(providers = [
        "transitive_zipfiles",
        "transitive_versions",
        "transitive_licenses",
    ]),
}

def _js_component(ctx):
    dir = ctx.outputs.zip.path + ".dir"
    name = ctx.outputs.zip.basename
    if name.endswith(".zip"):
        name = name[:-4]
    dest = "%s/%s" % (dir, name)
    cmd = " && ".join([
        "TZ=UTC",
        "export TZ",
        "mkdir -p %s" % dest,
        "cp %s %s/" % (" ".join([s.path for s in ctx.files.srcs]), dest),
        "cd %s" % dir,
        "find . -exec touch -t 198001010000 '{}' ';'",
        "zip -Xqr ../%s *" % ctx.outputs.zip.basename,
    ])

    ctx.actions.run_shell(
        inputs = ctx.files.srcs,
        outputs = [ctx.outputs.zip],
        command = cmd,
        mnemonic = "GenBowerZip",
    )

    licenses = []
    if ctx.file.license:
        licenses.append(ctx.file.license)

    return struct(
        transitive_zipfiles = list([ctx.outputs.zip]),
        transitive_versions = depset(),
        transitive_licenses = depset(licenses),
    )

js_component = rule(
    _js_component,
    attrs = dict(_common_attrs.items() + {
        "srcs": attr.label_list(allow_files = [".js"]),
        "license": attr.label(allow_single_file = True),
    }.items()),
    outputs = {
        "zip": "%{name}.zip",
    },
)

_bower_component = rule(
    _bower_component_impl,
    attrs = dict(_common_attrs.items() + {
        "license": attr.label(allow_single_file = True),

        # If set, define by hand, and don't regenerate this entry in bower2bazel.
        "seed": attr.bool(default = False),
        "version_json": attr.label(allow_files = [".json"]),
        "zipfile": attr.label(allow_single_file = [".zip"]),
    }.items()),
)

# TODO(hanwen): make license mandatory.
def bower_component(name, license = None, **kwargs):
    prefix = "//lib:LICENSE-"
    if license and not license.startswith(prefix):
        license = prefix + license
    _bower_component(
        name = name,
        license = license,
        zipfile = "@%s//:zipfile" % name,
        version_json = "@%s//:version_json" % name,
        **kwargs
    )

def _bower_component_bundle_impl(ctx):
    """A bunch of bower components zipped up."""
    zips = depset()
    for d in ctx.attr.deps:
        files = d.transitive_zipfiles

        # TODO(davido): Make sure the field always contains a depset
        if type(files) == "list":
            files = depset(files)
        zips = depset(transitive = [zips, files])

    versions = depset(transitive = [d.transitive_versions for d in ctx.attr.deps])

    licenses = depset(transitive = [d.transitive_versions for d in ctx.attr.deps])

    out_zip = ctx.outputs.zip
    out_versions = ctx.outputs.version_json

    ctx.actions.run_shell(
        inputs = zips.to_list(),
        outputs = [out_zip],
        command = " && ".join([
            "p=$PWD",
            "TZ=UTC",
            "export TZ",
            "rm -rf %s.dir" % out_zip.path,
            "mkdir -p %s.dir/bower_components" % out_zip.path,
            "cd %s.dir/bower_components" % out_zip.path,
            "for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips.to_list()])),
            "cd ..",
            "find . -exec touch -t 198001010000 '{}' ';'",
            "zip -Xqr $p/%s bower_components/*" % out_zip.path,
        ]),
        mnemonic = "BowerCombine",
    )

    ctx.actions.run_shell(
        inputs = versions.to_list(),
        outputs = [out_versions],
        mnemonic = "BowerVersions",
        command = "(echo '{' ; for j in  %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions.to_list()]), out_versions.path),
    )

    return struct(
        transitive_zipfiles = zips,
        transitive_versions = versions,
        transitive_licenses = licenses,
    )

bower_component_bundle = rule(
    _bower_component_bundle_impl,
    attrs = _common_attrs,
    outputs = {
        "version_json": "%{name}-versions.json",
        "zip": "%{name}.zip",
    },
)
"""Groups a set of bower components together in a zip file.

Outputs:
  NAME-versions.json:
    a JSON file containing a PKG-NAME => PKG-NAME#VERSION mapping for the
    transitive dependencies.
  NAME.zip:
    a zip file containing the transitive dependencies for this bundle.
"""

def _vulcanize_impl(ctx):
    # intermediate artifact.
    vulcanized = ctx.actions.declare_file(
        ctx.outputs.html.path + ".vulcanized.html",
    )
    destdir = ctx.outputs.html.path + ".dir"
    zips = [z for d in ctx.attr.deps for z in d.transitive_zipfiles.to_list()]

    hermetic_npm_binary = " ".join([
        "python",
        "$p/" + ctx.file._run_npm.path,
        "$p/" + ctx.file._vulcanize_archive.path,
        "--inline-scripts",
        "--inline-css",
        "--strip-comments",
        "--out-html",
        "$p/" + vulcanized.path,
        ctx.file.app.path,
    ])

    pkg_dir = ctx.attr.pkg.lstrip("/")
    cmd = " && ".join([
        # unpack dependencies.
        "export PATH",
        "p=$PWD",
        "rm -rf %s" % destdir,
        "mkdir -p %s/%s/bower_components" % (destdir, pkg_dir),
        "for z in %s; do unzip -qd %s/%s/bower_components/ $z; done" % (
            " ".join([z.path for z in zips]),
            destdir,
            pkg_dir,
        ),
        "tar -cf - %s | tar -C %s -xf -" % (" ".join([s.path for s in ctx.files.srcs]), destdir),
        "cd %s" % destdir,
        hermetic_npm_binary,
    ])

    # Node/NPM is not (yet) hermeticized, so we have to get the binary
    # from the environment, and it may be under $HOME, so we can't run
    # in the sandbox.
    node_tweaks = dict(
        use_default_shell_env = True,
        execution_requirements = {"local": "1"},
    )
    ctx.actions.run_shell(
        mnemonic = "Vulcanize",
        inputs = [
            ctx.file._run_npm,
            ctx.file.app,
            ctx.file._vulcanize_archive,
        ] + list(zips) + ctx.files.srcs,
        outputs = [vulcanized],
        command = cmd,
        **node_tweaks
    )

    hermetic_npm_command = "export PATH && " + " ".join([
        "python",
        ctx.file._run_npm.path,
        ctx.file._crisper_archive.path,
        "--always-write-script",
        "--source",
        vulcanized.path,
        "--html",
        ctx.outputs.html.path,
        "--js",
        ctx.outputs.js.path,
    ])

    ctx.actions.run_shell(
        mnemonic = "Crisper",
        inputs = [
            ctx.file._run_npm,
            ctx.file.app,
            ctx.file._crisper_archive,
            vulcanized,
        ],
        outputs = [ctx.outputs.js, ctx.outputs.html],
        command = hermetic_npm_command,
        **node_tweaks
    )

_vulcanize_rule = rule(
    _vulcanize_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = [
            ".js",
            ".html",
            ".txt",
            ".css",
            ".ico",
        ]),
        "app": attr.label(
            mandatory = True,
            allow_single_file = True,
        ),
        "pkg": attr.string(mandatory = True),
        "deps": attr.label_list(providers = ["transitive_zipfiles"]),
        "_crisper_archive": attr.label(
            default = Label("@crisper//:%s" % _npm_tarball("crisper")),
            allow_single_file = True,
        ),
        "_run_npm": attr.label(
            default = Label("//tools/js:run_npm_binary.py"),
            allow_single_file = True,
        ),
        "_vulcanize_archive": attr.label(
            default = Label("@vulcanize//:%s" % _npm_tarball("vulcanize")),
            allow_single_file = True,
        ),
    },
    outputs = {
        "html": "%{name}.html",
        "js": "%{name}.js",
    },
)

def vulcanize(*args, **kwargs):
    """Vulcanize runs vulcanize and crisper on a set of sources."""
    _vulcanize_rule(pkg = native.package_name(), *args, **kwargs)
<commit_msg>Bazel: Make build tool chain forward compatible<commit_after>NPMJS = "NPMJS"

GERRIT = "GERRIT:"

NPM_VERSIONS = {
    "bower": "1.8.8",
    "crisper": "2.0.2",
    "vulcanize": "1.14.8",
}

NPM_SHA1S = {
    "bower": "82544be34a33aeae7efb8bdf9905247b2cffa985",
    "crisper": "7183c58cea33632fb036c91cefd1b43e390d22a2",
    "vulcanize": "679107f251c19ab7539529b1e3fdd40829e6fc63",
}

def _npm_tarball(name):
    return "%s@%s.npm_binary.tgz" % (name, NPM_VERSIONS[name])

def _npm_binary_impl(ctx):
    """rule to download a NPM archive."""
    name = ctx.name
    version = NPM_VERSIONS[name]
    sha1 = NPM_VERSIONS[name]

    dir = "%s-%s" % (name, version)
    filename = "%s.tgz" % dir
    base = "%s@%s.npm_binary.tgz" % (name, version)
    dest = ctx.path(base)
    repository = ctx.attr.repository
    if repository == GERRIT:
        url = "https://gerrit-maven.storage.googleapis.com/npm-packages/%s" % filename
    elif repository == NPMJS:
        url = "https://registry.npmjs.org/%s/-/%s" % (name, filename)
    else:
        fail("repository %s not in {%s,%s}" % (repository, GERRIT, NPMJS))

    python = ctx.which("python")
    script = ctx.path(ctx.attr._download_script)

    sha1 = NPM_SHA1S[name]
    args = [python, script, "-o", dest, "-u", url, "-v", sha1]
    out = ctx.execute(args)
    if out.return_code:
        fail("failed %s: %s" % (args, out.stderr))
    ctx.file("BUILD", "package(default_visibility=['//visibility:public'])\nfilegroup(name='tarball', srcs=['%s'])" % base, False)

npm_binary = repository_rule(
    attrs = {
        "repository": attr.string(default = NPMJS),
        # Label resolves within repo of the .bzl file.
        "_download_script": attr.label(default = Label("//tools:download_file.py")),
    },
    local = True,
    implementation = _npm_binary_impl,
)

# for use in repo rules.
def _run_npm_binary_str(ctx, tarball, args):
    python_bin = ctx.which("python")
    return " ".join([
        str(python_bin),
        str(ctx.path(ctx.attr._run_npm)),
        str(ctx.path(tarball)),
    ] + args)

def _bower_archive(ctx):
    """Download a bower package."""
    download_name = "%s__download_bower.zip" % ctx.name
    renamed_name = "%s__renamed.zip" % ctx.name
    version_name = "%s__version.json" % ctx.name

    cmd = [
        ctx.which("python"),
        ctx.path(ctx.attr._download_bower),
        "-b",
        "%s" % _run_npm_binary_str(ctx, ctx.attr._bower_archive, []),
        "-n",
        ctx.name,
        "-p",
        ctx.attr.package,
        "-v",
        ctx.attr.version,
        "-s",
        ctx.attr.sha1,
        "-o",
        download_name,
    ]

    out = ctx.execute(cmd)
    if out.return_code:
        fail("failed %s: %s" % (" ".join(cmd), out.stderr))

    _bash(ctx, " && ".join([
        "TMP=$(mktemp -d || mktemp -d -t bazel-tmp)",
        "TZ=UTC",
        "export UTC",
        "cd $TMP",
        "mkdir bower_components",
        "cd bower_components",
        "unzip %s" % ctx.path(download_name),
        "cd ..",
        "find . -exec touch -t 198001010000 '{}' ';'",
        "zip -Xr %s bower_components" % renamed_name,
        "cd ..",
        "rm -rf ${TMP}",
    ]))

    dep_version = ctx.attr.semver if ctx.attr.semver else ctx.attr.version
    ctx.file(
        version_name,
        '"%s":"%s#%s"' % (ctx.name, ctx.attr.package, dep_version),
    )
    ctx.file(
        "BUILD",
        "\n".join([
            "package(default_visibility=['//visibility:public'])",
            "filegroup(name = 'zipfile', srcs = ['%s'], )" % download_name,
            "filegroup(name = 'version_json', srcs = ['%s'], visibility=['//visibility:public'])" % version_name,
        ]),
        False,
    )

def _bash(ctx, cmd):
    cmd_list = ["bash", "-c", cmd]
    out = ctx.execute(cmd_list)
    if out.return_code:
        fail("failed %s: %s" % (" ".join(cmd_list), out.stderr))

bower_archive = repository_rule(
    _bower_archive,
    attrs = {
        "package": attr.string(mandatory = True),
        "semver": attr.string(),
        "sha1": attr.string(mandatory = True),
        "version": attr.string(mandatory = True),
        "_bower_archive": attr.label(default = Label("@bower//:%s" % _npm_tarball("bower"))),
        "_download_bower": attr.label(default = Label("//tools/js:download_bower.py")),
        "_run_npm": attr.label(default = Label("//tools/js:run_npm_binary.py")),
    },
)

def _bower_component_impl(ctx):
    transitive_zipfiles = depset(
        direct = [ctx.file.zipfile],
        transitive = [d.transitive_zipfiles for d in ctx.attr.deps],
    )

    transitive_licenses = depset(
        direct = [ctx.file.license],
        transitive = [d.transitive_licenses for d in ctx.attr.deps],
    )

    transitive_versions = depset(
        direct = ctx.files.version_json,
        transitive = [d.transitive_versions for d in ctx.attr.deps],
    )

    return struct(
        transitive_zipfiles = transitive_zipfiles,
        transitive_versions = transitive_versions,
        transitive_licenses = transitive_licenses,
    )

_common_attrs = {
    "deps": attr.label_list(providers = [
        "transitive_zipfiles",
        "transitive_versions",
        "transitive_licenses",
    ]),
}

def _js_component(ctx):
    dir = ctx.outputs.zip.path + ".dir"
    name = ctx.outputs.zip.basename
    if name.endswith(".zip"):
        name = name[:-4]
    dest = "%s/%s" % (dir, name)
    cmd = " && ".join([
        "TZ=UTC",
        "export TZ",
        "mkdir -p %s" % dest,
        "cp %s %s/" % (" ".join([s.path for s in ctx.files.srcs]), dest),
        "cd %s" % dir,
        "find . -exec touch -t 198001010000 '{}' ';'",
        "zip -Xqr ../%s *" % ctx.outputs.zip.basename,
    ])

    ctx.actions.run_shell(
        inputs = ctx.files.srcs,
        outputs = [ctx.outputs.zip],
        command = cmd,
        mnemonic = "GenBowerZip",
    )

    licenses = []
    if ctx.file.license:
        licenses.append(ctx.file.license)

    return struct(
        transitive_zipfiles = list([ctx.outputs.zip]),
        transitive_versions = depset(),
        transitive_licenses = depset(licenses),
    )

js_component = rule(
    _js_component,
    attrs = dict(_common_attrs.items() + {
        "srcs": attr.label_list(allow_files = [".js"]),
        "license": attr.label(allow_single_file = True),
    }.items()),
    outputs = {
        "zip": "%{name}.zip",
    },
)

_bower_component = rule(
    _bower_component_impl,
    attrs = dict(_common_attrs.items() + {
        "license": attr.label(allow_single_file = True),

        # If set, define by hand, and don't regenerate this entry in bower2bazel.
        "seed": attr.bool(default = False),
        "version_json": attr.label(allow_files = [".json"]),
        "zipfile": attr.label(allow_single_file = [".zip"]),
    }.items()),
)

# TODO(hanwen): make license mandatory.
def bower_component(name, license = None, **kwargs):
    prefix = "//lib:LICENSE-"
    if license and not license.startswith(prefix):
        license = prefix + license
    _bower_component(
        name = name,
        license = license,
        zipfile = "@%s//:zipfile" % name,
        version_json = "@%s//:version_json" % name,
        **kwargs
    )

def _bower_component_bundle_impl(ctx):
    """A bunch of bower components zipped up."""
    zips = depset()
    for d in ctx.attr.deps:
        files = d.transitive_zipfiles

        # TODO(davido): Make sure the field always contains a depset
        if type(files) == "list":
            files = depset(files)
        zips = depset(transitive = [zips, files])

    versions = depset(transitive = [d.transitive_versions for d in ctx.attr.deps])

    licenses = depset(transitive = [d.transitive_versions for d in ctx.attr.deps])

    out_zip = ctx.outputs.zip
    out_versions = ctx.outputs.version_json

    ctx.actions.run_shell(
        inputs = zips.to_list(),
        outputs = [out_zip],
        command = " && ".join([
            "p=$PWD",
            "TZ=UTC",
            "export TZ",
            "rm -rf %s.dir" % out_zip.path,
            "mkdir -p %s.dir/bower_components" % out_zip.path,
            "cd %s.dir/bower_components" % out_zip.path,
            "for z in %s; do unzip -q $p/$z ; done" % " ".join(sorted([z.path for z in zips.to_list()])),
            "cd ..",
            "find . -exec touch -t 198001010000 '{}' ';'",
            "zip -Xqr $p/%s bower_components/*" % out_zip.path,
        ]),
        mnemonic = "BowerCombine",
    )

    ctx.actions.run_shell(
        inputs = versions.to_list(),
        outputs = [out_versions],
        mnemonic = "BowerVersions",
        command = "(echo '{' ; for j in  %s ; do cat $j; echo ',' ; done ; echo \\\"\\\":\\\"\\\"; echo '}') > %s" % (" ".join([v.path for v in versions.to_list()]), out_versions.path),
    )

    return struct(
        transitive_zipfiles = zips,
        transitive_versions = versions,
        transitive_licenses = licenses,
    )

bower_component_bundle = rule(
    _bower_component_bundle_impl,
    attrs = _common_attrs,
    outputs = {
        "version_json": "%{name}-versions.json",
        "zip": "%{name}.zip",
    },
)
"""Groups a set of bower components together in a zip file.

Outputs:
  NAME-versions.json:
    a JSON file containing a PKG-NAME => PKG-NAME#VERSION mapping for the
    transitive dependencies.
  NAME.zip:
    a zip file containing the transitive dependencies for this bundle.
"""

def _vulcanize_impl(ctx):
    # intermediate artifact.
    vulcanized = ctx.actions.declare_file(
        ctx.outputs.html.path + ".vulcanized.html",
    )
    destdir = ctx.outputs.html.path + ".dir"
    zips = [z for d in ctx.attr.deps for z in d.transitive_zipfiles.to_list()]

    hermetic_npm_binary = " ".join([
        "python",
        "$p/" + ctx.file._run_npm.path,
        "$p/" + ctx.file._vulcanize_archive.path,
        "--inline-scripts",
        "--inline-css",
        "--strip-comments",
        "--out-html",
        "$p/" + vulcanized.path,
        ctx.file.app.path,
    ])

    pkg_dir = ctx.attr.pkg.lstrip("/")
    cmd = " && ".join([
        # unpack dependencies.
        "export PATH",
        "p=$PWD",
        "rm -rf %s" % destdir,
        "mkdir -p %s/%s/bower_components" % (destdir, pkg_dir),
        "for z in %s; do unzip -qd %s/%s/bower_components/ $z; done" % (
            " ".join([z.path for z in zips]),
            destdir,
            pkg_dir,
        ),
        "tar -cf - %s | tar -C %s -xf -" % (" ".join([s.path for s in ctx.files.srcs]), destdir),
        "cd %s" % destdir,
        hermetic_npm_binary,
    ])

    # Node/NPM is not (yet) hermeticized, so we have to get the binary
    # from the environment, and it may be under $HOME, so we can't run
    # in the sandbox.
    node_tweaks = dict(
        use_default_shell_env = True,
        execution_requirements = {"local": "1"},
    )
    ctx.actions.run_shell(
        mnemonic = "Vulcanize",
        inputs = [
            ctx.file._run_npm,
            ctx.file.app,
            ctx.file._vulcanize_archive,
        ] + list(zips) + ctx.files.srcs,
        outputs = [vulcanized],
        command = cmd,
        **node_tweaks
    )

    hermetic_npm_command = "export PATH && " + " ".join([
        "python",
        ctx.file._run_npm.path,
        ctx.file._crisper_archive.path,
        "--always-write-script",
        "--source",
        vulcanized.path,
        "--html",
        ctx.outputs.html.path,
        "--js",
        ctx.outputs.js.path,
    ])

    ctx.actions.run_shell(
        mnemonic = "Crisper",
        inputs = [
            ctx.file._run_npm,
            ctx.file.app,
            ctx.file._crisper_archive,
            vulcanized,
        ],
        outputs = [ctx.outputs.js, ctx.outputs.html],
        command = hermetic_npm_command,
        **node_tweaks
    )

_vulcanize_rule = rule(
    _vulcanize_impl,
    attrs = {
        "srcs": attr.label_list(allow_files = [
            ".js",
            ".html",
            ".txt",
            ".css",
            ".ico",
        ]),
        "app": attr.label(
            mandatory = True,
            allow_single_file = True,
        ),
        "pkg": attr.string(mandatory = True),
        "deps": attr.label_list(providers = ["transitive_zipfiles"]),
        "_crisper_archive": attr.label(
            default = Label("@crisper//:%s" % _npm_tarball("crisper")),
            allow_single_file = True,
        ),
        "_run_npm": attr.label(
            default = Label("//tools/js:run_npm_binary.py"),
            allow_single_file = True,
        ),
        "_vulcanize_archive": attr.label(
            default = Label("@vulcanize//:%s" % _npm_tarball("vulcanize")),
            allow_single_file = True,
        ),
    },
    outputs = {
        "html": "%{name}.html",
        "js": "%{name}.js",
    },
)

def vulcanize(*args, **kwargs):
    """Vulcanize runs vulcanize and crisper on a set of sources."""
    _vulcanize_rule(pkg = native.package_name(), *args, **kwargs)
<|endoftext|>


<commit_before>#!/usr/bin/python
# This just takes a (list of) range(s) and makes a fake bedfile with one line per location...

def get_peak_range(pre_line):
    line = pre_line.strip()
    colon = line.find(':')
    hyphen = line.find('-')
    chro = line[:colon]
    start = int(line[(colon+1):hyphen])
    end = int(line[(hyphen+1):])
    return (chro,start,end)

import sys
import math

print 'Expanding peaks!'

if len(sys.argv<3):
    sys.exit('Requires list of peaks and window size!')

peakfile = sys.argv[1]
window_size = float(sys.argv[2])
win_edge = int(math.ceil(window_size/2))
outfile = open(peakfile+'.exp','w')

for line in open(peakfile,'r'):
    [chro,start,end] = get_peak_range(line)
    for i in range(start-win_edge,end+win_edge):
        outline=chro+"\t"+str(i)+"\t"+str(i+1)+"\n"
        outfile.write(outline)
<commit_msg>i always make this error in len() checks...<commit_after>#!/usr/bin/python
# This just takes a (list of) range(s) and makes a fake bedfile with one line per location...

def get_peak_range(pre_line):
    line = pre_line.strip()
    colon = line.find(':')
    hyphen = line.find('-')
    chro = line[:colon]
    start = int(line[(colon+1):hyphen])
    end = int(line[(hyphen+1):])
    return (chro,start,end)

import sys
import math

print 'Expanding peaks!'

if len(sys.argv)<3:
    sys.exit('Requires list of peaks and window size!')

peakfile = sys.argv[1]
window_size = float(sys.argv[2])
win_edge = int(math.ceil(window_size/2))
outfile = open(peakfile+'.exp','w')

for line in open(peakfile,'r'):
    [chro,start,end] = get_peak_range(line)
    for i in range(start-win_edge,end+win_edge):
        outline=chro+"\t"+str(i)+"\t"+str(i+1)+"\n"
        outfile.write(outline)
<|endoftext|>


<commit_before>from astrobin_apps_equipment.api.filters.equipment_item_filter import EquipmentItemFilter
from astrobin_apps_equipment.models import Camera

class CameraFilter(EquipmentItemFilter):
    class Meta(EquipmentItemFilter.Meta):
        model = Camera
        fields = EquipmentItemFilter.Meta.fields + ['modified']
<commit_msg>(equipment) Don't show modified/cooled DSLR/mirrorless cameras on review page<commit_after>from django.db.models import QuerySet

from astrobin_apps_equipment.api.filters.equipment_item_filter import EquipmentItemFilter
from astrobin_apps_equipment.models import Camera
from astrobin_apps_equipment.services.camera_service import CameraService

class CameraFilter(EquipmentItemFilter):
    def has_pending_review(self, queryset: QuerySet, value, *args, **kwargs):
        queryset = super().has_pending_review(queryset, value, args, kwargs)
        queryset = queryset.filter(CameraService.variant_exclusion_query())

        return queryset

    class Meta(EquipmentItemFilter.Meta):
        model = Camera
        fields = EquipmentItemFilter.Meta.fields + ['modified']
<|endoftext|>