<commit_before>"""Module for user account views"""
# pylint: disable=too-many-ancestors
import logging

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import (
    LogoutView, LoginView, PasswordResetDoneView, PasswordResetView,
    PasswordChangeView, PasswordResetConfirmView
)
from django.db import IntegrityError
from django.db.models import Q
from django.http import (
    Http404, HttpResponseBadRequest,
    HttpResponseRedirect, JsonResponse
)
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse, reverse_lazy
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import CreateView, UpdateView
from openid.fetchers import HTTPFetchingError
from django_openid_auth.auth import OpenIDBackend
from django_openid_auth.exceptions import IdentityAlreadyClaimed
from django_openid_auth.views import login_complete, parse_openid_response
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from rest_framework.authtoken.models import Token

from games import models
from games.views.pages import GameList

from . import forms, sso, tasks, serializers
from .models import EmailConfirmationToken, User

LOGGER = logging.getLogger(__name__)

class LutrisRegisterView(CreateView):
    """Account registration view"""
    form_class = forms.RegistrationForm
    template_name = 'accounts/register.html'
    success_url = reverse_lazy('homepage')

class LutrisLoginView(LoginView):
    """Sign in view"""
    template_name = 'accounts/login.html'
    authentication_form = forms.LoginForm

class LutrisLogoutView(LogoutView):
    """Sign out view"""
    next_page = '/'

    def dispatch(self, request, *args, **kwargs):
        messages.success(request, 'You are now logged out of Lutris.')
        return super().dispatch(request, *args, **kwargs)

class LutrisPasswordResetView(PasswordResetView):
    """View to reset a user's password"""
    template_name = 'accounts/password_reset.html'
    form_class = forms.LutrisPasswordResetForm

class LutrisPasswordResetDoneView(PasswordResetDoneView):
    """Tell the user an email has been sent with a password reset link"""
    template_name = "accounts/password_reset_done.html"

class LutrisPasswordChangeView(PasswordChangeView):
    """View confirming the password reset is sent"""
    template_name = 'accounts/password_change.html'

class LutrisPasswordResetConfirmView(PasswordResetConfirmView):
    """View where the user confirms the password reset"""
    template_name = 'accounts/password_reset_confirm.html'
    success_url = "/"

    def form_valid(self, form):
        messages.success(self.request, 'Your password has been updated.')
        return super().form_valid(form)

def clear_auth_token(request):
    """Delete the REST API token for the currently logged in user"""
    if not request.user.is_authenticated:
        # Anonymous users fuck off
        return redirect("/")
    try:
        token = Token.objects.get(user=request.user)
    except Token.DoesNotExist:
        raise Http404
    token.delete()
    messages.info(
        request,
        "You authentication token has been cleared. "
        "Please sign-in in Lutris again to generate a new one."
    )
    return redirect(
        reverse('user_account', kwargs={"username": request.user.username})
    )

@login_required
def profile(request):
    """Redirect to user account
    Takes the username from the request, allows to have a unique URL for all profiles.
    """
    return HttpResponseRedirect(
        reverse('user_account', args=(request.user.username, ))
    )

def user_account(request, username):
    """Profile view"""
    if request.user.username != username:
        raise Http404
    return render(request, 'accounts/profile.html', {
        'user': request.user,
        'profile_page': 'profile'
    })

@login_required
def user_submissions(request):
    """Lists a user game submissions"""
    pending_submissions = models.GameSubmission.objects.filter(
        user=request.user, accepted_at__isnull=True
    )
    accepted_submissions = models.GameSubmission.objects.filter(
        user=request.user, accepted_at__isnull=False
    )
    return render(request, 'accounts/game_submissions.html', {
        'pending_submissions': pending_submissions,
        'accepted_submissions': accepted_submissions
    })

@login_required
def user_send_confirmation(request):
    """Send an email with a confirmation link"""
    user = request.user
    if user.email_confirmed:
        messages.info(request, "Your email has already been confirmed.")
        return HttpResponseRedirect(
            reverse('user_account', args=(user.username, ))
        )
    token = EmailConfirmationToken(email=user.email)
    token.create_token()
    token.save()
    token.send(request)
    messages.info(request, 'An email with a confirmation link has been sent to the specified '
                           'address. Click the link to confirm your email address.')
    return HttpResponseRedirect(
        reverse('user_account', args=(user.username,))
    )

def user_require_confirmation(request):
    """Display an error message that the resource is reserved for confirmed
    accounts only.
    """
    if request.user.is_authenticated:
        messages.error(
            request,
            u"The page you have requested requires that "
            u"you have confirmed your email address."
        )
        return redirect(reverse("user_account", args=(request.user.username,)))
    login_url = settings.LOGIN_URL
    if 'next' in request.GET:
        login_url += "?next=" + request.GET['next']
    return redirect(login_url)

def user_email_confirm(request):
    """Confirm an user's account

    This is the view pointed by the link in the confirmation email
    """
    token = request.GET.get('token')
    confirmation_token = get_object_or_404(EmailConfirmationToken, token=token)
    if confirmation_token.is_valid():
        confirmation_token.confirm_user()
        confirmation_token.delete()
    return render(request, 'accounts/confirmation_received.html',
                  {'confirmation_token': confirmation_token})

class ProfileUpdateView(LoginRequiredMixin, UpdateView):
    """Edit the user's profile info"""
    template_name = 'accounts/profile_edit.html'
    form_class = forms.ProfileForm
    success_url = reverse_lazy('profile')

    def get_object(self, queryset=None):
        return self.request.user

@login_required
def profile_delete(request, username):
    """Deactivate a user account"""
    user = get_object_or_404(User, username=username)
    if user != request.user:
        raise Http404
    form = forms.ProfileDeleteForm(request.POST or None)
    if form.is_valid():
        logout(request)
        user.deactivate()
        messages.success(request, 'Your account is now deleted')
        return redirect(reverse('homepage'))
    return render(request, 'accounts/profile_delete.html', {'form': form})

@csrf_exempt
def associate_steam(request):
    """Associate a Steam account with a Lutris account"""
    LOGGER.info("Associating Steam user with Lutris account")
    if not request.user.is_authenticated:
        return login_complete(request)

    account_url = reverse('user_account', args=(request.user.username, ))
    try:
        openid_response = parse_openid_response(request)
    except HTTPFetchingError:
        messages.warning(request, "Steam server is unreachable, please try again in a few moments")
        return redirect(account_url)

    if openid_response.status == 'failure':
        messages.warning(request, "Failed to associate Steam account")
        LOGGER.warning("Failed to associate Steam account for %s", request.user.username)
        return redirect(account_url)
    openid_backend = OpenIDBackend()
    try:
        openid_backend.associate_openid(request.user, openid_response)
    except IdentityAlreadyClaimed:
        messages.warning(
            request,
            "This Steam account is already claimed by another Lutris "
            "account.\nPlease contact an administrator if you want "
            "to reattribute your Steam account to this current account."
        )
        return redirect(account_url)

    request.user.set_steamid()
    request.user.save()
    return redirect(reverse("library_steam_sync"))

@login_required
def steam_disconnect(request):
    """Clears the Steam ID and OpenID key"""
    request.user.useropenid_set.all().delete()
    request.user.steamid = ""
    request.user.save()
    return redirect(reverse("profile"))

class LibraryList(GameList):  # pylint: disable=too-many-ancestors
    """Access the user's game library"""
    template_name = 'accounts/library_show.html'
    context_object_name = 'games'
    paginate_by = 25
    paginate_orphans = 10
    ordering = 'name'

    def get_user(self):
        """Return a user object from the username url segment"""
        try:
            user = User.objects.get(username=self.kwargs['username'])
        except User.DoesNotExist:
            try:
                user = User.objects.get(username__iexact=self.kwargs['username'])
            except User.DoesNotExist:
                raise Http404
            except User.MultipleObjectsReturned:
                raise Http404
        return user

    def get_queryset(self):
        user = self.get_user()
        queryset = models.GameLibrary.objects.get(user=user).games.filter(is_public=True)
        if self.q_params['q']:
            queryset = queryset.order_by('-rank', self.get_ordering())
        else:
            queryset = queryset.order_by(self.get_ordering())
        return self.get_filtered_queryset(queryset)

    def get_context_data(self, *, object_list=None, **kwargs):  # pylint: disable=unused-argument
        """Display the user's library"""
        context = super(LibraryList, self).get_context_data(object_list=object_list, **kwargs)
        user = self.get_user()
        if self.request.user != user:
            # Libraries are currently private. This will change once public
            # profiles are implemented
            raise Http404
        context['user'] = user
        context['is_library'] = True
        context['profile_page'] = 'library'
        return context

@login_required
def library_add(request, slug):
    """Add a game to the user's library"""
    user = request.user
    library = models.GameLibrary.objects.get(user=user)
    game = get_object_or_404(models.Game, slug=slug)
    try:
        library.games.add(game)
    except IntegrityError:
        LOGGER.debug('Game already in library')
    return redirect(game.get_absolute_url())

@login_required
def library_remove(request, slug):
    """Remove a game from a user's library"""
    library = models.GameLibrary.objects.get(user=request.user)
    game = get_object_or_404(models.Game, slug=slug)
    library.games.remove(game)
    redirect_url = request.META.get('HTTP_REFERER')
    if not redirect_url:
        redirect_url = reverse('library_show', kwargs={'username': request.user.username})
    return redirect(redirect_url)

@login_required
def library_steam_sync(request):
    """Launch a Steam library sync in the background"""
    user = request.user
    LOGGER.info("Syncing contents of Steam library for user %s", user.username)
    tasks.sync_steam_library.delay(user.id)
    messages.success(
        request,
        'Your Steam library is being synced with your Lutris account'
    )
    return redirect(reverse("library_show",
                            kwargs={'username': user.username}))

@login_required
def discourse_sso(request):
    """View used to sign in a user to the Discourse forums"""
    if not request.user.email_confirmed:
        return HttpResponseBadRequest('You must confirm your email to use the forums')
    payload = request.GET.get('sso')
    signature = request.GET.get('sig')
    try:
        nonce = sso.validate(payload, signature, settings.DISCOURSE_SSO_SECRET)
    except RuntimeError as ex:
        return HttpResponseBadRequest(ex.args[0])

    url = sso.redirect_url(nonce, settings.DISCOURSE_SSO_SECRET, request.user.email,
                           request.user.id, request.user.username)
    return redirect(settings.DISCOURSE_URL + url)

class UserDetailView(generics.RetrieveAPIView):
    """Return the information for the currently logged in user"""
    permission_classes = [IsAuthenticated]
    serializer_class = serializers.UserSerializer
    queryset = User.objects.all()

    def get_object(self):
        return self.request.user
