<commit_before>"""
Defines MemBlock, a block of memory that can be read (potentially async) and written (sync)
"""

from __future__ import print_function, unicode_literals
import collections

from .pyrtlexceptions import PyrtlError
from .core import working_block, next_tempvar_name, next_memid, LogicNet
from .wire import WireVector, Const
from .helperfuncs import as_wires

# ------------------------------------------------------------------------
#
#         ___        __   __          __        __   __
#   |\/| |__   |\/| /  \ |__) \ /    |__) |    /  \ /  ` |__/
#   |  | |___  |  | \__/ |  \  |     |__) |___ \__/ \__, |  \
#

# MemBlock supports any number of the following operations:
# read: d = mem[address]
# write: mem[address] = d
# write with an enable: mem[address] = MemBlock.EnabledWrite(d,enable=we)
# Based on the number of reads and writes a memory will be inferred
# with the correct number of ports to support that

# _MemAssignment is the type returned from assignment by |= or <<=
_MemAssignment = collections.namedtuple('_MemAssignment', 'rhs, is_conditional')

class _MemIndexed(WireVector):
    """ Object used internally to route memory assigns correctly.

    The normal PyRTL user should never need to be aware that this class exists,
    hence the underscore in the name.  It presents a very similar interface to
    wiresVectors (all of the normal wirevector operations should still work),
    but if you try to *set* the value with <<= or |= then it will generate a
    _MemAssignment object rather than the normal wire assignment. """

    def __init__(self, mem, index):
        self.mem = mem
        self.index = index

    def __ilshift__(self, other):
        return _MemAssignment(rhs=other, is_conditional=False)

    def __ior__(self, other):
        return _MemAssignment(rhs=other, is_conditional=True)

    def logicop(self, other, op):
        return as_wires(self).logicop(other, op)

    def __invert__(self):
        return as_wires(self).__invert__()

    def __getitem__(self, item):
        return as_wires(self).__getitem__(item)

    def __len__(self):
        return self.mem.bitwidth

    def sign_extended(self, bitwidth):
        return as_wires(self).sign_extended(bitwidth)

    def zero_extended(self, bitwidth):
        return as_wires(self).zero_extended(bitwidth)

class _MemReadBase(object):
    """This is the base class for the memories and ROM blocks and
    it implements the read and initialization operations needed for
    both of them"""

    # FIXME: right now read port is built unconditionally (no read enable)

    def __init__(self,  bitwidth, addrwidth, name, asynchronous, block):

        self.block = working_block(block)
        name = next_tempvar_name(name)

        if bitwidth <= 0:
            raise PyrtlError('bitwidth must be >= 1')
        if addrwidth <= 0:
            raise PyrtlError('addrwidth must be >= 1')

        self.bitwidth = bitwidth
        self.name = name
        self.addrwidth = addrwidth
        self.readport_nets = []
        self.id = next_memid()
        self.asynchronous = asynchronous

    def __getitem__(self, item):
        """ Builds circitry to retrieve an item from the memory
        """
        from .helperfuncs import as_wires
        item = as_wires(item, bitwidth=self.addrwidth, truncating=False)
        if len(item) > self.addrwidth:
            raise PyrtlError('memory index bitwidth > addrwidth')
        return _MemIndexed(mem=self, index=item)

    def _readaccess(self, addr):
        # FIXME: add conditional read ports
        return self._build_read_port(addr)

    def _build_read_port(self, addr):
        data = WireVector(bitwidth=self.bitwidth)
        readport_net = LogicNet(
            op='m',
            op_param=(self.id, self),
            args=(addr,),
            dests=(data,))
        working_block().add_net(readport_net)
        self.readport_nets.append(readport_net)
        return data

    def __setitem__(self, key, value):
        """ Not legal on a object that only allows for reads"""
        raise PyrtlError("error, invalid call __setitem__ made on _MemReadBase")

    def _make_copy(self, block):
        pass

class MemBlock(_MemReadBase):
    """ An object for specifying read and write enabled block memories """
    # FIXME: write ports assume that only one port is under control of the conditional

    EnabledWrite = collections.namedtuple('EnabledWrite', 'data, enable')
    """ Allows for an enable bit for each write port

    Usage:
    mem[address] = MemBlock.EnabledWrite(d,enable=we)

    When the address of a memory is assigned to using a EnableWrite object
    items will only be written to the memory when the enable WireVector is
    set to high (1)
    """

    # data <<= memory[addr]  (infer read port)
    # memory[addr] <<= data  (infer write port)
    def __init__(self, bitwidth, addrwidth, name=None, asynchronous=False, block=None):
        """ Create MemBlock.

        :param int bitwidth: Defines the bitwidth of each element in the memory
        :param int addrwidth: The number of bits used to address an element of the
         memory. This also defines the size of the memory
        :param bool asynchronous: if false check that memories only indexed by registers
        :param basestring or None name: Name of the memory. Defaults to an autogenerated
         name
        :param block: the block to add it to. Defaults to the working block

        It is best practice to make sure your block memory/fifos read/write
        operations start on a clock edge.  MemBlocks will enforce this by making sure that
        you only address them with a register or input, unless you explicitly declare
        the memory as asynchronous with that flag.  Note that asynchronous mems are
        harder to synthesize (and can't be mapped to block rams in FPGAs).
        """
        super(MemBlock, self).__init__(bitwidth, addrwidth, name, asynchronous, block)
        self.writeport_nets = []

    def __setitem__(self, item, assignment):
        """ Builds circuitry to set an item in the memory """
        if isinstance(assignment, _MemAssignment):
            self._assignment(item, assignment.rhs, is_conditional=assignment.is_conditional)
        else:
            raise PyrtlError('error, assigment to memories should use "<<=" not "=" operator')

    def _assignment(self, item, val, is_conditional):
        from .helperfuncs import as_wires
        from .conditional import _build

        item = as_wires(item, bitwidth=self.addrwidth, truncating=False)
        if len(item) > self.addrwidth:
            raise PyrtlError('error, memory index bitwidth > addrwidth')
        addr = item

        if isinstance(val, MemBlock.EnabledWrite):
            data, enable = val.data, val.enable
        else:
            data, enable = val, Const(1, bitwidth=1)
        data = as_wires(data, bitwidth=self.bitwidth, truncating=False)
        enable = as_wires(enable, bitwidth=1, truncating=False)

        if len(data) != self.bitwidth:
            raise PyrtlError('error, write data larger than memory  bitwidth')
        if len(enable) != 1:
            raise PyrtlError('error, enable signal not exactly 1 bit')

        if is_conditional:
            _build(self, (addr, data, enable))
        else:
            self._build(addr, data, enable)

    def _build(self, addr, data, enable):
        """ Builds a write port. """
        writeport_net = LogicNet(
            op='@',
            op_param=(self.id, self),
            args=(addr, data, enable),
            dests=tuple())
        working_block().add_net(writeport_net)
        self.writeport_nets.append(writeport_net)

    def _make_copy(self, block=None):
        block = working_block(block)
        return MemBlock(bitwidth=self.bitwidth,
                        addrwidth=self.addrwidth,
                        name=self.name,
                        asynchronous=self.asynchronous,
                        block=block)

