<commit_before>import socket
import re

class Bot(object):

    hooks = []

    def __setup(self, config):

        self.socket = socket.socket()

        self.socket.connect((config['server'], config['port']))
        self.__send('NICK %s\r\n' % config['nick'])
        self.__send('USER %(n)s %(n)s %(n)s :%(n)s\r\n' % {'n':config['nick']})
        self.__join(config['channel'])

    def __send(self, message):

        self.socket.send(message)

    def __join(self, channel):

        self.__send('JOIN #%s\r\n' % channel)

    def __speak(self, target, message):

        self.__send("PRIVMSG %s :%s\r\n" % (target, message))

    def on(self, rule):

        def decorator(function):

            self.hooks.append({
                'rule': re.compile(rule),
                'function': function
            })

            return function

        return decorator

    def monitor(self, **kwargs):

        config = {
            'port': 6667,
            'server': 'chat.freenode.com',
        }

        config['nick'] = kwargs['nick']
        config['channel'] = kwargs['channel']

        for key in ['port', 'server']:

            if key in kwargs.keys():

                config[key] = kwargs[key]

        self.__setup(config)

        while True:

            content = self.socket.recv(4096)

            if content[0:4] == "PING":

                self.__send('PONG %s \r\n' % content.split()[1])
                continue

            for line in content.split('\n'):

                line = str(line).strip()

                parsed = line.split(None, 3)

                if len(parsed) != 4:

                    continue

                context = {
                    'sender': parsed[0][1:],
                    'type': parsed[1],
                    'target': parsed[2],
                    'message': parsed[3][1:]
                }

                if context['target'] == config['nick']:

                    context['target'] = context['sender'].split('!')[0]

                for hook in self.hooks:

                    match = hook['rule'].match(context['message'])

                    if match:

                        response = hook['function'](context, match.groups())
                        self.__speak(context['target'], response)
<commit_msg>Added support for SSL<commit_after>import socket
import re
import ssl

class Bot(object):

    hooks = []

    def __setup(self, config):

        self.socket = socket.socket()

        if config['port'] in [6697, 7000, 7070]:

            self.socket = ssl.wrap_socket(self.socket)

        self.socket.connect((config['server'], config['port']))
        self.__send('NICK %s\r\n' % config['nick'])
        self.__send('USER %(n)s %(n)s %(n)s :%(n)s\r\n' % {'n':config['nick']})
        self.__join(config['channel'])

    def __send(self, message):

        self.socket.send(message)

    def __join(self, channel):

        self.__send('JOIN #%s\r\n' % channel)

    def __speak(self, target, message):

        self.__send("PRIVMSG %s :%s\r\n" % (target, message))

    def on(self, rule):

        def decorator(function):

            self.hooks.append({
                'rule': re.compile(rule),
                'function': function
            })

            return function

        return decorator

    def monitor(self, **kwargs):

        config = {
            'port': 6667,
            'server': 'chat.freenode.com',
        }

        config['nick'] = kwargs['nick']
        config['channel'] = kwargs['channel']

        for key in ['port', 'server']:

            if key in kwargs.keys():

                config[key] = kwargs[key]

        self.__setup(config)

        while True:

            content = self.socket.recv(4096)

            if content[0:4] == "PING":

                self.__send('PONG %s \r\n' % content.split()[1])
                continue

            for line in content.split('\n'):

                line = str(line).strip()

                parsed = line.split(None, 3)

                if len(parsed) != 4:

                    continue

                context = {
                    'sender': parsed[0][1:],
                    'type': parsed[1],
                    'target': parsed[2],
                    'message': parsed[3][1:]
                }

                if context['target'] == config['nick']:

                    context['target'] = context['sender'].split('!')[0]

                for hook in self.hooks:

                    match = hook['rule'].match(context['message'])

                    if match:

                        response = hook['function'](context, match.groups())
                        self.__speak(context['target'], response)
<|endoftext|>


<commit_before>"""
Decorator for views that supports conditional get on ETag and Last-Modified
headers.
"""

from django.utils.decorators import decorator_from_middleware
from django.middleware.http import ConditionalGetMiddleware

conditional_page = decorator_from_middleware(ConditionalGetMiddleware)
<commit_msg>Fixed #703: added decorators to require that view be called with a given HTTP REQUEST_METHOD<commit_after>"""
Decorators for views based on HTTP headers.
"""

from django.utils.decorators import decorator_from_middleware
from django.middleware.http import ConditionalGetMiddleware
from django.utils.httpwrappers import HttpResponseForbidden

conditional_page = decorator_from_middleware(ConditionalGetMiddleware)

def require_http_methods(request_method_list):
    """
    Decorator to make a view only accept particular request methods.  Usage::

        @require_http_methods(["GET", "POST"])
        def my_view(request):
            # I can assume now that only GET or POST requests make it this far
            # ...

    Note that request methods ARE case sensitive.
    """
    def decorator(func):
        def inner(request, *args, **kwargs):
            method = request.META.get("REQUEST_METHOD", None)
            if method not in request_method_list:
                raise HttpResponseForbidden("REQUEST_METHOD '%s' not allowed" % method)
            return func(request, *args, **kwargs)
        return inner
    return decorator

require_GET = require_http_methods(["GET"])
require_GET.__doc__ = "Decorator to require that a view only accept the GET method."

require_POST = require_http_methods(["POST"])
require_POST.__doc__ = "Decorator to require that a view only accept the POST method."<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from django.db import models
from django.db.models import Q
from django.db.models import permalink
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.template.defaultfilters import slugify

from tagging.models import Tag, TaggedItem
from tagging.fields import TagField

from django_de.apps.ticker import textutils

class EntryManager(models.Manager):
    def public(self):
        return self.filter(status=Entry.STATUS_OPEN)

class Entry(models.Model):

    STATUS_CLOSED = 1
    STATUS_DRAFT = 2
    STATUS_OPEN = 3

    STATUS_CHOICES = (
        (STATUS_CLOSED, 'Geschlossen'),
        (STATUS_DRAFT, 'Frei zum Veröffentlichen'),
        (STATUS_OPEN, 'Veröffentlicht'),
    )
    objects = EntryManager()

    # Title and Slug
    title = models.CharField('Titel', max_length=255)
    slug = models.SlugField('Slug', blank=True)

    content = models.TextField('Inhalt')
    content_processed = models.TextField('Inhalt (geparsed)', blank=True)
    source_url = models.URLField('Quelle', blank=True)

    # Date Fields
    published = models.DateTimeField(_('Published'), auto_now_add=True)
    modified = models.DateTimeField(_('Modified'), auto_now=True)

    # Status Fields
    status = models.SmallIntegerField(_('Status'),
        choices=STATUS_CHOICES,
        default=STATUS_OPEN)

    # Related
    tags = TagField()
    author = models.ForeignKey(User)

    enable_comments = models.BooleanField(default=True)

    class Meta:
        ordering = ('-published',)
        permissions = (
            ('can_change_foreign', 'Can change foreign entry'),
            ('can_publish', 'Publish instantly'),
        )

    def get_author(self):
        return self.author.username

    def get_tags(self):
        return Tag.objects.get_for_object(self)

    def get_related(self):
        return TaggedItem.objects.get_related(self, Entry.objects.public())

    def get_related_tags(self):
        return Tag.objects.related_for_model(self.tags, Entry)

    def get_next(self):
        return self.get_next_by_published(status=self.STATUS_OPEN)

    def get_prev(self):
        return self.get_previous_by_published(status=self.STATUS_OPEN)

    def __unicode__(self):
        return self.title

    def save(self):
        self.slug = slugify(self.title)
        self.content_processed = textutils.textfilter(self.content)
        super(Entry, self).save()

    @permalink
    def get_absolute_url(self):
        return ('ticker_details', (), {
            'id': str(self.id),
            'slug': self.slug,
        })

<commit_msg>yeaaah<commit_after># -*- coding: utf-8 -*-
from django.db import models
from django.db.models import Q
from django.db.models import permalink
from django.contrib.auth.models import User
from django.utils.translation import ugettext as _
from django.template.defaultfilters import slugify

from tagging.models import Tag, TaggedItem
from tagging.fields import TagField

from django_de.apps.ticker import textutils

class EntryManager(models.Manager):
    def public(self):
        return self.filter(status=Entry.STATUS_OPEN)

class Entry(models.Model):

    STATUS_CLOSED = 1
    STATUS_DRAFT = 2
    STATUS_OPEN = 3

    STATUS_CHOICES = (
        (STATUS_CLOSED, 'Geschlossen'),
        (STATUS_DRAFT, 'Frei zum Veröffentlichen'),
        (STATUS_OPEN, 'Veröffentlicht'),
    )
    objects = EntryManager()

    # Title and Slug
    title = models.CharField('Titel', max_length=255)
    slug = models.SlugField('Slug', blank=True)

    content = models.TextField('Inhalt')
    content_processed = models.TextField('Inhalt (geparsed)', blank=True)
    source_url = models.URLField('Quelle', blank=True)

    # Date Fields
    published = models.DateTimeField('Published', auto_now_add=True)
    modified = models.DateTimeField('Modified', auto_now=True)

    # Status Fields
    status = models.SmallIntegerField('Status',
        choices=STATUS_CHOICES,
        default=STATUS_OPEN)

    # Related
    tags = TagField()
    author = models.ForeignKey(User)

    enable_comments = models.BooleanField(default=True)

    class Meta:
        ordering = ('-published',)
        permissions = (
            ('can_change_foreign', 'Can change foreign entry'),
            ('can_publish', 'Publish instantly'),
        )

    def get_author(self):
        return self.author.username

    def get_tags(self):
        return Tag.objects.get_for_object(self)

    def get_related(self):
        return TaggedItem.objects.get_related(self, Entry.objects.public())

    def get_related_tags(self):
        return Tag.objects.related_for_model(self.tags, Entry)

    def get_next(self):
        return self.get_next_by_published(status=self.STATUS_OPEN)

    def get_prev(self):
        return self.get_previous_by_published(status=self.STATUS_OPEN)

    def __unicode__(self):
        return self.title

    def save(self):
        self.slug = slugify(self.title)
        self.content_processed = textutils.textfilter(self.content)
        super(Entry, self).save()

    @permalink
    def get_absolute_url(self):
        return ('ticker_details', (), {
            'id': str(self.id),
            'slug': self.slug,
        })

<|endoftext|>


<commit_before>from django import template
from django.utils.safestring import mark_safe
from django.utils.html import escape
from django.utils.text import capfirst

from django_easyfilters.filters import FILTER_ADD, FILTER_REMOVE, FILTER_ONLY_CHOICE, \
    ValuesFilter, ChoicesFilter, ForeignKeyFilter, ManyToManyFilter

def non_breaking_spaces(val):
    # This helps a lot with presentation, by stopping the links+count from being
    # split over a line end.
    return mark_safe(u' '.join(escape(part) for part in val.split(u' ')))

class FilterSet(object):

    template = """