<commit_msg>Redirect to login page after password reset<commit_after>"""Module for user account views"""
# pylint: disable=too-many-ancestors
import logging

from django.conf import settings
from django.contrib import messages
from django.contrib.auth import logout
from django.contrib.auth.decorators import login_required
from django.contrib.auth.mixins import LoginRequiredMixin
from django.contrib.auth.views import (
    LogoutView, LoginView, PasswordResetDoneView, PasswordResetView,
    PasswordChangeView, PasswordResetConfirmView
)
from django.db import IntegrityError
from django.db.models import Q
from django.http import (
    Http404, HttpResponseBadRequest,
    HttpResponseRedirect, JsonResponse
)
from django.shortcuts import get_object_or_404, redirect, render
from django.template.loader import render_to_string
from django.urls import reverse, reverse_lazy
from django.views.decorators.csrf import csrf_exempt
from django.views.generic import CreateView, UpdateView
from openid.fetchers import HTTPFetchingError
from django_openid_auth.auth import OpenIDBackend
from django_openid_auth.exceptions import IdentityAlreadyClaimed
from django_openid_auth.views import login_complete, parse_openid_response
from rest_framework import generics
from rest_framework.permissions import IsAuthenticated
from rest_framework.authtoken.models import Token

from games import models
from games.views.pages import GameList

from . import forms, sso, tasks, serializers
from .models import EmailConfirmationToken, User

LOGGER = logging.getLogger(__name__)

class LutrisRegisterView(CreateView):
    """Account registration view"""
    form_class = forms.RegistrationForm
    template_name = 'accounts/register.html'
    success_url = reverse_lazy('homepage')

class LutrisLoginView(LoginView):
    """Sign in view"""
    template_name = 'accounts/login.html'
    authentication_form = forms.LoginForm

class LutrisLogoutView(LogoutView):
    """Sign out view"""
    next_page = '/'

    def dispatch(self, request, *args, **kwargs):
        messages.success(request, 'You are now logged out of Lutris.')
        return super().dispatch(request, *args, **kwargs)

class LutrisPasswordResetView(PasswordResetView):
    """View to reset a user's password"""
    template_name = 'accounts/password_reset.html'
    form_class = forms.LutrisPasswordResetForm

class LutrisPasswordResetDoneView(PasswordResetDoneView):
    """Tell the user an email has been sent with a password reset link"""
    template_name = "accounts/password_reset_done.html"

class LutrisPasswordChangeView(PasswordChangeView):
    """View confirming the password reset is sent"""
    template_name = 'accounts/password_change.html'

class LutrisPasswordResetConfirmView(PasswordResetConfirmView):
    """View where the user confirms the password reset"""
    template_name = 'accounts/password_reset_confirm.html'
    success_url = reverse_lazy('login')

    def form_valid(self, form):
        messages.success(self.request, 'Your password has been updated.')
        return super().form_valid(form)

def clear_auth_token(request):
    """Delete the REST API token for the currently logged in user"""
    if not request.user.is_authenticated:
        # Anonymous users fuck off
        return redirect("/")
    try:
        token = Token.objects.get(user=request.user)
    except Token.DoesNotExist:
        raise Http404
    token.delete()
    messages.info(
        request,
        "You authentication token has been cleared. "
        "Please sign-in in Lutris again to generate a new one."
    )
    return redirect(
        reverse('user_account', kwargs={"username": request.user.username})
    )

@login_required
def profile(request):
    """Redirect to user account
    Takes the username from the request, allows to have a unique URL for all profiles.
    """
    return HttpResponseRedirect(
        reverse('user_account', args=(request.user.username, ))
    )

def user_account(request, username):
    """Profile view"""
    if request.user.username != username:
        raise Http404
    return render(request, 'accounts/profile.html', {
        'user': request.user,
        'profile_page': 'profile'
    })

@login_required
def user_submissions(request):
    """Lists a user game submissions"""
    pending_submissions = models.GameSubmission.objects.filter(
        user=request.user, accepted_at__isnull=True
    )
    accepted_submissions = models.GameSubmission.objects.filter(
        user=request.user, accepted_at__isnull=False
    )
    return render(request, 'accounts/game_submissions.html', {
        'pending_submissions': pending_submissions,
        'accepted_submissions': accepted_submissions
    })

@login_required
def user_send_confirmation(request):
    """Send an email with a confirmation link"""
    user = request.user
    if user.email_confirmed:
        messages.info(request, "Your email has already been confirmed.")
        return HttpResponseRedirect(
            reverse('user_account', args=(user.username, ))
        )
    token = EmailConfirmationToken(email=user.email)
    token.create_token()
    token.save()
    token.send(request)
    messages.info(request, 'An email with a confirmation link has been sent to the specified '
                           'address. Click the link to confirm your email address.')
    return HttpResponseRedirect(
        reverse('user_account', args=(user.username,))
    )

def user_require_confirmation(request):
    """Display an error message that the resource is reserved for confirmed
    accounts only.
    """
    if request.user.is_authenticated:
        messages.error(
            request,
            u"The page you have requested requires that "
            u"you have confirmed your email address."
        )
        return redirect(reverse("user_account", args=(request.user.username,)))
    login_url = settings.LOGIN_URL
    if 'next' in request.GET:
        login_url += "?next=" + request.GET['next']
    return redirect(login_url)

def user_email_confirm(request):
    """Confirm an user's account

    This is the view pointed by the link in the confirmation email
    """
    token = request.GET.get('token')
    confirmation_token = get_object_or_404(EmailConfirmationToken, token=token)
    if confirmation_token.is_valid():
        confirmation_token.confirm_user()
        confirmation_token.delete()
    return render(request, 'accounts/confirmation_received.html',
                  {'confirmation_token': confirmation_token})

class ProfileUpdateView(LoginRequiredMixin, UpdateView):
    """Edit the user's profile info"""
    template_name = 'accounts/profile_edit.html'
    form_class = forms.ProfileForm
    success_url = reverse_lazy('profile')

    def get_object(self, queryset=None):
        return self.request.user

@login_required
def profile_delete(request, username):
    """Deactivate a user account"""
    user = get_object_or_404(User, username=username)
    if user != request.user:
        raise Http404
    form = forms.ProfileDeleteForm(request.POST or None)
    if form.is_valid():
        logout(request)
        user.deactivate()
        messages.success(request, 'Your account is now deleted')
        return redirect(reverse('homepage'))
    return render(request, 'accounts/profile_delete.html', {'form': form})

@csrf_exempt
def associate_steam(request):
    """Associate a Steam account with a Lutris account"""
    LOGGER.info("Associating Steam user with Lutris account")
    if not request.user.is_authenticated:
        return login_complete(request)

    account_url = reverse('user_account', args=(request.user.username, ))
    try:
        openid_response = parse_openid_response(request)
    except HTTPFetchingError:
        messages.warning(request, "Steam server is unreachable, please try again in a few moments")
        return redirect(account_url)

    if openid_response.status == 'failure':
        messages.warning(request, "Failed to associate Steam account")
        LOGGER.warning("Failed to associate Steam account for %s", request.user.username)
        return redirect(account_url)
    openid_backend = OpenIDBackend()
    try:
        openid_backend.associate_openid(request.user, openid_response)
    except IdentityAlreadyClaimed:
        messages.warning(
            request,
            "This Steam account is already claimed by another Lutris "
            "account.\nPlease contact an administrator if you want "
            "to reattribute your Steam account to this current account."
        )
        return redirect(account_url)

    request.user.set_steamid()
    request.user.save()
    return redirect(reverse("library_steam_sync"))

@login_required
def steam_disconnect(request):
    """Clears the Steam ID and OpenID key"""
    request.user.useropenid_set.all().delete()
    request.user.steamid = ""
    request.user.save()
    return redirect(reverse("profile"))

class LibraryList(GameList):  # pylint: disable=too-many-ancestors
    """Access the user's game library"""
    template_name = 'accounts/library_show.html'
    context_object_name = 'games'
    paginate_by = 25
    paginate_orphans = 10
    ordering = 'name'

    def get_user(self):
        """Return a user object from the username url segment"""
        try:
            user = User.objects.get(username=self.kwargs['username'])
        except User.DoesNotExist:
            try:
                user = User.objects.get(username__iexact=self.kwargs['username'])
            except User.DoesNotExist:
                raise Http404
            except User.MultipleObjectsReturned:
                raise Http404
        return user

    def get_queryset(self):
        user = self.get_user()
        queryset = models.GameLibrary.objects.get(user=user).games.filter(is_public=True)
        if self.q_params['q']:
            queryset = queryset.order_by('-rank', self.get_ordering())
        else:
            queryset = queryset.order_by(self.get_ordering())
        return self.get_filtered_queryset(queryset)

    def get_context_data(self, *, object_list=None, **kwargs):  # pylint: disable=unused-argument
        """Display the user's library"""
        context = super(LibraryList, self).get_context_data(object_list=object_list, **kwargs)
        user = self.get_user()
        if self.request.user != user:
            # Libraries are currently private. This will change once public
            # profiles are implemented
            raise Http404
        context['user'] = user
        context['is_library'] = True
        context['profile_page'] = 'library'
        return context

@login_required
def library_add(request, slug):
    """Add a game to the user's library"""
    user = request.user
    library = models.GameLibrary.objects.get(user=user)
    game = get_object_or_404(models.Game, slug=slug)
    try:
        library.games.add(game)
    except IntegrityError:
        LOGGER.debug('Game already in library')
    return redirect(game.get_absolute_url())

@login_required
def library_remove(request, slug):
    """Remove a game from a user's library"""
    library = models.GameLibrary.objects.get(user=request.user)
    game = get_object_or_404(models.Game, slug=slug)
    library.games.remove(game)
    redirect_url = request.META.get('HTTP_REFERER')
    if not redirect_url:
        redirect_url = reverse('library_show', kwargs={'username': request.user.username})
    return redirect(redirect_url)

@login_required
def library_steam_sync(request):
    """Launch a Steam library sync in the background"""
    user = request.user
    LOGGER.info("Syncing contents of Steam library for user %s", user.username)
    tasks.sync_steam_library.delay(user.id)
    messages.success(
        request,
        'Your Steam library is being synced with your Lutris account'
    )
    return redirect(reverse("library_show",
                            kwargs={'username': user.username}))

@login_required
def discourse_sso(request):
    """View used to sign in a user to the Discourse forums"""
    if not request.user.email_confirmed:
        return HttpResponseBadRequest('You must confirm your email to use the forums')
    payload = request.GET.get('sso')
    signature = request.GET.get('sig')
    try:
        nonce = sso.validate(payload, signature, settings.DISCOURSE_SSO_SECRET)
    except RuntimeError as ex:
        return HttpResponseBadRequest(ex.args[0])

    url = sso.redirect_url(nonce, settings.DISCOURSE_SSO_SECRET, request.user.email,
                           request.user.id, request.user.username)
    return redirect(settings.DISCOURSE_URL + url)