class RomBlock(_MemReadBase):
    """ PyRTL Read Only Memory.

    RomBlocks are the read only memory format in PyRTL
    By default, they synthesize down to transistor-based
    logic during synthesis
    """
    def __init__(self, bitwidth, addrwidth, romdata, name=None, asynchronous=False, block=None):
        """ Create a RomBlock
        :param int bitwidth: The bitwidth of each item stored in the ROM
        :param int addrwidth: The bitwidth of the address bus (determines number of addresses)
        :param function or iterable romdata: This can either be a function or an array that maps
          an address as an input to a result as an output
        :param str name: The identifier for the memory
        :param bool asynchronous: If False, check that memory reads start on clock edge

        It is best practice to make sure your block memory/fifos read/write
        operations start on a clock edge.  MemBlocks will enforce this by making sure that
        you only address them with a register or input, unless you explicitly declare
        the memory as asynchronous with that flag.  Note that asynchronous mems are
        harder to synthesize (and can't be mapped to block rams in FPGAs).
        """

        super(RomBlock, self).__init__(bitwidth, addrwidth, name, asynchronous, block)
        self.data = romdata

    def __getitem__(self, item):
        import numbers
        if isinstance(item, numbers.Number):
            raise PyrtlError("There is no point in indexing into a RomBlock with an int "
                             "Instead, get the value from the source data for this Rom")
            # If you really know what you are doing, use a Const WireVector instead.
        return super(RomBlock, self).__getitem__(item)

    def _get_read_data(self, address):
        import types
        try:
            if address < 0 or address > 2**self.addrwidth - 1:
                raise PyrtlError("Invalid address, " + str(address) + " specified")
        except TypeError:
            raise PyrtlError("Address: {} with invalid type specified".format(address))
        if isinstance(self.data, types.FunctionType):
            try:
                value = self.data(address)
            except Exception:
                raise PyrtlError("Invalid data function for RomBlock")
        else:
            try:
                value = self.data[address]
            except KeyError:
                value = 0
            except:
                raise PyrtlError("invalid type for RomBlock data object")

        try:
            if value < 0 or value >= 2**self.bitwidth:
                raise PyrtlError("invalid value for RomBlock data")
        except TypeError:
            raise PyrtlError("Value: {} from rom {} has an invalid type"
                             .format(value, self))
        return value

    def _make_copy(self, block=None):
        block = working_block(block)
        return RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth,
                        romdata=self.data, name=self.name,
                        asynchronous=self.asynchronous, block=block)
<commit_msg>Working on docstrings for memories. Fixes #115<commit_after>"""
Defines PyRTL memories.
These blocks of memories can be read (potentially async) and written (sync)

