<commit_before># -*- coding: utf-8 -*-

import os
from datetime import datetime
from ChatExchange.chatexchange.client import Client
import HTMLParser
import md5
import ConfigParser
from helpers import environ_or_none
import threading

class GlobalVars:
    false_positives = []
    whitelisted_users = []
    blacklisted_users = []
    ignored_posts = []
    auto_ignored_posts = []
    startup_utc = datetime.utcnow().strftime("%H:%M:%S")
    latest_questions = []
    api_backoff_time = 0
    charcoal_room_id = "11540"
    meta_tavern_room_id = "89"
    socvr_room_id = "41570"
    blockedTime = {"all": 0, charcoal_room_id: 0, meta_tavern_room_id: 0, socvr_room_id: 0}

    experimental_reasons = []  # Don't widely report these
    non_socvr_reasons = []    # Don't report to SOCVR
    non_tavern_reasons = [    # Don't report in the Tavern
        "all-caps body",
        "all-caps answer",
        "repeating characters in body",
        "repeating characters in title",
        "repeating characters in answer",
        "few unique characters in body",
        "few unique characters in answer",
        "title has only one unique char",
        "phone number detected in title",
        "offensive body detected",
        "no whitespace in body",
        "no whitespace in answer",
    ]
    non_tavern_sites = ["stackoverflow.com"]

    parser = HTMLParser.HTMLParser()
    wrap = Client("stackexchange.com")
    wrapm = Client("meta.stackexchange.com")
    wrapso = Client("stackoverflow.com")
    privileged_users = {
        charcoal_room_id: [
            "117490",   # Normal Human
            "66258",    # Andy
            "31768",    # ManishEarth
            "103081",   # hichris123
            "73046",    # Undo
            "88521",    # ProgramFOX
            "59776",    # Doorknob
            "31465",    # Seth
            "88577",    # Santa Claus
            "34124",    # Andrew Leach
            "54229",    # apnorton
            "20459",    # S.L. Barth
            "32436",    # tchrist
            "30477",    # Brock Adams
            "58529",    # ferrybig
            "145208",   # Robert Longson
            "178825",   # Ms Yvette
            "171800",   # JAL
            "64978",    # PeterJ
            "125141",   # Jeffrey Bosboom
            "54902",    # bummi
            "135450",   # M.A.R.
            "145604",   # Quill
            "60548",    # rene
            "121401",   # michaelpri
            "116218",   # JamesENL
            "82927",    # Braiam
            "11606",    # bwDraco
            "19761",    # Ilmari Karonen
            "108271",   # Andrew T.
            "171054",   # Magisch
            "190011",   # Petter Friberg
            "165661",   # Tunaki
            "145086",   # Wai Ha Lee
            "137665",   # ByteCommander
            "147884",   # wythagoras
            "186395",   # Åna
            "193364",   # Ashish Ahuja
            "163686",   # Gothdo
            "145827",   # angussidney
            "121520",   # ArtOfCode
            "215783",   # KarmaBot (ArtOfCode's sock to test things with)
            "137388",   # QPaysTaxes
            "212311",   # Ryan Bemrose
            "172397",   # Kyll
            "224538",   # FrankerZ
            "61202",    # OldSkool
            "56166",    # Jan Dvorak
            "133966"    # DavidPostill
        ],
        meta_tavern_room_id: [
            "315433",   # Normal Human
            "244519",   # CRABOLO
            "244382",   # TGMCians
            "194047",   # Jan Dvorak
            "158100",   # rene
            "178438",   # Manishearth
            "237685",   # hichris123
            "215468",   # Undo
            "229438",   # ProgramFOX
            "180276",   # Doorknob
            "161974",   # Lynn Crumbling
            "186281",   # Andy
            "266094",   # Unihedro
            "245167",   # Infinite Recursion
            "230261",   # Jason C
            "213575",   # Braiam
            "241919",   # Andrew T.
            "203389",   # backwards-Seth
            "202832",   # Mooseman
            "160017",   # bwDraco
            "201151",   # bummi
            "188558",   # Frank
            "229166",   # Santa Claus
            "159034",   # Kevin Brown
            "203972",   # PeterJ
            "188673",   # Alexis King
            "258672",   # AstroCB
            "227577",   # Sam
            "255735",   # cybermonkey
            "279182",   # Ixrec
            "271104",   # James
            "220428",   # Qantas 94 Heavy
            "153355",   # tchrist
            "238426",   # Ed Cottrell
            "166899",   # Second Rikudo
            "287999",   # ASCIIThenANSI
            "208518",   # JNat
            "284141",   # michaelpri
            "260312",   # vaultah
            "244062",   # SouravGhosh
            "152859",   # Shadow Wizard
            "201314",   # apnorton
            "280934",   # M.A.Ramezani
            "200235",   # durron597
            "148310",   # Awesome Poodles / Brock Adams
            "168333",   # S.L. Barth
            "257207",   # Unikitty
            "244282",   # DroidDev
            "163250",   # Cupcake
            "298265",   # BoomsPlus
            "253560",   # josilber
            "244254",   # misterManSam
            "188189",   # Robert Longson
            "174699",   # Ilmari Karonen
            "202362",   # chmod 666 telkitty
            "289717",   # Quill
            "237813",   # bjb568
            "311345",   # Simon Klaver
            "171881",   # rekire
            "260388",   # Pandya
            "310756",   # Ms Yvette
            "262399",   # Jeffrey Bosboom
            "242209",   # JAL
            "280883",   # ByteCommander
            "302251",   # kos
            "262823",   # ArtOfCode
            "215067",   # Ferrybig
            "308386",   # Magisch
            "285368"    # angussidney
        ],
        socvr_room_id: [
            "1849664",  # Undo
            "2581872",  # hichris123
            "1198729",  # Manishearth
            "3717023",  # Normal Human aka 1999
            "2619912",  # ProgramFOX
            "578411",   # rene
            "1043380",  # gunr2171
            "2246344",  # Sam
            "2756409",  # TylerH
            "1768232",  # durron597
            "359284",   # Kevin Brown
            "258400",   # easwee
            "3622940",  # Unihedron
            "3204551",  # Deduplicator
            "4342498",  # NathanOliver
            "4639281",  # Tiny Giant
            "3093387",  # josilber
            "1652962",  # cimmanon
            "1677912",  # Mogsdad
            "656243",   # Lynn Crumbling
            "3933332",  # Rizier123
            "2422013",  # cybermonkey
            "3478852",  # Nisse Engström
            "2302862",  # Siguza
            "1324",     # Paul Roub
            "1743880",  # Tunaki
            "1663001",  # DavidG
            "2415822",  # JAL
            "4174897",  # Kyll
            "5299236",  # Kevin Guan
            "4050842",  # Thaillie
            "1816093",  # Drew
            "874188",   # Triplee
            "880772",   # approxiblue
            "1835379",  # Cerbrus
            "1843331",  # Tim Castelijns
            "3956566",  # JamesENL
            "2357233",  # Ms Yvette
            "3155639",  # AlexanderOMara
            "462627",   # Praveen Kumar
            "4490559",  # intboolstring
            "1364007",  # Wai Ha Lee
            "1699210",  # bummi
            "563532",   # Rob
            "5389107",  # Magisch
            "4099593",  # bhargav-rao
            "1542723",  # Ferrybig
            "2025923",  # Tushar
            "5292302",  # Petter Friberg
            "792066",   # Braiam
            "5666987",  # Ian
            "3160466",  # ArtOfCode
            "5735775",  # Ashish Ahuja
            "3476191",  # Nobody Nada
            "2227743",  # Eric D
            "821878",   # Ryan Bemrose
            "1413395",  # Panta Rei
            "4875631",  # FrankerZ
            "2958086",  # Compass
            "499214"    # JanDvorak
        ]
    }
    smokeDetector_user_id = {charcoal_room_id: "120914", meta_tavern_room_id: "266345",
                             socvr_room_id: "3735529"}

    censored_committer_names = {"3f4ed0f38df010ce300dba362fa63a62": "Undo1"}

    commit = os.popen('git log --pretty=format:"%h" -n 1').read()
    commit_author = os.popen('git log --pretty=format:"%an" -n 1').read()

    if md5.new(commit_author).hexdigest() in censored_committer_names:
        commit_author = censored_committer_names[md5.new(commit_author).hexdigest()]

    commit_with_author = os.popen('git log --pretty=format:"%h (' + commit_author + ': *%s*)" -n 1').read()
    on_master = os.popen("git rev-parse --abbrev-ref HEAD").read().strip() == "master"
    charcoal_hq = None
    tavern_on_the_meta = None
    socvr = None
    s = ""
    s_reverted = ""
    specialrooms = []
    apiquota = -1
    bodyfetcher = None
    se_sites = []
    users_chatting = {meta_tavern_room_id: [], charcoal_room_id: [], socvr_room_id: []}
    why_data = []
    why_data_allspam = []
    notifications = []
    listen_to_these_if_edited = []
    multiple_reporters = []
    api_calls_per_site = {}

    api_request_lock = threading.Lock()

    config = ConfigParser.RawConfigParser()
    config.read('config')

    latest_smokedetector_messages = {meta_tavern_room_id: [], charcoal_room_id: [], socvr_room_id: []}

    # environ_or_none defined in helpers.py
    bot_name = environ_or_none("SMOKEDETECTOR_NAME") or "SmokeDetector"
    bot_repository = environ_or_none("SMOKEDETECTOR_REPO") or "//github.com/Charcoal-SE/SmokeDetector"
    chatmessage_prefix = "[{}]({})".format(bot_name, bot_repository)

    site_id_dict = {}
    post_site_id_to_question = {}

    location = config.get("Config", "location")
    print location

    metasmoke_ws = None

    try:
        metasmoke_host = config.get("Config", "metasmoke_host")
        print metasmoke_host
    except ConfigParser.NoOptionError:
        metasmoke_host = None
        print "metasmoke host not found. Set it as metasmoke_host in the config file. See https://github.com/Charcoal-SE/metasmoke."

    try:
        metasmoke_key = config.get("Config", "metasmoke_key")
    except ConfigParser.NoOptionError:
        metasmoke_key = ""
        print "No metasmoke key found, which is okay if both are running on the same host"

    try:
        metasmoke_ws_host = config.get("Config", "metasmoke_ws_host")
    except ConfigParser.NoOptionError:
        metasmoke_ws_host = ""
        print "No metasmoke websocket host found, which is okay if you're anti-websocket"