class UserDetailView(generics.RetrieveAPIView):
    """Return the information for the currently logged in user"""
    permission_classes = [IsAuthenticated]
    serializer_class = serializers.UserSerializer
    queryset = User.objects.all()

    def get_object(self):
        return self.request.user
<|endoftext|>


<commit_before>#!/usr/bin/python2.3
# -*- mode: python -*-
#
# Copyright (c) 2004 Specifix, Inc.
# All rights reserved
#

import os
import posixpath
import select
import sys
import tempfile
import urllib
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from SimpleXMLRPCServer import SimpleXMLRPCServer

if len(sys.argv) != 3:
    print "needs path to srs and to the repository"
    sys.exit(1)

sys.path.append(sys.argv[1])

from netserver import NetworkRepositoryServer

FILE_PATH="/tmp/conary-server"
BASE_URL="http://localhost:8001/"

class SRSServer(SimpleXMLRPCServer):

    allow_reuse_address = 1

class HttpRequests(SimpleHTTPRequestHandler):

    outFiles = {}
    inFiles = {}

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        """
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = FILE_PATH
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)

	path += "-out"

	self.cleanup = path
        return path

    def do_GET(self):
	self.cleanup = None
	SimpleHTTPRequestHandler.do_GET(self)
	if self.cleanup:
	    os.unlink(self.cleanup)

    def do_PUT(self):
	path = FILE_PATH + '/' + os.path.basename(self.path) + "-in"

	size = os.stat(path).st_size
	if size != 0:
	    self.send_response(410, "Gone")
	    return

	out = open(path, "w")

	contentLength = int(self.headers['Content-Length'])
	while contentLength:
	    s = self.rfile.read(contentLength)
	    contentLength -= len(s)
	    out.write(s)

	self.send_response(200, 'OK')

def handler(req):
    req.content_type = "text/xml"
    req.send_http_header()
    data = req.read()
    try:
        params, method = xmlrpclib.loads(data)
    except xmlrpclib.ResponseError, e:
        req.write ( xmlrpclib.dumps(e))
    return apache.OK

if __name__ == '__main__':
    netRepos = NetworkRepositoryServer(sys.argv[2], FILE_PATH, BASE_URL)
    xmlServer = SRSServer(("localhost", 8000))
    xmlServer.register_instance(netRepos)
    xmlServer.register_introspection_functions()

    httpServer = HTTPServer(("localhost", 8001), HttpRequests)

    fds = {}
    fds[xmlServer.fileno()] = xmlServer
    fds[httpServer.fileno()] = httpServer

    p = select.poll()
    for fd in fds.iterkeys():
        p.register(fd, select.POLLIN)

    while True:
        try:
            events = p.poll()
            for (fd, event) in events:
                fds[fd].handle_request()
        except select.error:
            pass
<commit_msg>fixes to take connections from anyone<commit_after>#!/usr/bin/python2.3
# -*- mode: python -*-
#
# Copyright (c) 2004 Specifix, Inc.
# All rights reserved
#

import os
import posixpath
import select
import sys
import tempfile
import urllib
from BaseHTTPServer import HTTPServer
from SimpleHTTPServer import SimpleHTTPRequestHandler
from SimpleXMLRPCServer import SimpleXMLRPCServer

if len(sys.argv) != 3:
    print "needs path to srs and to the repository"
    sys.exit(1)

sys.path.append(sys.argv[1])

from netserver import NetworkRepositoryServer

FILE_PATH="/tmp/conary-server"
BASE_URL="http://bradley:8001/"

class SRSServer(SimpleXMLRPCServer):

    allow_reuse_address = 1

class HttpRequests(SimpleHTTPRequestHandler):

    outFiles = {}
    inFiles = {}

    def translate_path(self, path):
        """Translate a /-separated PATH to the local filename syntax.

        Components that mean special things to the local file system
        (e.g. drive or directory names) are ignored.  (XXX They should
        probably be diagnosed.)

        """
        path = posixpath.normpath(urllib.unquote(path))
        words = path.split('/')
        words = filter(None, words)
        path = FILE_PATH
        for word in words:
            drive, word = os.path.splitdrive(word)
            head, word = os.path.split(word)
            if word in (os.curdir, os.pardir): continue
            path = os.path.join(path, word)

	path += "-out"

	self.cleanup = path
        return path

    def do_GET(self):
	self.cleanup = None
	SimpleHTTPRequestHandler.do_GET(self)
	if self.cleanup:
	    os.unlink(self.cleanup)

    def do_PUT(self):
	path = FILE_PATH + '/' + os.path.basename(self.path) + "-in"

	size = os.stat(path).st_size
	if size != 0:
	    self.send_response(410, "Gone")
	    return

	out = open(path, "w")

	contentLength = int(self.headers['Content-Length'])
	while contentLength:
	    s = self.rfile.read(contentLength)
	    contentLength -= len(s)
	    out.write(s)

	self.send_response(200, 'OK')

def handler(req):
    req.content_type = "text/xml"
    req.send_http_header()
    data = req.read()
    try:
        params, method = xmlrpclib.loads(data)
    except xmlrpclib.ResponseError, e:
        req.write ( xmlrpclib.dumps(e))
    return apache.OK

if __name__ == '__main__':
    netRepos = NetworkRepositoryServer(sys.argv[2], FILE_PATH, BASE_URL)
    xmlServer = SRSServer(("", 8000))
    xmlServer.register_instance(netRepos)
    xmlServer.register_introspection_functions()

    httpServer = HTTPServer(("", 8001), HttpRequests)

    fds = {}
    fds[xmlServer.fileno()] = xmlServer
    fds[httpServer.fileno()] = httpServer

    p = select.poll()
    for fd in fds.iterkeys():
        p.register(fd, select.POLLIN)

    while True:
        try:
            events = p.poll()
            for (fd, event) in events:
                fds[fd].handle_request()
        except select.error:
            pass
<|endoftext|>


<commit_before>"""Provides the repository macro to import LLVM."""

load("//third_party:repo.bzl", "tfrt_http_archive")

def repo(name):
    """Imports LLVM."""
    LLVM_COMMIT = "95923c0ba245377205f783607aaacbf8c667b353"
    LLVM_SHA256 = "1d9af74e08ad281096fd53bd8225c247d4612dea528d36c00586bc44e263b313"

    tfrt_http_archive(
        name = name,
        sha256 = LLVM_SHA256,
        strip_prefix = "llvm-project-" + LLVM_COMMIT,
        urls = [
            "https://storage.googleapis.com/mirror.tensorflow.org/github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
            "https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
        ],
        link_files = {
            "//third_party/llvm:llvm.autogenerated.BUILD": "llvm/BUILD",
            "//third_party/mlir:BUILD": "mlir/BUILD",
            "//third_party/mlir:test.BUILD": "mlir/test/BUILD",
        },
    )
<commit_msg>Integrate LLVM at llvm/llvm-project@98f078324fc5<commit_after>"""Provides the repository macro to import LLVM."""

load("//third_party:repo.bzl", "tfrt_http_archive")

def repo(name):
    """Imports LLVM."""
    LLVM_COMMIT = "98f078324fc51da460660920f4a1aa308bfc3547"
    LLVM_SHA256 = "4f00486263fe6acd5722dac45be22c2adf1a2f6f6f585a6fb6bdcd0f4b1ed458"

    tfrt_http_archive(
        name = name,
        sha256 = LLVM_SHA256,
        strip_prefix = "llvm-project-" + LLVM_COMMIT,
        urls = [
            "https://storage.googleapis.com/mirror.tensorflow.org/github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
            "https://github.com/llvm/llvm-project/archive/{commit}.tar.gz".format(commit = LLVM_COMMIT),
        ],
        link_files = {
            "//third_party/llvm:llvm.autogenerated.BUILD": "llvm/BUILD",
            "//third_party/mlir:BUILD": "mlir/BUILD",
            "//third_party/mlir:test.BUILD": "mlir/test/BUILD",
        },
    )
<|endoftext|>


<commit_before>#!/usr/bin/env python3
import click
import os
import sys
from scbt.logging import log
from scbt.daemon import daemon as _daemon
from scbt.client import send_action
from scbt.common import chunks

@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    if ctx.invoked_subcommand is None:
        status([])

@cli.command(help="Runs the scbt daemon.")
@click.option("--fork", default=False, is_flag=True)
def daemon(fork):
    if fork:
        log.info("Forking to background")
        if os.fork() != 0:
            sys.exit()
    log.info("Running as daemon")
    _daemon()

@cli.command(help="Add a new torrent")
@click.argument('f', type=click.Path(exists=True))
@click.option("--paused", default=False, is_flag=True)
def add(f, paused):
    payload = {
        "paused": paused,
        "path": f
    }
    output = send_action("add_torrent", payload)
    if output["success"]:
        sys.stdout.write("Added {}\n".format(output["info_hash"]))
    else:
        sys.stderr.write("Error: {}\n", output["error"])

@cli.command(help="Show status information")
@click.argument('what', nargs=-1)
@click.option('--daemon', default=False, is_flag=True)
def status(what, daemon):
    cwd = os.getcwd() # TODO: See if cwd is a download target

    if len(what) == 0:
        output = send_action("status")
        print("scbt is running on pid {} (running for {} seconds)"\
            .format(output["session"]["pid"], output["session"]["uptime"]))
        print(":: [{} downloading] [{} seeding] [{} idle]"\
            .format(output["downloading"], output["seeding"], output["idle"]))
        print(":: [{} kb/s up] [{} kb/s down] [{} peers] [{} ratio]"\
            .format(output["session"]["upload_rate"],
                output["session"]["download_rate"],
                output["session"]["num_peers"],
                output["session"]["ratio"]))
    else:
        # Show status for what
        pass

@cli.command(help="List torrents loaded on daemon")
def list():
    status = send_action("status")
    response = send_action("list_torrents")
    print("[{} downloading] [{} seeding] [{} idle]"\
        .format(status["downloading"], status["seeding"], status["idle"]))
    for torrent in response["torrents"]:
        print("")
        print("{}".format(torrent["name"]))
        state = torrent["state"]
        state = state[0:1].upper() + state[1:]
        if state == "Downloading":
            print(":: {} since {} ({:.0f}%)".format(state, "TODO", torrent["progress"]))
        print(":: Info hash: {}".format(torrent["info_hash"]))
        total = len(torrent["pieces"])
        sys.stdout.write(":: Progress:\n:: [")
        for pieces in chunks(torrent["pieces"], int(total / 49)):
            if all(pieces):
                sys.stdout.write(":")
            elif any(pieces):
                sys.stdout.write(".")
            else:
                sys.stdout.write(" ")
        sys.stdout.write("]\n")

if __name__ == '__main__':
    cli()
<commit_msg>Let's merge the list and status commands<commit_after>#!/usr/bin/env python3
import click
import os
import sys
from scbt.logging import log
from scbt.daemon import daemon as _daemon
from scbt.client import send_action
from scbt.common import chunks

@click.group(invoke_without_command=True)
@click.pass_context
def cli(ctx):
    if ctx.invoked_subcommand is None:
        status([])

@cli.command(help="Runs the scbt daemon.")
@click.option("--fork", default=False, is_flag=True)
def daemon(fork):
    if fork:
        log.info("Forking to background")
        if os.fork() != 0:
            sys.exit()
    log.info("Running as daemon")
    _daemon()

@cli.command(help="Add a new torrent")
@click.argument('f', type=click.Path(exists=True))
@click.option("--paused", default=False, is_flag=True)
def add(f, paused):
    payload = {
        "paused": paused,
        "path": f
    }
    output = send_action("add_torrent", payload)
    if output["success"]:
        sys.stdout.write("Added {}\n".format(output["info_hash"]))
    else:
        sys.stderr.write("Error: {}\n", output["error"])

def meta_status(status, torrents):
    print("scbt is running on pid {} (running for {} seconds)"\
        .format(status["session"]["pid"], status["session"]["uptime"]))
    print(":: [{} downloading] [{} seeding] [{} idle]"\
        .format(status["downloading"], status["seeding"], status["idle"]))
    print(":: [{} kb/s up] [{} kb/s down] [{} peers] [{:.2f} ratio]"\
        .format(status["session"]["upload_rate"],
            status["session"]["download_rate"],
            status["session"]["num_peers"],
            status["session"]["ratio"]))
    for torrent in torrents["torrents"]:
        print("")
        print("{}".format(torrent["name"]))
        state = torrent["state"]
        state = state[0:1].upper() + state[1:]
        if state == "Downloading":
            print(":: {} since {} ({:.0f}%)".format(state, "TODO", torrent["progress"]))
        print(":: Info hash: {}".format(torrent["info_hash"]))
        total = len(torrent["pieces"])
        sys.stdout.write(":: Progress:\n:: [")
        for pieces in chunks(torrent["pieces"], int(total / 49)):
            if all(pieces):
                sys.stdout.write(":")
            elif any(pieces):
                sys.stdout.write(".")
            else:
                sys.stdout.write(" ")
        sys.stdout.write("]\n")

@cli.command(help="Show status information")
@click.argument('what', nargs=-1)
@click.option('--daemon', default=False, is_flag=True)
def status(what, daemon):
    cwd = os.getcwd() # TODO: See if cwd is a download target
    status = send_action("status")
    torrents = send_action("list_torrents")

    if len(what) == 0:
        meta_status(status, torrents)
    else:
        # what_status(status, torrents) # TODO
        pass

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


<commit_before># python3
# Copyright 2018 DeepMind Technologies Limited. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Package metadata for acme.

This is kept in a separate module so that it can be imported from setup.py, at
a time when acme's dependencies may not have been installed yet.
"""