{{ filterlabel }}:
{% for choice in remove_choices %}
  {{ choice.label }} [«]
{% endfor %}
{% if add_choices and remove_choices or only_choices and remove_choices %} | {% endif %}
{% for choice in add_choices %}
  {{ choice.label }} ({{ choice.count }})
{% endfor %}
{% for choice in only_choices %}
  {{ choice.label }}
{% endfor %}

"""

    def __init__(self, queryset, params):
        self.params = params
        self.initial_queryset = queryset
        self.model = queryset.model
        self.filters = self.setup_filters()
        self.qs = self.apply_filters(queryset, params)

    def apply_filters(self, queryset, params):
        for f in self.filters:
            queryset = f.apply_filter(queryset, params)
        return queryset

    def render_filter(self, filter_, qs, params):
        field_obj = self.model._meta.get_field(filter_.field)
        choices = filter_.get_choices(qs, params)
        ctx = {'filterlabel': capfirst(field_obj.verbose_name)}
        ctx['remove_choices'] = [dict(label=non_breaking_spaces(c.label),
                                      url=u'?' + c.params.urlencode())
                                 for c in choices if c.link_type == FILTER_REMOVE]
        ctx['add_choices'] = [dict(label=non_breaking_spaces(c.label),
                                   url=u'?' + c.params.urlencode(),
                                   count=c.count)
                              for c in choices if c.link_type == FILTER_ADD]
        ctx['only_choices'] = [dict(label=non_breaking_spaces(c.label),
                                    count=c.count)
                               for c in choices if c.link_type == FILTER_ONLY_CHOICE]

        return self.get_template().render(template.Context(ctx))

    def get_template(self):
        return template.Template(self.template)

    def render(self):
        return mark_safe(u'\n'.join(self.render_filter(f, self.qs, self.params) for f in self.filters))

    def get_fields(self):
        return self.fields

    def get_filter_for_field(self, field, **kwargs):
        f, model, direct, m2m = self.model._meta.get_field_by_name(field)
        if f.rel is not None:
            if m2m:
                klass = ManyToManyFilter
            else:
                klass = ForeignKeyFilter
        elif f.choices:
            klass = ChoicesFilter
        else:
            klass = ValuesFilter
        return klass(field, self.model, **kwargs)

    def setup_filters(self):
        filters = []
        for i, f in enumerate(self.get_fields()):
            if isinstance(f, basestring):
                f = self.get_filter_for_field(f)
            else:
                # (field name, FilterOptions)
                field = f[0]
                opts = f[1].__dict__.copy()
                f = self.get_filter_for_field(field, **opts)
            filters.append(f)
        return filters

    def __unicode__(self):
        return self.render()
<commit_msg>Tweaked filterset HTML<commit_after>from django import template
from django.utils.safestring import mark_safe
from django.utils.html import escape
from django.utils.text import capfirst

from django_easyfilters.filters import FILTER_ADD, FILTER_REMOVE, FILTER_ONLY_CHOICE, \
    ValuesFilter, ChoicesFilter, ForeignKeyFilter, ManyToManyFilter

def non_breaking_spaces(val):
    # This helps a lot with presentation, by stopping the links+count from being
    # split over a line end.
    return mark_safe(u' '.join(escape(part) for part in val.split(u' ')))

class FilterSet(object):

    template = """

{{ filterlabel }}:
{% for choice in remove_choices %}
  {{ choice.label }} «
{% endfor %}
{% for choice in add_choices %}
  {{ choice.label }} ({{ choice.count }})
{% endfor %}
{% for choice in only_choices %}
  {{ choice.label }}
{% endfor %}

"""

    def __init__(self, queryset, params):
        self.params = params
        self.initial_queryset = queryset
        self.model = queryset.model
        self.filters = self.setup_filters()
        self.qs = self.apply_filters(queryset, params)

    def apply_filters(self, queryset, params):
        for f in self.filters:
            queryset = f.apply_filter(queryset, params)
        return queryset

    def render_filter(self, filter_, qs, params):
        field_obj = self.model._meta.get_field(filter_.field)
        choices = filter_.get_choices(qs, params)
        ctx = {'filterlabel': capfirst(field_obj.verbose_name)}
        ctx['remove_choices'] = [dict(label=non_breaking_spaces(c.label),
                                      url=u'?' + c.params.urlencode())
                                 for c in choices if c.link_type == FILTER_REMOVE]
        ctx['add_choices'] = [dict(label=non_breaking_spaces(c.label),
                                   url=u'?' + c.params.urlencode(),
                                   count=c.count)
                              for c in choices if c.link_type == FILTER_ADD]
        ctx['only_choices'] = [dict(label=non_breaking_spaces(c.label),
                                    count=c.count)
                               for c in choices if c.link_type == FILTER_ONLY_CHOICE]

        return self.get_template().render(template.Context(ctx))

    def get_template(self):
        return template.Template(self.template)

    def render(self):
        return mark_safe(u'\n'.join(self.render_filter(f, self.qs, self.params) for f in self.filters))

    def get_fields(self):
        return self.fields

    def get_filter_for_field(self, field, **kwargs):
        f, model, direct, m2m = self.model._meta.get_field_by_name(field)
        if f.rel is not None:
            if m2m:
                klass = ManyToManyFilter
            else:
                klass = ForeignKeyFilter
        elif f.choices:
            klass = ChoicesFilter
        else:
            klass = ValuesFilter
        return klass(field, self.model, **kwargs)

    def setup_filters(self):
        filters = []
        for i, f in enumerate(self.get_fields()):
            if isinstance(f, basestring):
                f = self.get_filter_for_field(f)
            else:
                # (field name, FilterOptions)
                field = f[0]
                opts = f[1].__dict__.copy()
                f = self.get_filter_for_field(field, **opts)
            filters.append(f)
        return filters

    def __unicode__(self):
        return self.render()
<|endoftext|>


<commit_before>"""
.. image:: images/thread.png
   :align: right
   :target: http://dev.thread.com/

===================
django-force-logout
===================

-----------------------------------------------------------------
Framework to be able to forcibly log users out of Django projects
-----------------------------------------------------------------

This project provides the ability to log specific users out of your
`Django <http://www.djangoproject.com/>`_ project.

Whilst you can easily log all users out by clearing your session table or
similar blunt technique, due to the difficulty in enumerating specific user's
actual session entries from a user ID, logging-out troublemakers etc. is not
really feasible "out of the box".

You can iterate over all possible sessions and match them against a user, but
with a heavy-traffic site with long-lasting sessions this can be prohibitively
expensive.

Installation
------------

#. Add ``django_force_logout.middleware.ForceLogoutMiddleware`` to
   ``MIDDLEWARE_CLASSES``.

#. Configure ``FORCE_LOGOUT_CALLBACK`` in your settings to point to a method which,
   given a ``User`` instance, will return a nullable timestamp for that user.
   This would typically be stored on custom ``User``, profile or some other
   field depending on your setup.

   For example::

       def force_logout_callback(user):
           return user.some_profile_model.force_logout

       FORCE_LOGOUT_CALLBACK = 'path.to.force_logout_callback'

   Alternatively, you can just specify a lambda directly::

       FORCE_LOGOUT_CALLBACK = lambda x: x.some_profile_model.force_logout

.. important::

   This callback is executed on every request by a logged-in user. Therefore,
   it is advisable that you have some sort of caching preventing additional
   database queries. Remember to ensure that you clear the cached value when
   wish to log a user out, otherwise you will have to wait for the cache entry
   to expire before the user will actually be logged out.

You are not restricted to returning a field from a SQL database (`Redis
<http://redis.io/>`_ may suit your needs better and avoid the caching
requirement), but you must return a nullable timestamp.

Usage
-----

To forcibly log that user out, simply set your timestamp field to the current
time. For example::

   user.some_profile_model.force_logout = datetime.datetime.utcnow()
   user.some_profile_model.save()

That's it. The middleware will then log this user out on their next request.

Configuration
-------------

``FORCE_LOGOUT_CALLBACK``
~~~~~~~~~~~~~~~~~~~~~~~~~

A method which, when passed a User instance, will return a nullable timestamp for
that user. See **Installation** for more details.

Thanks
------

This project was inspired by a code snippet by
`Clement Nodet <http://clementnodet.com/>_`.

Links
-----

Homepage/documentation:
  https://django-force-logout.readthedocs.org/

View/download code
  https://github.com/thread/django-force-logout

File a bug
  https://github.com/thread/django-force-logout/issues

----

.. figure:: images/thread.png
   :align: center
   :target: http://dev.thread.com/

   `See more open source projects from Thread.com <http://dev.thread.com/>`_
"""
<commit_msg>Update URLs.<commit_after>"""
===================
django-force-logout
===================

-----------------------------------------------------------------
Framework to be able to forcibly log users out of Django projects
-----------------------------------------------------------------

This project provides the ability to log specific users out of your
`Django <http://www.djangoproject.com/>`_ project.

Whilst you can easily log all users out by clearing your session table or
similar blunt technique, due to the difficulty in enumerating specific user's
actual session entries from a user ID, logging-out troublemakers etc. is not
really feasible "out of the box".

You can iterate over all possible sessions and match them against a user, but
with a heavy-traffic site with long-lasting sessions this can be prohibitively
expensive.

Installation
------------

#. Add ``django_force_logout.middleware.ForceLogoutMiddleware`` to
   ``MIDDLEWARE_CLASSES``.

#. Configure ``FORCE_LOGOUT_CALLBACK`` in your settings to point to a method which,
   given a ``User`` instance, will return a nullable timestamp for that user.
   This would typically be stored on custom ``User``, profile or some other
   field depending on your setup.

   For example::

       def force_logout_callback(user):
           return user.some_profile_model.force_logout

       FORCE_LOGOUT_CALLBACK = 'path.to.force_logout_callback'

   Alternatively, you can just specify a lambda directly::

       FORCE_LOGOUT_CALLBACK = lambda x: x.some_profile_model.force_logout