<commit_msg>+djsmiley2k to CHQ<commit_after># -*- coding: utf-8 -*-

import os
from datetime import datetime
from ChatExchange.chatexchange.client import Client
import HTMLParser
import md5
import ConfigParser
from helpers import environ_or_none
import threading

class GlobalVars:
    false_positives = []
    whitelisted_users = []
    blacklisted_users = []
    ignored_posts = []
    auto_ignored_posts = []
    startup_utc = datetime.utcnow().strftime("%H:%M:%S")
    latest_questions = []
    api_backoff_time = 0
    charcoal_room_id = "11540"
    meta_tavern_room_id = "89"
    socvr_room_id = "41570"
    blockedTime = {"all": 0, charcoal_room_id: 0, meta_tavern_room_id: 0, socvr_room_id: 0}

    experimental_reasons = []  # Don't widely report these
    non_socvr_reasons = []    # Don't report to SOCVR
    non_tavern_reasons = [    # Don't report in the Tavern
        "all-caps body",
        "all-caps answer",
        "repeating characters in body",
        "repeating characters in title",
        "repeating characters in answer",
        "few unique characters in body",
        "few unique characters in answer",
        "title has only one unique char",
        "phone number detected in title",
        "offensive body detected",
        "no whitespace in body",
        "no whitespace in answer",
    ]
    non_tavern_sites = ["stackoverflow.com"]

    parser = HTMLParser.HTMLParser()
    wrap = Client("stackexchange.com")
    wrapm = Client("meta.stackexchange.com")
    wrapso = Client("stackoverflow.com")
    privileged_users = {
        charcoal_room_id: [
            "117490",   # Normal Human
            "66258",    # Andy
            "31768",    # ManishEarth
            "103081",   # hichris123
            "73046",    # Undo
            "88521",    # ProgramFOX
            "59776",    # Doorknob
            "31465",    # Seth
            "88577",    # Santa Claus
            "34124",    # Andrew Leach
            "54229",    # apnorton
            "20459",    # S.L. Barth
            "32436",    # tchrist
            "30477",    # Brock Adams
            "58529",    # ferrybig
            "145208",   # Robert Longson
            "178825",   # Ms Yvette
            "171800",   # JAL
            "64978",    # PeterJ
            "125141",   # Jeffrey Bosboom
            "54902",    # bummi
            "135450",   # M.A.R.
            "145604",   # Quill
            "60548",    # rene
            "121401",   # michaelpri
            "116218",   # JamesENL
            "82927",    # Braiam
            "11606",    # bwDraco
            "19761",    # Ilmari Karonen
            "108271",   # Andrew T.
            "171054",   # Magisch
            "190011",   # Petter Friberg
            "165661",   # Tunaki
            "145086",   # Wai Ha Lee
            "137665",   # ByteCommander
            "147884",   # wythagoras
            "186395",   # Åna
            "193364",   # Ashish Ahuja
            "163686",   # Gothdo
            "145827",   # angussidney
            "121520",   # ArtOfCode
            "215783",   # KarmaBot (ArtOfCode's sock to test things with)
            "137388",   # QPaysTaxes
            "212311",   # Ryan Bemrose
            "172397",   # Kyll
            "224538",   # FrankerZ
            "61202",    # OldSkool
            "56166",    # Jan Dvorak
            "133966",   # DavidPostill
            "22839"     # djsmiley2k
        ],
        meta_tavern_room_id: [
            "315433",   # Normal Human
            "244519",   # CRABOLO
            "244382",   # TGMCians
            "194047",   # Jan Dvorak
            "158100",   # rene
            "178438",   # Manishearth
            "237685",   # hichris123
            "215468",   # Undo
            "229438",   # ProgramFOX
            "180276",   # Doorknob
            "161974",   # Lynn Crumbling
            "186281",   # Andy
            "266094",   # Unihedro
            "245167",   # Infinite Recursion
            "230261",   # Jason C
            "213575",   # Braiam
            "241919",   # Andrew T.
            "203389",   # backwards-Seth
            "202832",   # Mooseman
            "160017",   # bwDraco
            "201151",   # bummi
            "188558",   # Frank
            "229166",   # Santa Claus
            "159034",   # Kevin Brown
            "203972",   # PeterJ
            "188673",   # Alexis King
            "258672",   # AstroCB
            "227577",   # Sam
            "255735",   # cybermonkey
            "279182",   # Ixrec
            "271104",   # James
            "220428",   # Qantas 94 Heavy
            "153355",   # tchrist
            "238426",   # Ed Cottrell
            "166899",   # Second Rikudo
            "287999",   # ASCIIThenANSI
            "208518",   # JNat
            "284141",   # michaelpri
            "260312",   # vaultah
            "244062",   # SouravGhosh
            "152859",   # Shadow Wizard
            "201314",   # apnorton
            "280934",   # M.A.Ramezani
            "200235",   # durron597
            "148310",   # Awesome Poodles / Brock Adams
            "168333",   # S.L. Barth
            "257207",   # Unikitty
            "244282",   # DroidDev
            "163250",   # Cupcake
            "298265",   # BoomsPlus
            "253560",   # josilber
            "244254",   # misterManSam
            "188189",   # Robert Longson
            "174699",   # Ilmari Karonen
            "202362",   # chmod 666 telkitty
            "289717",   # Quill
            "237813",   # bjb568
            "311345",   # Simon Klaver
            "171881",   # rekire
            "260388",   # Pandya
            "310756",   # Ms Yvette
            "262399",   # Jeffrey Bosboom
            "242209",   # JAL
            "280883",   # ByteCommander
            "302251",   # kos
            "262823",   # ArtOfCode
            "215067",   # Ferrybig
            "308386",   # Magisch
            "285368"    # angussidney
        ],
        socvr_room_id: [
            "1849664",  # Undo
            "2581872",  # hichris123
            "1198729",  # Manishearth
            "3717023",  # Normal Human aka 1999
            "2619912",  # ProgramFOX
            "578411",   # rene
            "1043380",  # gunr2171
            "2246344",  # Sam
            "2756409",  # TylerH
            "1768232",  # durron597
            "359284",   # Kevin Brown
            "258400",   # easwee
            "3622940",  # Unihedron
            "3204551",  # Deduplicator
            "4342498",  # NathanOliver
            "4639281",  # Tiny Giant
            "3093387",  # josilber
            "1652962",  # cimmanon
            "1677912",  # Mogsdad
            "656243",   # Lynn Crumbling
            "3933332",  # Rizier123
            "2422013",  # cybermonkey
            "3478852",  # Nisse Engström
            "2302862",  # Siguza
            "1324",     # Paul Roub
            "1743880",  # Tunaki
            "1663001",  # DavidG
            "2415822",  # JAL
            "4174897",  # Kyll
            "5299236",  # Kevin Guan
            "4050842",  # Thaillie
            "1816093",  # Drew
            "874188",   # Triplee
            "880772",   # approxiblue
            "1835379",  # Cerbrus
            "1843331",  # Tim Castelijns
            "3956566",  # JamesENL
            "2357233",  # Ms Yvette
            "3155639",  # AlexanderOMara
            "462627",   # Praveen Kumar
            "4490559",  # intboolstring
            "1364007",  # Wai Ha Lee
            "1699210",  # bummi
            "563532",   # Rob
            "5389107",  # Magisch
            "4099593",  # bhargav-rao
            "1542723",  # Ferrybig
            "2025923",  # Tushar
            "5292302",  # Petter Friberg
            "792066",   # Braiam
            "5666987",  # Ian
            "3160466",  # ArtOfCode
            "5735775",  # Ashish Ahuja
            "3476191",  # Nobody Nada
            "2227743",  # Eric D
            "821878",   # Ryan Bemrose
            "1413395",  # Panta Rei
            "4875631",  # FrankerZ
            "2958086",  # Compass
            "499214"    # JanDvorak
        ]
    }
    smokeDetector_user_id = {charcoal_room_id: "120914", meta_tavern_room_id: "266345",
                             socvr_room_id: "3735529"}

    censored_committer_names = {"3f4ed0f38df010ce300dba362fa63a62": "Undo1"}

    commit = os.popen('git log --pretty=format:"%h" -n 1').read()
    commit_author = os.popen('git log --pretty=format:"%an" -n 1').read()

    if md5.new(commit_author).hexdigest() in censored_committer_names:
        commit_author = censored_committer_names[md5.new(commit_author).hexdigest()]

    commit_with_author = os.popen('git log --pretty=format:"%h (' + commit_author + ': *%s*)" -n 1').read()
    on_master = os.popen("git rev-parse --abbrev-ref HEAD").read().strip() == "master"
    charcoal_hq = None
    tavern_on_the_meta = None
    socvr = None
    s = ""
    s_reverted = ""
    specialrooms = []
    apiquota = -1
    bodyfetcher = None
    se_sites = []
    users_chatting = {meta_tavern_room_id: [], charcoal_room_id: [], socvr_room_id: []}
    why_data = []
    why_data_allspam = []
    notifications = []
    listen_to_these_if_edited = []
    multiple_reporters = []
    api_calls_per_site = {}

    api_request_lock = threading.Lock()

    config = ConfigParser.RawConfigParser()
    config.read('config')

    latest_smokedetector_messages = {meta_tavern_room_id: [], charcoal_room_id: [], socvr_room_id: []}

    # environ_or_none defined in helpers.py
    bot_name = environ_or_none("SMOKEDETECTOR_NAME") or "SmokeDetector"
    bot_repository = environ_or_none("SMOKEDETECTOR_REPO") or "//github.com/Charcoal-SE/SmokeDetector"
    chatmessage_prefix = "[{}]({})".format(bot_name, bot_repository)

    site_id_dict = {}
    post_site_id_to_question = {}

    location = config.get("Config", "location")
    print location

    metasmoke_ws = None

    try:
        metasmoke_host = config.get("Config", "metasmoke_host")
        print metasmoke_host
    except ConfigParser.NoOptionError:
        metasmoke_host = None
        print "metasmoke host not found. Set it as metasmoke_host in the config file. See https://github.com/Charcoal-SE/metasmoke."

    try:
        metasmoke_key = config.get("Config", "metasmoke_key")
    except ConfigParser.NoOptionError:
        metasmoke_key = ""
        print "No metasmoke key found, which is okay if both are running on the same host"

    try:
        metasmoke_ws_host = config.get("Config", "metasmoke_ws_host")
    except ConfigParser.NoOptionError:
        metasmoke_ws_host = ""
        print "No metasmoke websocket host found, which is okay if you're anti-websocket"