# We follow Semantic Versioning (https://semver.org/)
_MAJOR_VERSION = '0'
_MINOR_VERSION = '1'
_PATCH_VERSION = '5'

# Example: '0.4.2'
__version__ = '.'.join([_MAJOR_VERSION, _MINOR_VERSION, _PATCH_VERSION])
<commit_msg>Bump version to distribute wrapper fix.<commit_after># python3
# Copyright 2018 DeepMind Technologies Limited. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

"""Package metadata for acme.

This is kept in a separate module so that it can be imported from setup.py, at
a time when acme's dependencies may not have been installed yet.
"""

# We follow Semantic Versioning (https://semver.org/)
_MAJOR_VERSION = '0'
_MINOR_VERSION = '1'
_PATCH_VERSION = '6'

# Example: '0.4.2'
__version__ = '.'.join([_MAJOR_VERSION, _MINOR_VERSION, _PATCH_VERSION])
<|endoftext|>


<commit_before># Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

{
  'variables': {
    'werror': '',
  },
  'includes': [
    '../../native_client/build/untrusted.gypi',
  ],
  'targets': [
    {
      'target_name': 'opus_nacl',
      'type': 'none',
      'variables': {
        'nlib_target': 'libopus_nacl.a',
        'build_glibc': 0,
        'build_newlib': 0,
        'build_pnacl_newlib': 1,
      },
      'dependencies': [
        '<(DEPTH)/native_client/tools.gyp:prep_toolchain',
      ],
      'defines': [
        'OPUS_BUILD',
        'OPUS_EXPORT=',
        'HAVE_LRINT',
        'HAVE_LRINTF',
        'VAR_ARRAYS',
      ],
      'include_dirs': [
        'src/celt',
        'src/include',
        'src/silk',
        'src/silk/float',
      ],
      'includes': ['opus_srcs.gypi', ],
      'sources': [
        '<@(opus_common_sources)',
        '<@(opus_float_sources)',
      ],
    },  # end of target 'opus_nacl'
  ],
}
<commit_msg>Suppress opus warning about optimization in opus_nacl<commit_after># Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

{
  'includes': [
    '../../native_client/build/untrusted.gypi',
  ],
  'targets': [
    {
      'target_name': 'opus_nacl',
      'type': 'none',
      'variables': {
        'nlib_target': 'libopus_nacl.a',
        'build_glibc': 0,
        'build_newlib': 0,
        'build_pnacl_newlib': 1,
      },
      'dependencies': [
        '<(DEPTH)/native_client/tools.gyp:prep_toolchain',
      ],
      'defines': [
        'OPUS_BUILD',
        'OPUS_EXPORT=',
        'HAVE_LRINT',
        'HAVE_LRINTF',
        'VAR_ARRAYS',
      ],
      'include_dirs': [
        'src/celt',
        'src/include',
        'src/silk',
        'src/silk/float',
      ],
      'includes': ['opus_srcs.gypi', ],
      'sources': [
        '<@(opus_common_sources)',
        '<@(opus_float_sources)',
      ],
      # Suppress a warning given by opus_decoder.c that tells us
      # optimizations are turned off.
      'cflags': [
        '-Wno-#pragma-messages',
      ],
    },  # end of target 'opus_nacl'
  ],
}
<|endoftext|>


<commit_before>from igorpro import IgorThread, IgorCallError
from PyQt4 import QtCore

def __reload__(old):
    MIES._bridge = old['MIES']._bridge

class MIES(QtCore.QObject):
    """Bridge for communicating with MIES (multi-patch ephys and pressure control in IgorPro)
    """
    sigDataReady = QtCore.Signal(object)
    _sigFutureComplete = QtCore.Signal(object)
    _bridge = None
    ALLDATA = None
    PEAKRES = 1
    SSRES = 2

    @classmethod
    def getBridge(cls, useZMQ=False):
        """Return a singleton MIESBridge instance.
        """
        # TODO: Handle switching between ZMQ and ActiveX?
        if cls._bridge is None:
            cls._bridge = MIES(useZMQ=useZMQ)
        return cls._bridge

    def __init__(self, useZMQ=False):
        super(MIES, self).__init__(parent=None)
        self.igor = IgorThread(useZMQ)
        self.usingZMQ = useZMQ
        self.currentData = None
        self._exiting = False
        self.windowName = 'ITC1600_Dev_0'
        self._sigFutureComplete.connect(self.processUpdate)
        self._initTPTime = None
        self._lastTPTime = None
        self._TPTimer = QtCore.QTimer()
        self._TPTimer.setSingleShot(True)
        self._TPTimer.timeout.connect(self.getMIESUpdate)
        self.start()

    def start(self):
        self._exiting = False
        if self.usingZMQ:
            self.getMIESUpdate()

    def getMIESUpdate(self):
        if self.usingZMQ:
            future = self.igor("FFI_ReturnTPValues")
            future.add_done_callback(self._sigFutureComplete.emit)
            self._TPTimer.start(5000) # by default recheck after 5 seconds, overridden if we get data
        else:
            raise RuntimeError("getMIESUpdate not supported in ActiveX")

    def processUpdate(self, future):
        if not self._exiting:
            try:
                res = future.result()
                data = res[...,0] # dimension hack when return value suddenly changed
                self.currentData = data
                self._updateTPTimes(data)
                self.sigDataReady.emit(data)
                nextCallWait = 0
            except IgorCallError:
                # Test pulse isn't running, let's wait a little longer
                nextCallWait = 200
            self._TPTimer.start(nextCallWait)

    def _updateTPTimes(self, TPArray):
        """Update globally tracked initial and end TP times"""
        if self._initTPTime is None:
            try:
                self._initTPTime = TPArray[0,:][TPArray[0,:] > 0].min()
            except ValueError:
                pass
        self._lastTPTime = TPArray[0,:].max()

    def getTPRange(self):
        if self._initTPTime is None:
            return 0, 0
        else:
            return self._initTPTime, self._lastTPTime

    def resetData(self):
        self.currentData = None

    def selectHeadstage(self, hs):
        return self.setCtrl("slider_DataAcq_ActiveHeadstage", hs)

    def setManualPressure(self, pressure):
        return self.setCtrl("setvar_DataAcq_SSPressure", pressure)

    def setApproach(self, hs):
        windowName = '"{}"'.format(self.windowName)
        return self.igor("P_MethodApproach", windowName, hs)
        #return self.setCtrl("button_DataAcq_Approach")

    def setSeal(self, hs):
        windowName = '"{}"'.format(self.windowName)
        return self.igor("P_MethodSeal", windowName, hs)
        #return self.setCtrl("button_DataAcq_Seal")

    def setHeadstageActive(self, hs, active):
        return self.setCtrl('Check_DataAcqHS_%02d' % hs, active)

    def autoPipetteOffset(self):
        return self.setCtrl('button_DataAcq_AutoPipOffset_VC')

    def setCtrl(self, name, value=None):
        """Set or activate a GUI control in MIES."""
        name_arg = '"{}"'.format(name)
        if value is None:
            return self.igor('PGC_SetAndActivateControl', self.windowName, name)
        else:
            return self.igor('PGC_SetAndActivateControlVar', self.windowName, name, value)

    def quit(self):
        self._exiting = True