.. important::

   This callback is executed on every request by a logged-in user. Therefore,
   it is advisable that you have some sort of caching preventing additional
   database queries. Remember to ensure that you clear the cached value when
   wish to log a user out, otherwise you will have to wait for the cache entry
   to expire before the user will actually be logged out.

You are not restricted to returning a field from a SQL database (`Redis
<http://redis.io/>`_ may suit your needs better and avoid the caching
requirement), but you must return a nullable timestamp.

Usage
-----

To forcibly log that user out, simply set your timestamp field to the current
time. For example::

   user.some_profile_model.force_logout = datetime.datetime.utcnow()
   user.some_profile_model.save()

That's it. The middleware will then log this user out on their next request.

Configuration
-------------

``FORCE_LOGOUT_CALLBACK``
~~~~~~~~~~~~~~~~~~~~~~~~~

A method which, when passed a User instance, will return a nullable timestamp for
that user. See **Installation** for more details.

Thanks
------

This project was inspired by a code snippet by
`Clement Nodet <http://clementnodet.com/>_`.

Links
-----

Homepage/documentation:
  https://django-force-logout.readthedocs.org/

View/download code
  https://github.com/lamby/django-force-logout

File a bug
  https://github.com/lamby/django-force-logout/issues
"""
<|endoftext|>


<commit_before>import courseware.content_parser as content_parser
import courseware.modules
import logging
import random
import urllib

from collections import namedtuple
from django.conf import settings
from lxml import etree
from models import StudentModule
from student.models import UserProfile

log = logging.getLogger("mitx.courseware")

Score = namedtuple("Score", "earned possible graded section")
SectionPercentage = namedtuple("SectionPercentage", "percentage label summary")

def get_grade(user, problem, cache):
    ## HACK: assumes max score is fixed per problem
    id = problem.get('id')
    correct = 0

    # If the ID is not in the cache, add the item
    if id not in cache:
        module = StudentModule(module_type = 'problem',  # TODO: Move into StudentModule.__init__?
                               module_id = id,
                               student = user,
                               state = None,
                               grade = 0,
                               max_grade = None,
                               done = 'i')
        cache[id] = module

    # Grab the # correct from cache
    if id in cache:
        response = cache[id]
        if response.grade!=None:
            correct=response.grade

    # Grab max grade from cache, or if it doesn't exist, compute and save to DB
    if id in cache and response.max_grade != None:
        total = response.max_grade
    else:
        total=courseware.modules.capa_module.Module(etree.tostring(problem), "id").max_score()
        response.max_grade = total
        response.save()

    return (correct, total)

def grade_sheet(student):
    """
    This pulls a summary of all problems in the course. It returns a dictionary with two datastructures:

    - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters,
    each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded
    problems, and is good for displaying a course summary with due dates, etc.

    - grade_summary is a summary of how the final grade breaks down. It is an array of "sections". Each section can either be
    a conglomerate of scores (like labs or homeworks) which has subscores and a totalscore, or a section can be all from one assignment
    (such as a midterm or final) and only has a totalscore. Each section has a weight that shows how it contributes to the total grade.
    """
    dom=content_parser.course_file(student)
    course = dom.xpath('//course/@name')[0]
    xmlChapters = dom.xpath('//course[@name=$course]/chapter', course=course)

    responses=StudentModule.objects.filter(student=student)
    response_by_id = {}
    for response in responses:
        response_by_id[response.module_id] = response

    totaled_scores = {}
    chapters=[]
    for c in xmlChapters:
        sections = []
        chname=c.get('name')

        for s in dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section',
                           course=course, chname=chname):
            problems=dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section[@name=$section]//problem',
                           course=course, chname=chname, section=s.get('name'))

            graded = True if s.get('graded') == "true" else False
            scores=[]
            if len(problems)>0:
                for p in problems:
                    (correct,total) = get_grade(student, p, response_by_id)
                    # id = p.get('id')
                    # correct = 0
                    # if id in response_by_id:
                    #     response = response_by_id[id]
                    #     if response.grade!=None:
                    #         correct=response.grade

                    # total=courseware.modules.capa_module.Module(etree.tostring(p), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores?
                    # print correct, total
                    if settings.GENERATE_PROFILE_SCORES:
                        if total > 1:
                            correct = random.randrange( max(total-2, 1) , total + 1 )
                        else:
                            correct = total

                    scores.append( Score(int(correct),total, graded, s.get("name")) )

                section_total = Score(sum([score.earned for score in scores]),
                                        sum([score.possible for score in scores]),
                                        False,
                                        s.get("name"))

                graded_total = Score(sum([score.earned for score in scores if score.graded]),
                                sum([score.possible for score in scores if score.graded]),
                                True,
                                s.get("name"))

                #Add the graded total to totaled_scores
                format = s.get('format') if s.get('format') else ""
                subtitle = s.get('subtitle') if s.get('subtitle') else format
                if format and graded_total[1] > 0:
                    format_scores = totaled_scores.get(format, [])
                    format_scores.append( graded_total )
                    totaled_scores[ format ] = format_scores

                score={'section':s.get("name"),
                       'scores':scores,
                       'section_total' : section_total,
                       'format' : format,
                       'subtitle' : subtitle,
                       'due' : s.get("due") or "",
                       'graded' : graded,
                       }
                sections.append(score)

        chapters.append({'course':course,
                         'chapter' : c.get("name"),
                         'sections' : sections,})

    grade_summary = grade_summary_6002x(totaled_scores)

    return {'courseware_summary' : chapters,
            'grade_summary' : grade_summary}

def grade_summary_6002x(totaled_scores):
    """
    This function takes the a dictionary of (graded) section scores, and applies the course grading rules to create
    the grade_summary. For 6.002x this means homeworks and labs all have equal weight, with the lowest 2 of each
    being dropped. There is one midterm and one final.
    """

    def totalWithDrops(scores, drop_count):
        #Note that this key will sort the list descending
        sorted_scores = sorted( enumerate(scores), key=lambda x: -x[1].percentage )
        # A list of the indices of the dropped scores
        dropped_indices = [score[0] for score in sorted_scores[-drop_count:]]
        aggregate_score = 0
        for index, score in enumerate(scores):
            if index not in dropped_indices:
                aggregate_score += score.percentage

        aggregate_score /= len(scores) - drop_count

        return aggregate_score, dropped_indices

    #Figure the homework scores
    homework_scores = totaled_scores['Homework'] if 'Homework' in totaled_scores else []
    homework_percentages = []
    for i in range(12):
        if i < len(homework_scores):
            percentage = homework_scores[i].earned / float(homework_scores[i].possible)
            summary = "Homework {0} - {1} - {2:.0%} ({3:g}/{4:g})".format( i + 1, homework_scores[i].section , percentage, homework_scores[i].earned, homework_scores[i].possible )
        else:
            percentage = 0
            summary = "Unreleased Homework {0} - 0% (?/?)".format(i + 1)

            if settings.GENERATE_PROFILE_SCORES:
                points_possible = random.randrange(10, 50)
                points_earned = random.randrange(5, points_possible)
                percentage = points_earned / float(points_possible)
                summary = "Random Homework - {0:.0%} ({1:g}/{2:g})".format( percentage, points_earned, points_possible )

        label = "HW {0:02d}".format(i + 1)

        homework_percentages.append(SectionPercentage(percentage, label, summary) )
    homework_total, homework_dropped_indices = totalWithDrops(homework_percentages, 2)

    #Figure the lab scores
    lab_scores = totaled_scores['Lab'] if 'Lab' in totaled_scores else []
    lab_percentages = []
    for i in range(12):
        if i < len(lab_scores):
            percentage = lab_scores[i].earned / float(lab_scores[i].possible)
            summary = "Lab {0} - {1} - {2:.0%} ({3:g}/{4:g})".format( i + 1, lab_scores[i].section , percentage, lab_scores[i].earned, lab_scores[i].possible )
        else:
            percentage = 0
            summary = "Unreleased Lab {0} - 0% (?/?)".format(i + 1)

            if settings.GENERATE_PROFILE_SCORES:
                points_possible = random.randrange(10, 50)
                points_earned = random.randrange(5, points_possible)
                percentage = points_earned / float(points_possible)
                summary = "Random Lab - {0:.0%} ({1:g}/{2:g})".format( percentage, points_earned, points_possible )

        label = "Lab {0:02d}".format(i + 1)

        lab_percentages.append(SectionPercentage(percentage, label, summary) )
    lab_total, lab_dropped_indices = totalWithDrops(lab_percentages, 2)

    #TODO: Pull this data about the midterm and final from the databse. It should be exactly similar to above, but we aren't sure how exams will be done yet.
    midterm_score = Score('?', '?', True, "?")
    midterm_percentage = 0

    final_score = Score('?', '?', True, "?")
    final_percentage = 0

    if settings.GENERATE_PROFILE_SCORES:
        midterm_score = Score(random.randrange(50, 150), 150, True, "?")
        midterm_percentage = midterm_score.earned / float(midterm_score.possible)

        final_score = Score(random.randrange(100, 300), 300, True, "?")
        final_percentage = final_score.earned / float(final_score.possible)

    grade_summary = [
        {
            'category': 'Homework',
            'subscores' : homework_percentages,
            'dropped_indices' : homework_dropped_indices,
            'totalscore' : homework_total,
            'totalscore_summary' : "Homework Average - {0:.0%}".format(homework_total),
            'totallabel' : 'HW Avg',
            'weight' : 0.15,
        },
        {
            'category': 'Labs',
            'subscores' : lab_percentages,
            'dropped_indices' : lab_dropped_indices,
            'totalscore' : lab_total,
            'totalscore_summary' : "Lab Average - {0:.0%}".format(lab_total),
            'totallabel' : 'Lab Avg',
            'weight' : 0.15,
        },
        {
            'category': 'Midterm',
            'totalscore' : midterm_percentage,
            'totalscore_summary' : "Midterm - {0:.0%} ({1}/{2})".format(midterm_percentage, midterm_score.earned, midterm_score.possible),
            'totallabel' : 'Midterm',
            'weight' : 0.30,
        },
        {
            'category': 'Final',
            'totalscore' : final_percentage,
            'totalscore_summary' : "Final - {0:.0%} ({1}/{2})".format(final_percentage, final_score.earned, final_score.possible),
            'totallabel' : 'Final',
            'weight' : 0.40,
        }
    ]

    return grade_summary
<commit_msg>Refactoring grades. Adding more generic grading classes. Probably broken right now. Just committing to save progress.<commit_after>import courseware.content_parser as content_parser
import courseware.modules
import logging
import random
import urllib

from collections import namedtuple
from django.conf import settings
from lxml import etree
from models import StudentModule
from student.models import UserProfile

log = logging.getLogger("mitx.courseware")

Score = namedtuple("Score", "earned possible graded section")
SectionPercentage = namedtuple("SectionPercentage", "percentage label summary")

class CourseGrader:
    def grade(self, grade_sheet):
        raise NotImplementedError

class FormatWithDropsGrader(CourseGrader):
    """
    Grades all sections specified in course_format with an equal weight. A specified
    number of lowest scores can be dropped from the calculation. The minimum number of
    sections in this format must be specified (even if those sections haven't been
    written yet).

    section_detail_formatter is a format string with the parameters (index, name, percent, earned, possible).
    ex: "Homework {index} - {name} - {percent:.0%} ({earned:g}/{possible:g})"

    section_missing_detail_formatter is a format string with the parameters (index) for
    when the minimum number of sections weren't found in the course.
    ex: "Unreleased Homework {index} - 0% (?/?)"

    section_label_formatter is a format string for a short label with the parameters (index).
    These look best when fixed-length.
    ex: "HW {index:02d}"

    total_detail_formatter is a format string for displaying the average score with the
    parameters (percent).
    ex: "Homework Average = {percent:.0%}"

    total_label_formatter is a string (with no parameters).
    ex: "HW Avg"

    """
    def __init__(self, course_format, min_number, drop_count, category, section_detail_formatter, section_missing_detail_formatter,
                        section_label_formatter, total_detail_formatter, total_label_formatter):

        self.course_format = course_format
        self.min_number = min_number
        self.drop_count = drop_count
        self.category = category
        self.section_detail_formatter = section_detail_formatter
        self.section_missing_detail_formatter = section_missing_detail_formatter
        self.section_label_formatter = section_label_formatter
        self.total_detail_formatter = total_detail_formatter
        self.total_label_formatter = total_label_formatter

    def grade(self, grade_sheet):
        def totalWithDrops(breakdown, drop_count):
            #create an array of tuples with (index, mark), sorted by mark['percentage'] descending
            sorted_breakdown = sorted( enumerate(breakdown), key=lambda x: -x[1]['percentage'] )
            # A list of the indices of the dropped scores
            dropped_indices = [x[0] for x in sorted_breakdown[-drop_count:]]
            aggregate_score = 0
            for index, mark in enumerate(breakdown):
                if index not in dropped_indices:
                    aggregate_score += mark['percentage']

            aggregate_score /= len(scores) - drop_count

            return aggregate_score, dropped_indices

        #Figure the homework scores
        scores = grade_sheet.get(self.course_format, [])
        breakdown = []
        for i in range(12):
            if i < len(scores):
                percentage = scores[i].earned / float(scores[i].possible)
                summary = self.section_detail_formatter.format(index: i+1,
                                                                name: scores[i].section,
                                                                percentage: percentage,
                                                                earned: scores[i].earned,
                                                                possible: scores[i].possible )
            else:
                percentage = 0
                summary = self.section_missing_detail_formatter.format(index: i+1)

                if settings.GENERATE_PROFILE_SCORES:
                    points_possible = random.randrange(10, 50)
                    points_earned = random.randrange(5, points_possible)
                    percentage = points_earned / float(points_possible)
                    summary = self.section_detail_formatter.format(index: i+1,
                                                                    name: "Randomly Generated",
                                                                    percentage: percentage,
                                                                    earned: points_earned,
                                                                    possible: points_possible )

            label = self.section_label_formatter.format(index: i+1)

            breakdown.append( {'percent': percentage, 'label': label, 'detail': summary, category: self.category} )

        total_percent, dropped_indices = totalWithDrops(breakdown, self.drop_count)

        for dropped_index in dropped_indicies:
            breakdown[dropped_index]['mark'] = {'detail': "The lowest {0} scores are dropped.".format(self.drop_count) }

        total_detail = self.total_detail_formatter.format(percent: total_percent)
        breakdown.append( {'percent': total_percent, 'label': self.total_label_formatter, 'detail': total_detail, category: self.category, prominent: True} )

        return {'percent' : total_percent,
                'section_breakdown' : breakdown,
                #No grade_breakdown here
                }

def get_score(user, problem, cache):
    ## HACK: assumes max score is fixed per problem
    id = problem.get('id')
    correct = 0

    # If the ID is not in the cache, add the item
    if id not in cache:
        module = StudentModule(module_type = 'problem',  # TODO: Move into StudentModule.__init__?
                               module_id = id,
                               student = user,
                               state = None,
                               grade = 0,
                               max_grade = None,
                               done = 'i')
        cache[id] = module

    # Grab the # correct from cache
    if id in cache:
        response = cache[id]
        if response.grade!=None:
            correct=response.grade

    # Grab max grade from cache, or if it doesn't exist, compute and save to DB
    if id in cache and response.max_grade != None:
        total = response.max_grade
    else:
        total=courseware.modules.capa_module.Module(etree.tostring(problem), "id").max_score()
        response.max_grade = total
        response.save()

    return (correct, total)

def grade_sheet(student):
    """
    This pulls a summary of all problems in the course. It returns a dictionary with two datastructures:

    - courseware_summary is a summary of all sections with problems in the course. It is organized as an array of chapters,
    each containing an array of sections, each containing an array of scores. This contains information for graded and ungraded
    problems, and is good for displaying a course summary with due dates, etc.

    - grade_summary is a summary of how the final grade breaks down. It is an array of "sections". Each section can either be
    a conglomerate of scores (like labs or homeworks) which has subscores and a totalscore, or a section can be all from one assignment
    (such as a midterm or final) and only has a totalscore. Each section has a weight that shows how it contributes to the total grade.
    """
    dom=content_parser.course_file(student)
    course = dom.xpath('//course/@name')[0]
    xmlChapters = dom.xpath('//course[@name=$course]/chapter', course=course)

    responses=StudentModule.objects.filter(student=student)
    response_by_id = {}
    for response in responses:
        response_by_id[response.module_id] = response

    totaled_scores = {}
    chapters=[]
    for c in xmlChapters:
        sections = []
        chname=c.get('name')

        for s in dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section',
                           course=course, chname=chname):
            problems=dom.xpath('//course[@name=$course]/chapter[@name=$chname]/section[@name=$section]//problem',
                           course=course, chname=chname, section=s.get('name'))

            graded = True if s.get('graded') == "true" else False
            scores=[]
            if len(problems)>0:
                for p in problems:
                    (correct,total) = get_score(student, p, response_by_id)
                    # id = p.get('id')
                    # correct = 0
                    # if id in response_by_id:
                    #     response = response_by_id[id]
                    #     if response.grade!=None:
                    #         correct=response.grade

                    # total=courseware.modules.capa_module.Module(etree.tostring(p), "id").max_score() # TODO: Add state. Not useful now, but maybe someday problems will have randomized max scores?
                    # print correct, total
                    if settings.GENERATE_PROFILE_SCORES:
                        if total > 1:
                            correct = random.randrange( max(total-2, 1) , total + 1 )
                        else:
                            correct = total

                    scores.append( Score(int(correct),total, graded, s.get("name")) )

                section_total = Score(sum([score.earned for score in scores]),
                                        sum([score.possible for score in scores]),
                                        False,
                                        s.get("name"))

                graded_total = Score(sum([score.earned for score in scores if score.graded]),
                                sum([score.possible for score in scores if score.graded]),
                                True,
                                s.get("name"))

                #Add the graded total to totaled_scores
                format = s.get('format') if s.get('format') else ""
                subtitle = s.get('subtitle') if s.get('subtitle') else format
                if format and graded_total[1] > 0:
                    format_scores = totaled_scores.get(format, [])
                    format_scores.append( graded_total )
                    totaled_scores[ format ] = format_scores

                section_score={'section':s.get("name"),
                       'scores':scores,
                       'section_total' : section_total,
                       'format' : format,
                       'subtitle' : subtitle,
                       'due' : s.get("due") or "",
                       'graded' : graded,
                       }
                sections.append(section_score)

        chapters.append({'course':course,
                         'chapter' : c.get("name"),
                         'sections' : sections,})

    grade_summary = grade_summary_6002x(totaled_scores)

    return {'courseware_summary' : chapters,
            'grade_summary' : grade_summary}

def grade_summary_6002x(totaled_scores):
    """
    This function takes the a dictionary of (graded) section scores, and applies the course grading rules to create
    the grade_summary. For 6.002x this means homeworks and labs all have equal weight, with the lowest 2 of each
    being dropped. There is one midterm and one final.
    """

    def totalWithDrops(scores, drop_count):
        #Note that this key will sort the list descending
        sorted_scores = sorted( enumerate(scores), key=lambda x: -x[1].percentage )
        # A list of the indices of the dropped scores
        dropped_indices = [score[0] for score in sorted_scores[-drop_count:]]
        aggregate_score = 0
        for index, score in enumerate(scores):
            if index not in dropped_indices:
                aggregate_score += score.percentage

        aggregate_score /= len(scores) - drop_count

        return aggregate_score, dropped_indices

    #Figure the homework scores
    homework_scores = totaled_scores['Homework'] if 'Homework' in totaled_scores else []
    homework_percentages = []
    for i in range(12):
        if i < len(homework_scores):
            percentage = homework_scores[i].earned / float(homework_scores[i].possible)
            summary = "Homework {0} - {1} - {2:.0%} ({3:g}/{4:g})".format( i + 1, homework_scores[i].section , percentage, homework_scores[i].earned, homework_scores[i].possible )
        else:
            percentage = 0
            summary = "Unreleased Homework {0} - 0% (?/?)".format(i + 1)

            if settings.GENERATE_PROFILE_SCORES:
                points_possible = random.randrange(10, 50)
                points_earned = random.randrange(5, points_possible)
                percentage = points_earned / float(points_possible)
                summary = "Random Homework - {0:.0%} ({1:g}/{2:g})".format( percentage, points_earned, points_possible )

        label = "HW {0:02d}".format(i + 1)

        homework_percentages.append(SectionPercentage(percentage, label, summary) )
    homework_total, homework_dropped_indices = totalWithDrops(homework_percentages, 2)

    #Figure the lab scores
    lab_scores = totaled_scores['Lab'] if 'Lab' in totaled_scores else []
    lab_percentages = []
    for i in range(12):
        if i < len(lab_scores):
            percentage = lab_scores[i].earned / float(lab_scores[i].possible)
            summary = "Lab {0} - {1} - {2:.0%} ({3:g}/{4:g})".format( i + 1, lab_scores[i].section , percentage, lab_scores[i].earned, lab_scores[i].possible )
        else:
            percentage = 0
            summary = "Unreleased Lab {0} - 0% (?/?)".format(i + 1)

            if settings.GENERATE_PROFILE_SCORES:
                points_possible = random.randrange(10, 50)
                points_earned = random.randrange(5, points_possible)
                percentage = points_earned / float(points_possible)
                summary = "Random Lab - {0:.0%} ({1:g}/{2:g})".format( percentage, points_earned, points_possible )

        label = "Lab {0:02d}".format(i + 1)

        lab_percentages.append(SectionPercentage(percentage, label, summary) )
    lab_total, lab_dropped_indices = totalWithDrops(lab_percentages, 2)

    #TODO: Pull this data about the midterm and final from the databse. It should be exactly similar to above, but we aren't sure how exams will be done yet.
    midterm_score = Score('?', '?', True, "?")
    midterm_percentage = 0

    final_score = Score('?', '?', True, "?")
    final_percentage = 0

    if settings.GENERATE_PROFILE_SCORES:
        midterm_score = Score(random.randrange(50, 150), 150, True, "?")
        midterm_percentage = midterm_score.earned / float(midterm_score.possible)

        final_score = Score(random.randrange(100, 300), 300, True, "?")
        final_percentage = final_score.earned / float(final_score.possible)

    grade_summary = [
        {
            'category': 'Homework',
            'subscores' : homework_percentages,
            'dropped_indices' : homework_dropped_indices,
            'totalscore' : homework_total,
            'totalscore_summary' : "Homework Average - {0:.0%}".format(homework_total),
            'totallabel' : 'HW Avg',
            'weight' : 0.15,
        },
        {
            'category': 'Labs',
            'subscores' : lab_percentages,
            'dropped_indices' : lab_dropped_indices,
            'totalscore' : lab_total,
            'totalscore_summary' : "Lab Average - {0:.0%}".format(lab_total),
            'totallabel' : 'Lab Avg',
            'weight' : 0.15,
        },
        {
            'category': 'Midterm',
            'totalscore' : midterm_percentage,
            'totalscore_summary' : "Midterm - {0:.0%} ({1}/{2})".format(midterm_percentage, midterm_score.earned, midterm_score.possible),
            'totallabel' : 'Midterm',
            'weight' : 0.30,
        },
        {
            'category': 'Final',
            'totalscore' : final_percentage,
            'totalscore_summary' : "Final - {0:.0%} ({1}/{2})".format(final_percentage, final_score.earned, final_score.possible),
            'totallabel' : 'Final',
            'weight' : 0.40,
        }
    ]

    return grade_summary
<|endoftext|>


<commit_before>#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'Iacopo Spalletti'
__email__ = 'i.spalletti@nephila.it'
__version__ = '0.7.2.post1'
<commit_msg>Bump version<commit_after>#!/usr/bin/env python
# -*- coding: utf-8 -*-
__author__ = 'Iacopo Spalletti'
__email__ = 'i.spalletti@nephila.it'
__version__ = '0.7.3'
<|endoftext|>


<commit_before>import errno
import subprocess
import sys
import os
import re
from shutil import copyfile
from subprocess import Popen

from dmoj.error import CompileError, InternalError
from .base_executor import CompiledExecutor
from dmoj.result import Result

recomment = re.compile(r'/\*.*?\*/', re.DOTALL)
restring = re.compile(r''''(?:\\.|[^'\\])'|"(?:\\.|[^"\\])*"''', re.DOTALL)
reinline_comment = re.compile(r'//.*?(?=[\r\n])')
reclass = re.compile(r'\bpublic\s+class\s+([_a-zA-Z\$][_0-9a-zA-z\$]*?)\b')
repackage = re.compile(r'\bpackage\s+([^.;]+(?:\.[^.;]+)*?);')
redeunicode = re.compile(r'\\u([0-9a-f]{4})', re.I)
deunicode = lambda x: redeunicode.sub(lambda a: unichr(int(a.group(1), 16)), x)

JAVA_SANDBOX = os.path.abspath(os.path.join(os.path.dirname(__file__), 'java-sandbox.jar'))

POLICY_PREFIX = '''\
grant codeBase "file:///{agent}" {{
    permission java.io.FilePermission "state", "write";
}};

'''

with open(os.path.join(os.path.dirname(__file__), 'java-security.policy')) as policy_file:
    policy = policy_file.read()

def find_class(source):
    source = reinline_comment.sub('', restring.sub('', recomment.sub('', source)))
    class_name = reclass.search(source)
    if class_name is None:
        raise CompileError('No public class: your main class must be declared as a "public class"\n')
    package = repackage.search(source)
    if package:
        raise CompileError('Invalid package %s: do not declare package\n' % package.group(1))
    return class_name

class JavaExecutor(CompiledExecutor):
    ext = '.java'

    vm = None
    compiler = None
    nproc = -1

    jvm_regex = None
    security_policy = policy

    def __init__(self, problem_id, source_code):
        self._class_name = None
        super(JavaExecutor, self).__init__(problem_id, source_code)

    def create_files(self, problem_id, source_code, *args, **kwargs):
        super(JavaExecutor, self).create_files(problem_id, source_code, *args, **kwargs)

        if os.name == 'nt':
            self._agent_file = self._file('java-sandbox.jar')
            copyfile(JAVA_SANDBOX, self._agent_file)
        else:
            self._agent_file = JAVA_SANDBOX

        self._policy_file = self._file('security.policy')
        with open(self._policy_file, 'w') as file:
            # Normalize path separators because the security policy is processed by a StringTokenizer which treats
            # escapes sequences as... escape sequences.
            path = self._agent_file.replace('\\', '/') if os.name == 'nt' else self._agent_file
            file.write(POLICY_PREFIX.format(agent=path) + self.security_policy)

    def get_compile_popen_kwargs(self):
        return {'executable': self.get_compiler()}

    def get_compiled_file(self):
        return None

    def get_security(self, launch_kwargs=None):
        return None

    def get_executable(self):
        return self.get_vm()

    def get_cmdline(self):
        return ['java', '-client', '-javaagent:%s=policy:%s' % (self._agent_file, self._policy_file),
                '-Xss128m', '-Xmx%dK' % self.__memory_limit, '-XX:ErrorFile=submission_jvm_crash.log',
                self._class_name]  # 128m is equivalent to 1<<27 in Thread constructor

    def launch(self, *args, **kwargs):
        self.__memory_limit = kwargs['memory']
        kwargs['memory'] = 0
        return super(JavaExecutor, self).launch(*args, **kwargs)

    def launch_unsafe(self, *args, **kwargs):
        return Popen(['java', '-client', self._class_name] + list(args),
                     executable=self.get_vm(), cwd=self._dir, **kwargs)

    def get_feedback(self, stderr, result, process):
        if process.returncode:
            try:
                with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err:
                    raise InternalError('\n\n' + err.read())
            except IOError:
                pass
        if not result.result_flag & Result.IR:
            return ''

        try:
            with open(os.path.join(self._dir, 'state'), 'r') as state:
                exception = state.read().strip()
        except IOError:
            exception = "abnormal termination"  # Probably exited without calling shutdown hooks

        return exception

    @classmethod
    def get_vm(cls):
        return cls.runtime_dict.get(cls.vm)

    @classmethod
    def get_compiler(cls):
        return cls.runtime_dict.get(cls.compiler)

    @classmethod
    def initialize(cls, sandbox=True):
        if cls.get_vm() is None or cls.get_compiler() is None:
            return False
        if not os.path.isfile(cls.get_vm()) or not os.path.isfile(cls.get_compiler()):
            return False
        return cls.run_self_test(sandbox)

    @classmethod
    def test_jvm(cls, name, path):
        raise NotImplementedError()

    @classmethod
    def get_versionable_commands(cls):
        return [('javac', cls.get_compiler())]

    @classmethod
    def get_version_flags(cls, command):
        return ['-version']

    @classmethod
    def autoconfig(cls):
        if cls.jvm_regex is None:
            return {}, False, 'Unimplemented'

        JVM_DIR = '/usr/local' if sys.platform.startswith('freebsd') else '/usr/lib/jvm'
        regex = re.compile(cls.jvm_regex)

        try:
            vms = os.listdir(JVM_DIR)
        except OSError:
            vms = []

        for item in vms:
            path = os.path.join(JVM_DIR, item)
            if not os.path.isdir(path) or os.path.islink(path):
                continue

            if regex.match(item):
                try:
                    config, success, message = cls.test_jvm(item, path)
                except (NotImplementedError, TypeError, ValueError):
                    return {}, False, 'Unimplemented'
                else:
                    if success:
                        return config, success, message
        return {}, False, 'Could not find JVM'

    @classmethod
    def unravel_java(cls, path):
        with open(path, 'rb') as f:
            if f.read(2) != '#!':
                return path

        with open(os.devnull, 'w') as devnull:
            process = subprocess.Popen(['bash', '-x', path, '-version'], stdout=devnull, stderr=subprocess.PIPE)

        log = [i for i in process.communicate()[1].split('\n') if 'exec' in i]
        cmdline = log[-1].lstrip('+ ').split()
        return cmdline[1] if len(cmdline) > 1 else path

class JavacExecutor(JavaExecutor):
    def create_files(self, problem_id, source_code, *args, **kwargs):
        super(JavacExecutor, self).create_files(problem_id, source_code, *args, **kwargs)
        source_code = deunicode(source_code)
        class_name = find_class(source_code)
        self._code = self._file('%s.java' % class_name.group(1))
        try:
            with open(self._code, 'wb') as fo:
                fo.write(source_code.encode('utf8'))
        except IOError as e:
            if e.errno in (errno.ENAMETOOLONG, errno.ENOENT):
                raise CompileError('Why do you need a class name so long? '
                                   'As a judge, I sentence your code to death.\n')
            raise
        self._class_name = class_name.group(1)

    def get_compile_args(self):
        return [self.get_compiler(), '-encoding', 'UTF-8', self._code]

    def handle_compile_error(self, output):
        if 'is public, should be declared in a file named' in output:
            raise CompileError('You are a troll. Trolls are not welcome. '
                               'As a judge, I sentence your code to death.\n')
        raise CompileError(output)

    @classmethod
    def test_jvm(cls, name, path):
        vm_path = os.path.join(path, 'bin', 'java')
        compiler_path = os.path.join(path, 'bin', 'javac')
        result = {cls.vm: vm_path, cls.compiler: compiler_path}

        if os.path.isfile(vm_path) and os.path.isfile(compiler_path):
            executor = type('Executor', (cls,), {'runtime_dict': result})
            success = executor.run_self_test(output=False)
            return result, success, 'Using %s' % vm_path if success else 'Failed self-test'
        else:
            return result, False, 'Invalid JDK'
<commit_msg>Don't encode blindly<commit_after>import errno
import subprocess
import sys
import os
import re
from shutil import copyfile
from subprocess import Popen

from dmoj.error import CompileError, InternalError
from .base_executor import CompiledExecutor
from dmoj.result import Result

recomment = re.compile(r'/\*.*?\*/', re.DOTALL)
restring = re.compile(r''''(?:\\.|[^'\\])'|"(?:\\.|[^"\\])*"''', re.DOTALL)
reinline_comment = re.compile(r'//.*?(?=[\r\n])')
reclass = re.compile(r'\bpublic\s+class\s+([_a-zA-Z\$][_0-9a-zA-z\$]*?)\b')
repackage = re.compile(r'\bpackage\s+([^.;]+(?:\.[^.;]+)*?);')
redeunicode = re.compile(r'\\u([0-9a-f]{4})', re.I)
deunicode = lambda x: redeunicode.sub(lambda a: unichr(int(a.group(1), 16)), x)

JAVA_SANDBOX = os.path.abspath(os.path.join(os.path.dirname(__file__), 'java-sandbox.jar'))

POLICY_PREFIX = '''\
grant codeBase "file:///{agent}" {{
    permission java.io.FilePermission "state", "write";
}};

'''

with open(os.path.join(os.path.dirname(__file__), 'java-security.policy')) as policy_file:
    policy = policy_file.read()

def find_class(source):
    source = reinline_comment.sub('', restring.sub('', recomment.sub('', source)))
    class_name = reclass.search(source)
    if class_name is None:
        raise CompileError('No public class: your main class must be declared as a "public class"\n')
    package = repackage.search(source)
    if package:
        raise CompileError('Invalid package %s: do not declare package\n' % package.group(1))
    return class_name

class JavaExecutor(CompiledExecutor):
    ext = '.java'

    vm = None
    compiler = None
    nproc = -1

    jvm_regex = None
    security_policy = policy

    def __init__(self, problem_id, source_code):
        self._class_name = None
        super(JavaExecutor, self).__init__(problem_id, source_code)

    def create_files(self, problem_id, source_code, *args, **kwargs):
        super(JavaExecutor, self).create_files(problem_id, source_code, *args, **kwargs)

        if os.name == 'nt':
            self._agent_file = self._file('java-sandbox.jar')
            copyfile(JAVA_SANDBOX, self._agent_file)
        else:
            self._agent_file = JAVA_SANDBOX

        self._policy_file = self._file('security.policy')
        with open(self._policy_file, 'w') as file:
            # Normalize path separators because the security policy is processed by a StringTokenizer which treats
            # escapes sequences as... escape sequences.
            path = self._agent_file.replace('\\', '/') if os.name == 'nt' else self._agent_file
            file.write(POLICY_PREFIX.format(agent=path) + self.security_policy)

    def get_compile_popen_kwargs(self):
        return {'executable': self.get_compiler()}

    def get_compiled_file(self):
        return None

    def get_security(self, launch_kwargs=None):
        return None

    def get_executable(self):
        return self.get_vm()

    def get_cmdline(self):
        return ['java', '-client', '-javaagent:%s=policy:%s' % (self._agent_file, self._policy_file),
                '-Xss128m', '-Xmx%dK' % self.__memory_limit, '-XX:ErrorFile=submission_jvm_crash.log',
                self._class_name]  # 128m is equivalent to 1<<27 in Thread constructor

    def launch(self, *args, **kwargs):
        self.__memory_limit = kwargs['memory']
        kwargs['memory'] = 0
        return super(JavaExecutor, self).launch(*args, **kwargs)

    def launch_unsafe(self, *args, **kwargs):
        return Popen(['java', '-client', self._class_name] + list(args),
                     executable=self.get_vm(), cwd=self._dir, **kwargs)

    def get_feedback(self, stderr, result, process):
        if process.returncode:
            try:
                with open(os.path.join(self._dir, 'submission_jvm_crash.log'), 'r') as err:
                    raise InternalError('\n\n' + err.read())
            except IOError:
                pass
        if not result.result_flag & Result.IR:
            return ''

        try:
            with open(os.path.join(self._dir, 'state'), 'r') as state:
                exception = state.read().strip()
        except IOError:
            exception = "abnormal termination"  # Probably exited without calling shutdown hooks

        return exception

    @classmethod
    def get_vm(cls):
        return cls.runtime_dict.get(cls.vm)

    @classmethod
    def get_compiler(cls):
        return cls.runtime_dict.get(cls.compiler)

    @classmethod
    def initialize(cls, sandbox=True):
        if cls.get_vm() is None or cls.get_compiler() is None:
            return False
        if not os.path.isfile(cls.get_vm()) or not os.path.isfile(cls.get_compiler()):
            return False
        return cls.run_self_test(sandbox)

    @classmethod
    def test_jvm(cls, name, path):
        raise NotImplementedError()

    @classmethod
    def get_versionable_commands(cls):
        return [('javac', cls.get_compiler())]

    @classmethod
    def get_version_flags(cls, command):
        return ['-version']

    @classmethod
    def autoconfig(cls):
        if cls.jvm_regex is None:
            return {}, False, 'Unimplemented'

        JVM_DIR = '/usr/local' if sys.platform.startswith('freebsd') else '/usr/lib/jvm'
        regex = re.compile(cls.jvm_regex)

        try:
            vms = os.listdir(JVM_DIR)
        except OSError:
            vms = []

        for item in vms:
            path = os.path.join(JVM_DIR, item)
            if not os.path.isdir(path) or os.path.islink(path):
                continue

            if regex.match(item):
                try:
                    config, success, message = cls.test_jvm(item, path)
                except (NotImplementedError, TypeError, ValueError):
                    return {}, False, 'Unimplemented'
                else:
                    if success:
                        return config, success, message
        return {}, False, 'Could not find JVM'

    @classmethod
    def unravel_java(cls, path):
        with open(path, 'rb') as f:
            if f.read(2) != '#!':
                return path

        with open(os.devnull, 'w') as devnull:
            process = subprocess.Popen(['bash', '-x', path, '-version'], stdout=devnull, stderr=subprocess.PIPE)

        log = [i for i in process.communicate()[1].split('\n') if 'exec' in i]
        cmdline = log[-1].lstrip('+ ').split()
        return cmdline[1] if len(cmdline) > 1 else path

class JavacExecutor(JavaExecutor):
    def create_files(self, problem_id, source_code, *args, **kwargs):
        super(JavacExecutor, self).create_files(problem_id, source_code, *args, **kwargs)
        source_code = deunicode(source_code)
        class_name = find_class(source_code)
        self._code = self._file('%s.java' % class_name.group(1))
        try:
            with open(self._code, 'wb') as fo:
                if isinstance(source_code, unicode):
                    source_code.encode('utf-8')
                fo.write(source_code)
        except IOError as e:
            if e.errno in (errno.ENAMETOOLONG, errno.ENOENT):
                raise CompileError('Why do you need a class name so long? '
                                   'As a judge, I sentence your code to death.\n')
            raise
        self._class_name = class_name.group(1)

    def get_compile_args(self):
        return [self.get_compiler(), '-encoding', 'UTF-8', self._code]

    def handle_compile_error(self, output):
        if 'is public, should be declared in a file named' in output:
            raise CompileError('You are a troll. Trolls are not welcome. '
                               'As a judge, I sentence your code to death.\n')
        raise CompileError(output)

    @classmethod
    def test_jvm(cls, name, path):
        vm_path = os.path.join(path, 'bin', 'java')
        compiler_path = os.path.join(path, 'bin', 'javac')
        result = {cls.vm: vm_path, cls.compiler: compiler_path}

        if os.path.isfile(vm_path) and os.path.isfile(compiler_path):
            executor = type('Executor', (cls,), {'runtime_dict': result})
            success = executor.run_self_test(output=False)
            return result, success, 'Using %s' % vm_path if success else 'Failed self-test'
        else:
            return result, False, 'Invalid JDK'
<|endoftext|>


<commit_before>#
# File: exceptions.py
# Author: Ivan Gonzalez
#
"""Exception class for the DMRG code
"""
class DMRGException(Exception):
    """A base exception for the DMRG code

    Parameters
    ----------
    msg : a string
        A message explaining the error
    """
    def __init__(self, msg):
    	super(DMRGException, self).__init__()
    	self.msg = msg

    def __srt__(self, msg):
    	return repr(self.msg)
<commit_msg>Minor changes.<commit_after>#
# File: dmrg_exceptions.py
# Author: Ivan Gonzalez
#
"""Exception class for the DMRG code
"""
class DMRGException(Exception):
    """A base exception for the DMRG code

    Parameters
    ----------
    msg : a string
        A message explaining the error
    """
    def __init__(self, msg):
    	super(DMRGException, self).__init__()
    	self.msg = msg

    def __srt__(self, msg):
    	return repr(self.msg)
<|endoftext|>


<commit_before>from cms.utils import get_site_from_request, get_page_from_request
from django.utils.cache import patch_vary_headers
from django.utils import translation
from django.conf import settings
import re

class LazySite(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_cached_site'):
            request._cached_site = get_site_from_request(request)
        return request._cached_site

class CurrentSiteMiddleware(object):
    def process_request(self, request):
        request.__class__.site = LazySite()
        return None

class LazyPage(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_current_page_cache'):
            request._current_page_cache = get_page_from_request(request)
        return request._current_page_cache

class CurrentPageMiddleware(object):
    def process_request(self, request):
        request.__class__.current_page = LazyPage()
        return None

SUB = re.compile(ur'<a([^>]+)href="/([^"]*)"([^>]*)>')
SUB2 = re.compile(ur'<form([^>]+)action="/([^"]*)"([^>]*)>')

class MultilingualURLMiddleware:
    def get_language_from_request (self,request):
        supported = dict(settings.LANGUAGES)
        lang = settings.LANGUAGE_CODE[:2]
        langs = "|".join(map(lambda l: l[0], settings.LANGUAGES))
        check = re.match(r"^/(%s)/.*" % langs, request.path_info)
        changed = False
        if check is not None:
            request.path = request.path[3:]
            request.path_info = request.path_info[3:]
            t = check.group(1)
            if t in supported:
                lang = t
                if hasattr(request, "session"):
                    request.session["django_language"] = lang
                else:
                    request.set_cookie("django_language", lang)
                changed = True
        else:
            lang = translation.get_language_from_request(request)
        if not changed:
            if hasattr(request, "session"):
                lang = request.session.get("django_language", None)
                if lang in supported and lang is not None:
                    return lang
            elif "django_language" in request.COOKIES.keys():
                lang = request.COOKIES.get("django_language", None)
                if lang in supported and lang is not None:
                    return lang
            if not lang:
                lang = translation.get_language_from_request(request)
        return lang

    def process_request(self, request):
        from django.conf import settings
        language = self.get_language_from_request(request)
        if language is None:
            language = settings.LANGUAGE_CODE[:2]
        translation.activate(language)
        request.LANGUAGE_CODE = translation.get_language()

    def process_response(self, request, response):
        patch_vary_headers(response, ("Accept-Language",))
        translation.deactivate()
        if response.status_code == 200 and not request.path.startswith(settings.MEDIA_URL) and response._headers['content-type'][1].split(';')[0] == "text/html":
            response.content = SUB.sub(ur'<a\1href="/%s/\2"\3>' % request.LANGUAGE_CODE, response.content.decode('utf-8'))
            response.content = SUB2.sub(ur'<form\1action="/%s/\2"\3>' % request.LANGUAGE_CODE, response.content.decode('utf-8'))
        return response<commit_msg>fix for urls with prefix start<commit_after>from cms.utils import get_site_from_request, get_page_from_request
from django.utils.cache import patch_vary_headers
from django.utils import translation
from django.conf import settings
import re

class LazySite(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_cached_site'):
            request._cached_site = get_site_from_request(request)
        return request._cached_site

class CurrentSiteMiddleware(object):
    def process_request(self, request):
        request.__class__.site = LazySite()
        return None

class LazyPage(object):
    def __get__(self, request, obj_type=None):
        if not hasattr(request, '_current_page_cache'):
            request._current_page_cache = get_page_from_request(request)
        return request._current_page_cache

class CurrentPageMiddleware(object):
    def process_request(self, request):
        request.__class__.current_page = LazyPage()
        return None

SUB = re.compile(ur'<a([^>]+)href="/(?!(%s))([^"]*)"([^>]*)>' % "|".join(map(lambda l: l[0] + "/" , settings.LANGUAGES)))
SUB2 = re.compile(ur'<form([^>]+)action="/(?!(%s))([^"]*)"([^>]*)>' % "|".join(map(lambda l: l[0] + "/" , settings.LANGUAGES)))

class MultilingualURLMiddleware:
    def get_language_from_request (self,request):
        supported = dict(settings.LANGUAGES)
        lang = settings.LANGUAGE_CODE[:2]
        langs = "|".join(map(lambda l: l[0], settings.LANGUAGES))
        check = re.match(r"^/(%s)/.*" % langs, request.path_info)
        changed = False
        if check is not None:
            request.path = request.path[3:]
            request.path_info = request.path_info[3:]
            t = check.group(1)
            if t in supported:
                lang = t
                if hasattr(request, "session"):
                    request.session["django_language"] = lang
                else:
                    request.set_cookie("django_language", lang)
                changed = True
        else:
            lang = translation.get_language_from_request(request)
        if not changed:
            if hasattr(request, "session"):
                lang = request.session.get("django_language", None)
                if lang in supported and lang is not None:
                    return lang
            elif "django_language" in request.COOKIES.keys():
                lang = request.COOKIES.get("django_language", None)
                if lang in supported and lang is not None:
                    return lang
            if not lang:
                lang = translation.get_language_from_request(request)
        return lang

    def process_request(self, request):
        from django.conf import settings
        language = self.get_language_from_request(request)
        if language is None:
            language = settings.LANGUAGE_CODE[:2]
        translation.activate(language)
        request.LANGUAGE_CODE = translation.get_language()

    def process_response(self, request, response):
        patch_vary_headers(response, ("Accept-Language",))
        translation.deactivate()
        if response.status_code == 200 and not request.path.startswith(settings.MEDIA_URL) and response._headers['content-type'][1].split(';')[0] == "text/html":
            response.content = SUB.sub(ur'<a\1href="/%s/\3"\4>' % request.LANGUAGE_CODE, response.content.decode('utf-8'))
            response.content = SUB2.sub(ur'<form\1action="/%s/\3"\4>' % request.LANGUAGE_CODE, response.content.decode('utf-8'))
        return response<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
from cms.models import Page, Title
from cms.tests.base import CMSTestCase, URL_CMS_PAGE, URL_CMS_PAGE_ADD
from cms.sitemaps import CMSSitemap
from django.conf import settings
from django.contrib.auth.models import User
from django.http import HttpRequest
import os.path

class PagesTestCase(CMSTestCase):

    def setUp(self):
        u = User(username="test", is_staff = True, is_active = True, is_superuser = True)
        u.set_password("test")
        u.save()

        self.login_user(u)

    def test_01_add_page(self):
        """
        Test that the add admin page could be displayed via the admin
        """
        response = self.client.get(URL_CMS_PAGE_ADD)
        self.assertEqual(response.status_code, 200)

    def test_02_create_page(self):
        """
        Test that a page can be created via the admin
        """
        page_data = self.get_new_page_data()

        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        title = Title.objects.get(slug=page_data['slug'])
        self.assertEqual(title is not None, True)
        page = title.page
        page.published = True
        page.save()
        self.assertEqual(page.get_title(), page_data['title'])
        self.assertEqual(page.get_slug(), page_data['slug'])
        self.assertEqual(page.placeholders.all().count(), 2)

        # were public instanes created?
        title = Title.objects.drafts().get(slug=page_data['slug'])

    def test_03_slug_collision(self):
        """
        Test a slug collision
        """
        page_data = self.get_new_page_data()
        # create first page
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)

        #page1 = Title.objects.get(slug=page_data['slug']).page
        # create page with the same page_data

        response = self.client.post(URL_CMS_PAGE_ADD, page_data)

        if settings.i18n_installed:
            self.assertEqual(response.status_code, 302)
            # did we got right redirect?
            self.assertEqual(response['Location'].endswith(URL_CMS_PAGE), True)
        else:
            self.assertEqual(response.status_code, 200)
            self.assertEqual(response['Location'].endswith(URL_CMS_PAGE_ADD), True)
        # TODO: check for slug collisions after move
        # TODO: check for slug collisions with different settings

    def test_04_details_view(self):
        """
        Test the details view
        """
        response = self.client.get(self.get_pages_root())
        self.assertEqual(response.status_code, 404)
        self.create_page(title='test page 1', published=False)
        response = self.client.get(self.get_pages_root())
        self.assertEqual(response.status_code, 404)
        self.create_page(title='test page 2', published=True)
        homepage = Page.objects.get_home()
        self.assertTrue(homepage.get_slug(), 'test-page-2')
        response = self.client.get(self.get_pages_root(), {'ACCEPT_LANGUAGE': 'en'})
        self.assertEqual(response.status_code, 200)

    def test_05_edit_page(self):
        """
        Test that a page can edited via the admin
        """
        page_data = self.get_new_page_data()
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        response = self.client.get('/admin/cms/page/%s/' %page.id)
        self.assertEqual(response.status_code, 200)
        page_data['title'] = 'changed title'
        response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        self.assertEqual(page.get_title(), 'changed title')

    def test_06_meta_description_and_keywords_fields_from_admin(self):
        """
        Test that description and keywords tags can be set via the admin
        """
        page_data = self.get_new_page_data()
        page_data["meta_description"] = "I am a page"
        page_data["meta_keywords"] = "page,cms,stuff"
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        response = self.client.get('/admin/cms/page/%s/' %page.id)
        self.assertEqual(response.status_code, 200)
        page_data['meta_description'] = 'I am a duck'
        response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        page = Page.objects.get(title_set__slug=page_data["slug"])
        self.assertEqual(page.get_meta_description(), 'I am a duck')
        self.assertEqual(page.get_meta_keywords(), 'page,cms,stuff')

    def test_07_meta_description_and_keywords_from_template_tags(self):
        from django import template
        page_data = self.get_new_page_data()
        page_data["title"] = "Hello"
        page_data["meta_description"] = "I am a page"
        page_data["meta_keywords"] = "page,cms,stuff"
        self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        t = template.Template("{% load cms_tags %}{% page_attribute title %} {% page_attribute meta_description %} {% page_attribute meta_keywords %}")
        req = HttpRequest()
        page.published = True
        page.save()
        req.current_page = page
        req.REQUEST = {}
        self.assertEqual(t.render(template.Context({"request": req})), "Hello I am a page page,cms,stuff")

    def test_08_copy_page(self):
        """
        Test that a page can be copied via the admin
        """
        page_a = self.create_page()
        page_a_a = self.create_page(page_a)
        page_a_a_a = self.create_page(page_a_a)

        page_b = self.create_page()
        page_b_a = self.create_page(page_b)

        count = Page.objects.drafts().count()

        self.copy_page(page_a, page_b_a)

        self.assertEqual(Page.objects.drafts().count() - count, 3)

    def test_09_language_change(self):
        page_data = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data)
        pk = Page.objects.all()[0].pk
        response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"en" })
        self.assertEqual(response.status_code, 200)
        response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"de" })
        self.assertEqual(response.status_code, 200)

    def test_10_move_page(self):
        page_data1 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data1)
        page_data2 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data2)
        page_data3 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data3)
        page1 = Page.objects.all()[0]
        page2 = Page.objects.all()[1]
        page3 = Page.objects.all()[2]
        # move pages
        response = self.client.post("/admin/cms/page/%s/move-page/" % page3.pk, {"target":page2.pk, "position":"last-child" })
        self.assertEqual(response.status_code, 200)
        response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"last-child" })
        self.assertEqual(response.status_code, 200)
        # check page2 path and url
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_path(), page_data1['slug']+"/"+page_data2['slug'])
        self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/")
        # check page3 path and url
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_path(), page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug'])
        self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug']+"/")
        # publish page 1 (becomes home)
        page1 = Page.objects.all()[0]
        page1.published = True
        page1.save()
        # check that page2 and page3 url have changed
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/")
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/"+page_data3['slug']+"/")
        # move page2 back to root and check path of 2 and 3
        response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"left" })
        self.assertEqual(response.status_code, 200)
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_path(), page_data2['slug'])
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_path(), page_data2['slug']+"/"+page_data3['slug'])

    def test_11_add_placeholder(self):
        # create page
        page = self.create_page(None, None, "last-child", "Add Placeholder", 1, True, True)
        page.template = 'add_placeholder.html'
        page.save()
        url = page.get_absolute_url()
        response = self.client.get(url)
        self.assertEqual(200, response.status_code)
        path = os.path.join(settings.PROJECT_DIR, 'templates', 'add_placeholder.html')
        f = open(path, 'r')
        old = f.read()
        f.close()
        new = old.replace(
            '<!-- SECOND_PLACEHOLDER -->',
            '{% placeholder second_placeholder %}'
        )
        f = open(path, 'w')
        f.write(new)
        f.close()
        response = self.client.get(url)
        self.assertEqual(200, response.status_code)
        f = open(path, 'w')
        f.write(old)
        f.close()

    def test_12_sitemap_login_required_pages(self):
        """
        Test that CMSSitemap object contains only published,public (login_required=False) pages
        """
        self.create_page(parent_page=None, published=True, in_navigation=True)
        page1 = Page.objects.all()[0]
        page1.login_required = True
        page1.save()
        self.assertEqual(CMSSitemap().items().count(),0)<commit_msg>accept lang snuck in<commit_after># -*- coding: utf-8 -*-
from cms.models import Page, Title
from cms.tests.base import CMSTestCase, URL_CMS_PAGE, URL_CMS_PAGE_ADD
from cms.sitemaps import CMSSitemap
from django.conf import settings
from django.contrib.auth.models import User
from django.http import HttpRequest
import os.path

class PagesTestCase(CMSTestCase):

    def setUp(self):
        u = User(username="test", is_staff = True, is_active = True, is_superuser = True)
        u.set_password("test")
        u.save()

        self.login_user(u)

    def test_01_add_page(self):
        """
        Test that the add admin page could be displayed via the admin
        """
        response = self.client.get(URL_CMS_PAGE_ADD)
        self.assertEqual(response.status_code, 200)

    def test_02_create_page(self):
        """
        Test that a page can be created via the admin
        """
        page_data = self.get_new_page_data()

        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        title = Title.objects.get(slug=page_data['slug'])
        self.assertEqual(title is not None, True)
        page = title.page
        page.published = True
        page.save()
        self.assertEqual(page.get_title(), page_data['title'])
        self.assertEqual(page.get_slug(), page_data['slug'])
        self.assertEqual(page.placeholders.all().count(), 2)

        # were public instanes created?
        title = Title.objects.drafts().get(slug=page_data['slug'])

    def test_03_slug_collision(self):
        """
        Test a slug collision
        """
        page_data = self.get_new_page_data()
        # create first page
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)

        #page1 = Title.objects.get(slug=page_data['slug']).page
        # create page with the same page_data

        response = self.client.post(URL_CMS_PAGE_ADD, page_data)

        if settings.i18n_installed:
            self.assertEqual(response.status_code, 302)
            # did we got right redirect?
            self.assertEqual(response['Location'].endswith(URL_CMS_PAGE), True)
        else:
            self.assertEqual(response.status_code, 200)
            self.assertEqual(response['Location'].endswith(URL_CMS_PAGE_ADD), True)
        # TODO: check for slug collisions after move
        # TODO: check for slug collisions with different settings

    def test_04_details_view(self):
        """
        Test the details view
        """
        response = self.client.get(self.get_pages_root())
        self.assertEqual(response.status_code, 404)
        self.create_page(title='test page 1', published=False)
        response = self.client.get(self.get_pages_root())
        self.assertEqual(response.status_code, 404)
        self.create_page(title='test page 2', published=True)
        homepage = Page.objects.get_home()
        self.assertTrue(homepage.get_slug(), 'test-page-2')
        response = self.client.get(self.get_pages_root())
        self.assertEqual(response.status_code, 200)

    def test_05_edit_page(self):
        """
        Test that a page can edited via the admin
        """
        page_data = self.get_new_page_data()
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        response = self.client.get('/admin/cms/page/%s/' %page.id)
        self.assertEqual(response.status_code, 200)
        page_data['title'] = 'changed title'
        response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        self.assertEqual(page.get_title(), 'changed title')

    def test_06_meta_description_and_keywords_fields_from_admin(self):
        """
        Test that description and keywords tags can be set via the admin
        """
        page_data = self.get_new_page_data()
        page_data["meta_description"] = "I am a page"
        page_data["meta_keywords"] = "page,cms,stuff"
        response = self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        response = self.client.get('/admin/cms/page/%s/' %page.id)
        self.assertEqual(response.status_code, 200)
        page_data['meta_description'] = 'I am a duck'
        response = self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        self.assertRedirects(response, URL_CMS_PAGE)
        page = Page.objects.get(title_set__slug=page_data["slug"])
        self.assertEqual(page.get_meta_description(), 'I am a duck')
        self.assertEqual(page.get_meta_keywords(), 'page,cms,stuff')

    def test_07_meta_description_and_keywords_from_template_tags(self):
        from django import template
        page_data = self.get_new_page_data()
        page_data["title"] = "Hello"
        page_data["meta_description"] = "I am a page"
        page_data["meta_keywords"] = "page,cms,stuff"
        self.client.post(URL_CMS_PAGE_ADD, page_data)
        page =  Page.objects.get(title_set__slug=page_data['slug'])
        self.client.post('/admin/cms/page/%s/' %page.id, page_data)
        t = template.Template("{% load cms_tags %}{% page_attribute title %} {% page_attribute meta_description %} {% page_attribute meta_keywords %}")
        req = HttpRequest()
        page.published = True
        page.save()
        req.current_page = page
        req.REQUEST = {}
        self.assertEqual(t.render(template.Context({"request": req})), "Hello I am a page page,cms,stuff")

    def test_08_copy_page(self):
        """
        Test that a page can be copied via the admin
        """
        page_a = self.create_page()
        page_a_a = self.create_page(page_a)
        page_a_a_a = self.create_page(page_a_a)

        page_b = self.create_page()
        page_b_a = self.create_page(page_b)

        count = Page.objects.drafts().count()

        self.copy_page(page_a, page_b_a)

        self.assertEqual(Page.objects.drafts().count() - count, 3)

    def test_09_language_change(self):
        page_data = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data)
        pk = Page.objects.all()[0].pk
        response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"en" })
        self.assertEqual(response.status_code, 200)
        response = self.client.get("/admin/cms/page/%s/" % pk, {"language":"de" })
        self.assertEqual(response.status_code, 200)

    def test_10_move_page(self):
        page_data1 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data1)
        page_data2 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data2)
        page_data3 = self.get_new_page_data()
        self.client.post(URL_CMS_PAGE_ADD, page_data3)
        page1 = Page.objects.all()[0]
        page2 = Page.objects.all()[1]
        page3 = Page.objects.all()[2]
        # move pages
        response = self.client.post("/admin/cms/page/%s/move-page/" % page3.pk, {"target":page2.pk, "position":"last-child" })
        self.assertEqual(response.status_code, 200)
        response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"last-child" })
        self.assertEqual(response.status_code, 200)
        # check page2 path and url
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_path(), page_data1['slug']+"/"+page_data2['slug'])
        self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/")
        # check page3 path and url
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_path(), page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug'])
        self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data1['slug']+"/"+page_data2['slug']+"/"+page_data3['slug']+"/")
        # publish page 1 (becomes home)
        page1 = Page.objects.all()[0]
        page1.published = True
        page1.save()
        # check that page2 and page3 url have changed
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/")
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_absolute_url(), self.get_pages_root()+page_data2['slug']+"/"+page_data3['slug']+"/")
        # move page2 back to root and check path of 2 and 3
        response = self.client.post("/admin/cms/page/%s/move-page/" % page2.pk, {"target":page1.pk, "position":"left" })
        self.assertEqual(response.status_code, 200)
        page2 = Page.objects.get(pk=page2.pk)
        self.assertEqual(page2.get_path(), page_data2['slug'])
        page3 = Page.objects.get(pk=page3.pk)
        self.assertEqual(page3.get_path(), page_data2['slug']+"/"+page_data3['slug'])

    def test_11_add_placeholder(self):
        # create page
        page = self.create_page(None, None, "last-child", "Add Placeholder", 1, True, True)
        page.template = 'add_placeholder.html'
        page.save()
        url = page.get_absolute_url()
        response = self.client.get(url)
        self.assertEqual(200, response.status_code)
        path = os.path.join(settings.PROJECT_DIR, 'templates', 'add_placeholder.html')
        f = open(path, 'r')
        old = f.read()
        f.close()
        new = old.replace(
            '<!-- SECOND_PLACEHOLDER -->',
            '{% placeholder second_placeholder %}'
        )
        f = open(path, 'w')
        f.write(new)
        f.close()
        response = self.client.get(url)
        self.assertEqual(200, response.status_code)
        f = open(path, 'w')
        f.write(old)
        f.close()

    def test_12_sitemap_login_required_pages(self):
        """
        Test that CMSSitemap object contains only published,public (login_required=False) pages
        """
        self.create_page(parent_page=None, published=True, in_navigation=True)
        page1 = Page.objects.all()[0]
        page1.login_required = True
        page1.save()
        self.assertEqual(CMSSitemap().items().count(),0)<|endoftext|>