<|endoftext|>


<commit_before>import pytest

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from scrapi.linter.document import NormalizedDocument, RawDocument

# Need to force cassandra to ignore set keyspace
from scrapi.processing.postgres import PostgresProcessor, Document

from . import utils

test_db = PostgresProcessor()

engine = create_engine('postgresql://localhost/scrapi', echo=True)
session = sessionmaker(bind=engine)()

NORMALIZED = NormalizedDocument(utils.RECORD)
RAW = RawDocument(utils.RAW_DOC)

def test_process_raw():
    test_db.process_raw(RAW)
    queryset = Document(docID='someID', source=RAW['source'])
    assert queryset.docID == RAW.attributes['docID']
<commit_msg>Remove test db setup from postgres processor<commit_after>import pytest

from sqlalchemy import create_engine
from sqlalchemy.orm import sessionmaker

from scrapi.linter.document import NormalizedDocument, RawDocument

from scrapi.processing.postgres import PostgresProcessor, Document

from . import utils

test_db = PostgresProcessor()

engine = create_engine('postgresql://localhost/test', echo=True)
session = sessionmaker(bind=engine)()

NORMALIZED = NormalizedDocument(utils.RECORD)
RAW = RawDocument(utils.RAW_DOC)

@pytest.mark.postgres
def test_process_raw():
    test_db.process_raw(RAW)
    queryset = Document(docID='someID', source=RAW['source'])
    assert queryset.docID == RAW.attributes['docID']
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

import uuid
import re
from smtplib import SMTPException

from django.contrib import auth
from django.contrib import messages
from django.core.mail import send_mail
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from django.views.decorators.debug import sensitive_post_parameters

from django.conf import settings
from apps.authentication.forms import (LoginForm, RegisterForm,
                            RecoveryForm, ChangePasswordForm)
from apps.authentication.models import OnlineUser as User, RegisterToken, Email

@sensitive_post_parameters()
def login(request):
    redirect_url = request.REQUEST.get('next', '')
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.login(request):
            messages.success(request, _(u'Du er nå logget inn.'))
            if redirect_url:
                return HttpResponseRedirect(redirect_url)
            return HttpResponseRedirect('/')
        else: form = LoginForm(request.POST, auto_id=True)
    else:
        form = LoginForm()

    response_dict = { 'form' : form, 'next' : redirect_url}
    return render(request, 'auth/login.html', response_dict)

def logout(request):
    auth.logout(request)
    messages.success(request, _(u'Du er nå logget ut.'))
    return HttpResponseRedirect('/')

@sensitive_post_parameters()
def register(request):
    if request.user.is_authenticated():
        messages.error(request, _(u'Registrering av ny konto krever at du er logget ut.'))
        return HttpResponseRedirect('/')
    else:
        if request.method == 'POST':
            form = RegisterForm(request.POST)
            if form.is_valid():
                cleaned = form.cleaned_data

                # Create user
                user = User(
                    username=cleaned['username'],
                    first_name=cleaned['first_name'].title(),
                    last_name=cleaned['last_name'].title(),
                )
                # Set remaining fields
                user.phone_number=cleaned['phone']
                user.address=cleaned['address'].title()
                user.zip_code=cleaned['zip_code']
                # Store password properly
                user.set_password(cleaned['password'])
                # Users need to be manually activated
                user.is_active = False
                user.save()

                # Set email address
                email = Email(
                    user=user,
                    email=cleaned['email'].lower(),
                )
                email.primary = True
                email.save()

                # Create the registration token
                token = uuid.uuid4().hex
                rt = RegisterToken(user=user, email=cleaned['email'], token=token)
                rt.save()

                email_message = _(u"""
En konto har blitt registrert på online.ntnu.no med denne epostadressen. Dersom du ikke
har utført denne handlingen ber vi deg se bort fra denne eposten.

For å bruke denne kontoen kreves det at du verifiserer epostadressen. Du kan gjøre
dette ved å besøke linken under.

http://%s/auth/verify/%s/

Denne lenken vil være gyldig i 24 timer. Dersom du behøver å få tilsendt en ny lenke
kan dette gjøres med funksjonen for å gjenopprette passord.
""") % (request.META['HTTP_HOST'], token)
                try:
                    send_mail(_(u'Verifiser din konto'), email_message, settings.DEFAULT_FROM_EMAIL, [email.email,])
                except SMTPException:
                    messages.error(request, u'Det oppstod en kritisk feil, epostadressen er ugyldig!')
                    return redirect('home')

                messages.success(request, _(u'Registreringen var vellykket. Se tilsendt epost for verifiseringsinstrukser.'))

                return HttpResponseRedirect('/')
            else:
                form = RegisterForm(request.POST, auto_id=True)
        else:
            form = RegisterForm()

        return render(request, 'auth/register.html', {'form': form, })

def verify(request, token):
    rt = get_object_or_404(RegisterToken, token=token)

    if rt.is_valid:
        email = get_object_or_404(Email, email=rt.email)
        email.verified = True
        email.save()

        user = getattr(rt, 'user')

        # If it is a stud email, set the ntnu_username for user
        if re.match(r'[^@]+@stud\.ntnu\.no', rt.email):
            user.ntnu_username = rt.email.split("@")[0]

        user_activated = False
        if not user.is_active:
            user.is_active = True
            user_activated = True

        try:
            user.save()
            rt.delete()

            if user_activated:
                messages.success(request, _(u'Bruker %s ble aktivert. Du kan nå logge inn.') % user.username)
                return redirect('auth_login')
            else:
                messages.success(request, _(u'Eposten %s er nå verifisert.') % email)
                return redirect('profiles')

        except IntegrityError:
            email_message = u"""
Problemer med en verifikasjon av en epost, klager på duplikat av ntnu_brukernavn.

Det er umulig å fikse denne bugen uten å vite hvilken konto det er, så kan man finne ut hvorfor det skjer, folk skal ikke kunne legge til duplikater av eposter uansett, så det hele er meget rart.

Brukerid = %d
NTNU brukernavn = %s
            """ % (user.id, user.ntnu_username)
            send_mail(_(u'Halvsketchy debug epost for rar bug'), email_message, u"havardsv@rambo.drift.biz", ["dotkom@online.ntnu.no",])
            messages.error(request, _(u"Noe gikk meget galt mens vi forsøkte å verifisere eposten din. Vennligst send en epost til dotkom@online.ntnu.no med detaljer."))

    else:
        messages.error(request, _(u'Denne lenken er utløpt. Bruk gjenopprett passord for å få tilsendt en ny lenke.'))
        return HttpResponseRedirect('/')

def recover(request):
    if request.user.is_authenticated():
        messages.error(request, _(u'Gjenoppretning av passord krever at du er logget ut.'))
        return HttpResponseRedirect('/')
    else:
        if request.method == 'POST':
            form = RecoveryForm(request.POST)
            if form.is_valid():
                email_string = form.cleaned_data['email']
                emails = Email.objects.filter(email=email_string)

                if len(emails) == 0:
                    messages.error(request, _(u'Denne eposten er ikke registrert i våre systemer.'))
                    return HttpResponseRedirect('/')

                email = emails[0]

                # Create the registration token
                token = uuid.uuid4().hex
                rt = RegisterToken(user=email.user, email=email.email, token=token)
                rt.save()

                email_message = _(u"""
Vi har mottat forespørsel om å gjenopprette passordet for kontoen bundet til %s.
Dersom du ikke har bedt om denne handlingen ber vi deg se bort fra denne eposten.

Brukernavn: %s

Hvis du ønsker å gjennomføre en gjenoppretning av passord, bruk lenken under.

http://%s/auth/set_password/%s/

Denne lenken vil være gyldig i 24 timer. Dersom du behøver å få tilsendt en ny lenke
kan dette gjøres med funksjonen for å gjenopprette passord.
""") % (email.email, email.user.username, request.META['HTTP_HOST'], token)

                send_mail(_(u'Gjenoppretning av passord'), email_message, settings.DEFAULT_FROM_EMAIL, [email.email,])

                messages.success(request, _(u'En lenke for gjenoppretning har blitt sendt til %s.') % email.email)

                return HttpResponseRedirect('/')
            else:
                form = RecoveryForm(request.POST, auto_id=True)
        else:
            form = RecoveryForm()

        return render(request, 'auth/recover.html', {'form': form})

@sensitive_post_parameters()
def set_password(request, token=None):
    if request.user.is_authenticated():
        return HttpResponseRedirect('/')
    else:
        tokens = RegisterToken.objects.filter(token=token)

        if tokens.count() == 1:
            rt = tokens[0]
            if rt.is_valid:
                if request.method == 'POST':
                    form = ChangePasswordForm(request.POST, auto_id=True)
                    if form.is_valid():
                        user = getattr(rt, 'user')

                        user.is_active = True
                        user.set_password(form.cleaned_data['new_password'])
                        user.save()

                        rt.delete()

                        messages.success(request, _(u'Bruker %s har gjennomført vellykket gjenoppretning av passord. Du kan nå logge inn.') % user.username)

                        return HttpResponseRedirect('/')
                else:
                    form = ChangePasswordForm()

                    messages.success(request, _(u'Lenken er akseptert. Vennligst skriv inn ønsket passord.'))

                return render(request, 'auth/set_password.html', {'form': form, 'token': token})

        else:
            messages.error(request, _(u'Lenken er ugyldig. Vennligst bruk gjenoppretning av passord for å få tilsendt en ny lenke.'))
            return HttpResponseRedirect('/')
<commit_msg>Forgot integrity error.. fuck.<commit_after># -*- coding: utf-8 -*-

import uuid
import re
from smtplib import SMTPException

from django.contrib import auth
from django.contrib import messages
from django.core.mail import send_mail
from django.db.utils import IntegrityErro
from django.shortcuts import render, redirect, get_object_or_404
from django.http import HttpResponseRedirect
from django.utils.translation import ugettext as _
from django.views.decorators.debug import sensitive_post_parameters

from django.conf import settings
from apps.authentication.forms import (LoginForm, RegisterForm,
                            RecoveryForm, ChangePasswordForm)