if __name__ == "__main__":
    from PyQt4 import QtGui
    import pyqtgraph as pg
    import sys

    class W(QtGui.QWidget):
        def __init__(self, parent=None):
            super(W, self).__init__(parent=parent)
            self.mies = MIES.getBridge(True)
            self.mies.sigDataReady.connect(self.printit)
            self.b = QtGui.QPushButton("stop", parent=self)
            self.b.clicked.connect(self.mies.quit)
            l = QtGui.QVBoxLayout()
            l.addWidget(self.b)
            self.setLayout(l)

        def printit(self, data):
            print data

    app = pg.mkQApp()
    w = W()
    w.show()
    sys.exit(app.exec_())<commit_msg>Fixed setApproach and setSeal by calling non-static MIES functions.<commit_after>from igorpro import IgorThread, IgorCallError
from PyQt4 import QtCore

# MIES constants, see MIES_Constants.ipf
PRESSURE_METHOD_APPROACH = 0
PRESSURE_METHOD_SEAL = 1

def __reload__(old):
    MIES._bridge = old['MIES']._bridge

class MIES(QtCore.QObject):
    """Bridge for communicating with MIES (multi-patch ephys and pressure control in IgorPro)
    """
    sigDataReady = QtCore.Signal(object)
    _sigFutureComplete = QtCore.Signal(object)
    _bridge = None
    ALLDATA = None
    PEAKRES = 1
    SSRES = 2

    @classmethod
    def getBridge(cls, useZMQ=False):
        """Return a singleton MIESBridge instance.
        """
        # TODO: Handle switching between ZMQ and ActiveX?
        if cls._bridge is None:
            cls._bridge = MIES(useZMQ=useZMQ)
        return cls._bridge

    def __init__(self, useZMQ=False):
        super(MIES, self).__init__(parent=None)
        self.igor = IgorThread(useZMQ)
        self.usingZMQ = useZMQ
        self.currentData = None
        self._exiting = False
        self.windowName = 'ITC1600_Dev_0'
        self._sigFutureComplete.connect(self.processUpdate)
        self._initTPTime = None
        self._lastTPTime = None
        self._TPTimer = QtCore.QTimer()
        self._TPTimer.setSingleShot(True)
        self._TPTimer.timeout.connect(self.getMIESUpdate)
        self.start()

    def start(self):
        self._exiting = False
        if self.usingZMQ:
            self.getMIESUpdate()

    def getMIESUpdate(self):
        if self.usingZMQ:
            future = self.igor("FFI_ReturnTPValues")
            future.add_done_callback(self._sigFutureComplete.emit)
            self._TPTimer.start(5000) # by default recheck after 5 seconds, overridden if we get data
        else:
            raise RuntimeError("getMIESUpdate not supported in ActiveX")

    def processUpdate(self, future):
        if not self._exiting:
            try:
                res = future.result()
                data = res[...,0] # dimension hack when return value suddenly changed
                self.currentData = data
                self._updateTPTimes(data)
                self.sigDataReady.emit(data)
                nextCallWait = 0
            except IgorCallError:
                # Test pulse isn't running, let's wait a little longer
                nextCallWait = 200
            self._TPTimer.start(nextCallWait)

    def _updateTPTimes(self, TPArray):
        """Update globally tracked initial and end TP times"""
        if self._initTPTime is None:
            try:
                self._initTPTime = TPArray[0,:][TPArray[0,:] > 0].min()
            except ValueError:
                pass
        self._lastTPTime = TPArray[0,:].max()

    def getTPRange(self):
        if self._initTPTime is None:
            return 0, 0
        else:
            return self._initTPTime, self._lastTPTime

    def resetData(self):
        self.currentData = None

    def selectHeadstage(self, hs):
        return self.setCtrl("slider_DataAcq_ActiveHeadstage", hs)

    def setManualPressure(self, pressure):
        return self.setCtrl("setvar_DataAcq_SSPressure", pressure)

    def setApproach(self, hs):
        return self.igor("P_SetPressureMode", self.windowName, hs, PRESSURE_METHOD_APPROACH)

    def setSeal(self, hs):
        return self.igor("P_SetPressureMode", self.windowName, hs, PRESSURE_METHOD_SEAL)

    def setHeadstageActive(self, hs, active):
        return self.setCtrl('Check_DataAcqHS_%02d' % hs, active)

    def autoPipetteOffset(self):
        return self.setCtrl('button_DataAcq_AutoPipOffset_VC')

    def setCtrl(self, name, value=None):
        """Set or activate a GUI control in MIES."""
        name_arg = '"{}"'.format(name)
        if value is None:
            return self.igor('PGC_SetAndActivateControl', self.windowName, name)
        else:
            return self.igor('PGC_SetAndActivateControlVar', self.windowName, name, value)

    def quit(self):
        self._exiting = True

if __name__ == "__main__":
    from PyQt4 import QtGui
    import pyqtgraph as pg
    import sys

    class W(QtGui.QWidget):
        def __init__(self, parent=None):
            super(W, self).__init__(parent=parent)
            self.mies = MIES.getBridge(True)
            self.mies.sigDataReady.connect(self.printit)
            self.b = QtGui.QPushButton("stop", parent=self)
            self.b.clicked.connect(self.mies.quit)
            l = QtGui.QVBoxLayout()
            l.addWidget(self.b)
            self.setLayout(l)

        def printit(self, data):
            print data

    app = pg.mkQApp()
    w = W()
    w.show()
    sys.exit(app.exec_())<|endoftext|>


<commit_before>"""//***********************************************************************
 * Exp6_LineFollowing_IRSensors -- RedBot Experiment 6
 *
 * This code reads the three line following sensors on A3, A6, and A7
 * and prints them out to the Serial Monitor. Upload this example to your
 * RedBot and open up the Serial Monitor by clicking the magnifying glass
 * in the upper-right hand corner.
 *
 * This sketch was written by SparkFun Electronics,with lots of help from
 * the Arduino community. This code is completely free for any use.
 *
 * 8 Oct 2013 M. Hord
 * Revised, 31 Oct 2014 B. Huang
 ***********************************************************************/"""

from pymata_aio.pymata3 import PyMata3
from pymata_aio.constants import Constants
from library.redbot import RedBotSensor

COM_PORT = None # If the auto detection method fails uncomment the line below and modify to your Redbot's COM
# COM_PORT = "COM6"

# This line "includes" the RedBot library into your sketch.
# Provides special objects, methods, and functions for the RedBot.
LEFT_LINE_FOLLOWER = 3  # pin number assignments for each IR sensor
CENTRE_LINE_FOLLOWER = 6
RIGHT_LINE_FOLLOWER = 7

board = PyMata3(com_port=COM_PORT)
IR_sensor_1 = RedBotSensor(board, LEFT_LINE_FOLLOWER)
IR_sensor_2 = RedBotSensor(board, CENTRE_LINE_FOLLOWER)
IR_sensor_3 = RedBotSensor(board, RIGHT_LINE_FOLLOWER)

def setup():
    print("Welcome to Experiment 6!")
    print("------------------------")

def loop():
    board.sleep(0.1)
    print("IR Sensor Readings: {},   {},    {}".format(IR_sensor_1.read(), IR_sensor_2.read(), IR_sensor_3.read()))

if __name__ == "__main__":
    setup()
    while True:
        loop()
<commit_msg>Update COM_PORT constant for Exp6<commit_after>"""//***********************************************************************
 * Exp6_LineFollowing_IRSensors -- RedBot Experiment 6
 *
 * This code reads the three line following sensors on A3, A6, and A7
 * and prints them out to the Serial Monitor. Upload this example to your
 * RedBot and open up the Serial Monitor by clicking the magnifying glass
 * in the upper-right hand corner.
 *
 * This sketch was written by SparkFun Electronics,with lots of help from
 * the Arduino community. This code is completely free for any use.
 *
 * 8 Oct 2013 M. Hord
 * Revised, 31 Oct 2014 B. Huang
 ***********************************************************************/"""

from pymata_aio.pymata3 import PyMata3
from pymata_aio.constants import Constants
from library.redbot import RedBotSensor

COM_PORT = None # Use automatic com port detection (the default)
#COM_PORT = "COM7" # Manually specify the com port (optional)

# This line "includes" the RedBot library into your sketch.
# Provides special objects, methods, and functions for the RedBot.
LEFT_LINE_FOLLOWER = 3  # pin number assignments for each IR sensor
CENTRE_LINE_FOLLOWER = 6
RIGHT_LINE_FOLLOWER = 7

board = PyMata3(com_port=COM_PORT)
IR_sensor_1 = RedBotSensor(board, LEFT_LINE_FOLLOWER)
IR_sensor_2 = RedBotSensor(board, CENTRE_LINE_FOLLOWER)
IR_sensor_3 = RedBotSensor(board, RIGHT_LINE_FOLLOWER)

def setup():
    print("Welcome to Experiment 6!")
    print("------------------------")

def loop():
    board.sleep(0.1)
    print("IR Sensor Readings: {},   {},    {}".format(IR_sensor_1.read(), IR_sensor_2.read(), IR_sensor_3.read()))

if __name__ == "__main__":
    setup()
    while True:
        loop()
<|endoftext|>


<commit_before>#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2
import jinja2
import os
import logging
import texter

from webapp2_extras import sessions

from wish_model import Wish
from user_model import User

from google.appengine.ext import db

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
config = {}
config['webapp2_extras.sessions'] = {
    'secret_key': 'my-super-secret-key',
}

class BaseHandler(webapp2.RequestHandler):
    def dispatch(self):
        # Get a session store for this request.
        self.session_store = sessions.get_store(request=self.request)

        try:
            # Dispatch the request.
            webapp2.RequestHandler.dispatch(self)
        finally:
            # Save all sessions.
            self.session_store.save_sessions(self.response)

    @webapp2.cached_property
    def session(self):
        # Returns a session using the default cookie key.
        return self.session_store.get_session()

class MainHandler(BaseHandler):
    def get(self):
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/home.html")
        self.response.out.write(template.render(template_values))

class WishHandler(BaseHandler):
    def get(self):
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/make_a_wish.html")
        self.response.out.write(template.render(template_values))

    def post(self):
        wish = Wish(
            name=self.request.get("name"),
            details=self.request.get("details"),
            type_of_request=self.request.get("type_of_request"),
            location_dependent=(True if self.request.get("location_dependent") else False),
            location=self.request.get("location"),
            status="requested"
        )
        wish.put()
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/make_a_wish_post.html")
        self.response.out.write(template.render(template_values))

class WishIndexHandler(BaseHandler):
    def get(self):
        template_values = {}
        search = self.request.get("status")
        if not search:
            search = 'requested'
        template_values['wishes'] = Wish.gql("WHERE status = :1", search)
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/fulfill_a_wish.html")
        self.response.out.write(template.render(template_values))

    def post(self):
        template_values = {}
        wish = Wish.get(self.request.get("key"))
        wish.status = 'in progress'
        wish.put()
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/fulfill_a_wish_post.html")
        self.response.out.write(template.render(template_values))