MemBlocks supports any number of the following operations:
read: d = mem[address]
write: mem[address] = d
write with an enable: mem[address] = MemBlock.EnabledWrite(d,enable=we)
Based on the number of reads and writes a memory will be inferred
with the correct number of ports to support that
"""

from __future__ import print_function, unicode_literals
import collections

from .pyrtlexceptions import PyrtlError
from .core import working_block, next_tempvar_name, next_memid, LogicNet
from .wire import WireVector, Const
from .helperfuncs import as_wires

# ------------------------------------------------------------------------
#
#         ___        __   __          __        __   __
#   |\/| |__   |\/| /  \ |__) \ /    |__) |    /  \ /  ` |__/
#   |  | |___  |  | \__/ |  \  |     |__) |___ \__/ \__, |  \
#

_MemAssignment = collections.namedtuple('_MemAssignment', 'rhs, is_conditional')
"""_MemAssignment is the type returned from assignment by |= or <<="""

class _MemIndexed(WireVector):
    """ Object used internally to route memory assigns correctly.

    The normal PyRTL user should never need to be aware that this class exists,
    hence the underscore in the name.  It presents a very similar interface to
    wiresVectors (all of the normal wirevector operations should still work),
    but if you try to *set* the value with <<= or |= then it will generate a
    _MemAssignment object rather than the normal wire assignment. """

    def __init__(self, mem, index):
        self.mem = mem
        self.index = index

    def __ilshift__(self, other):
        return _MemAssignment(rhs=other, is_conditional=False)

    def __ior__(self, other):
        return _MemAssignment(rhs=other, is_conditional=True)

    def logicop(self, other, op):
        return as_wires(self).logicop(other, op)

    def __invert__(self):
        return as_wires(self).__invert__()

    def __getitem__(self, item):
        return as_wires(self).__getitem__(item)

    def __len__(self):
        return self.mem.bitwidth

    def sign_extended(self, bitwidth):
        return as_wires(self).sign_extended(bitwidth)

    def zero_extended(self, bitwidth):
        return as_wires(self).zero_extended(bitwidth)

class _MemReadBase(object):
    """This is the base class for the memories and ROM blocks and
    it implements the read and initialization operations needed for
    both of them"""

    # FIXME: right now read port is built unconditionally (no read enable)

    def __init__(self,  bitwidth, addrwidth, name, asynchronous, block):
        self.block = working_block(block)
        name = next_tempvar_name(name)

        if bitwidth <= 0:
            raise PyrtlError('bitwidth must be >= 1')
        if addrwidth <= 0:
            raise PyrtlError('addrwidth must be >= 1')

        self.bitwidth = bitwidth
        self.name = name
        self.addrwidth = addrwidth
        self.readport_nets = []
        self.id = next_memid()
        self.asynchronous = asynchronous

    def __getitem__(self, item):
        """ Builds circuitry to retrieve an item from the memory
        """
        from .helperfuncs import as_wires
        item = as_wires(item, bitwidth=self.addrwidth, truncating=False)
        if len(item) > self.addrwidth:
            raise PyrtlError('memory index bitwidth > addrwidth')
        return _MemIndexed(mem=self, index=item)

    def _readaccess(self, addr):
        # FIXME: add conditional read ports
        return self._build_read_port(addr)

    def _build_read_port(self, addr):
        data = WireVector(bitwidth=self.bitwidth)
        readport_net = LogicNet(
            op='m',
            op_param=(self.id, self),
            args=(addr,),
            dests=(data,))
        working_block().add_net(readport_net)
        self.readport_nets.append(readport_net)
        return data

    def __setitem__(self, key, value):
        """ Not legal on a object that only allows for reads"""
        raise PyrtlError("error, invalid call __setitem__ made on _MemReadBase")

    def _make_copy(self, block):
        pass

class MemBlock(_MemReadBase):
    """ An object for specifying read and write enabled block memories """
    # FIXME: write ports assume that only one port is under control of the conditional

    EnabledWrite = collections.namedtuple('EnabledWrite', 'data, enable')
    """ Allows for an enable bit for each write port

    Usage:
    mem[address] = MemBlock.EnabledWrite(d,enable=we)

    When the address of a memory is assigned to using a EnableWrite object
    items will only be written to the memory when the enable WireVector is
    set to high (1)
    """

    # data <<= memory[addr]  (infer read port)
    # memory[addr] <<= data  (infer write port)
    def __init__(self, bitwidth, addrwidth, name=None, asynchronous=False, block=None):
        """
        Create a PyRTL read-write memory.

        :param int bitwidth: Defines the bitwidth of each element in the memory
        :param int addrwidth: The number of bits used to address an element of the
         memory. This also defines the size of the memory
        :param bool asynchronous: if false check that memories only indexed by registers
        :param basestring or None name: Name of the memory. Defaults to an autogenerated
         name
        :param block: the block to add it to. Defaults to the working block

        It is best practice to make sure your block memory/fifos read/write
        operations start on a clock edge.  MemBlocks will enforce this by making sure that
        you only address them with a register or input, unless you explicitly declare
        the memory as asynchronous with that flag.  Note that asynchronous mems are
        harder to synthesize (and can't be mapped to block rams in FPGAs).
        """
        super(MemBlock, self).__init__(bitwidth, addrwidth, name, asynchronous, block)
        self.writeport_nets = []

    def __setitem__(self, item, assignment):
        """ Builds circuitry to set an item in the memory """
        if isinstance(assignment, _MemAssignment):
            self._assignment(item, assignment.rhs, is_conditional=assignment.is_conditional)
        else:
            raise PyrtlError('error, assigment to memories should use "<<=" not "=" operator')

    def _assignment(self, item, val, is_conditional):
        from .helperfuncs import as_wires
        from .conditional import _build

        item = as_wires(item, bitwidth=self.addrwidth, truncating=False)
        if len(item) > self.addrwidth:
            raise PyrtlError('error, memory index bitwidth > addrwidth')
        addr = item

        if isinstance(val, MemBlock.EnabledWrite):
            data, enable = val.data, val.enable
        else:
            data, enable = val, Const(1, bitwidth=1)
        data = as_wires(data, bitwidth=self.bitwidth, truncating=False)
        enable = as_wires(enable, bitwidth=1, truncating=False)

        if len(data) != self.bitwidth:
            raise PyrtlError('error, write data larger than memory  bitwidth')
        if len(enable) != 1:
            raise PyrtlError('error, enable signal not exactly 1 bit')

        if is_conditional:
            _build(self, (addr, data, enable))
        else:
            self._build(addr, data, enable)

    def _build(self, addr, data, enable):
        """ Builds a write port. """
        writeport_net = LogicNet(
            op='@',
            op_param=(self.id, self),
            args=(addr, data, enable),
            dests=tuple())
        working_block().add_net(writeport_net)
        self.writeport_nets.append(writeport_net)

    def _make_copy(self, block=None):
        block = working_block(block)
        return MemBlock(bitwidth=self.bitwidth,
                        addrwidth=self.addrwidth,
                        name=self.name,
                        asynchronous=self.asynchronous,
                        block=block)

class RomBlock(_MemReadBase):
    """ PyRTL Read Only Memory.

    RomBlocks are the read only memory format in PyRTL
    """
    def __init__(self, bitwidth, addrwidth, romdata, name=None, asynchronous=False, block=None):
        """
        Create a Python Read Only Memory

        :param int bitwidth: The bitwidth of each item stored in the ROM
        :param int addrwidth: The bitwidth of the address bus (determines number of addresses)
        :param function or iterable romdata: This can either be a function or an array that maps
          an address as an input to a result as an output
        :param str name: The identifier for the memory
        :param bool asynchronous: If False, check that memory reads start on clock edge

        It is best practice to make sure your block memory/fifos read/write
        operations start on a clock edge.  MemBlocks will enforce this by making sure that
        you only address them with a register or input, unless you explicitly declare
        the memory as asynchronous with that flag.  Note that asynchronous mems are
        harder to synthesize (and can't be mapped to block rams in FPGAs).
        """

        super(RomBlock, self).__init__(bitwidth, addrwidth, name, asynchronous, block)
        self.data = romdata

    def __getitem__(self, item):
        import numbers
        if isinstance(item, numbers.Number):
            raise PyrtlError("There is no point in indexing into a RomBlock with an int "
                             "Instead, get the value from the source data for this Rom")
            # If you really know what you are doing, use a Const WireVector instead.
        return super(RomBlock, self).__getitem__(item)

    def _get_read_data(self, address):
        import types
        try:
            if address < 0 or address > 2**self.addrwidth - 1:
                raise PyrtlError("Invalid address, " + str(address) + " specified")
        except TypeError:
            raise PyrtlError("Address: {} with invalid type specified".format(address))
        if isinstance(self.data, types.FunctionType):
            try:
                value = self.data(address)
            except Exception:
                raise PyrtlError("Invalid data function for RomBlock")
        else:
            try:
                value = self.data[address]
            except KeyError:
                value = 0
            except:
                raise PyrtlError("invalid type for RomBlock data object")

        try:
            if value < 0 or value >= 2**self.bitwidth:
                raise PyrtlError("invalid value for RomBlock data")
        except TypeError:
            raise PyrtlError("Value: {} from rom {} has an invalid type"
                             .format(value, self))
        return value

    def _make_copy(self, block=None):
        block = working_block(block)
        return RomBlock(bitwidth=self.bitwidth, addrwidth=self.addrwidth,
                        romdata=self.data, name=self.name,
                        asynchronous=self.asynchronous, block=block)
<|endoftext|>


<commit_before>"""Helpers for sparkle packaging."""

load("@io_tweag_clodl//clodl:clodl.bzl", "library_closure")

def _mangle_dir(name):
    """Creates a unique directory name from the repo name and package
      name of the package being evaluated, and a given name.
    """
    components = [native.repository_name(), native.package_name(), name]
    components = [c.replace("@", "") for c in components]
    components = [c for c in components if c]
    return "/".join(components).replace("_", "_U").replace("/", "_S")

def sparkle_package(name, src, **kwargs):
  libclosure = "libclosure-%s" % name

  library_closure(
    name = libclosure,
    srcs = [src],
    excludes = [
      "ld\.so.*",
      "ld-linux\.so.*",
      "ld-linux-x86-64\.so.*",
      "libgcc_s\.so.*",
      "libc\.so.*",
      "libcrypt\.so.*",
      "libdl\.so.*",
      "libjava\.so.*",
      "libjli\.so.*",
      "libjvm\.so.*",
      "libm\.so.*",
      "libpthread\.so.*",
      "librt\.so.*",
      "libresolv\.so.*",
      "libstdc++\.so.*",
      "libutil\.so.*",
      "libz\.so.*",
    ],
    **kwargs
  )

  libclosure_renamed = "libclosure-%s-renamed"
  native.genrule(
    name = libclosure_renamed,
    srcs = [libclosure],
    outs = [_mangle_dir(libclosure) + "/sparkle-app.zip"],
    cmd = "cp $< $@",
  )

  native.java_binary(
    name = name,
    create_executable = False,
    classpath_resources = [libclosure_renamed],
    resource_jars = ["@io_tweag_sparkle//:sparkle-jar"],
    deploy_manifest_lines = ["Main-Class: io.tweag.sparkle.SparkMain"]
  )
<commit_msg>Allow to pass jar dependencies to sparkle_package<commit_after>"""Helpers for sparkle packaging."""

load("@io_tweag_clodl//clodl:clodl.bzl", "library_closure")

def _mangle_dir(name):
    """Creates a unique directory name from the repo name and package
      name of the package being evaluated, and a given name.
    """
    components = [native.repository_name(), native.package_name(), name]
    components = [c.replace("@", "") for c in components]
    components = [c for c in components if c]
    return "/".join(components).replace("_", "_U").replace("/", "_S")

def sparkle_package(name, src, resource_jars=[], **kwargs):
  libclosure = "libclosure-%s" % name

  library_closure(
    name = libclosure,
    srcs = [src],
    excludes = [
      "ld\.so.*",
      "ld-linux\.so.*",
      "ld-linux-x86-64\.so.*",
      "libgcc_s\.so.*",
      "libc\.so.*",
      "libcrypt\.so.*",
      "libdl\.so.*",
      "libjava\.so.*",
      "libjli\.so.*",
      "libjvm\.so.*",
      "libm\.so.*",
      "libpthread\.so.*",
      "librt\.so.*",
      "libresolv\.so.*",
      "libstdc++\.so.*",
      "libutil\.so.*",
      "libz\.so.*",
    ],
    **kwargs
  )

  libclosure_renamed = "libclosure-%s-renamed"
  native.genrule(
    name = libclosure_renamed,
    srcs = [libclosure],
    outs = [_mangle_dir(libclosure) + "/sparkle-app.zip"],
    cmd = "cp $< $@",
  )

  native.java_binary(
    name = name,
    create_executable = False,
    classpath_resources = [libclosure_renamed],
    resource_jars = ["@io_tweag_sparkle//:sparkle-jar"] + resource_jars,
    deploy_manifest_lines = ["Main-Class: io.tweag.sparkle.SparkMain"]
  )
<|endoftext|>


<commit_before>"""Views for lutris main app"""
# pylint: disable=E1101, W0613
import logging
from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.core.mail import mail_managers
from django.contrib.syndication.views import Feed
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from .models import Game, Runner, Installer, GameSubmission
from . import models
from .forms import InstallerForm, ScreenshotForm, GameForm

LOGGER = logging.getLogger(__name__)

class GameList(ListView):
    model = Game
    context_object_name = "games"
    paginate_by = 25

    def get_queryset(self):
        without_installer = self.request.GET.get('without_installer')
        if without_installer:
            queryset = Game.objects.published()
        else:
            queryset = Game.objects.with_installer()
        search_terms = self.request.GET.get('q')
        if search_terms:
            queryset = queryset.filter(name__icontains=search_terms)
        return queryset

    def get_context_data(self, **kwargs):
        context = super(GameList, self).get_context_data(**kwargs)
        search_terms = self.request.GET.get('q')
        context['platforms'] = models.Platform.objects.all()
        context['genres'] = models.Genre.objects.all()
        if search_terms:
            context['search_terms'] = search_terms
        return context

class GameListByYear(GameList):
    def get_queryset(self):
        queryset = super(GameListByYear, self).get_queryset()
        return queryset.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(GameList):
    """View for games filtered by genre"""
    def get_queryset(self):
        queryset = super(GameListByGenre, self).get_queryset()
        return queryset.filter(genres__slug=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        try:
            context['genre'] = models.Genre.objects.get(slug=self.args[0])
        except models.Genre.DoesNotExist:
            raise Http404
        return context

class GameListByCompany(GameList):
    """View for games filtered by publisher"""
    def get_queryset(self):
        queryset = super(GameListByCompany, self).get_queryset()
        return queryset.filter(Q(publisher__slug=self.args[0])
                               | Q(developer__slug=self.args[0]))

    def get_context_data(self, **kwargs):
        context = super(GameListByCompany, self).get_context_data(**kwargs)
        try:
            context['company'] = models.Company.objects.get(slug=self.args[0])
        except models.Company.DoesNotExist:
            raise Http404
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        queryset = super(GameListByPlatform, self).get_queryset()
        return queryset.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        try:
            context['platform'] = models.Platform.objects.get(
                slug=self.kwargs['slug']
            )
        except models.Platform.DoesNotExist:
            raise Http404
        return context

def game_for_installer(request, slug):
    """ Redirects to the game details page from a valid installer slug """
    try:
        installers = models.Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    installer = installers[0]
    game_slug = installer.game.slug
    return redirect(reverse('game_detail', kwargs={'slug': game_slug}))

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    banner_options = {'crop': 'top', 'blur': '14x6'}
    banner_size = "940x352"
    user = request.user
    game.website_text = game.website.strip('htps:').strip('/')

    if user.is_authenticated():
        in_library = game in user.gamelibrary.games.all()
        installers = game.installer_set.published(user=user,
                                                  is_staff=user.is_staff)
        screenshots = game.screenshot_set.published(user=user,
                                                    is_staff=user.is_staff)
    else:
        in_library = False
        installers = game.installer_set.published()
        screenshots = game.screenshot_set.published()

    # auto_installers = game.get_default_installers()
    auto_installers = []
    return render(request, 'games/detail.html',
                  {'game': game,
                   'banner_options': banner_options,
                   'banner_size': banner_size,
                   'in_library': in_library,
                   'installers': installers,
                   'auto_installers': auto_installers,
                   'screenshots': screenshots})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    installer = Installer(game=game)
    installer.set_default_installer()
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user = request.user
        installer.save()
        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

@login_required
def publish_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if not request.user.is_staff:
        raise Http404
    installer.published = True
    installer.save()
    return redirect('game_detail', slug=installer.game.slug)

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if installer.user != request.user and not request.user.is_staff:
        raise Http404
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(_request, slug):
    """Serve the content of an installer in yaml format."""
    try:
        installers = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    installer = installers[0]
    return HttpResponse(installer.as_yaml(), content_type='application/yaml')

def get_installers(request, slug):
    try:
        installers_json = Installer.objects.get_json(slug)
    except Installer.DoesNotExist:
        raise Http404
    return HttpResponse(installers_json, content_type='application/json')

class InstallerFeed(Feed):
    title = "Lutris installers"
    link = '/games/'
    description = u"Latest lutris installers"
    feed_size = 20

    def items(self):
        return Installer.objects.order_by("-created_at")[:self.feed_size]

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.content

    def item_link(self, item):
        return item.get_absolute_url()

def get_game_by_slug(slug):
    """Return game matching an installer slug or game slug"""
    game = None
    try:
        installers = Installer.objects.fuzzy_get(slug)
        installer = installers[0]
        game = installer.game
    except Installer.DoesNotExist:
        try:
            game = Game.objects.get(slug=slug)
        except Game.DoesNotExist:
            pass
    return game

def get_banner(request, slug):
    """Serve game title in an appropriate format for the client."""
    game = get_game_by_slug(slug)
    if not game or not game.title_logo:
        raise Http404
    thumbnail = get_thumbnail(game.title_logo, settings.BANNER_SIZE,
                              crop="center")
    return redirect(thumbnail.url)

def serve_installer_banner(request, slug):
    return get_banner(request, slug)

def get_icon(request, slug):
    game = get_game_by_slug(slug)
    if not game or not game.icon:
        raise Http404
    thumbnail = get_thumbnail(game.icon, settings.ICON_SIZE, crop="center",
                              format="PNG")
    return redirect(thumbnail.url)

def serve_installer_icon(request, slug):
    """ Legacy url, remove by Lutris 0.4 """
    return get_icon(request, slug)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

@login_required
def submit_game(request):
    form = GameForm(request.POST or None, request.FILES or None)
    if request.method == "POST" and form.is_valid():
        game = form.save()
        submission = GameSubmission(user=request.user, game=game)
        submission.save()

        # Notify managers a game has been submitted
        subject = "New game submitted: {0}".format(game.name)
        admin_url = reverse("admin:games_game_change", args=(game.id, ))
        body = """
        The game {0} has been added by {1}.

        It can be modified and published at https://lutris.net{2}
        """.format(game.name, request.user, admin_url)
        mail_managers(subject, body)
        redirect_url = request.build_absolute_uri(reverse("game-submitted"))

        # Enforce https
        if not settings.DEBUG:
            redirect_url = redirect_url.replace('http:', 'https:')

        LOGGER.info('Game submitted, redirecting to %s', redirect_url)
        return redirect(redirect_url)
    return render(request, 'games/submit.html', {'form': form})

@login_required
def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, request.FILES or None,
                          game_id=game.id)
    if form.is_valid():
        form.instance.uploaded_by = request.user
        form.save()
        return redirect(reverse("game_detail", kwargs={'slug': slug}))
    return render(request, 'games/screenshot/add.html', {'form': form})

@login_required
def publish_screenshot(request, id):
    screenshot = get_object_or_404(models.Screenshot, id=id)
    if not request.user.is_staff:
        raise Http404
    screenshot.published = True
    screenshot.save()
    return redirect('game_detail', slug=screenshot.game.slug)
<commit_msg>Make email submission string into unicode<commit_after>"""Views for lutris main app"""
# pylint: disable=E1101, W0613
import logging
from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.core.mail import mail_managers
from django.contrib.syndication.views import Feed
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from .models import Game, Runner, Installer, GameSubmission
from . import models
from .forms import InstallerForm, ScreenshotForm, GameForm

LOGGER = logging.getLogger(__name__)

class GameList(ListView):
    model = Game
    context_object_name = "games"
    paginate_by = 25

    def get_queryset(self):
        without_installer = self.request.GET.get('without_installer')
        if without_installer:
            queryset = Game.objects.published()
        else:
            queryset = Game.objects.with_installer()
        search_terms = self.request.GET.get('q')
        if search_terms:
            queryset = queryset.filter(name__icontains=search_terms)
        return queryset

    def get_context_data(self, **kwargs):
        context = super(GameList, self).get_context_data(**kwargs)
        search_terms = self.request.GET.get('q')
        context['platforms'] = models.Platform.objects.all()
        context['genres'] = models.Genre.objects.all()
        if search_terms:
            context['search_terms'] = search_terms
        return context

class GameListByYear(GameList):
    def get_queryset(self):
        queryset = super(GameListByYear, self).get_queryset()
        return queryset.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(GameList):
    """View for games filtered by genre"""
    def get_queryset(self):
        queryset = super(GameListByGenre, self).get_queryset()
        return queryset.filter(genres__slug=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        try:
            context['genre'] = models.Genre.objects.get(slug=self.args[0])
        except models.Genre.DoesNotExist:
            raise Http404
        return context

class GameListByCompany(GameList):
    """View for games filtered by publisher"""
    def get_queryset(self):
        queryset = super(GameListByCompany, self).get_queryset()
        return queryset.filter(Q(publisher__slug=self.args[0])
                               | Q(developer__slug=self.args[0]))

    def get_context_data(self, **kwargs):
        context = super(GameListByCompany, self).get_context_data(**kwargs)
        try:
            context['company'] = models.Company.objects.get(slug=self.args[0])
        except models.Company.DoesNotExist:
            raise Http404
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        queryset = super(GameListByPlatform, self).get_queryset()
        return queryset.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        try:
            context['platform'] = models.Platform.objects.get(
                slug=self.kwargs['slug']
            )
        except models.Platform.DoesNotExist:
            raise Http404
        return context

def game_for_installer(request, slug):
    """ Redirects to the game details page from a valid installer slug """
    try:
        installers = models.Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    installer = installers[0]
    game_slug = installer.game.slug
    return redirect(reverse('game_detail', kwargs={'slug': game_slug}))

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    banner_options = {'crop': 'top', 'blur': '14x6'}
    banner_size = "940x352"
    user = request.user
    game.website_text = game.website.strip('htps:').strip('/')

    if user.is_authenticated():
        in_library = game in user.gamelibrary.games.all()
        installers = game.installer_set.published(user=user,
                                                  is_staff=user.is_staff)
        screenshots = game.screenshot_set.published(user=user,
                                                    is_staff=user.is_staff)
    else:
        in_library = False
        installers = game.installer_set.published()
        screenshots = game.screenshot_set.published()

    # auto_installers = game.get_default_installers()
    auto_installers = []
    return render(request, 'games/detail.html',
                  {'game': game,
                   'banner_options': banner_options,
                   'banner_size': banner_size,
                   'in_library': in_library,
                   'installers': installers,
                   'auto_installers': auto_installers,
                   'screenshots': screenshots})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    installer = Installer(game=game)
    installer.set_default_installer()
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user = request.user
        installer.save()
        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

@login_required
def publish_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if not request.user.is_staff:
        raise Http404
    installer.published = True
    installer.save()
    return redirect('game_detail', slug=installer.game.slug)

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if installer.user != request.user and not request.user.is_staff:
        raise Http404
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(_request, slug):
    """Serve the content of an installer in yaml format."""
    try:
        installers = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    installer = installers[0]
    return HttpResponse(installer.as_yaml(), content_type='application/yaml')

def get_installers(request, slug):
    try:
        installers_json = Installer.objects.get_json(slug)
    except Installer.DoesNotExist:
        raise Http404
    return HttpResponse(installers_json, content_type='application/json')

class InstallerFeed(Feed):
    title = "Lutris installers"
    link = '/games/'
    description = u"Latest lutris installers"
    feed_size = 20

    def items(self):
        return Installer.objects.order_by("-created_at")[:self.feed_size]

    def item_title(self, item):
        return item.title

    def item_description(self, item):
        return item.content

    def item_link(self, item):
        return item.get_absolute_url()

def get_game_by_slug(slug):
    """Return game matching an installer slug or game slug"""
    game = None
    try:
        installers = Installer.objects.fuzzy_get(slug)
        installer = installers[0]
        game = installer.game
    except Installer.DoesNotExist:
        try:
            game = Game.objects.get(slug=slug)
        except Game.DoesNotExist:
            pass
    return game

def get_banner(request, slug):
    """Serve game title in an appropriate format for the client."""
    game = get_game_by_slug(slug)
    if not game or not game.title_logo:
        raise Http404
    thumbnail = get_thumbnail(game.title_logo, settings.BANNER_SIZE,
                              crop="center")
    return redirect(thumbnail.url)

def serve_installer_banner(request, slug):
    return get_banner(request, slug)

def get_icon(request, slug):
    game = get_game_by_slug(slug)
    if not game or not game.icon:
        raise Http404
    thumbnail = get_thumbnail(game.icon, settings.ICON_SIZE, crop="center",
                              format="PNG")
    return redirect(thumbnail.url)

def serve_installer_icon(request, slug):
    """ Legacy url, remove by Lutris 0.4 """
    return get_icon(request, slug)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

@login_required
def submit_game(request):
    form = GameForm(request.POST or None, request.FILES or None)
    if request.method == "POST" and form.is_valid():
        game = form.save()
        submission = GameSubmission(user=request.user, game=game)
        submission.save()

        # Notify managers a game has been submitted
        subject = u"New game submitted: {0}".format(game.name)
        admin_url = reverse("admin:games_game_change", args=(game.id, ))
        body = u"""
        The game {0} has been added by {1}.

        It can be modified and published at https://lutris.net{2}
        """.format(game.name, request.user, admin_url)
        mail_managers(subject, body)
        redirect_url = request.build_absolute_uri(reverse("game-submitted"))

        # Enforce https
        if not settings.DEBUG:
            redirect_url = redirect_url.replace('http:', 'https:')

        LOGGER.info('Game submitted, redirecting to %s', redirect_url)
        return redirect(redirect_url)
    return render(request, 'games/submit.html', {'form': form})

@login_required
def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, request.FILES or None,
                          game_id=game.id)
    if form.is_valid():
        form.instance.uploaded_by = request.user
        form.save()
        return redirect(reverse("game_detail", kwargs={'slug': slug}))
    return render(request, 'games/screenshot/add.html', {'form': form})

@login_required
def publish_screenshot(request, id):
    screenshot = get_object_or_404(models.Screenshot, id=id)
    if not request.user.is_staff:
        raise Http404
    screenshot.published = True
    screenshot.save()
    return redirect('game_detail', slug=screenshot.game.slug)
<|endoftext|>


<commit_before>"""Views for lutris main app"""
# pylint: disable=E1101, R0901
import yaml

from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from .models import Game, Runner, Installer
from . import models
from .forms import InstallerForm, ScreenshotForm, GameForm

class GameList(ListView):
    model = Game
    context_object_name = "games"
    paginate_by = 25

    def get_queryset(self):
        queryset = Game.objects.published()
        installers = Installer.objects.published().values("game_id")
        search_terms = self.request.GET.get('q')
        without_installer = self.request.GET.get('without_installer')
        if search_terms:
            queryset = queryset.filter(name__icontains=search_terms)
        if not without_installer:
            queryset = queryset.filter(id__in=installers)
        return queryset

    def get_context_data(self, **kwargs):
        context = super(GameList, self).get_context_data(**kwargs)
        search_terms = self.request.GET.get('q')
        context['platforms'] = models.Platform.objects.all()
        context['genres'] = models.Genre.objects.all()
        if search_terms:
            context['search_terms'] = search_terms
        return context

class GameListByYear(GameList):
    def get_queryset(self):
        queryset = super(GameListByYear, self).get_queryset()
        return queryset.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(GameList):
    """View for games filtered by genre"""
    def get_queryset(self):
        queryset = super(GameListByGenre, self).get_queryset()
        return queryset.filter(genres__slug=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        try:
            context['genre'] = models.Genre.objects.get(slug=self.args[0])
        except models.Genre.DoesNotExist:
            raise Http404
        return context

class GameListByCompany(GameList):
    """View for games filtered by publisher"""
    def get_queryset(self):
        queryset = super(GameListByCompany, self).get_queryset()
        return queryset.filter(Q(publisher__slug=self.args[0])
                               | Q(developer__slug=self.args[0]))

    def get_context_data(self, **kwargs):
        context = super(GameListByCompany, self).get_context_data(**kwargs)
        try:
            context['company'] = models.Company.objects.get(slug=self.args[0])
        except models.Company.DoesNotExist:
            raise Http404
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        queryset = super(GameListByPlatform, self).get_queryset()
        return queryset.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        try:
            context['platform'] = models.Platform.objects.get(
                slug=self.kwargs['slug']
            )
        except models.Platform.DoesNotExist:
            raise Http404
        return context

def game_for_installer(request, slug):
    """ Redirects to the game details page from a valid installer slug """
    try:
        installer = models.Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    game_slug = installer.game.slug
    return redirect(reverse('game_detail', kwargs={'slug': game_slug}))

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    banner_options = {'crop': 'top', 'blur': '14x6'}
    banner_size = "940x352"
    user = request.user

    if user.is_authenticated():
        in_library = game in user.gamelibrary.games.all()
        installers = game.installer_set.published(user=user)
    else:
        in_library = False
        installers = game.installer_set.published()

    return render(request, 'games/detail.html',
                  {'game': game,
                   'banner_options': banner_options,
                   'banner_size': banner_size,
                   'in_library': in_library,
                   'installers': installers})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    installer = Installer(game=game)
    installer.set_default_installer()
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user = request.user
        installer.save()
        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

@login_required
def publish_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if not request.user.is_staff:
        raise Http404
    installer.published = True
    installer.save()
    return redirect('game_detail', slug=installer.game.slug)

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if installer.user is not request.user and not request.user.is_staff:
        raise Http404
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(_request, slug):
    """ Serve the content of an installer in yaml format. """
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    yaml_content = yaml.safe_load(installer.content)
    yaml_content['version'] = installer.version
    yaml_content['name'] = installer.game.name
    yaml_content['runner'] = installer.runner.slug
    content = yaml.safe_dump(yaml_content)
    return HttpResponse(content, content_type="application/yaml")

def get_game_by_slug(slug):
    game = None
    try:
        installer = Installer.objects.fuzzy_get(slug)
        game = installer.game
    except Installer.DoesNotExist:
        try:
            game = Game.objects.get(slug=slug)
        except Game.DoesNotExist:
            pass
    return game

def serve_installer_banner(_request, slug):
    """ Serve game title in an appropriate format for the client. """
    game = get_game_by_slug(slug)
    if not game or not game.title_logo:
        raise Http404
    thumbnail = get_thumbnail(game.title_logo, settings.BANNER_SIZE,
                              crop="top")
    return redirect(thumbnail.url)

def serve_installer_icon(_request, slug):
    game = get_game_by_slug(slug)
    if not game or not game.icon:
        raise Http404
    thumbnail = get_thumbnail(game.icon, settings.ICON_SIZE, crop="top")
    return redirect(thumbnail.url)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def submit_game(request):
    form = GameForm(request.POST or None, request.FILES or None)
    if request.method == "POST" and form.is_valid():
        form.save()
        return redirect(reverse("game-submitted"))
    return render(request, 'games/submit.html', {'form': form})

@login_required
def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, request.FILES or None,
                          game_id=game.id)
    if form.is_valid():
        form.instance.uploaded_by = request.user
        form.save()
        return redirect(reverse("game_detail", kwargs={'slug': slug}))
    return render(request, 'games/screenshot/add.html', {'form': form})
<commit_msg>Add installer slug to installer scripts<commit_after>"""Views for lutris main app"""
# pylint: disable=E1101, R0901
import yaml

from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.db.models import Q
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from .models import Game, Runner, Installer
from . import models
from .forms import InstallerForm, ScreenshotForm, GameForm

class GameList(ListView):
    model = Game
    context_object_name = "games"
    paginate_by = 25

    def get_queryset(self):
        queryset = Game.objects.published()
        installers = Installer.objects.published().values("game_id")
        search_terms = self.request.GET.get('q')
        without_installer = self.request.GET.get('without_installer')
        if search_terms:
            queryset = queryset.filter(name__icontains=search_terms)
        if not without_installer:
            queryset = queryset.filter(id__in=installers)
        return queryset

    def get_context_data(self, **kwargs):
        context = super(GameList, self).get_context_data(**kwargs)
        search_terms = self.request.GET.get('q')
        context['platforms'] = models.Platform.objects.all()
        context['genres'] = models.Genre.objects.all()
        if search_terms:
            context['search_terms'] = search_terms
        return context

class GameListByYear(GameList):
    def get_queryset(self):
        queryset = super(GameListByYear, self).get_queryset()
        return queryset.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(GameList):
    """View for games filtered by genre"""
    def get_queryset(self):
        queryset = super(GameListByGenre, self).get_queryset()
        return queryset.filter(genres__slug=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        try:
            context['genre'] = models.Genre.objects.get(slug=self.args[0])
        except models.Genre.DoesNotExist:
            raise Http404
        return context

class GameListByCompany(GameList):
    """View for games filtered by publisher"""
    def get_queryset(self):
        queryset = super(GameListByCompany, self).get_queryset()
        return queryset.filter(Q(publisher__slug=self.args[0])
                               | Q(developer__slug=self.args[0]))

    def get_context_data(self, **kwargs):
        context = super(GameListByCompany, self).get_context_data(**kwargs)
        try:
            context['company'] = models.Company.objects.get(slug=self.args[0])
        except models.Company.DoesNotExist:
            raise Http404
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        queryset = super(GameListByPlatform, self).get_queryset()
        return queryset.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        try:
            context['platform'] = models.Platform.objects.get(
                slug=self.kwargs['slug']
            )
        except models.Platform.DoesNotExist:
            raise Http404
        return context

def game_for_installer(request, slug):
    """ Redirects to the game details page from a valid installer slug """
    try:
        installer = models.Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    game_slug = installer.game.slug
    return redirect(reverse('game_detail', kwargs={'slug': game_slug}))

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    banner_options = {'crop': 'top', 'blur': '14x6'}
    banner_size = "940x352"
    user = request.user

    if user.is_authenticated():
        in_library = game in user.gamelibrary.games.all()
        installers = game.installer_set.published(user=user)
    else:
        in_library = False
        installers = game.installer_set.published()

    return render(request, 'games/detail.html',
                  {'game': game,
                   'banner_options': banner_options,
                   'banner_size': banner_size,
                   'in_library': in_library,
                   'installers': installers})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    installer = Installer(game=game)
    installer.set_default_installer()
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user = request.user
        installer.save()
        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

@login_required
def publish_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if not request.user.is_staff:
        raise Http404
    installer.published = True
    installer.save()
    return redirect('game_detail', slug=installer.game.slug)

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    if installer.user is not request.user and not request.user.is_staff:
        raise Http404
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(_request, slug):
    """ Serve the content of an installer in yaml format. """
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    yaml_content = yaml.safe_load(installer.content)
    yaml_content['version'] = installer.version
    yaml_content['name'] = installer.game.name
    yaml_content['runner'] = installer.runner.slug
    yaml_content['installer_slug'] = installer.slug
    content = yaml.safe_dump(yaml_content)
    return HttpResponse(content, content_type="application/yaml")

def get_game_by_slug(slug):
    game = None
    try:
        installer = Installer.objects.fuzzy_get(slug)
        game = installer.game
    except Installer.DoesNotExist:
        try:
            game = Game.objects.get(slug=slug)
        except Game.DoesNotExist:
            pass
    return game

def serve_installer_banner(_request, slug):
    """ Serve game title in an appropriate format for the client. """
    game = get_game_by_slug(slug)
    if not game or not game.title_logo:
        raise Http404
    thumbnail = get_thumbnail(game.title_logo, settings.BANNER_SIZE,
                              crop="top")
    return redirect(thumbnail.url)

def serve_installer_icon(_request, slug):
    game = get_game_by_slug(slug)
    if not game or not game.icon:
        raise Http404
    thumbnail = get_thumbnail(game.icon, settings.ICON_SIZE, crop="top")
    return redirect(thumbnail.url)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def submit_game(request):
    form = GameForm(request.POST or None, request.FILES or None)
    if request.method == "POST" and form.is_valid():
        form.save()
        return redirect(reverse("game-submitted"))
    return render(request, 'games/submit.html', {'form': form})

@login_required
def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, request.FILES or None,
                          game_id=game.id)
    if form.is_valid():
        form.instance.uploaded_by = request.user
        form.save()
        return redirect(reverse("game_detail", kwargs={'slug': slug}))
    return render(request, 'games/screenshot/add.html', {'form': form})
<|endoftext|>


<commit_before>"""Views for lutris main app"""
# pylint: disable=E1101
import yaml

from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from games.models import Game, Runner, Installer, Platform
from games.forms import InstallerForm, ScreenshotForm, GameForm

class GameList(ListView):
    model = Game
    context_object_name = "games"

class GameListByYear(GameList):
    def get_queryset(self):
        return Game.objects.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(ListView):
    """View for games filtered by genre"""
    def get_queryset(self):
        return Game.objects.filter(genre=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['genre'] = self.args[0]
        return context

class GameListByPublisher(ListView):
    """View for games filtered by publisher"""
    def get_queryset(self):
        return Game.objects.filter(publisher=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['publisher'] = self.args[0]
        return context

class GameListByDeveloper(ListView):
    """View for games filtered by developer"""
    def get_queryset(self):
        return Game.objects.filter(developer=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['developer'] = self.args[0]
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        return Game.objects.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        context['platform'] = Platform.objects.get(slug=self.kwargs['slug'])
        return context

def download_latest(request):
    archive_url = settings.LATEST_LUSTRIS_DEB
    return redirect(archive_url)

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/detail.html', {'game': game})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = InstallerForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(request, slug):
    """Serve the content of an installer in yaml format"""
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    yaml_content = yaml.safe_load(installer.content)
    yaml_content['version'] = installer.version
    yaml_content['name'] = installer.game.name
    content = yaml.safe_dump(yaml_content)
    return HttpResponse(content, content_type="application/yaml")

def serve_installer_banner(request, slug):
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    if not installer.game.title_logo:
        raise Http404
    banner_thumbnail = get_thumbnail(installer.game.title_logo,
                                     settings.BANNER_SIZE,
                                     crop="top")
    return redirect(banner_thumbnail.url)

def serve_installer_icon(request, slug):
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    if not installer.game.icon:
        raise Http404
    banner_thumbnail = get_thumbnail(installer.game.icon,
                                     settings.ICON_SIZE,
                                     crop="top")
    return redirect(banner_thumbnail.url)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def submit_game(request):
    form = GameForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        form.save()
        return redirect(reverse("game-submitted"))
    return render(request, 'games/submit.html', {'form': form})

def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, game_id=game.id)
    if form.is_valid():
        form.save()
    return render(request, 'games/screenshot/add.html', {'form': form})
<commit_msg>Add runner to installer file<commit_after>"""Views for lutris main app"""
# pylint: disable=E1101
import yaml

from django.conf import settings
from django.http import HttpResponse, Http404
from django.views.generic import ListView
from django.shortcuts import render, redirect, get_object_or_404
from django.core.urlresolvers import reverse
from django.contrib.auth.decorators import login_required

from sorl.thumbnail import get_thumbnail

from games.models import Game, Runner, Installer, Platform
from games.forms import InstallerForm, ScreenshotForm, GameForm

class GameList(ListView):
    model = Game
    context_object_name = "games"

class GameListByYear(GameList):
    def get_queryset(self):
        return Game.objects.filter(year=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByYear, self).get_context_data(**kwargs)
        context['year'] = self.args[0]
        return context

class GameListByGenre(ListView):
    """View for games filtered by genre"""
    def get_queryset(self):
        return Game.objects.filter(genre=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['genre'] = self.args[0]
        return context

class GameListByPublisher(ListView):
    """View for games filtered by publisher"""
    def get_queryset(self):
        return Game.objects.filter(publisher=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['publisher'] = self.args[0]
        return context

class GameListByDeveloper(ListView):
    """View for games filtered by developer"""
    def get_queryset(self):
        return Game.objects.filter(developer=self.args[0])

    def get_context_data(self, **kwargs):
        context = super(GameListByGenre, self).get_context_data(**kwargs)
        context['developer'] = self.args[0]
        return context

class GameListByPlatform(GameList):
    """View for games filtered by platform"""
    def get_queryset(self):
        return Game.objects.filter(platforms__slug=self.kwargs['slug'])

    def get_context_data(self, **kwargs):
        context = super(GameListByPlatform, self).get_context_data(**kwargs)
        context['platform'] = Platform.objects.get(slug=self.kwargs['slug'])
        return context

def download_latest(request):
    archive_url = settings.LATEST_LUSTRIS_DEB
    return redirect(archive_url)

def game_detail(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/detail.html', {'game': game})

@login_required
def new_installer(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = InstallerForm(request.POST or None)
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

        return redirect("installer_complete", slug=game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': game})

def validate(game, request, form):
    if request.method == 'POST' and form.is_valid():
        installer = form.save(commit=False)
        installer.game_id = game.id
        installer.user_id = request.user.id
        installer.save()

@login_required
def edit_installer(request, slug):
    installer = get_object_or_404(Installer, slug=slug)
    form = InstallerForm(request.POST or None, instance=installer)
    if request.method == 'POST' and form.is_valid():
        form.save()
        return redirect("installer_complete", slug=installer.game.slug)
    return render(request, 'games/installer-form.html',
                  {'form': form, 'game': installer.game, 'new': False})

def installer_complete(request, slug):
    game = get_object_or_404(Game, slug=slug)
    return render(request, 'games/installer-complete.html', {'game': game})

def serve_installer(request, slug):
    """Serve the content of an installer in yaml format"""
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    yaml_content = yaml.safe_load(installer.content)
    yaml_content['version'] = installer.version
    yaml_content['name'] = installer.game.name
    yaml_content['runner'] = installer.runner.slug
    content = yaml.safe_dump(yaml_content)
    return HttpResponse(content, content_type="application/yaml")

def serve_installer_banner(request, slug):
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    if not installer.game.title_logo:
        raise Http404
    banner_thumbnail = get_thumbnail(installer.game.title_logo,
                                     settings.BANNER_SIZE,
                                     crop="top")
    return redirect(banner_thumbnail.url)

def serve_installer_icon(request, slug):
    try:
        installer = Installer.objects.fuzzy_get(slug)
    except Installer.DoesNotExist:
        raise Http404
    if not installer.game.icon:
        raise Http404
    banner_thumbnail = get_thumbnail(installer.game.icon,
                                     settings.ICON_SIZE,
                                     crop="top")
    return redirect(banner_thumbnail.url)

def game_list(request):
    """View for all games"""
    games = Game.objects.all()
    return render(request, 'games/game_list.html', {'games': games})

def games_by_runner(request, runner_slug):
    """View for games filtered by runner"""
    runner = get_object_or_404(Runner, slug=runner_slug)
    games = Game.objects.filter(runner__slug=runner.slug)
    return render(request, 'games/game_list.html',
                  {'games': games})

def submit_game(request):
    form = GameForm(request.POST or None)
    if request.method == "POST" and form.is_valid():
        form.save()
        return redirect(reverse("game-submitted"))
    return render(request, 'games/submit.html', {'form': form})

def screenshot_add(request, slug):
    game = get_object_or_404(Game, slug=slug)
    form = ScreenshotForm(request.POST or None, game_id=game.id)
    if form.is_valid():
        form.save()
    return render(request, 'games/screenshot/add.html', {'form': form})
<|endoftext|>


<commit_before>"""
https://gist.github.com/uroshekic/11078820
Inspired by http://code.activestate.com/recipes/578253-an-entry-with-autocompletion-for-the-tkinter-gui/
Changes:
    - Fixed AttributeError: 'AutocompleteEntry' object has no attribute 'listbox'
    - Fixed scrolling listbox
    - Case-insensitive search
    - Added focus to entry field
    - Custom listbox length, listbox width matches entry field width
    - Custom matches function
"""

from tkinter import *
from tkinter.ttk import *
import re

class AutoCompleteEntry(Entry):
    def __init__(self, autocomplete_list, *args, **kwargs):

        Entry.__init__(self, *args, **kwargs)
        pass

if __name__ == '__main__':
    """
    list_of_names = []
    tk_root = Tk()
    sv = StringVar()

    entry = AutoCompleteEntry(list_of_names, tk_root)
    entry.grid(row=0, column=0)

    root.mainloop()
    """
<commit_msg>autocomplete entry start<commit_after>"""
https://gist.github.com/uroshekic/11078820
Inspired by http://code.activestate.com/recipes/578253-an-entry-with-autocompletion-for-the-tkinter-gui/
Changes:
    - Fixed AttributeError: 'AutocompleteEntry' object has no attribute 'listbox'
    - Fixed scrolling listbox
    - Case-insensitive search
    - Added focus to entry field
    - Custom listbox length, listbox width matches entry field width
    - Custom matches function
"""

from tkinter import *
from tkinter.ttk import *
import re

class AutoCompleteEntry(Entry):
    def __init__(self, autocomplete_list, list_box_length=8, *args, **kwargs):
        if 'matches_function' in kwargs:
            self.matches_function = kwargs['matches_function']
            del kwargs['matches_function']
        else:
            def matches(fieldValue, acListEntry):
                pattern = re.compile('.*' + re.escape(fieldValue) +
                                     '.*', re.IGNORECASE)
                return re.match(pattern, acListEntry)

            self.matchesFunction = matches

        Entry.__init__(self, *args, **kwargs)
        self.focus()

        self.autocomplete_list = autocomplete_list

        self.var = self['text_variable']
        if self.var == '':
            self.var = self["textvariable"] = StringVar()

if __name__ == '__main__':
    list_of_names = [ str(x) for x in range(60000) ]

    tk_root = Tk()
    sv = StringVar()

    entry = AutoCompleteEntry(list_of_names, tk_root)
    entry.grid(row=0, column=0)

    root.mainloop()
<|endoftext|>