from apps.authentication.models import OnlineUser as User, RegisterToken, Email

@sensitive_post_parameters()
def login(request):
    redirect_url = request.REQUEST.get('next', '')
    if request.method == 'POST':
        form = LoginForm(request.POST)
        if form.login(request):
            messages.success(request, _(u'Du er nå logget inn.'))
            if redirect_url:
                return HttpResponseRedirect(redirect_url)
            return HttpResponseRedirect('/')
        else: form = LoginForm(request.POST, auto_id=True)
    else:
        form = LoginForm()

    response_dict = { 'form' : form, 'next' : redirect_url}
    return render(request, 'auth/login.html', response_dict)

def logout(request):
    auth.logout(request)
    messages.success(request, _(u'Du er nå logget ut.'))
    return HttpResponseRedirect('/')

@sensitive_post_parameters()
def register(request):
    if request.user.is_authenticated():
        messages.error(request, _(u'Registrering av ny konto krever at du er logget ut.'))
        return HttpResponseRedirect('/')
    else:
        if request.method == 'POST':
            form = RegisterForm(request.POST)
            if form.is_valid():
                cleaned = form.cleaned_data

                # Create user
                user = User(
                    username=cleaned['username'],
                    first_name=cleaned['first_name'].title(),
                    last_name=cleaned['last_name'].title(),
                )
                # Set remaining fields
                user.phone_number=cleaned['phone']
                user.address=cleaned['address'].title()
                user.zip_code=cleaned['zip_code']
                # Store password properly
                user.set_password(cleaned['password'])
                # Users need to be manually activated
                user.is_active = False
                user.save()

                # Set email address
                email = Email(
                    user=user,
                    email=cleaned['email'].lower(),
                )
                email.primary = True
                email.save()

                # Create the registration token
                token = uuid.uuid4().hex
                rt = RegisterToken(user=user, email=cleaned['email'], token=token)
                rt.save()

                email_message = _(u"""
En konto har blitt registrert på online.ntnu.no med denne epostadressen. Dersom du ikke
har utført denne handlingen ber vi deg se bort fra denne eposten.

For å bruke denne kontoen kreves det at du verifiserer epostadressen. Du kan gjøre
dette ved å besøke linken under.

http://%s/auth/verify/%s/

Denne lenken vil være gyldig i 24 timer. Dersom du behøver å få tilsendt en ny lenke
kan dette gjøres med funksjonen for å gjenopprette passord.
""") % (request.META['HTTP_HOST'], token)
                try:
                    send_mail(_(u'Verifiser din konto'), email_message, settings.DEFAULT_FROM_EMAIL, [email.email,])
                except SMTPException:
                    messages.error(request, u'Det oppstod en kritisk feil, epostadressen er ugyldig!')
                    return redirect('home')

                messages.success(request, _(u'Registreringen var vellykket. Se tilsendt epost for verifiseringsinstrukser.'))

                return HttpResponseRedirect('/')
            else:
                form = RegisterForm(request.POST, auto_id=True)
        else:
            form = RegisterForm()

        return render(request, 'auth/register.html', {'form': form, })

def verify(request, token):
    rt = get_object_or_404(RegisterToken, token=token)

    if rt.is_valid:
        email = get_object_or_404(Email, email=rt.email)
        email.verified = True
        email.save()

        user = getattr(rt, 'user')

        # If it is a stud email, set the ntnu_username for user
        if re.match(r'[^@]+@stud\.ntnu\.no', rt.email):
            user.ntnu_username = rt.email.split("@")[0]

        user_activated = False
        if not user.is_active:
            user.is_active = True
            user_activated = True

        try:
            user.save()
            rt.delete()

            if user_activated:
                messages.success(request, _(u'Bruker %s ble aktivert. Du kan nå logge inn.') % user.username)
                return redirect('auth_login')
            else:
                messages.success(request, _(u'Eposten %s er nå verifisert.') % email)
                return redirect('profiles')

        except IntegrityError:
            email_message = u"""
Problemer med en verifikasjon av en epost, klager på duplikat av ntnu_brukernavn.

Det er umulig å fikse denne bugen uten å vite hvilken konto det er, så kan man finne ut hvorfor det skjer, folk skal ikke kunne legge til duplikater av eposter uansett, så det hele er meget rart.

Brukerid = %d
NTNU brukernavn = %s
            """ % (user.id, user.ntnu_username)
            send_mail(_(u'Halvsketchy debug epost for rar bug'), email_message, u"havardsv@rambo.drift.biz", ["dotkom@online.ntnu.no",])
            messages.error(request, _(u"Noe gikk meget galt mens vi forsøkte å verifisere eposten din. Vennligst send en epost til dotkom@online.ntnu.no med detaljer."))

    else:
        messages.error(request, _(u'Denne lenken er utløpt. Bruk gjenopprett passord for å få tilsendt en ny lenke.'))
        return HttpResponseRedirect('/')

def recover(request):
    if request.user.is_authenticated():
        messages.error(request, _(u'Gjenoppretning av passord krever at du er logget ut.'))
        return HttpResponseRedirect('/')
    else:
        if request.method == 'POST':
            form = RecoveryForm(request.POST)
            if form.is_valid():
                email_string = form.cleaned_data['email']
                emails = Email.objects.filter(email=email_string)

                if len(emails) == 0:
                    messages.error(request, _(u'Denne eposten er ikke registrert i våre systemer.'))
                    return HttpResponseRedirect('/')

                email = emails[0]

                # Create the registration token
                token = uuid.uuid4().hex
                rt = RegisterToken(user=email.user, email=email.email, token=token)
                rt.save()

                email_message = _(u"""
Vi har mottat forespørsel om å gjenopprette passordet for kontoen bundet til %s.
Dersom du ikke har bedt om denne handlingen ber vi deg se bort fra denne eposten.

Brukernavn: %s

Hvis du ønsker å gjennomføre en gjenoppretning av passord, bruk lenken under.

http://%s/auth/set_password/%s/

Denne lenken vil være gyldig i 24 timer. Dersom du behøver å få tilsendt en ny lenke
kan dette gjøres med funksjonen for å gjenopprette passord.
""") % (email.email, email.user.username, request.META['HTTP_HOST'], token)

                send_mail(_(u'Gjenoppretning av passord'), email_message, settings.DEFAULT_FROM_EMAIL, [email.email,])

                messages.success(request, _(u'En lenke for gjenoppretning har blitt sendt til %s.') % email.email)

                return HttpResponseRedirect('/')
            else:
                form = RecoveryForm(request.POST, auto_id=True)
        else:
            form = RecoveryForm()

        return render(request, 'auth/recover.html', {'form': form})

@sensitive_post_parameters()
def set_password(request, token=None):
    if request.user.is_authenticated():
        return HttpResponseRedirect('/')
    else:
        tokens = RegisterToken.objects.filter(token=token)

        if tokens.count() == 1:
            rt = tokens[0]
            if rt.is_valid:
                if request.method == 'POST':
                    form = ChangePasswordForm(request.POST, auto_id=True)
                    if form.is_valid():
                        user = getattr(rt, 'user')

                        user.is_active = True
                        user.set_password(form.cleaned_data['new_password'])
                        user.save()

                        rt.delete()

                        messages.success(request, _(u'Bruker %s har gjennomført vellykket gjenoppretning av passord. Du kan nå logge inn.') % user.username)

                        return HttpResponseRedirect('/')
                else:
                    form = ChangePasswordForm()

                    messages.success(request, _(u'Lenken er akseptert. Vennligst skriv inn ønsket passord.'))

                return render(request, 'auth/set_password.html', {'form': form, 'token': token})

        else:
            messages.error(request, _(u'Lenken er ugyldig. Vennligst bruk gjenoppretning av passord for å få tilsendt en ny lenke.'))
            return HttpResponseRedirect('/')
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-

#
# Copyright (c) 2011-2015 Genestack Limited
# All Rights Reserved
# THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF GENESTACK LIMITED
# The copyright notice above does not evidence any
# actual or intended publication of such source code.
#

from argparse import ArgumentParser
import sys
import os
import cmd
import shlex
from traceback import print_exc
from Exceptions import GenestackException
from utils import isatty, make_connection_parser, get_connection

if isatty():
    # To have autocomplete and console navigation on windows you need to have pyreadline installed.
    # Pyreadline replace readline with alias to itself.
    try:
        import readline
    except:
        pass

HELP_SEPARATOR = '\n%s  Help  %s' % ('=' * 20, '=' * 20)

def get_help(parser):
    """
    Return help text for parser.

    :param parser: parser
    :type parser: ArgumentParser
    :return:
    """
    # Code almost identical with parser.print_help() with next changes:
    # it return text instead print
    # it place group 'command arguments' to the first place
    formatter = parser._get_formatter()
    # usage
    formatter.add_usage(parser.usage, parser._actions,
                        parser._mutually_exclusive_groups)
    # description
    formatter.add_text(parser.description)

    # positionals, optionals and user-defined groups
    groups = list(parser._action_groups)
    groups.sort(key=lambda x: x.title != 'command arguments')
    for action_group in groups:
        formatter.start_section(action_group.title)
        formatter.add_text(action_group.description)
        formatter.add_arguments(action_group._group_actions)
        formatter.end_section()

    # epilog
    formatter.add_text(parser.epilog)

    # determine help from format above
    return formatter.format_help()

class Command(object):
    """
    Command class to be inherited.

    COMMAND - name of command that used to call it
    DESCRIPTION - description is shown in help
    OFFLINE - if true then command don't require connection to server.
    """
    COMMAND = None
    DESCRIPTION = ''
    OFFLINE = False

    # TODO make private all that possible

    def __init__(self):
        self.connection = None
        self.args = None

    def get_command_parser(self, parser=None):
        """
        Return command parser. This function called each time before command run.
        To add new argument to command overwrite :py:meth:`update_parser` method

        :param parser: base argument parser, for OFFLINE commands and commands inside shell it will be None,
            for other cases it will be result of :py:func:`~genestack.utils.make_connection_parser`
        :type parser: argparse.ArgumentParser
        :return: parser
        :rtype: argparse.ArgumentParser
        """
        parser = parser or ArgumentParser(description=self.DESCRIPTION)
        parser.description = self.DESCRIPTION
        group = parser.add_argument_group("command arguments")
        self.update_parser(group)
        return parser

    def update_parser(self, parent):
        """
        Add arguments for command. Overwrite it in children.

        :param parent: argument group
        :type parent: argparse._ArgumentGroup
        :rtype: None
        """
        pass

    def set_connection(self, conn):
        """
        Set connection to command.

        :param conn: connection
        :type conn: genestack.Connection.Connection
        """
        self.connection = conn

    def set_arguments(self, args):
        """
        Set parsed arguments to command.

        :param args: parsed arguments
        :type args: argparse.Namespace
        """
        self.args = args

    def get_short_description(self):
        """
        Return short description for command, used in call of help command.
        """
        return self.DESCRIPTION