class LoginHandler(BaseHandler):
    def get(self):
        template = jinja_environment.get_template("views/login.html")
        template_values = {"denied": False, 'session':self.session}

        self.response.out.write(template.render(template_values))

    def post(self):
        username = self.request.get("username")
        print username
        num = texter.num_parse(self.request.get("phonenumber"))
        cur_user = User.get_by_key_name(username)
        template = jinja_environment.get_template("views/login.html")

        if cur_user == None:
            cur_user = User.get_or_insert(username, name=username, phone_number = num)
        if cur_user.phone_number == num:
            # terrible authentication hacks, sorry Wagner
            self.session['user_name'] = username
            self.session['num'] = num
            self.session['authenticated'] = True
            self.redirect('/')

        else:
            self.session['authenticated'] = False
            template_values = {"denied": True, 'session':self.session}
            self.response.out.write(template.render(template_values))

class LogoutHandler(BaseHandler):
    def get(self):
        self.session['authenticated'] = False
        self.redirect('/')

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/make_a_wish', WishHandler),
    ('/fulfill_a_wish', WishIndexHandler),
    ('/login', LoginHandler),
    ('/logout', LogoutHandler)
], debug=True, config=config)
<commit_msg>template fails<commit_after>#!/usr/bin/env python
#
# Copyright 2007 Google Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
import webapp2
import jinja2
import os
import logging
import texter

from webapp2_extras import sessions

from wish_model import Wish
from user_model import User

from google.appengine.ext import db

jinja_environment = jinja2.Environment(
    loader=jinja2.FileSystemLoader(os.path.dirname(__file__)))
config = {}
config['webapp2_extras.sessions'] = {
    'secret_key': 'my-super-secret-key',
}

class BaseHandler(webapp2.RequestHandler):
    def dispatch(self):
        # Get a session store for this request.
        self.session_store = sessions.get_store(request=self.request)

        try:
            # Dispatch the request.
            webapp2.RequestHandler.dispatch(self)
        finally:
            # Save all sessions.
            self.session_store.save_sessions(self.response)

    @webapp2.cached_property
    def session(self):
        # Returns a session using the default cookie key.
        return self.session_store.get_session()

class MainHandler(BaseHandler):
    def get(self):
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/home.html")
        self.response.out.write(template.render(template_values))

class WishHandler(BaseHandler):
    def get(self):
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/make_a_wish.html")
        self.response.out.write(template.render(template_values))

    def post(self):
        wish = Wish(
            name=self.request.get("name"),
            details=self.request.get("details"),
            type_of_request=self.request.get("type_of_request"),
            location_dependent=(True if self.request.get("location_dependent") else False),
            location=self.request.get("location"),
            status="requested"
        )
        print wish.put()
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/make_a_wish_post.html")
        self.response.out.write(template.render(template_values))

class WishIndexHandler(BaseHandler):
    def get(self):
        template_values = {}
        search = self.request.get("status")
        if not search:
            search = 'requested'
        template_values = {'session':self.session}
        template_values['wishes'] = Wish.all()
        template = jinja_environment.get_template("views/fulfill_a_wish.html")
        self.response.out.write(template.render(template_values))

    def post(self):
        template_values = {}
        wish = Wish.get(self.request.get("key"))
        wish.status = 'in progress'
        wish.put()
        template_values = {'session':self.session}
        template = jinja_environment.get_template("views/fulfill_a_wish_post.html")
        self.response.out.write(template.render(template_values))

class LoginHandler(BaseHandler):
    def get(self):
        template = jinja_environment.get_template("views/login.html")
        template_values = {"denied": False, 'session':self.session}

        self.response.out.write(template.render(template_values))

    def post(self):
        username = self.request.get("username")
        print username
        num = texter.num_parse(self.request.get("phonenumber"))
        cur_user = User.get_by_key_name(username)
        template = jinja_environment.get_template("views/login.html")

        if cur_user == None:
            cur_user = User.get_or_insert(username, name=username, phone_number = num)
        if cur_user.phone_number == num:
            # terrible authentication hacks, sorry Wagner
            self.session['user_name'] = username
            self.session['num'] = num
            self.session['authenticated'] = True
            self.redirect('/')

        else:
            self.session['authenticated'] = False
            template_values = {"denied": True, 'session':self.session}
            self.response.out.write(template.render(template_values))

class LogoutHandler(BaseHandler):
    def get(self):
        self.session['authenticated'] = False
        self.redirect('/')

app = webapp2.WSGIApplication([
    ('/', MainHandler),
    ('/make_a_wish', WishHandler),
    ('/fulfill_a_wish', WishIndexHandler),
    ('/login', LoginHandler),
    ('/logout', LogoutHandler)
], debug=True, config=config)
<|endoftext|>


<commit_before>'''
The main module which spawns a gui and a effect thread and opens a socket connection to the specified
host. The effect algorithm is in the effect module. Change this file to develop your effect.
Change the host and port to your needs in this main file and also the values representing your led configuration.

Created on 27.11.2014

@author: Fabian Hertwig
'''

from threading import Thread
import gui
import hyperion
import runpy
import json_client

# Change this to your Pis / Hyperion data. There is no harm done if wrong data is set here.
# The connection will simply time out.
hyperion_host = '192.168.178.32'
hyperion_port = 19444

# Change this according to your led configuration.
horizontal_led_num = 17
vertical_led_num = 9
first_led_offset_num = 17
leds_in_clockwise_direction = False
has_corner_leds = False

def run_effect():
    """
    Runs the module effect. Copy any hyperion effect code in this module or create your own.
    Note that effects that call hyperion.setColor(r, g, b) or hyperion.setImage(img) are not supported.
    """
    runpy.run_module("effect")

def main():
    hyperion.init(horizontal_led_num, vertical_led_num, first_led_offset_num, leds_in_clockwise_direction, has_corner_leds)

    # create own thread for the gui and the effect as they have to update simultaneously
    effect_thread = Thread(target=run_effect)
    window_thread = Thread(target=gui.createWindow)

    effect_thread.start()
    window_thread.start()

    # Open the connection to the json server after the threads started, so they won't have to wait until
    # the timeout to start. Uncomment if you do not want to send data to the server.
    json_client.open_connection(hyperion_host, hyperion_port)

    # wait for the threads to stop
    window_thread.join()
    # After the window was closed abort the effect through the fake hyperion module
    hyperion.set_abort(True)
    effect_thread.join()

    # close potential connections
    json_client.close_connection()
    print "Exiting"

if __name__ == '__main__':
    main()

<commit_msg>moved tkinter mainloop in main thread<commit_after>'''
The main module which spawns a gui and a effect thread and opens a socket connection to the specified
host. The effect algorithm is in the effect module. Change this file to develop your effect.
Change the host and port to your needs in this main file and also the values representing your led configuration.

Created on 27.11.2014

@author: Fabian Hertwig
'''

from threading import Thread
import gui
import hyperion
import runpy
import json_client

# Change this to your Pis / Hyperion data. There is no harm done if wrong data is set here.
# The connection will simply time out.
hyperion_host = '192.168.178.32'
hyperion_port = 19444

# Change this according to your led configuration.
horizontal_led_num = 17
vertical_led_num = 9
first_led_offset_num = 17
leds_in_clockwise_direction = False
has_corner_leds = False

def run_effect():
    """
    Runs the module effect. Copy any hyperion effect code in this module or create your own.
    Note that effects that call hyperion.setColor(r, g, b) or hyperion.setImage(img) are not supported.
    """
    runpy.run_module("effect")

def main():
    hyperion.init(horizontal_led_num, vertical_led_num, first_led_offset_num, leds_in_clockwise_direction,
                  has_corner_leds)

    # Open the connection to the json server. Uncomment if you do not want to send data to the server.
    json_client.open_connection(hyperion_host, hyperion_port)

    # create own thread for the effect
    effect_thread = Thread(target=run_effect)

    effect_thread.start()
    gui.createWindow()

    # After the window was closed abort the effect through the fake hyperion module
    hyperion.set_abort(True)
    # wait for the thread to stop
    effect_thread.join()

    # close potential connections
    json_client.close_connection()
    print("Exiting")

if __name__ == '__main__':
    main()

<|endoftext|>


<commit_before>#------------------------------------------------------------------------------
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in enthought/LICENSE.txt and may be redistributed only
# under the conditions described in the aforementioned license.  The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
# Thanks for using Enthought open source!
#------------------------------------------------------------------------------
""" Chaco's SVG backend

    :Copyright:   ActiveState
    :License:     BSD Style
    :Author:      David Ascher (davida@activestate.com)
    :Version:     $Revision: 1.5 $
"""

####
#
# Known limitations
#
# * BUG: Weird behavior with compound plots
# * Limitation: text widths are lousy if reportlab is not installed
# * Missing feature: rotated text

"""
Miscellaneous notes:

* the way to do links:
  <a xlink:href="http://www.w3.org">
    <ellipse cx="2.5" cy="1.5" rx="2" ry="1" fill="red" />
  </a>
"""

# Major library imports
import os
import sys
import cStringIO
from numpy import arange, ravel, pi

# Local, relative Kiva imports
import affine
import basecore2d
import constants
from constants import FILL, FILL_STROKE, EOF_FILL_STROKE, EOF_FILL, STROKE

try:
    import logging
    import tempfile
    _logfile = os.path.join(tempfile.gettempdir(), "kivasvg.log")
    hdlr = logging.FileHandler(_logfile)
    BASIC_FORMAT = "%(levelname)s: %(name)s: %(message)s"
    fmt = logging.Formatter(BASIC_FORMAT)
    hdlr.setFormatter(fmt)
    logging.root.addHandler(hdlr)
    log = logging.getLogger('')
    log.setLevel(logging.INFO)
except ImportError:
    class FakeLogger:
        def debug(self, message):
            print >> sys.stderr, "DEBUG:", message
        def info(self, message):
            print >> sys.stderr, "INFO:", message
        def warn(self, message):
            print >> sys.stderr, "WARN:", message
        def error(self, message):
            print >> sys.stderr, "ERROR:", message
        def critical(self, message):
            print >> sys.stderr, "CRITICAL:", message
    log = FakeLogger()

def _strpoints(points):
    c = cStringIO.StringIO()
    for x,y in points:
        c.write('%3.2f,%3.2f ' % (x,y))
    return c.getvalue()

def _mkstyle(kw):
    return '"' + '; '.join([str(k) + ':' + str(v) for k,v in kw.items()]) +'"'

def default_filter(kw1):
    kw = {}
    for (k,v) in kw1.items():
        if type(v) == type(()):
            if v[0] != v[1]:
                kw[k] = v[0]
        else:
            kw[k] = v
    return kw

line_cap_map = {
    constants.CAP_ROUND: 'round',
    constants.CAP_SQUARE: 'square',
    constants.CAP_BUTT: 'butt'
    }

line_join_map = {
    constants.JOIN_ROUND: 'round',
    constants.JOIN_BEVEL: 'bevel',
    constants.JOIN_MITER: 'miter'
    }

font_map = {'Arial': 'Helvetica',
            }
import _fontdata

xmltemplate = """<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
        xmlns:text="http://xmlns.graougraou.com/svg/text/"
        xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
        a3:scriptImplementation="Adobe"
        width="100%%"
        height="100%%"
        viewBox="0 0 %(width)f %(height)f"
        >
<g transform="translate(0,%(height)f)">
<g transform="scale(1,-1)">
%(contents)s
</g>
</g>
</svg>
"""

htmltemplate = """<html xmlns:svg="http://www.w3.org/2000/svg">
<object id="AdobeSVG" CLASSID="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2">
</object>
<?import namespace="svg" implementation="#AdobeSVG"?>
<body>
<svg:svg width="100%%" height="100%%" viewBox="0 0 %(width)f %(height)f">
%(contents)s
</svg:svg>
</body>
</html>
"""

font_map = {'Arial': 'Helvetica',
            }
try:
    # expensive way of computing string widths
    import reportlab.pdfbase.pdfmetrics as pdfmetrics
    import reportlab.pdfbase._fontdata as _fontdata
    _reportlab_loaded = 1
except ImportError:
    import pdfmetrics
    import _fontdata
    _reportlab_loaded = 0

font_face_map = {'Arial': 'Helvetica'}

# This backend has no compiled path object, yet.
class CompiledPath(object):
    pass

_clip_counter = 0
class GraphicsContext(basecore2d.GraphicsContextBase):

    def __init__(self, size):
        basecore2d.GraphicsContextBase.__init__(self)
        self.size = size
        self._height = size[1]
        self.contents = cStringIO.StringIO()
        self._clipmap = {}
        self.clip_id = None

    def render(self, format):
        assert format == 'svg'
        height, width = self.size
        contents = self.contents.getvalue().replace("<svg:", "<").replace("</svg:", "</")
        return xmltemplate % locals()

    def clear(self, size):
        # TODO: clear the contents
        pass

    def width(self):
        return self.size[0]

    def height(self):
        return self.size[1]

    def save(self, filename):
        f = open(filename, 'w')
        ext = os.path.splitext(filename)[1]
        if ext == '.svg':
            template = xmltemplate
            height, width = self.size
            contents = self.contents.getvalue().replace("<svg:", "<").replace("</svg:", "</")
        elif ext == '.html':
            height, width = self.size[0]*3, self.size[1]*3
            contents = self.contents.getvalue()
            template = htmltemplate
        else:
            raise ValueError, "don't know how to write a %s file" % ext
        f.write(template % locals())

    # Text handling code

    def set_font(self, font):
        if font.face_name == '':
            font.face_name = 'Arial'
        self.face_name = font_face_map.get(font.face_name, font.face_name)
        self.font = pdfmetrics.Font(self.face_name, self.face_name, pdfmetrics.defaultEncoding)
        self.font_size = font.size

    def device_show_text(self, text):
        x,y = self.get_text_position()
        x,y = self._fixpoints([[x,y]])[0]
        ttm = self.get_text_matrix()
        ctm = self.get_ctm()  # not device_ctm!!
        m = affine.concat(ctm,ttm)
        tx,ty,sx,sy,angle = affine.trs_factor(m)
        angle = '%3.3f' % (-angle / pi * 180.)
        height = self.get_full_text_extent(text)[1]
        self.contents.write('<g transform="translate(%(x)f,%(y)f)">\n' % locals())
        self.contents.write('<g transform="scale(1,-1)">\n')
        self._emit('text', contents=text, transform='"rotate('+angle+')"', kw={'font-family':repr(self.font.fontName),
                                                        'font-size': '"'+ str(self.font_size) + '"'})
        self.contents.write('</g>\n')
        self.contents.write('</g>\n')
    def get_full_text_extent(self, text):
        ascent,descent=_fontdata.ascent_descent[self.face_name]
        descent = (-descent) * self.font_size / 1000.0
        ascent = ascent * self.font_size / 1000.0
        height = ascent + descent
        width = pdfmetrics.stringWidth(text, self.face_name, self.font_size)
        return width, height, descent, height*1.2 # assume leading of 1.2*height

    # actual implementation =)

    def device_fill_points(self, points, mode):
        points = self._fixpoints(points)
        if mode in (FILL, FILL_STROKE, EOF_FILL_STROKE):
            fill = self._color(self.state.fill_color)
        else:
            fill = 'none'
        if mode in (STROKE, FILL_STROKE, EOF_FILL_STROKE):
            stroke = self._color(self.state.line_color)
        else:
            stroke = 'none'
        if mode in (EOF_FILL_STROKE, EOF_FILL):
            rule = 'evenodd'
        else:
            rule = 'nonzero'
        linecap = line_cap_map[self.state.line_cap]
        linejoin = line_join_map[self.state.line_join]
        dasharray = self._dasharray()
        width = '%3.3f' % self.state.line_width
        if self.clip_id:
            clip = '"url(#' + self.clip_id +')"'
        else:
            clip = None
        if mode == STROKE:
            opacity = '%1.3f' % self.state.line_color[-1]
            self._emit('polyline',
                        points='"'+_strpoints(points)+'"',
                        kw=default_filter({'clip-path': (clip, None)}),
                        style=_mkstyle(default_filter({'opacity': (opacity, "1.000"),
                                        'stroke': stroke,
                                        'fill': 'none',
                                        'stroke-width': (width, "1.000"),
                                        'stroke-linejoin': (linejoin, 'miter'),
                                        'stroke-linecap': (linecap, 'butt'),
                                        'stroke-dasharray': (dasharray, 'none')})))

        else:
            opacity = '%1.3f' % self.state.fill_color[-1]
            self._emit('polygon',
                        points='"'+_strpoints(points)+'"',
                        kw=default_filter({'clip-path': (clip, None)}),
                        style=_mkstyle(default_filter({'opacity': (opacity, "1.000"),
                                        'stroke-width': (width, "1.000"),
                                        'fill': fill,
                                        'fill-rule': rule,
                                        'stroke': stroke,
                                        'stroke-linejoin': (linejoin, 'miter'),
                                        'stroke-linecap': (linecap, 'butt'),
                                        'stroke-dasharray': (dasharray, 'none')})))

    def device_stroke_points(self, points, mode):
        # handled by device_fill_points
        pass

    def _build(self, elname, **kw):
        x = '<' + elname + ' '
        for k,v in kw.items():
            if type(v) == type(0.0):
                v = '"%3.3f"' % v
            elif type(v) == type(0):
                v = '"%d"' % v
            else:
                v = '"%s"' % str(v)
            x += k + '=' + v + ' '
        x += '/>\n'
        return x

    def device_set_clipping_path(self, x, y, width, height):
        ##x,y,width,height = map(lambda x: '"' + str(x) + '"', [x,y,width,height])
        ##self._emit('rect', x=x, y=y, width=width, height=height,
        ##                style=_mkstyle({'stroke-width': 5,
        ##                                'fill':'none',
        ##                                'stroke': 'green'}))
        ##
        ##return
        global _clip_counter
        self.clip_id = 'clip_%d' % _clip_counter
        _clip_counter += 1
        x,y = self._fixpoints([[x,y]])[0]
        rect = self._build('rect', x=x, y=y, width=width, height=height)
        self._emit('clipPath', contents=rect, id='"'+self.clip_id + '"')

    def device_destroy_clipping_path(self):
        self.clip_id = None

    # utility routines

    def _fixpoints(self, points):
        return points
        # convert lines from Kiva coordinate space to PIL coordinate space
        # XXX I suspect this is the location of the bug w.r.t. compound graphs and
        # "global" sizing.
        # XXX this should be made more efficient for NumPy arrays
        np = []
        for (x,y) in points:
            np.append((x,self._height-y))
        return np

    def _emit(self, name, contents=None, kw={}, **otherkw):
        self.contents.write('<svg:%(name)s ' % locals())
        for k, v in kw.items():
            self.contents.write("%(k)s=%(v)s " % locals())
        for k, v in otherkw.items():
            self.contents.write("%(k)s=%(v)s " % locals())
        if contents is None:
            self.contents.write('/>\n')
        else:
            self.contents.write('>\n')
            self.contents.write(contents)
            self.contents.write('</svg:'+name+'>\n')

    def _color(self, color):
        r,g,b,a = color
        return '#%02x%02x%02x' % (r*255,g*255,b*255)

    def _dasharray(self):
        dasharray = ''
        for x in self.state.line_dash:
            if type(x) == type(arange(3)):  # why is this so hard?
                x = ravel(x)[0]
            dasharray += ' ' + '%3.2f' % x
        if not dasharray or dasharray == " 0.00 0.00":
            dasharray = 'none'
        return dasharray

    # noops which seem to be needed

    def device_update_line_state(self):
        pass

    def device_update_fill_state(self):
        pass

def font_metrics_provider():
    return GraphicsContext((1,1))

class Canvas:
    def __init__(self, filename='', id = -1, size = (200,200)):
        self.filename = filename
        self._size = size
        self.gc = SVGGC(size)

    def size(self):
        return self._size

    def save(self):
        self.gc.save(self.filename)

SVGGC = GraphicsContext # for b/w compatibility

class CanvasWindow: # required by core2d.py import, not sure why
    pass

if __name__ == "__main__":
    if len(sys.argv) == 1:
        print "Usage: %s output_file (where output_file ends in .html or .svg" % sys.argv[0]
        raise SystemExit

<commit_msg>removed logger which wasn't being used, but was also setup incorrectly and was echoing other logs<commit_after>#------------------------------------------------------------------------------
# Copyright (c) 2005, Enthought, Inc.
# All rights reserved.
#
# This software is provided without warranty under the terms of the BSD
# license included in enthought/LICENSE.txt and may be redistributed only
# under the conditions described in the aforementioned license.  The license
# is also available online at http://www.enthought.com/licenses/BSD.txt
# Thanks for using Enthought open source!
#------------------------------------------------------------------------------
""" Chaco's SVG backend

    :Copyright:   ActiveState
    :License:     BSD Style
    :Author:      David Ascher (davida@activestate.com)
    :Version:     $Revision: 1.5 $
"""

####
#
# Known limitations
#
# * BUG: Weird behavior with compound plots
# * Limitation: text widths are lousy if reportlab is not installed
# * Missing feature: rotated text

"""
Miscellaneous notes:

* the way to do links:
  <a xlink:href="http://www.w3.org">
    <ellipse cx="2.5" cy="1.5" rx="2" ry="1" fill="red" />
  </a>
"""