class GenestackShell(cmd.Cmd):
    """
    Base shell class.
    INTRO - greeting at start of shell mode
    COMMAND_LIST - list of available commands
    DESCRIPTION - description for help.

    Lunch as script:

        .. code-block:: sh

            script.py [connection_args] command [command_args]

    Lunch as shell:

        .. code-block:: sh

            script.py [connection_args]

    Default shell commands:
        - help: show help about shell or command
        - quit: quits shell
        - ctrl+D: quits shell
    """
    INTRO = ''
    COMMAND_LIST = []
    DESCRIPTION = "Shell and commandline application"

    COMMANDS = {}  # filled in init

    # Don't add docstrings to methods, all methods should be considered private, but due design of Cmd it is not possible
    # TODO make private all that possible

    def get_history_file_path(self):
        """
        Get path to history file.

        :return: path to history file
        :rtype str:
        """
        return os.path.join(os.path.expanduser("~"), '.%s' % self.__class__.__name__)

    def __init__(self, *args, **kwargs):
        self.COMMANDS = {command.COMMAND: command for command in self.COMMAND_LIST}
        cmd.Cmd.__init__(self, *args, **kwargs)

    def get_shell_parser(self):
        parser = ArgumentParser(conflict_handler='resolve', description=self.DESCRIPTION,
                                parents=[make_connection_parser()])
        # override default help
        parser.add_argument('-h', '--help', action='store_true', help="show this help message and exit")
        parser.add_argument('command', metavar='<command>', help='"%s" or empty to use shell' % '", "'.join(self.COMMANDS), nargs='?')
        return parser

    def preloop(self):
        parser = self.get_shell_parser()
        args, others = parser.parse_known_args()

        command = self.COMMANDS.get(args.command)
        if command:
            command = command()
        elif args.command:
            print "*** Unknown command: %s" % args.command
            print get_help(parser)
            exit(0)
        elif others:
            print "*** Unknown arguments: %s" % ' '.join(others)
            print get_help(parser)
            exit(0)

        if args.help:
            if not command:
                print get_help(parser)
            elif command.OFFLINE:
                print get_help(command.get_command_parser())
            else:
                print get_help(command.get_command_parser(make_connection_parser()))
            exit(0)

        if command:
            if not command.OFFLINE:
                connection = get_connection(args)
            else:
                connection = None
            self.process_command(command, others, connection)
            exit(0)

        # do shell
        try:
            readline.read_history_file(self.get_history_file_path())
        except (IOError, NameError):
            pass
        self.set_shell_user(args)

    def set_shell_user(self, args):
        # set user for shell
        self.connection = get_connection(args)
        email = self.connection.whoami()
        self.prompt = '%s> ' % email
        self.INTRO = "Hello, %s!" % email

    def postloop(self):
        try:
            readline.write_history_file(self.get_history_file_path())
        except (IOError, NameError):
            pass

    def do_EOF(self, line):
        return True
    do_quit = do_EOF

    def process_command(self, command, argument_line, connection, shell=False):
        if shell or command.OFFLINE:
            p = command.get_command_parser()
        else:
            p = command.get_command_parser(make_connection_parser())
        try:
            args = p.parse_args(argument_line)
        except SystemExit:
            return
        command.set_connection(connection)
        command.set_arguments(args)
        try:
            return command.run()
        except (KeyboardInterrupt, EOFError):
            print
            print "Command interrupted."
            return
        except (GenestackException, Exception) as e:
            sys.stdout.flush()
            sys.stderr.write('%s\n' % e)
            sys.stderr.flush()
            print_exc()

    def do_help(self, line):
        print

        command = self.COMMANDS.get(line)
        if command:
            print get_help(command().get_command_parser())
            return

        if not line:
            commands = {}
            for name, value in self.COMMANDS.items():
                commands[name] = value().get_short_description()
            print self.doc_header
            print '=' * len(self.doc_header)
            for command_name, short_description in commands.items():
                print '%-20s%s' % (command_name, short_description)
            print '=' * len(self.doc_header)
            return

        try:
            getattr(self, 'help_' + line)()
            return
        except AttributeError:
            pass

        try:
            doc = getattr(self, 'do_' + line).__doc__
            if doc:
                self.stdout.write('%s\n' % str(doc))
                return
        except AttributeError:
            pass

        self.stdout.write('%s\n' % str(self.nohelp % (line,)))

    def emptyline(self):
        pass

    def default(self, line):
        args = shlex.split(line)
        if args and args[0] in self.COMMANDS:
            self.process_command(self.COMMANDS[args[0]](), args[1:], self.connection, shell=True)
        else:
            self.stdout.write('*** Unknown command: %s\n' % line)

    def completenames(self, text, *ignored):
        dotext = 'do_' + text
        commands = [a[3:] for a in self.get_names() if a.startswith(dotext)]
        commands += [x for x in self.COMMANDS.keys() if x.startswith(text)]
        return commands
<commit_msg>Update docs for shell.<commit_after># -*- coding: utf-8 -*-

#
# Copyright (c) 2011-2015 Genestack Limited
# All Rights Reserved
# THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF GENESTACK LIMITED
# The copyright notice above does not evidence any
# actual or intended publication of such source code.
#

from argparse import ArgumentParser
import sys
import os
import cmd
import shlex
from traceback import print_exc
from Exceptions import GenestackException
from utils import isatty, make_connection_parser, get_connection

if isatty():
    # To have autocomplete and console navigation on windows you need to have pyreadline installed.
    # Pyreadline replace readline with alias to itself.
    try:
        import readline
    except:
        pass

HELP_SEPARATOR = '\n%s  Help  %s' % ('=' * 20, '=' * 20)

def get_help(parser):
    """
    Return help text for parser.

    :param parser: parser
    :type parser: ArgumentParser
    :return:
    """
    # Code almost identical with parser.print_help() with next changes:
    # it return text instead print
    # it place group 'command arguments' to the first place
    formatter = parser._get_formatter()
    # usage
    formatter.add_usage(parser.usage, parser._actions,
                        parser._mutually_exclusive_groups)
    # description
    formatter.add_text(parser.description)

    # positionals, optionals and user-defined groups
    groups = list(parser._action_groups)
    groups.sort(key=lambda x: x.title != 'command arguments')
    for action_group in groups:
        formatter.start_section(action_group.title)
        formatter.add_text(action_group.description)
        formatter.add_arguments(action_group._group_actions)
        formatter.end_section()

    # epilog
    formatter.add_text(parser.epilog)

    # determine help from format above
    return formatter.format_help()

class Command(object):
    """
    Command class to be inherited.

    COMMAND - name of command that used to call it
    DESCRIPTION - description is shown in help
    OFFLINE - if true then command don't require connection to server.
    """
    COMMAND = None
    DESCRIPTION = ''
    OFFLINE = False

    # TODO make private all that possible

    def __init__(self):
        self.connection = None
        self.args = None

    def get_command_parser(self, parser=None):
        """
        Return command parser. This function called each time before command run.
        To add new argument to command overwrite :py:meth:`update_parser` method

        :param parser: base argument parser, for OFFLINE commands and commands inside shell it will be None,
            for other cases it will be result of :py:func:`~genestack.utils.make_connection_parser`
        :type parser: argparse.ArgumentParser
        :return: parser
        :rtype: argparse.ArgumentParser
        """
        parser = parser or ArgumentParser(description=self.DESCRIPTION)
        parser.description = self.DESCRIPTION
        group = parser.add_argument_group("command arguments")
        self.update_parser(group)
        return parser

    def update_parser(self, parent):
        """
        Add arguments for command. Overwrite it in children.

        :param parent: argument group
        :type parent: argparse._ArgumentGroup
        :rtype: None
        """
        pass

    def set_connection(self, conn):
        """
        Set connection to command.

        :param conn: connection
        :type conn: genestack.Connection.Connection
        """
        self.connection = conn

    def set_arguments(self, args):
        """
        Set parsed arguments to command.

        :param args: parsed arguments
        :type args: argparse.Namespace
        """
        self.args = args

    def get_short_description(self):
        """
        Return short description for command, used in call of help command.
        """
        return self.DESCRIPTION