# Major library imports
import os
import sys
import cStringIO
from numpy import arange, ravel, pi

# Local, relative Kiva imports
import affine
import basecore2d
import constants
from constants import FILL, FILL_STROKE, EOF_FILL_STROKE, EOF_FILL, STROKE

def _strpoints(points):
    c = cStringIO.StringIO()
    for x,y in points:
        c.write('%3.2f,%3.2f ' % (x,y))
    return c.getvalue()

def _mkstyle(kw):
    return '"' + '; '.join([str(k) + ':' + str(v) for k,v in kw.items()]) +'"'

def default_filter(kw1):
    kw = {}
    for (k,v) in kw1.items():
        if type(v) == type(()):
            if v[0] != v[1]:
                kw[k] = v[0]
        else:
            kw[k] = v
    return kw

line_cap_map = {
    constants.CAP_ROUND: 'round',
    constants.CAP_SQUARE: 'square',
    constants.CAP_BUTT: 'butt'
    }

line_join_map = {
    constants.JOIN_ROUND: 'round',
    constants.JOIN_BEVEL: 'bevel',
    constants.JOIN_MITER: 'miter'
    }

font_map = {'Arial': 'Helvetica',
            }
import _fontdata

xmltemplate = """<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN"
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg xmlns="http://www.w3.org/2000/svg"
        xmlns:text="http://xmlns.graougraou.com/svg/text/"
        xmlns:a3="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
        a3:scriptImplementation="Adobe"
        width="100%%"
        height="100%%"
        viewBox="0 0 %(width)f %(height)f"
        >
<g transform="translate(0,%(height)f)">
<g transform="scale(1,-1)">
%(contents)s
</g>
</g>
</svg>
"""

htmltemplate = """<html xmlns:svg="http://www.w3.org/2000/svg">
<object id="AdobeSVG" CLASSID="clsid:78156a80-c6a1-4bbf-8e6a-3cd390eeb4e2">
</object>
<?import namespace="svg" implementation="#AdobeSVG"?>
<body>
<svg:svg width="100%%" height="100%%" viewBox="0 0 %(width)f %(height)f">
%(contents)s
</svg:svg>
</body>
</html>
"""

font_map = {'Arial': 'Helvetica',
            }
try:
    # expensive way of computing string widths
    import reportlab.pdfbase.pdfmetrics as pdfmetrics
    import reportlab.pdfbase._fontdata as _fontdata
    _reportlab_loaded = 1
except ImportError:
    import pdfmetrics
    import _fontdata
    _reportlab_loaded = 0

font_face_map = {'Arial': 'Helvetica'}

# This backend has no compiled path object, yet.
class CompiledPath(object):
    pass

_clip_counter = 0
class GraphicsContext(basecore2d.GraphicsContextBase):

    def __init__(self, size):
        basecore2d.GraphicsContextBase.__init__(self)
        self.size = size
        self._height = size[1]
        self.contents = cStringIO.StringIO()
        self._clipmap = {}
        self.clip_id = None

    def render(self, format):
        assert format == 'svg'
        height, width = self.size
        contents = self.contents.getvalue().replace("<svg:", "<").replace("</svg:", "</")
        return xmltemplate % locals()

    def clear(self, size):
        # TODO: clear the contents
        pass

    def width(self):
        return self.size[0]

    def height(self):
        return self.size[1]

    def save(self, filename):
        f = open(filename, 'w')
        ext = os.path.splitext(filename)[1]
        if ext == '.svg':
            template = xmltemplate
            height, width = self.size
            contents = self.contents.getvalue().replace("<svg:", "<").replace("</svg:", "</")
        elif ext == '.html':
            height, width = self.size[0]*3, self.size[1]*3
            contents = self.contents.getvalue()
            template = htmltemplate
        else:
            raise ValueError, "don't know how to write a %s file" % ext
        f.write(template % locals())

    # Text handling code

    def set_font(self, font):
        if font.face_name == '':
            font.face_name = 'Arial'
        self.face_name = font_face_map.get(font.face_name, font.face_name)
        self.font = pdfmetrics.Font(self.face_name, self.face_name, pdfmetrics.defaultEncoding)
        self.font_size = font.size

    def device_show_text(self, text):
        x,y = self.get_text_position()
        x,y = self._fixpoints([[x,y]])[0]
        ttm = self.get_text_matrix()
        ctm = self.get_ctm()  # not device_ctm!!
        m = affine.concat(ctm,ttm)
        tx,ty,sx,sy,angle = affine.trs_factor(m)
        angle = '%3.3f' % (-angle / pi * 180.)
        height = self.get_full_text_extent(text)[1]
        self.contents.write('<g transform="translate(%(x)f,%(y)f)">\n' % locals())
        self.contents.write('<g transform="scale(1,-1)">\n')
        self._emit('text', contents=text, transform='"rotate('+angle+')"', kw={'font-family':repr(self.font.fontName),
                                                        'font-size': '"'+ str(self.font_size) + '"'})
        self.contents.write('</g>\n')
        self.contents.write('</g>\n')
    def get_full_text_extent(self, text):
        ascent,descent=_fontdata.ascent_descent[self.face_name]
        descent = (-descent) * self.font_size / 1000.0
        ascent = ascent * self.font_size / 1000.0
        height = ascent + descent
        width = pdfmetrics.stringWidth(text, self.face_name, self.font_size)
        return width, height, descent, height*1.2 # assume leading of 1.2*height

    # actual implementation =)

    def device_fill_points(self, points, mode):
        points = self._fixpoints(points)
        if mode in (FILL, FILL_STROKE, EOF_FILL_STROKE):
            fill = self._color(self.state.fill_color)
        else:
            fill = 'none'
        if mode in (STROKE, FILL_STROKE, EOF_FILL_STROKE):
            stroke = self._color(self.state.line_color)
        else:
            stroke = 'none'
        if mode in (EOF_FILL_STROKE, EOF_FILL):
            rule = 'evenodd'
        else:
            rule = 'nonzero'
        linecap = line_cap_map[self.state.line_cap]
        linejoin = line_join_map[self.state.line_join]
        dasharray = self._dasharray()
        width = '%3.3f' % self.state.line_width
        if self.clip_id:
            clip = '"url(#' + self.clip_id +')"'
        else:
            clip = None
        if mode == STROKE:
            opacity = '%1.3f' % self.state.line_color[-1]
            self._emit('polyline',
                        points='"'+_strpoints(points)+'"',
                        kw=default_filter({'clip-path': (clip, None)}),
                        style=_mkstyle(default_filter({'opacity': (opacity, "1.000"),
                                        'stroke': stroke,
                                        'fill': 'none',
                                        'stroke-width': (width, "1.000"),
                                        'stroke-linejoin': (linejoin, 'miter'),
                                        'stroke-linecap': (linecap, 'butt'),
                                        'stroke-dasharray': (dasharray, 'none')})))

        else:
            opacity = '%1.3f' % self.state.fill_color[-1]
            self._emit('polygon',
                        points='"'+_strpoints(points)+'"',
                        kw=default_filter({'clip-path': (clip, None)}),
                        style=_mkstyle(default_filter({'opacity': (opacity, "1.000"),
                                        'stroke-width': (width, "1.000"),
                                        'fill': fill,
                                        'fill-rule': rule,
                                        'stroke': stroke,
                                        'stroke-linejoin': (linejoin, 'miter'),
                                        'stroke-linecap': (linecap, 'butt'),
                                        'stroke-dasharray': (dasharray, 'none')})))

    def device_stroke_points(self, points, mode):
        # handled by device_fill_points
        pass

    def _build(self, elname, **kw):
        x = '<' + elname + ' '
        for k,v in kw.items():
            if type(v) == type(0.0):
                v = '"%3.3f"' % v
            elif type(v) == type(0):
                v = '"%d"' % v
            else:
                v = '"%s"' % str(v)
            x += k + '=' + v + ' '
        x += '/>\n'
        return x

    def device_set_clipping_path(self, x, y, width, height):
        ##x,y,width,height = map(lambda x: '"' + str(x) + '"', [x,y,width,height])
        ##self._emit('rect', x=x, y=y, width=width, height=height,
        ##                style=_mkstyle({'stroke-width': 5,
        ##                                'fill':'none',
        ##                                'stroke': 'green'}))
        ##
        ##return
        global _clip_counter
        self.clip_id = 'clip_%d' % _clip_counter
        _clip_counter += 1
        x,y = self._fixpoints([[x,y]])[0]
        rect = self._build('rect', x=x, y=y, width=width, height=height)
        self._emit('clipPath', contents=rect, id='"'+self.clip_id + '"')

    def device_destroy_clipping_path(self):
        self.clip_id = None

    # utility routines

    def _fixpoints(self, points):
        return points
        # convert lines from Kiva coordinate space to PIL coordinate space
        # XXX I suspect this is the location of the bug w.r.t. compound graphs and
        # "global" sizing.
        # XXX this should be made more efficient for NumPy arrays
        np = []
        for (x,y) in points:
            np.append((x,self._height-y))
        return np

    def _emit(self, name, contents=None, kw={}, **otherkw):
        self.contents.write('<svg:%(name)s ' % locals())
        for k, v in kw.items():
            self.contents.write("%(k)s=%(v)s " % locals())
        for k, v in otherkw.items():
            self.contents.write("%(k)s=%(v)s " % locals())
        if contents is None:
            self.contents.write('/>\n')
        else:
            self.contents.write('>\n')
            self.contents.write(contents)
            self.contents.write('</svg:'+name+'>\n')

    def _color(self, color):
        r,g,b,a = color
        return '#%02x%02x%02x' % (r*255,g*255,b*255)

    def _dasharray(self):
        dasharray = ''
        for x in self.state.line_dash:
            if type(x) == type(arange(3)):  # why is this so hard?
                x = ravel(x)[0]
            dasharray += ' ' + '%3.2f' % x
        if not dasharray or dasharray == " 0.00 0.00":
            dasharray = 'none'
        return dasharray

    # noops which seem to be needed

    def device_update_line_state(self):
        pass

    def device_update_fill_state(self):
        pass

def font_metrics_provider():
    return GraphicsContext((1,1))

class Canvas:
    def __init__(self, filename='', id = -1, size = (200,200)):
        self.filename = filename
        self._size = size
        self.gc = SVGGC(size)

    def size(self):
        return self._size

    def save(self):
        self.gc.save(self.filename)

SVGGC = GraphicsContext # for b/w compatibility

class CanvasWindow: # required by core2d.py import, not sure why
    pass

if __name__ == "__main__":
    if len(sys.argv) == 1:
        print "Usage: %s output_file (where output_file ends in .html or .svg" % sys.argv[0]
        raise SystemExit

<|endoftext|>