class GenestackShell(cmd.Cmd):
    """
    Base shell class.
    INTRO - greeting at start of shell mode
    COMMAND_LIST - list of available commands
    DESCRIPTION - description for help.

    Lunch as script:

        .. code-block:: sh

            script.py [connection_args] command [command_args]

    Lunch as shell:

        .. code-block:: sh

            script.py [connection_args]

    Default shell commands:
        - help: show help about shell or command
        - quit: quits shell
        - ctrl+D: quits shell
    """
    INTRO = ''
    COMMAND_LIST = []
    DESCRIPTION = "Shell and commandline application"

    COMMANDS = {}  # filled in init

    # Don't add docstrings to methods, all methods should be considered private, but due design of Cmd it is not possible
    # TODO make private all that possible

    def get_history_file_path(self):
        """
        Get path to history file.

        :return: path to history file
        :rtype: str
        """
        return os.path.join(os.path.expanduser("~"), '.%s' % self.__class__.__name__)

    def __init__(self, *args, **kwargs):
        self.COMMANDS = {command.COMMAND: command for command in self.COMMAND_LIST}
        cmd.Cmd.__init__(self, *args, **kwargs)

    def get_shell_parser(self):
        """
        Get parser for shell.
        :return: parser for shell commands
        :rtype: argparse.ArgumentParser

        :return:
        """
        parser = ArgumentParser(conflict_handler='resolve', description=self.DESCRIPTION,
                                parents=[make_connection_parser()])
        # override default help
        parser.add_argument('-h', '--help', action='store_true', help="show this help message and exit")
        parser.add_argument('command', metavar='<command>', help='"%s" or empty to use shell' % '", "'.join(self.COMMANDS), nargs='?')
        return parser

    def preloop(self):
        """
        Entry point. Check if should run script and exit or start shell.
        """

        parser = self.get_shell_parser()
        args, others = parser.parse_known_args()

        command = self.COMMANDS.get(args.command)
        if command:
            command = command()
        elif args.command:
            print "*** Unknown command: %s" % args.command
            print get_help(parser)
            exit(0)
        elif others:
            print "*** Unknown arguments: %s" % ' '.join(others)
            print get_help(parser)
            exit(0)

        if args.help:
            if not command:
                print get_help(parser)
            elif command.OFFLINE:
                print get_help(command.get_command_parser())
            else:
                print get_help(command.get_command_parser(make_connection_parser()))
            exit(0)

        if command:
            if not command.OFFLINE:
                connection = get_connection(args)
            else:
                connection = None
            self.process_command(command, others, connection)
            exit(0)

        # do shell
        try:
            readline.read_history_file(self.get_history_file_path())
        except (IOError, NameError):
            pass
        self.set_shell_user(args)

    def set_shell_user(self, args):
        """
        Set connection for shell mode.

        :param args: script arguments
        :type args: argparse.Namespace
        """
        # set user for shell
        self.connection = get_connection(args)
        email = self.connection.whoami()
        self.prompt = '%s> ' % email
        self.INTRO = "Hello, %s!" % email

    def postloop(self):
        try:
            readline.write_history_file(self.get_history_file_path())
        except (IOError, NameError):
            pass

    def do_EOF(self, line):
        return True
    do_quit = do_EOF

    def process_command(self, command, argument_line, connection, shell=False):
        """
        Run command with arguments.

        :param command: command
        :param command: Command
        :param argument_line: argument string for command
        :type argument_line: str
        :param connection: connection, for OFFLINE command can be None
        :param connection: genestack.Connection.Connection
        :param shell: flag if shell mode
        :type shell: bool
        """
        if shell or command.OFFLINE:
            p = command.get_command_parser()
        else:
            p = command.get_command_parser(make_connection_parser())
        try:
            args = p.parse_args(argument_line)
        except SystemExit:
            return
        command.set_connection(connection)
        command.set_arguments(args)
        try:
            return command.run()
        except (KeyboardInterrupt, EOFError):
            print
            print "Command interrupted."
            return
        except (GenestackException, Exception) as e:
            sys.stdout.flush()
            sys.stderr.write('%s\n' % e)
            sys.stderr.flush()
            print_exc()

    def do_help(self, line):
        print

        command = self.COMMANDS.get(line)
        if command:
            print get_help(command().get_command_parser())
            return

        if not line:
            commands = {}
            for name, value in self.COMMANDS.items():
                commands[name] = value().get_short_description()
            print self.doc_header
            print '=' * len(self.doc_header)
            for command_name, short_description in commands.items():
                print '%-20s%s' % (command_name, short_description)
            print '=' * len(self.doc_header)
            return

        try:
            getattr(self, 'help_' + line)()
            return
        except AttributeError:
            pass

        try:
            doc = getattr(self, 'do_' + line).__doc__
            if doc:
                self.stdout.write('%s\n' % str(doc))
                return
        except AttributeError:
            pass

        self.stdout.write('%s\n' % str(self.nohelp % (line,)))

    def emptyline(self):
        pass

    def default(self, line):
        args = shlex.split(line)
        if args and args[0] in self.COMMANDS:
            self.process_command(self.COMMANDS[args[0]](), args[1:], self.connection, shell=True)
        else:
            self.stdout.write('*** Unknown command: %s\n' % line)

    def completenames(self, text, *ignored):
        dotext = 'do_' + text
        commands = [a[3:] for a in self.get_names() if a.startswith(dotext)]
        commands += [x for x in self.COMMANDS.keys() if x.startswith(text)]
        return commands
<|endoftext|>


<commit_before>import json
import logging

from commands.branch import CommandBranch
from events.fork import EventFork
from sdk.codexbot_sdk import CodexBot
from config import APPLICATION_TOKEN, APPLICATION_NAME, DB, URL, SERVER
from config import USERS_COLLECTION_NAME
from commands.help import CommandHelp
from commands.start import CommandStart
from commands.link import CommandLink
from commands.comments import CommandComments
from commands.verbose import CommandVerbose
from events.ping import EventPing
from events.push import EventPush
from events.issues import EventIssues
from events.issue_comment import EventIssueComment
from events.pull_request import EventPullRequest
from events.pull_request_review import EventPullRequestReview
from events.watch import EventWatch

class Github:

    def __init__(self):

        self.sdk = CodexBot(APPLICATION_NAME, SERVER['host'], SERVER['port'], db_config=DB, token=APPLICATION_TOKEN)

        self.sdk.log("Github module initialized")

        self.sdk.register_commands([
            ('github',
             'GitHub app. Allows you receive notices about new issues, commits and pull-requests.',
             CommandHelp(self.sdk)),
            ('github_help', 'help', CommandHelp(self.sdk)),
            ('github_start', 'start', CommandStart(self.sdk)),
            ('github_link', 'link', CommandLink(self.sdk)),
            ('github_branch', 'branch', CommandBranch(self.sdk)),
            ('github_verbose', 'verbose', CommandVerbose(self.sdk)),
            ('github_comments', 'comments', CommandComments(self.sdk)),
        ])

        self.sdk.set_routes([
            ('POST', '/github/{user_token}', self.github_callback_handler)
        ])

        self.sdk.set_path_to_static('/img', 'static/img')

        self.sdk.start_server()

    @CodexBot.http_response
    async def github_callback_handler(self, request):

        # Check for route-token passed
        if 'user_token' not in request['params']:
            self.sdk.log("GitHub route handler: user_token is missed")
            return {
                'status': 404
            }

        # Get user data from DB by user token passed in URL
        user_token = request['params']['user_token']
        registered_chat = self.sdk.db.find_one(USERS_COLLECTION_NAME, {'user': user_token})

        # Check if chat was registered
        if not registered_chat or 'chat' not in registered_chat:
            self.sdk.log("GitHub route handler: wrong user token passed")
            return {
                'status': 404
            }

        event_name = request['headers']['X-Github-Event']

        events = {
            'watch': EventWatch(self.sdk),
            'fork': EventFork(self.sdk),
            'ping': EventPing(self.sdk),
            'push': EventPush(self.sdk),
            'issues': EventIssues(self.sdk),
            'issue_comment': EventIssueComment(self.sdk),
            'pull_request': EventPullRequest(self.sdk),
            'pull_request_review': EventPullRequestReview(self.sdk)
        }

        if event_name not in events:
            self.sdk.log("Github webhook callback: unsupported event taken: {}".format(event_name))
            return {
                'status': 404
            }

        try:
            # GitHub always pass JSON as request body
            payload = json.loads(request['text'])

            # Call event handler
            events[event_name].set_bot(registered_chat)
            await events[event_name].process(payload, registered_chat)

            return {
                'text': 'OK',
                'status': 200
            }

        except Exception as e:
            self.sdk.log('Cannot handle request from GitHub: {}'.format(e))
            return {
                'status': 404
            }

if __name__ == "__main__":
    github = Github()
<commit_msg>Remove comments feature from another request<commit_after>import json
import logging

from commands.branch import CommandBranch
from events.fork import EventFork
from sdk.codexbot_sdk import CodexBot
from config import APPLICATION_TOKEN, APPLICATION_NAME, DB, URL, SERVER
from config import USERS_COLLECTION_NAME
from commands.help import CommandHelp
from commands.start import CommandStart
from commands.link import CommandLink
from commands.verbose import CommandVerbose
from events.ping import EventPing
from events.push import EventPush
from events.issues import EventIssues
from events.issue_comment import EventIssueComment
from events.pull_request import EventPullRequest
from events.pull_request_review import EventPullRequestReview
from events.watch import EventWatch

class Github:

    def __init__(self):

        self.sdk = CodexBot(APPLICATION_NAME, SERVER['host'], SERVER['port'], db_config=DB, token=APPLICATION_TOKEN)

        self.sdk.log("Github module initialized")

        self.sdk.register_commands([
            ('github',
             'GitHub app. Allows you receive notices about new issues, commits and pull-requests.',
             CommandHelp(self.sdk)),
            ('github_help', 'help', CommandHelp(self.sdk)),
            ('github_start', 'start', CommandStart(self.sdk)),
            ('github_link', 'link', CommandLink(self.sdk)),
            ('github_branch', 'branch', CommandBranch(self.sdk)),
            ('github_verbose', 'verbose', CommandVerbose(self.sdk)),
        ])

        self.sdk.set_routes([
            ('POST', '/github/{user_token}', self.github_callback_handler)
        ])

        self.sdk.set_path_to_static('/img', 'static/img')

        self.sdk.start_server()

    @CodexBot.http_response
    async def github_callback_handler(self, request):

        # Check for route-token passed
        if 'user_token' not in request['params']:
            self.sdk.log("GitHub route handler: user_token is missed")
            return {
                'status': 404
            }

        # Get user data from DB by user token passed in URL
        user_token = request['params']['user_token']
        registered_chat = self.sdk.db.find_one(USERS_COLLECTION_NAME, {'user': user_token})

        # Check if chat was registered
        if not registered_chat or 'chat' not in registered_chat:
            self.sdk.log("GitHub route handler: wrong user token passed")
            return {
                'status': 404
            }

        event_name = request['headers']['X-Github-Event']

        events = {
            'watch': EventWatch(self.sdk),
            'fork': EventFork(self.sdk),
            'ping': EventPing(self.sdk),
            'push': EventPush(self.sdk),
            'issues': EventIssues(self.sdk),
            'issue_comment': EventIssueComment(self.sdk),
            'pull_request': EventPullRequest(self.sdk),
            'pull_request_review': EventPullRequestReview(self.sdk)
        }

        if event_name not in events:
            self.sdk.log("Github webhook callback: unsupported event taken: {}".format(event_name))
            return {
                'status': 404
            }

        try:
            # GitHub always pass JSON as request body
            payload = json.loads(request['text'])

            # Call event handler
            events[event_name].set_bot(registered_chat)
            await events[event_name].process(payload, registered_chat)

            return {
                'text': 'OK',
                'status': 200
            }

        except Exception as e:
            self.sdk.log('Cannot handle request from GitHub: {}'.format(e))
            return {
                'status': 404
            }

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


<commit_before>"""
This test does nothing besides connect, and then disconnect as soon as the
session is established, two thousand times. It was used to smoke out a bug
where connections were leaked (which ultimately meant that new connections
could not be established, since the file descriptors were leaked too); it may
also be useful for profiling the connection process (and test framework).
"""
from gabbletest import exec_test

def test(q, bus, conn, stream):
    pass

def main():
    for i in xrange(0, 2000):
        print i
        exec_test(test)
    print "we partied like it's %i" % i

if __name__ == '__main__':
    main()
<commit_msg>connect/torture: skip if $REALLY_TORTURE is unset<commit_after>"""
This test does nothing besides connect, and then disconnect as soon as the
session is established, two thousand times. It was used to smoke out a bug
where connections were leaked (which ultimately meant that new connections
could not be established, since the file descriptors were leaked too); it may
also be useful for profiling the connection process (and test framework).
"""
from gabbletest import exec_test
import os

if os.environ.get('REALLY_TORTURE', '') != 'yes':
    raise SystemExit(77)

def test(q, bus, conn, stream):
    pass

def main():
    for i in xrange(0, 2000):
        print i
        exec_test(test)
    print "we partied like it's %i" % i

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


<commit_before>#!/usr/bin/env python
import scipy
import numpy as np
import scipy.stats
import matplotlib
from pylab import *
from scipy.spatial.distance import pdist, squareform
import variograms

def readGeoEAS( fn ):
    '''
    Input:  (fn)   filename describing a GeoEAS file
    Output: (data) NumPy array
    --------------------------------------------------
    Read GeoEAS files as described by the GSLIB manual
    '''
    f = open( fn, "r" )
    # title of the data set
    title = f.readline()
    # number of variables
    nvar = int( f.readline() )
    # variable names
    columns = [ f.readline().strip() for i in range( nvar ) ]
    # make a list for the data
    data = list()
    # for each line of the data
    while True:
        # read a line
        line = f.readline()
        # if that line is empty
        if line == '':
            # the jump out of the while loop
            break
        # otherwise, append that line to the data list
        else:
            data.append( line )
    # strip off the newlines, and split by whitespace
    data = [ i.strip().split() for i in data ]
    # turn a list of list of strings into an array of floats
    data = np.array( data, dtype=np.float )
    # combine the data with the variable names into a DataFrame
    # df = pandas.DataFrame( data, columns=columns,  )
    return data

def pairwise( data ):
    '''
    Input:  (data) NumPy array where the first two columns
                   are the spatial coordinates, x and y
    '''
    # determine the size of the data
    npoints, cols = data.shape
    # give a warning for large data sets
    if npoints > 10000:
        print "You have more than 10,000 data points, this might take a minute."
    # return the square distance matrix
    return squareform( pdist( data[:,:2] ) )

def bearing( p0, p1 ):
    '''
    Input:  (p0,p1) two iterables representing x and y coordinates
    Output:         the bearing, a degree in the range [0,360) from
                    due North clockwise aroung the compass face
    '''
    y = p1[1] - p0[1]
    x = p1[0] - p0[0]
    rad, deg = None, None
    if x != 0:
        rad = np.arctan( y / float( x ) )
        deg = np.rad2deg( rad )
    else:
        if y > 0:
            deg = 90
        elif y < 0:
            deg = 270
    if( x < 0 )&( y > 0 ):
        deg = 180 + deg
    elif( x < 0 )&( y < 0 ):
        deg = 270 - deg
    elif( x > 0 )&( y < 0 ):
        deg = 360 + deg
    bearing = None
    if( deg >= 0 )&( deg <= 90 ):
        bearing = 90 - deg
    elif( deg >= 90 )&( deg < 180 ):
        bearing = 90 + 360 - deg
    elif( deg >= 180 )&( deg < 270 ):
        bearing = 90 + 360 - deg
    elif( deg >= 270 )&( deg <= 360 ):
        bearing = 90 + 360 - deg
    return bearing

def bearings( data, indices ):
    '''
    Input:  (data)    the original data set: x, y, variable
            (indices) the output of variograms.lagindices()
    Output:           a list of list of bearings corresponding
                      to variograms.lagindices()
    '''
    # indices is a list of lists
    # each list in indices represents a set of points at a certain lag
    # for a given lag, we have a list of index pairs
    # each pair represents the indices of two points in the data set having a given lag
    # --deep breath--
    # for each lag-set, we go through all of the index-pairs, and calculate the bearing
    # in the end, instead of a list of lag-sets containing index-pairs,
    # we have a list of lag-sets containing bearings
    return [ [ bearing( *data[ idx ] ) for idx in lag ] for lag in indices ]

def inangle( theta, angle, atol ):
    '''
    Input:  (theta) angle inquestion
            (angle) reference angle
            (atol)  tolerance about (angle)
    Output:         True or False, depending on whether
                    theta is in [angle-atol,angle+atol)
    '''
    lower = angle - atol
    upper = angle + atol
    if( lower >= 0 )&( upper <= 360 ):
        if( theta >= lower )&( theta < upper ):
            return True
    if( lower < 0 ):
        lower %= 360
        if( theta > upper )&( theta >= lower ):
            return True
        elif( theta >= 0 )&( theta < upper ):
            return True
    if( upper > 360 ):
        upper %= 360
        if( theta >= lower )&( theta < 0 ):
            return True
        if( theta >= 0 )&( theta < upper ):
            return True
    return False
<commit_msg>Update utilities.py<commit_after>#!/usr/bin/env python

import scipy, scipy.stats, numpy as np
from scipy.spatial.distance import pdist, squareform

def readGeoEAS( fn ):
    '''
    Input:  (fn)   filename describing a GeoEAS file
    Output: (data) NumPy array
    --------------------------------------------------
    Read GeoEAS files as described by the GSLIB manual
    '''
    f = open( fn, "r" )
    # title of the data set
    title = f.readline()
    # number of variables
    nvar = int( f.readline() )
    # variable names
    columns = [ f.readline().strip() for i in range( nvar ) ]
    # make a list for the data
    data = list()
    # for each line of the data
    while True:
        # read a line
        line = f.readline()
        # if that line is empty
        if line == '':
            # the jump out of the while loop
            break
        # otherwise, append that line to the data list
        else:
            data.append( line )
    # strip off the newlines, and split by whitespace
    data = [ i.strip().split() for i in data ]
    # turn a list of list of strings into an array of floats
    data = np.array( data, dtype=np.float )
    # combine the data with the variable names into a DataFrame
    # df = pandas.DataFrame( data, columns=columns,  )
    return data

def pairwise( data ):
    '''
    Input:  (data) NumPy array where the first two columns
                   are the spatial coordinates, x and y
    '''
    # determine the size of the data
    npoints, cols = data.shape
    # give a warning for large data sets
    if npoints > 10000:
        print "You have more than 10,000 data points, this might take a minute."
    # return the square distance matrix
    return squareform( pdist( data[:,:2] ) )

def bearing( p0, p1 ):
    '''
    Input:  (p0,p1) two iterables representing x and y coordinates
    Output:         the bearing, a degree in the range [0,360) from
                    due North clockwise aroung the compass face
    '''
    y = p1[1] - p0[1]
    x = p1[0] - p0[0]
    rad, deg = None, None
    if x != 0:
        rad = np.arctan( y / float( x ) )
        deg = np.rad2deg( rad )
    else:
        if y > 0:
            deg = 90
        elif y < 0:
            deg = 270
    if( x < 0 )&( y > 0 ):
        deg = 180 + deg
    elif( x < 0 )&( y < 0 ):
        deg = 270 - deg
    elif( x > 0 )&( y < 0 ):
        deg = 360 + deg
    bearing = None
    if( deg >= 0 )&( deg <= 90 ):
        bearing = 90 - deg
    elif( deg >= 90 )&( deg < 180 ):
        bearing = 90 + 360 - deg
    elif( deg >= 180 )&( deg < 270 ):
        bearing = 90 + 360 - deg
    elif( deg >= 270 )&( deg <= 360 ):
        bearing = 90 + 360 - deg
    return bearing

def bearings( data, indices ):
    '''
    Input:  (data)    the original data set: x, y, variable
            (indices) the output of variograms.lagindices()
    Output:           a list of list of bearings corresponding
                      to variograms.lagindices()
    '''
    # indices is a list of lists
    # each list in indices represents a set of points at a certain lag
    # for a given lag, we have a list of index pairs
    # each pair represents the indices of two points in the data set having a given lag
    # --deep breath--
    # for each lag-set, we go through all of the index-pairs, and calculate the bearing
    # in the end, instead of a list of lag-sets containing index-pairs,
    # we have a list of lag-sets containing bearings
    return [ [ bearing( *data[ idx ] ) for idx in lag ] for lag in indices ]

def inangle( theta, angle, atol ):
    '''
    Input:  (theta) angle inquestion
            (angle) reference angle
            (atol)  tolerance about (angle)
    Output:         True or False, depending on whether
                    theta is in [angle-atol,angle+atol)
    '''
    lower = angle - atol
    upper = angle + atol
    if( lower >= 0 )&( upper <= 360 ):
        if( theta >= lower )&( theta < upper ):
            return True
    if( lower < 0 ):
        lower %= 360
        if( theta > upper )&( theta >= lower ):
            return True
        elif( theta >= 0 )&( theta < upper ):
            return True
    if( upper > 360 ):
        upper %= 360
        if( theta >= lower )&( theta < 0 ):
            return True
        if( theta >= 0 )&( theta < upper ):
            return True
    return False
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, user_passes_test

from pdfdocument.utils import pdf_response
from reportlab.platypus import TableStyle, Paragraph
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet

class EventPDF:

    event = None
    attendees = None
    waiters = None
    reservees = None
    attendee_table_data = None
    waiters_table_data = None
    reservee_table_data = None
    allergies_table_data = None
    full_span_attendee_lines = []
    full_span_waiters_lines = []

    def __init__(self, event):
        self.event = event
        attendee_qs = event.attendance_event.attendees_qs
        self.attendees = sorted(attendee_qs, key=lambda attendee: attendee.user.last_name)
        self.waiters = event.attendance_event.waitlist_qs
        self.reservees = event.attendance_event.reservees_qs
        self.attendee_table_data = [(u'Navn', u'Klasse', u'Studie', u'Telefon'), ]
        self.waiters_table_data = [(u'Navn', u'Klasse', u'Studie', u'Telefon'), ]
        self.reservee_table_data = [(u'Navn', u'Notat'), ]
        self.allergies_table_data = [(u'Allergisk mot', u'Navn'), ]

        self.create_attendees_table_data()
        self.create_waiters_table_data()
        self.create_reservees_table_data()

    # Create table data for attendees with a spot
    def create_attendees_table_data(self):
        i = 1

        for attendee in self.attendees:
            user = attendee.user
            self.attendee_table_data.append((
                                            create_body_text("%s, %s" % (user.last_name, user.first_name)),
                                            user.year,
                                            create_body_text(user.get_field_of_study_display()),
                                            user.phone_number
                                            ))

            if attendee.note:
                self.attendee_table_data.append((create_body_text(u'Notat for %s: ' % attendee.user.first_name + attendee.note),))
                i += 1
                self.full_span_attendee_lines.append(i)
            if user.allergies:
                self.allergies_table_data.append((user.allergies, user.get_full_name(),))

            i += 1

    # Create table data for attendees waiting for a spot
    def create_waiters_table_data(self):
        i = 1

        for attendee in self.waiters:
            user = attendee.user
            self.waiters_table_data.append((
                                            create_body_text("%s, %s" % (user.last_name, user.first_name)),
                                            user.year,
                                            create_body_text(user.get_field_of_study_display()),
                                            user.phone_number
                                            ))

            if attendee.note:
                self.waiters_table_data.append((create_body_text(u'Notat for %s: ' % attendee.user.first_name + attendee.note),))
                i += 1
                self.full_span_waiters_lines.append(i)
            if user.allergies:
                self.allergies_table_data.append((user.allergies, user.get_full_name(),))

            i += 1

    def create_reservees_table_data(self):
        for reservee in self.reservees:
            self.reservee_table_data.append((
                                             create_body_text(reservee.name),
                                             create_body_text(reservee.note)
                                             ))
            if reservee.allergies:
                self.allergies_table_data.append((
                                                  create_body_text(reservee.allergies),
                                                  create_body_text(reservee.name),
                                                  ))
                if reservee.allergies:
                    #self.allergies_table_data = self.allergies_table_data + [reservee.name + ' ' + reservee.allergies]
                    pass

    def attendee_column_widths(self):
        return (185, 40, 170, 75)

    def reservee_column_widths(self):
        return (185, 285)

    def allergies_column_widths(self):
        return (285, 185)

    def render_pdf(self):
        pdf, response = pdf_response(self.event.title + u" attendees")
        pdf.init_report()

        pdf.p(self.event.title, style=create_paragraph_style(font_size=18))
        pdf.spacer(10)
        pdf.p(self.event.event_start.strftime('%d. %B %Y'), create_paragraph_style(font_size=9))
        pdf.spacer(height=25)

        pdf.p(u"Påmeldte", style=create_paragraph_style(font_size=14))
        pdf.spacer(height=20)
        pdf.table(self.attendee_table_data, self.attendee_column_widths(), style=get_table_style(self.full_span_attendee_lines))
        pdf.spacer(height=25)

        if self.waiters.count() > 0:
            pdf.p(u"Venteliste", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.waiters_table_data, self.attendee_column_widths(), style=get_table_style(self.full_span_waiters_lines))
            pdf.spacer(height=25)

        if self.reservees and self.reservees.count() > 0:
            pdf.p(u"Reservasjoner", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.reservee_table_data, self.reservee_column_widths(), style=get_table_style())
            pdf.spacer(height=25)

        if self.allergies_table_data:
            pdf.p(u"Allergier", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.allergies_table_data, self.allergies_column_widths(), style=get_table_style())
            pdf.spacer(height=25)

        pdf.generate()
        return response

# Table style for framed table with grids
def get_table_style(full_spans=None):
    style = [
                ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                ('BOX',(0,0),(-1,-1),1,colors.black),
            ]
    if full_spans:
        for line in full_spans:
            style.append(('SPAN',(0,line),(-1,line)))

    return TableStyle(style)

# Normal paragraph
def create_paragraph_style(font_name='Helvetica', font_size=10, color=colors.black):
    style = getSampleStyleSheet()['Normal']
    style.fontSize = font_size
    style.fontName = font_name
    style.textColor = color

    return style

# Paragraph with word-wrapping, useful for tables
def create_body_text(text, font_name='Helvetica', font_size=10, color=colors.black):
    style = getSampleStyleSheet()['BodyText']
    style.fontSize = font_size
    style.fontName = font_name
    style.textColor = color

    return Paragraph(text, style=style)
<commit_msg>Fix missing rows in pdf attendee list<commit_after># -*- coding: utf-8 -*-
from django.contrib.auth.decorators import login_required, user_passes_test

from pdfdocument.utils import pdf_response
from reportlab.platypus import TableStyle, Paragraph
from reportlab.lib import colors
from reportlab.lib.styles import getSampleStyleSheet

class EventPDF(object):

    event = None
    attendees = None
    waiters = None
    reservees = None
    attendee_table_data = None
    waiters_table_data = None
    reservee_table_data = None
    allergies_table_data = None

    def __init__(self, event):
        self.full_span_attendee_lines = []
        self.full_span_waiters_lines = []
        self.event = event
        attendee_qs = event.attendance_event.attendees_qs
        self.attendees = sorted(attendee_qs, key=lambda attendee: attendee.user.last_name)
        self.waiters = event.attendance_event.waitlist_qs
        self.reservees = event.attendance_event.reservees_qs
        self.attendee_table_data = [(u'Navn', u'Klasse', u'Studie', u'Telefon'), ]
        self.waiters_table_data = [(u'Navn', u'Klasse', u'Studie', u'Telefon'), ]
        self.reservee_table_data = [(u'Navn', u'Notat'), ]
        self.allergies_table_data = [(u'Allergisk mot', u'Navn'), ]

        self.create_attendees_table_data()
        self.create_waiters_table_data()
        self.create_reservees_table_data()

    # Create table data for attendees with a spot
    def create_attendees_table_data(self):
        i = 1

        for attendee in self.attendees:
            user = attendee.user
            self.attendee_table_data.append((
                                            create_body_text("%s, %s" % (user.last_name, user.first_name)),
                                            user.year,
                                            create_body_text(user.get_field_of_study_display()),
                                            user.phone_number
                                            ))

            if attendee.note:
                self.attendee_table_data.append((create_body_text(u'Notat for %s: ' % attendee.user.first_name + attendee.note),))
                i += 1
                self.full_span_attendee_lines.append(i)
            if user.allergies:
                self.allergies_table_data.append((user.allergies, user.get_full_name(),))

            i += 1

    # Create table data for attendees waiting for a spot
    def create_waiters_table_data(self):
        i = 1

        for attendee in self.waiters:
            user = attendee.user
            self.waiters_table_data.append((
                                            create_body_text("%s, %s" % (user.last_name, user.first_name)),
                                            user.year,
                                            create_body_text(user.get_field_of_study_display()),
                                            user.phone_number
                                            ))

            if attendee.note:
                self.waiters_table_data.append((create_body_text(u'Notat for %s: ' % attendee.user.first_name + attendee.note),))
                i += 1
                self.full_span_waiters_lines.append(i)
            if user.allergies:
                self.allergies_table_data.append((user.allergies, user.get_full_name(),))

            i += 1

    def create_reservees_table_data(self):
        for reservee in self.reservees:
            self.reservee_table_data.append((
                                             create_body_text(reservee.name),
                                             create_body_text(reservee.note)
                                             ))
            if reservee.allergies:
                self.allergies_table_data.append((
                                                  create_body_text(reservee.allergies),
                                                  create_body_text(reservee.name),
                                                  ))
                if reservee.allergies:
                    #self.allergies_table_data = self.allergies_table_data + [reservee.name + ' ' + reservee.allergies]
                    pass

    def attendee_column_widths(self):
        return (185, 40, 170, 75)

    def reservee_column_widths(self):
        return (185, 285)

    def allergies_column_widths(self):
        return (285, 185)

    def render_pdf(self):
        pdf, response = pdf_response(self.event.title + u" attendees")
        pdf.init_report()

        pdf.p(self.event.title, style=create_paragraph_style(font_size=18))
        pdf.spacer(10)
        pdf.p(self.event.event_start.strftime('%d. %B %Y'), create_paragraph_style(font_size=9))
        pdf.spacer(height=25)

        pdf.p(u"Påmeldte", style=create_paragraph_style(font_size=14))
        pdf.spacer(height=20)
        pdf.table(self.attendee_table_data, self.attendee_column_widths(), style=get_table_style(self.full_span_attendee_lines))
        pdf.spacer(height=25)

        if self.waiters.count() > 0:
            pdf.p(u"Venteliste", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.waiters_table_data, self.attendee_column_widths(), style=get_table_style(self.full_span_waiters_lines))
            pdf.spacer(height=25)

        if self.reservees and self.reservees.count() > 0:
            pdf.p(u"Reservasjoner", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.reservee_table_data, self.reservee_column_widths(), style=get_table_style())
            pdf.spacer(height=25)

        if self.allergies_table_data:
            pdf.p(u"Allergier", style=create_paragraph_style(font_size=14))
            pdf.spacer(height=20)
            pdf.table(self.allergies_table_data, self.allergies_column_widths(), style=get_table_style())
            pdf.spacer(height=25)

        pdf.generate()
        return response

# Table style for framed table with grids
def get_table_style(full_spans=None):
    style = [
                ('GRID',(0,0),(-1,-1),0.5,colors.grey),
                ('BOX',(0,0),(-1,-1),1,colors.black),
            ]
    if full_spans:
        for line in full_spans:
            style.append(('SPAN',(0,line),(-1,line)))

    return TableStyle(style)

# Normal paragraph
def create_paragraph_style(font_name='Helvetica', font_size=10, color=colors.black):
    style = getSampleStyleSheet()['Normal']
    style.fontSize = font_size
    style.fontName = font_name
    style.textColor = color

    return style

# Paragraph with word-wrapping, useful for tables
def create_body_text(text, font_name='Helvetica', font_size=10, color=colors.black):
    style = getSampleStyleSheet()['BodyText']
    style.fontSize = font_size
    style.fontName = font_name
    style.textColor = color

    return Paragraph(text, style=style)
<|endoftext|>