<commit_before># -*- coding: utf-8 -*-
'''
    tests.unit.modules.virtualenv_test
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
    :copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
    :license: Apache 2.0, see LICENSE for more details.
'''

# Import python libraries
import warnings

# Import Salt Testing libs
from salttesting import skipIf, TestCase
from salttesting.helpers import (
    ensure_in_syspath,
    TestsLoggingHandler,
    ForceImportErrorOn
)
ensure_in_syspath('../../')

# Import 3rd party libs
try:
    from mock import MagicMock, patch
    has_mock = True
except ImportError:
    has_mock = False
    patch = lambda x: lambda y: None

# Import salt libs
from salt.modules import virtualenv_mod
from salt.exceptions import CommandExecutionError

virtualenv_mod.__salt__ = {}

@skipIf(has_mock is False, 'mock python module is unavailable')
class VirtualenvTestCase(TestCase):

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6029_deprecated_distribute(self):
        virtualenv_mock = MagicMock()
        virtualenv_mock.__version__ = '1.9.1'
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            with patch.dict('sys.modules', {'virtualenv': virtualenv_mock}):
                virtualenv_mod.create(
                    '/tmp/foo', system_site_packages=True, distribute=True
                )
                mock.assert_called_once_with(
                    'virtualenv --distribute --system-site-packages /tmp/foo',
                    runas=None
                )

        with TestsLoggingHandler() as handler:
            virtualenv_mock = MagicMock()
            virtualenv_mock.__version__ = '1.10rc1'
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                with patch.dict('sys.modules',
                                {'virtualenv': virtualenv_mock}):
                    virtualenv_mod.create(
                        '/tmp/foo', system_site_packages=True, distribute=True
                    )
                    mock.assert_called_once_with(
                        'virtualenv --system-site-packages /tmp/foo',
                        runas=None
                    )

                # Are we logging the deprecation information?
                self.assertIn(
                    'INFO:The virtualenv \'--distribute\' option has been '
                    'deprecated in virtualenv(>=1.10), as such, the '
                    '\'distribute\' option to `virtualenv.create()` has '
                    'also been deprecated and it\'s not necessary anymore.',
                    handler.messages
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6030_deprecated_never_download(self):
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        virtualenv_mock = MagicMock()
        virtualenv_mock.__version__ = '1.9.1'

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            with patch.dict('sys.modules', {'virtualenv': virtualenv_mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_once_with(
                    'virtualenv --never-download /tmp/foo',
                    runas=None
                )

        with TestsLoggingHandler() as handler:
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            virtualenv_mock = MagicMock()
            virtualenv_mock.__version__ = '1.10rc1'
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                with patch.dict('sys.modules',
                                {'virtualenv': virtualenv_mock}):
                    virtualenv_mod.create(
                        '/tmp/foo', never_download=True
                    )
                    mock.assert_called_once_with('virtualenv /tmp/foo',
                                                 runas=None)

                # Are we logging the deprecation information?
                self.assertIn(
                    'INFO:The virtualenv \'--never-download\' option has been '
                    'deprecated in virtualenv(>=1.10), as such, the '
                    '\'never_download\' option to `virtualenv.create()` has '
                    'also been deprecated and it\'s not necessary anymore.',
                    handler.messages
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6031_multiple_extra_search_dirs(self):
        extra_search_dirs = [
            '/tmp/bar-1',
            '/tmp/bar-2',
            '/tmp/bar-3'
        ]

        # Passing extra_search_dirs as a list
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            virtualenv_mod.create(
                '/tmp/foo', extra_search_dir=extra_search_dirs
            )
            mock.assert_called_once_with(
                'virtualenv '
                '--extra-search-dir=/tmp/bar-1 '
                '--extra-search-dir=/tmp/bar-2 '
                '--extra-search-dir=/tmp/bar-3 '
                '/tmp/foo',
                runas=None
            )

        # Passing extra_search_dirs as comma separated list
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            virtualenv_mod.create(
                '/tmp/foo', extra_search_dir=','.join(extra_search_dirs)
            )
            mock.assert_called_once_with(
                'virtualenv '
                '--extra-search-dir=/tmp/bar-1 '
                '--extra-search-dir=/tmp/bar-2 '
                '--extra-search-dir=/tmp/bar-3 '
                '/tmp/foo',
                runas=None
            )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_system_site_packages_and_no_site_packages_mutual_exclusion(self):
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                no_site_packages=True,
                system_site_packages=True
            )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_no_site_packages_deprecation(self):
        # NOTE: If this test starts failing it might be because the deprecation
        # warning was removed, or because some other test in this module is
        # passing 'no_site_packages' to 'virtualenv_mod.create'. The
        # deprecation warning is shown only once.

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            with warnings.catch_warnings(record=True) as w:
                virtualenv_mod.create(
                    '/tmp/foo', no_site_packages=True
                )
                self.assertEqual(
                    '\'no_site_packages\' has been deprecated. Please start '
                    'using \'system_site_packages=False\' which means exactly '
                    'the same as \'no_site_packages=True\'', str(w[-1].message)
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_unapplicable_options(self):
        # ----- Virtualenv using pyvenv options ----------------------------->
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='virtualenv',
                upgrade=True
            )

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='virtualenv',
                symlinks=True
            )
        # <---- Virtualenv using pyvenv options ------------------------------

        # ----- pyvenv using virtualenv options ----------------------------->
        virtualenv_mod.__salt__ = {'cmd.which_bin': lambda _: 'pyvenv'}

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                no_site_packages=True
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                python='python2.7'
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                prompt='PY Prompt'
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                never_download=True
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                extra_search_dir='/tmp/bar'
            )
        # <---- pyvenv using virtualenv options ------------------------------

    def test_get_virtualenv_version_from_shell(self):
        with ForceImportErrorOn('virtualenv'):

            # ----- virtualenv binary not available ------------------------->
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                self.assertRaises(
                    CommandExecutionError,
                    virtualenv_mod.create,
                    '/tmp/foo',
                )
            # <---- virtualenv binary not available --------------------------

            # ----- virtualenv binary present but > 0 exit code ------------->
            mock = MagicMock(side_effect=[
                {'retcode': 1, 'stdout': '', 'stderr': 'This is an error'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                self.assertRaises(
                    CommandExecutionError,
                    virtualenv_mod.create,
                    '/tmp/foo',
                    venv_bin='virtualenv',
                )
            # <---- virtualenv binary present but > 0 exit code --------------

            # ----- virtualenv binary returns 1.9.1 as it's version --------->
            mock = MagicMock(side_effect=[
                {'retcode': 0, 'stdout': '1.9.1'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_with(
                    'virtualenv --never-download /tmp/foo',
                    runas=None
                )
            # <---- virtualenv binary returns 1.9.1 as it's version ----------

            # ----- virtualenv binary returns 1.10rc1 as it's version ------->
            mock = MagicMock(side_effect=[
                {'retcode': 0, 'stdout': '1.10rc1'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_with(
                    'virtualenv /tmp/foo',
                    runas=None
                )
            # <---- virtualenv binary returns 1.10rc1 as it's version --------

if __name__ == '__main__':
    from integration import run_tests
    run_tests(VirtualenvTestCase, needs_daemon=False)
<commit_msg>Patch `_install_script()` since the virtualenv module will try to install some scripts.<commit_after># -*- coding: utf-8 -*-
'''
    tests.unit.modules.virtualenv_test
    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

    :codeauthor: :email:`Pedro Algarvio (pedro@algarvio.me)`
    :copyright: © 2013 by the SaltStack Team, see AUTHORS for more details.
    :license: Apache 2.0, see LICENSE for more details.
'''

# Import python libraries
import warnings

# Import Salt Testing libs
from salttesting import skipIf, TestCase
from salttesting.helpers import (
    ensure_in_syspath,
    TestsLoggingHandler,
    ForceImportErrorOn
)
ensure_in_syspath('../../')

# Import 3rd party libs
try:
    from mock import MagicMock, patch
    has_mock = True
except ImportError:
    has_mock = False
    patch = lambda x: lambda y: None

# Import salt libs
from salt.modules import virtualenv_mod
from salt.exceptions import CommandExecutionError

virtualenv_mod.__salt__ = {}

@skipIf(has_mock is False, 'mock python module is unavailable')
class VirtualenvTestCase(TestCase):

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6029_deprecated_distribute(self):
        virtualenv_mock = MagicMock()
        virtualenv_mock.__version__ = '1.9.1'
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            virtualenv_mod._install_script = MagicMock(
                return_value={
                    'retcode': 0,
                    'stdout': 'Installed script!',
                    'stderr': ''
                }
            )
            with patch.dict('sys.modules', {'virtualenv': virtualenv_mock}):
                virtualenv_mod.create(
                    '/tmp/foo', system_site_packages=True, distribute=True
                )
                mock.assert_called_once_with(
                    'virtualenv --distribute --system-site-packages /tmp/foo',
                    runas=None
                )

        with TestsLoggingHandler() as handler:
            virtualenv_mock = MagicMock()
            virtualenv_mock.__version__ = '1.10rc1'
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                with patch.dict('sys.modules',
                                {'virtualenv': virtualenv_mock}):
                    virtualenv_mod.create(
                        '/tmp/foo', system_site_packages=True, distribute=True
                    )
                    mock.assert_called_once_with(
                        'virtualenv --system-site-packages /tmp/foo',
                        runas=None
                    )

                # Are we logging the deprecation information?
                self.assertIn(
                    'INFO:The virtualenv \'--distribute\' option has been '
                    'deprecated in virtualenv(>=1.10), as such, the '
                    '\'distribute\' option to `virtualenv.create()` has '
                    'also been deprecated and it\'s not necessary anymore.',
                    handler.messages
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6030_deprecated_never_download(self):
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        virtualenv_mock = MagicMock()
        virtualenv_mock.__version__ = '1.9.1'

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            with patch.dict('sys.modules', {'virtualenv': virtualenv_mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_once_with(
                    'virtualenv --never-download /tmp/foo',
                    runas=None
                )

        with TestsLoggingHandler() as handler:
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            virtualenv_mock = MagicMock()
            virtualenv_mock.__version__ = '1.10rc1'
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                with patch.dict('sys.modules',
                                {'virtualenv': virtualenv_mock}):
                    virtualenv_mod.create(
                        '/tmp/foo', never_download=True
                    )
                    mock.assert_called_once_with('virtualenv /tmp/foo',
                                                 runas=None)

                # Are we logging the deprecation information?
                self.assertIn(
                    'INFO:The virtualenv \'--never-download\' option has been '
                    'deprecated in virtualenv(>=1.10), as such, the '
                    '\'never_download\' option to `virtualenv.create()` has '
                    'also been deprecated and it\'s not necessary anymore.',
                    handler.messages
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_issue_6031_multiple_extra_search_dirs(self):
        extra_search_dirs = [
            '/tmp/bar-1',
            '/tmp/bar-2',
            '/tmp/bar-3'
        ]

        # Passing extra_search_dirs as a list
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            virtualenv_mod.create(
                '/tmp/foo', extra_search_dir=extra_search_dirs
            )
            mock.assert_called_once_with(
                'virtualenv '
                '--extra-search-dir=/tmp/bar-1 '
                '--extra-search-dir=/tmp/bar-2 '
                '--extra-search-dir=/tmp/bar-3 '
                '/tmp/foo',
                runas=None
            )

        # Passing extra_search_dirs as comma separated list
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            virtualenv_mod.create(
                '/tmp/foo', extra_search_dir=','.join(extra_search_dirs)
            )
            mock.assert_called_once_with(
                'virtualenv '
                '--extra-search-dir=/tmp/bar-1 '
                '--extra-search-dir=/tmp/bar-2 '
                '--extra-search-dir=/tmp/bar-3 '
                '/tmp/foo',
                runas=None
            )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_system_site_packages_and_no_site_packages_mutual_exclusion(self):
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                no_site_packages=True,
                system_site_packages=True
            )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_no_site_packages_deprecation(self):
        # NOTE: If this test starts failing it might be because the deprecation
        # warning was removed, or because some other test in this module is
        # passing 'no_site_packages' to 'virtualenv_mod.create'. The
        # deprecation warning is shown only once.

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            with warnings.catch_warnings(record=True) as w:
                virtualenv_mod.create(
                    '/tmp/foo', no_site_packages=True
                )
                self.assertEqual(
                    '\'no_site_packages\' has been deprecated. Please start '
                    'using \'system_site_packages=False\' which means exactly '
                    'the same as \'no_site_packages=True\'', str(w[-1].message)
                )

    @patch('salt.utils.which', lambda bin_name: bin_name)
    def test_unapplicable_options(self):
        # ----- Virtualenv using pyvenv options ----------------------------->
        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='virtualenv',
                upgrade=True
            )

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='virtualenv',
                symlinks=True
            )
        # <---- Virtualenv using pyvenv options ------------------------------

        # ----- pyvenv using virtualenv options ----------------------------->
        virtualenv_mod.__salt__ = {'cmd.which_bin': lambda _: 'pyvenv'}

        mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                no_site_packages=True
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                python='python2.7'
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                prompt='PY Prompt'
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                never_download=True
            )

        with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
            self.assertRaises(
                CommandExecutionError,
                virtualenv_mod.create,
                '/tmp/foo',
                venv_bin='pyvenv',
                extra_search_dir='/tmp/bar'
            )
        # <---- pyvenv using virtualenv options ------------------------------

    def test_get_virtualenv_version_from_shell(self):
        with ForceImportErrorOn('virtualenv'):

            # ----- virtualenv binary not available ------------------------->
            mock = MagicMock(return_value={'retcode': 0, 'stdout': ''})
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                self.assertRaises(
                    CommandExecutionError,
                    virtualenv_mod.create,
                    '/tmp/foo',
                )
            # <---- virtualenv binary not available --------------------------

            # ----- virtualenv binary present but > 0 exit code ------------->
            mock = MagicMock(side_effect=[
                {'retcode': 1, 'stdout': '', 'stderr': 'This is an error'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                self.assertRaises(
                    CommandExecutionError,
                    virtualenv_mod.create,
                    '/tmp/foo',
                    venv_bin='virtualenv',
                )
            # <---- virtualenv binary present but > 0 exit code --------------

            # ----- virtualenv binary returns 1.9.1 as it's version --------->
            mock = MagicMock(side_effect=[
                {'retcode': 0, 'stdout': '1.9.1'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_with(
                    'virtualenv --never-download /tmp/foo',
                    runas=None
                )
            # <---- virtualenv binary returns 1.9.1 as it's version ----------

            # ----- virtualenv binary returns 1.10rc1 as it's version ------->
            mock = MagicMock(side_effect=[
                {'retcode': 0, 'stdout': '1.10rc1'},
                {'retcode': 0, 'stdout': ''}
            ])
            with patch.dict(virtualenv_mod.__salt__, {'cmd.run_all': mock}):
                virtualenv_mod.create(
                    '/tmp/foo', never_download=True
                )
                mock.assert_called_with(
                    'virtualenv /tmp/foo',
                    runas=None
                )
            # <---- virtualenv binary returns 1.10rc1 as it's version --------

if __name__ == '__main__':
    from integration import run_tests
    run_tests(VirtualenvTestCase, needs_daemon=False)
<|endoftext|>


<commit_before># coding: utf-8
"""
:mod:`boardgamegeek.plays` - BoardGameGeek "Plays"
==================================================

.. module:: boardgamegeek.plays
   :platform: Unix, Windows
   :synopsis: BGG "Plays"

.. moduleauthor:: Cosmin Luță <q4break@gmail.com>

"""
from __future__ import unicode_literals
from copy import copy
import datetime

from .exceptions import BoardGameGeekError
from .utils import DictObject

class PlaysessionPlayer(DictObject):

    def __init__(self, data):
        self._data = data

    @property
    def username(self):
        return self._data.get("username")

    @property
    def user_id(self):
        return self._data.get("user_id")

    @property
    def name(self):
        return self._data.get("name")

    @property
    def startposition(self):
        return self._data.get("startposition")

    @property
    def new(self):
        return self._data.get("new")

    @property
    def win(self):
        return self._data.get("win")

    @property
    def rating(self):
        return self._data.get("rating")

    @property
    def score(self):
        return self._data.get("score")

class PlaySession(DictObject):
    """
    Container for a play session information.
    """

    def __init__(self, data):
        if "id" not in data:
            raise BoardGameGeekError("missing id of PlaySession")

        if "date" in data:
            if type(data["date"]) != datetime.datetime:
                try:
                    data["date"] = datetime.datetime.strptime(data["date"], "%Y-%m-%d")
                except:
                    data["date"] = None

        # create "nice" dictionaries out of plain ones, so you can .dot access stuff.
        data["players"] = [PlaysessionPlayer(player) for player in data.get("players", [])]

        super(PlaySession, self).__init__(data)

    def _format(self, log):
        log.info("play id         : {}".format(self.id))
        log.info("play user id    : {}".format(self.user_id))
        if self.date:
            log.info("play date       : {}".format(self.date.strftime("%Y-%m-%d")))
        log.info("play quantity   : {}".format(self.quantity))
        log.info("play duration   : {}".format(self.duration))
        log.info("play incomplete : {}".format(self.incomplete))
        log.info("play nowinstats : {}".format(self.nowinstats))
        log.info("play game       : {} ({})".format(self.game_name, self.game_id))
        log.info("play comment    : {}".format(self.comment))

        if self.players:
            log.info("players")
            for player in self.players:
                log.info(u"\t{} ({}): name: {}, score: {}".format(player.username,
                                                                  player.user_id,
                                                                  player.name,
                                                                  player.score))

    @property
    def id(self):
        """
        :return: the play session id
        """
        return self._data.get("id")

    @property
    def user_id(self):
        """
        :return: user ID whom this play session belongs to
        """
        return self._data.get("user_id")

    @property
    def date(self):
        """
        :return: the date when this play session was recorded
        """
        return self._data.get("date")

    @property
    def quantity(self):
        """
        :return:
        """
        return self._data.get("quantity")

    @property
    def duration(self):
        """
        :return: duration of the play session
        """
        return self._data.get("duration")

    @property
    def incomplete(self):
        """
        :return: whether the session was incomplete or not
        """
        return self._data.get("incomplete")

    @property
    def nowinstats(self):
        """
        :return:
        """
        return self._data.get("nowinstats")

    @property
    def game_id(self):
        """

        :return: id of the game played
        """
        return self._data.get("game_id")

    @property
    def game_name(self):
        """
        :return: name of the game played
        """
        return self._data.get("game_name")

    @property
    def comment(self):
        """
        :return: comment on the play session
        """
        return self._data.get("comment")

class Plays(DictObject):
    """
    A list of play sessions, associated either to an user or to a game.
    """

    def __init__(self, data):
        kw = copy(data)
        if "plays" not in kw:
            kw["plays"] = []
        self._plays = []

        for p in kw["plays"]:
            self._plays.append(PlaySession(p))

        super(Plays, self).__init__(kw)

    def _format(self, log):
        if self.user:
            log.info("plays of        : {} ({})".format(self.user, self.user_id))
        else:
            log.info("plays of game id: {}".format(self.game_id))
        log.info("count           : {}".format(len(self)))
        for p in self.plays:
            p._format(log)
            log.info("-------------")

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

    def __len__(self):
        return len(self._plays)

    def add_play(self, data):
        self._data["plays"].append(data)
        self._plays.append(PlaySession(data))

    @property
    def user(self):
        """
        :return: account name of the user owning this list of plays
        :return: ``None`` if this list is that of a game and not an user's
        """
        return self._data.get("username")

    @property
    def user_id(self):
        """

        :return: id of the user owning this list of plays
        :return: ``None`` if this list is that of a game and not an user's
        """
        return self._data.get("user_id")

    @property
    def game_id(self):
        """

        :return: id of the game this plays list belongs to
        :return: ``None`` if this list is that of an user
        """
        return self._data.get("game_id")

    @property
    def plays(self):
        """
        :return: list of :class:`PlaySession`
        """
        return self._plays<commit_msg>Added fix for Python 3.x<commit_after># coding: utf-8
"""
:mod:`boardgamegeek.plays` - BoardGameGeek "Plays"
==================================================

.. module:: boardgamegeek.plays
   :platform: Unix, Windows
   :synopsis: BGG "Plays"

.. moduleauthor:: Cosmin Luță <q4break@gmail.com>

"""
from __future__ import unicode_literals
from copy import copy
import datetime

from .exceptions import BoardGameGeekError
from .utils import DictObject

class PlaysessionPlayer(DictObject):

    def __init__(self, data):
        self._data = data

    @property
    def username(self):
        return self._data.get("username")

    @property
    def user_id(self):
        return self._data.get("user_id")

    @property
    def name(self):
        return self._data.get("name")

    @property
    def startposition(self):
        return self._data.get("startposition")

    @property
    def new(self):
        return self._data.get("new")

    @property
    def win(self):
        return self._data.get("win")

    @property
    def rating(self):
        return self._data.get("rating")

    @property
    def score(self):
        return self._data.get("score")

class PlaySession(DictObject):
    """
    Container for a play session information.
    """

    def __init__(self, data):
        if "id" not in data:
            raise BoardGameGeekError("missing id of PlaySession")

        if "date" in data:
            if type(data["date"]) != datetime.datetime:
                try:
                    data["date"] = datetime.datetime.strptime(data["date"], "%Y-%m-%d")
                except:
                    data["date"] = None

        # create "nice" dictionaries out of plain ones, so you can .dot access stuff.
        data["players"] = [PlaysessionPlayer(player) for player in data.get("players", [])]

        super(PlaySession, self).__init__(data)

    def _format(self, log):
        log.info("play id         : {}".format(self.id))
        log.info("play user id    : {}".format(self.user_id))
        if self.date:
            log.info("play date       : {}".format(self.date.strftime("%Y-%m-%d")))
        log.info("play quantity   : {}".format(self.quantity))
        log.info("play duration   : {}".format(self.duration))
        log.info("play incomplete : {}".format(self.incomplete))
        log.info("play nowinstats : {}".format(self.nowinstats))
        log.info("play game       : {} ({})".format(self.game_name, self.game_id))
        log.info("play comment    : {}".format(self.comment))

        if self.players:
            log.info("players")
            for player in self.players:
                log.info("\t{} ({}): name: {}, score: {}".format(player.username,
                                                                 player.user_id,
                                                                 player.name,
                                                                 player.score))

    @property
    def id(self):
        """
        :return: the play session id
        """
        return self._data.get("id")

    @property
    def user_id(self):
        """
        :return: user ID whom this play session belongs to
        """
        return self._data.get("user_id")

    @property
    def date(self):
        """
        :return: the date when this play session was recorded
        """
        return self._data.get("date")

    @property
    def quantity(self):
        """
        :return:
        """
        return self._data.get("quantity")

    @property
    def duration(self):
        """
        :return: duration of the play session
        """
        return self._data.get("duration")

    @property
    def incomplete(self):
        """
        :return: whether the session was incomplete or not
        """
        return self._data.get("incomplete")

    @property
    def nowinstats(self):
        """
        :return:
        """
        return self._data.get("nowinstats")

    @property
    def game_id(self):
        """

        :return: id of the game played
        """
        return self._data.get("game_id")

    @property
    def game_name(self):
        """
        :return: name of the game played
        """
        return self._data.get("game_name")

    @property
    def comment(self):
        """
        :return: comment on the play session
        """
        return self._data.get("comment")

class Plays(DictObject):
    """
    A list of play sessions, associated either to an user or to a game.
    """

    def __init__(self, data):
        kw = copy(data)
        if "plays" not in kw:
            kw["plays"] = []
        self._plays = []

        for p in kw["plays"]:
            self._plays.append(PlaySession(p))

        super(Plays, self).__init__(kw)

    def _format(self, log):
        if self.user:
            log.info("plays of        : {} ({})".format(self.user, self.user_id))
        else:
            log.info("plays of game id: {}".format(self.game_id))
        log.info("count           : {}".format(len(self)))
        for p in self.plays:
            p._format(log)
            log.info("-------------")

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

    def __len__(self):
        return len(self._plays)

    def add_play(self, data):
        self._data["plays"].append(data)
        self._plays.append(PlaySession(data))

    @property
    def user(self):
        """
        :return: account name of the user owning this list of plays
        :return: ``None`` if this list is that of a game and not an user's
        """
        return self._data.get("username")

    @property
    def user_id(self):
        """

        :return: id of the user owning this list of plays
        :return: ``None`` if this list is that of a game and not an user's
        """
        return self._data.get("user_id")

    @property
    def game_id(self):
        """

        :return: id of the game this plays list belongs to
        :return: ``None`` if this list is that of an user
        """
        return self._data.get("game_id")

    @property
    def plays(self):
        """
        :return: list of :class:`PlaySession`
        """
        return self._plays<|endoftext|>


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

from master import master_config
from master.factory import chromium_factory

defaults = {}

helper = master_config.Helper(defaults)
B = helper.Builder
F = helper.Factory
S = helper.Scheduler
T = helper.Triggerable

def win(): return chromium_factory.ChromiumFactory('src/build', 'win32')
def linux(): return chromium_factory.ChromiumFactory('src/build', 'linux2')

defaults['category'] = '7win latest'

################################################################################
## Release
################################################################################

# Archive location
rel_archive = master_config.GetArchiveUrl('ChromiumWebkit',
                                          'Win Builder',
                                          'win-latest-rel', 'win32')

#
# Main release scheduler for webkit
#
S('s7_webkit_builder_rel', branch='trunk', treeStableTimer=60)
S('s7_webkit_rel', branch='trunk', treeStableTimer=60)

# Create the triggerable scheduler for the reliability tests.
T('reliability')

# Triggerable scheduler for testers
T('s7_webkit_builder_rel_trigger')

#
# Win Rel Builders
#
B('Win Builder', 'f_win_rel', scheduler='s7_webkit_builder_rel',
  builddir='win-latest-rel')
F('f_win_rel', win().ChromiumWebkitLatestFactory(
    slave_type='Builder',
    project='all.sln;chromium_builder',
    factory_properties={
        'trigger': 's7_webkit_builder_rel_trigger',
        'gclient_env': { 'GYP_DEFINES': 'fastbuild=1' },
    }))

B('Win Reliability Builder', 'f_win_reliability_rel', scheduler='s7_webkit_rel',
  builddir='Win_Webkit_Latest')
F('f_win_reliability_rel', win().ChromiumWebkitLatestFactory(
    clobber=True,
    tests=[],
    project='all.sln',
    factory_properties={'archive_build': True,
                        'trigger': 'reliability',
                        'use_build_number': True}))

#
# Win Rel testers
#
B('Vista Perf', 'f_win_rel_perf', scheduler='s7_webkit_builder_rel_trigger',
  auto_reboot=True)
F('f_win_rel_perf', win().ChromiumWebkitLatestFactory(
    slave_type='Tester',
    build_url=rel_archive,
    tests=['dom_perf', 'page_cycler_moz', 'page_cycler_morejs',
           'page_cycler_intl1', 'page_cycler_intl2', 'page_cycler_dhtml',
           'page_cycler_database', 'page_cycler_indexeddb', 'sunspider'],
    factory_properties={'perf_id': 'chromium-rel-vista-webkit',
                        'show_perf_results': True,
                        'start_crash_handler': True,
                        }))

B('Vista Tests', 'f_win_rel_tests', scheduler='s7_webkit_builder_rel_trigger',
  auto_reboot=True)
F('f_win_rel_tests', win().ChromiumWebkitLatestFactory(
    slave_type='Tester',
    build_url=rel_archive,
    tests=['installer', 'unit', 'ui'],
    factory_properties={'perf_id': 'chromium-rel-vista-webkit',
                        'show_perf_results': True,
                        'start_crash_handler': True,
                        'test_results_server': 'test-results.appspot.com',
                        }))

B('Win Reliability', 'win_reliability', scheduler='reliability')
# The Windows reliability bot runs on Linux because it only needs to transfer
# the build from one part of the network to another, and it is easier on Linux.
F('win_reliability', linux().ReliabilityTestsFactory('win_webkit_canary'))

################################################################################
## Debug
################################################################################

#
# Main debug scheduler for webkit
#
S('s7_webkit_builder_dbg', branch='trunk', treeStableTimer=60)
S('s7_webkit_dbg', branch='trunk', treeStableTimer=60)

#
# Win Dbg Builder
#
B('Win (dbg)', 'f_win_dbg', scheduler='s7_webkit_builder_dbg',
  builddir='win-latest-dbg')
F('f_win_dbg', win().ChromiumWebkitLatestFactory(
    target='Debug',
    project='all.sln;chromium_builder',
    tests=['browser_tests', 'interactive_ui', 'unit', 'ui'],
    factory_properties={
        'start_crash_handler': True,
        'generate_gtest_json': True,
        'gclient_env': {'GYP_DEFINES': 'fastbuild=1'}}))

B('Win Shared Builder (dbg)', 'f_win_shared_dbg', scheduler='s7_webkit_dbg')
F('f_win_shared_dbg', win().ChromiumWebkitLatestFactory(
    project='all.sln',
    compile_timeout=2400,
    factory_properties={
        'gclient_env': {'GYP_DEFINES':
                            'component=shared_library fastbuild=1'}}))

def Update(config, active_master, c):
  return helper.Update(c)
<commit_msg>Temporarily move the win_latest webkit bots back to BuilderTesters.<commit_after># Copyright (c) 2011 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

from master import master_config
from master.factory import chromium_factory

defaults = {}

helper = master_config.Helper(defaults)
B = helper.Builder
F = helper.Factory
S = helper.Scheduler
T = helper.Triggerable

def win(): return chromium_factory.ChromiumFactory('src/build', 'win32')
def linux(): return chromium_factory.ChromiumFactory('src/build', 'linux2')

defaults['category'] = '7win latest'

################################################################################
## Release
################################################################################

# Archive location
rel_archive = master_config.GetArchiveUrl('ChromiumWebkit',
                                          'Win Builder',
                                          'win-latest-rel', 'win32')

#
# Main release scheduler for webkit
#
S('s7_webkit_builder_rel', branch='trunk', treeStableTimer=60)
S('s7_webkit_rel', branch='trunk', treeStableTimer=60)

# Create the triggerable scheduler for the reliability tests.
T('reliability')

# Triggerable scheduler for testers
# TODO: Reenable, http://crbug.com/102331
#T('s7_webkit_builder_rel_trigger')

#
# Win Rel Builders
#
B('Win Builder', 'f_win_rel', scheduler='s7_webkit_builder_rel',
  builddir='win-latest-rel')
F('f_win_rel', win().ChromiumWebkitLatestFactory(
    slave_type='Builder',
    project='all.sln;chromium_builder',
    factory_properties={
        #'trigger': 's7_webkit_builder_rel_trigger',
        'gclient_env': { 'GYP_DEFINES': 'fastbuild=1' },
    }))

B('Win Reliability Builder', 'f_win_reliability_rel', scheduler='s7_webkit_rel',
  builddir='Win_Webkit_Latest')
F('f_win_reliability_rel', win().ChromiumWebkitLatestFactory(
    clobber=True,
    tests=[],
    project='all.sln',
    factory_properties={'archive_build': True,
                        'trigger': 'reliability',
                        'use_build_number': True}))

#
# Win Rel testers+builders
#
# TODO: Switch back to trigger, http://crbug.com/102331
B('Vista Perf', 'f_win_rel_perf', scheduler='s7_webkit_builder_rel',
  auto_reboot=True)
F('f_win_rel_perf', win().ChromiumWebkitLatestFactory(
    # TODO: undo, http://crbug.com/102331
    #slave_type='Tester',
    #build_url=rel_archive,
    project='all.sln;chromium_builder_perf',
    tests=['dom_perf', 'page_cycler_moz', 'page_cycler_morejs',
           'page_cycler_intl1', 'page_cycler_intl2', 'page_cycler_dhtml',
           'page_cycler_database', 'page_cycler_indexeddb', 'sunspider'],
    factory_properties={'perf_id': 'chromium-rel-vista-webkit',
                        'show_perf_results': True,
                        'start_crash_handler': True,
                        # TODO: Remove, http://crbug.com/102331
                        'gclient_env': {'GYP_DEFINES': 'fastbuild=1'},
                        }))

# TODO: Switch back to trigger, http://crbug.com/102331
B('Vista Tests', 'f_win_rel_tests', scheduler='s7_webkit_builder_rel',
  auto_reboot=True)
F('f_win_rel_tests', win().ChromiumWebkitLatestFactory(
    # TODO: undo, http://crbug.com/102331
    #slave_type='Tester',
    #build_url=rel_archive,
    project='all.sln;chromium_builder',
    tests=['installer', 'unit', 'ui'],
    factory_properties={'perf_id': 'chromium-rel-vista-webkit',
                        'show_perf_results': True,
                        'start_crash_handler': True,
                        'test_results_server': 'test-results.appspot.com',
                        # TODO: Remove, http://crbug.com/102331
                        'gclient_env': {'GYP_DEFINES': 'fastbuild=1'},
                        }))

B('Win Reliability', 'win_reliability', scheduler='reliability')
# The Windows reliability bot runs on Linux because it only needs to transfer
# the build from one part of the network to another, and it is easier on Linux.
F('win_reliability', linux().ReliabilityTestsFactory('win_webkit_canary'))

################################################################################
## Debug
################################################################################

#
# Main debug scheduler for webkit
#
S('s7_webkit_builder_dbg', branch='trunk', treeStableTimer=60)
S('s7_webkit_dbg', branch='trunk', treeStableTimer=60)

#
# Win Dbg Builder
#
B('Win (dbg)', 'f_win_dbg', scheduler='s7_webkit_builder_dbg',
  builddir='win-latest-dbg')
F('f_win_dbg', win().ChromiumWebkitLatestFactory(
    target='Debug',
    project='all.sln;chromium_builder',
    tests=['browser_tests', 'interactive_ui', 'unit', 'ui'],
    factory_properties={
        'start_crash_handler': True,
        'generate_gtest_json': True,
        'gclient_env': {'GYP_DEFINES': 'fastbuild=1'}}))

B('Win Shared Builder (dbg)', 'f_win_shared_dbg', scheduler='s7_webkit_dbg')
F('f_win_shared_dbg', win().ChromiumWebkitLatestFactory(
    project='all.sln',
    compile_timeout=2400,
    factory_properties={
        'gclient_env': {'GYP_DEFINES':
                            'component=shared_library fastbuild=1'}}))

def Update(config, active_master, c):
  return helper.Update(c)
<|endoftext|>


<commit_before>from itertools import groupby

from django.contrib.auth import login as auth_login, logout as auth_logout
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm
from django.urls.exceptions import NoReverseMatch
from rest_framework import serializers, status, views, viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.reverse import reverse

from bananas.models import ModelDict

from .permissions import IsAnonymous
from .versioning import BananasVersioning

UNDEFINED = object()

class BananasAPI(object):

    versioning_class = BananasVersioning

    def get_reverse_name(self, url_name="list"):
        name = "{}-{}".format(self.basename, url_name)

        namespace = self.request.resolver_match.namespace
        if namespace:
            name = "{}:{}".format(namespace, name)

        return name

    @classmethod
    def get_admin_meta(cls):
        meta = getattr(cls, "_admin_meta", None)

        if meta is None:
            app_label, __, __ = cls.__module__.lower().partition(".")
            basename = getattr(cls, "basename", cls.__name__.lower())
            name = getattr(cls, "name", None)
            if name is None:
                name = cls().get_view_name()

            meta = ModelDict(
                app_label=app_label,
                basename=basename,
                name=name,
                # verbose_name=name,
                # verbose_name_plural=UNDEFINED,
            )

            admin = getattr(cls, "Admin", None)
            if admin is not None:
                meta.update(
                    {
                        key: getattr(admin, key)
                        for key in filter(
                            lambda key: key in meta, admin.__dict__.keys()
                        )
                    }
                )

            basename = "{}.{}".format(meta.app_label, meta.basename)
            # verbose_name_plural = (
            #     (meta.verbose_name + "s")
            #     if meta.verbose_name_plural is UNDEFINED
            #     else None
            # )
            meta.update(
                dict(
                    basename=basename,
                    # verbose_name_plural=verbose_name_plural,
                )
            )
            cls._admin_meta = meta

        return meta

class BananasAPIViewSet(BananasAPI, viewsets.ViewSet):
    pass

class NavigationAPIView(views.APIView):
    """
    The root view for DefaultRouter
    """

    _ignore_model_permissions = True
    schema = None  # exclude from schema
    api_root_dict = None

    def has_permission(self, viewset):
        view = viewset()
        for permission in view.get_permissions():
            if not permission.has_permission(self.request, view):
                return False
        return True

    def get(self, request, *args, **kwargs):
        ret = []
        namespace = request.resolver_match.namespace

        for key, (viewset, url_name) in self.api_root_dict.items():
            if not self.has_permission(viewset):
                continue

            meta = viewset.get_admin_meta()
            if namespace:
                url_name = namespace + ":" + url_name

            try:
                ret.append(
                    {
                        "endpoint": reverse(
                            url_name,
                            args=args,
                            kwargs=kwargs,
                            request=request,
                            format=kwargs.get("format", None),
                        ),
                        **meta,
                    }
                )
            except NoReverseMatch:
                # Don't bail out if eg. no list routes exist, only detail routes.
                continue

        # Sort and group by app_label
        grouper = lambda item: item["app_label"]
        ret = {
            app_label: sorted(items, key=lambda item: item["name"])
            for app_label, items in groupby(sorted(ret, key=grouper), grouper)
        }

        return Response(ret)

class LoginAPI(BananasAPIViewSet):

    name = "Login"
    basename = "login"
    permission_classes = (IsAnonymous,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        """
        # TODO: Decorate api with sensitive post parameters as Django admin do?
        # from django.utils.decorators import method_decorator
        # from django.views.decorators.debug import sensitive_post_parameters
        # sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())
        """
        login_form = AuthenticationForm(request, data=request.data)

        if not login_form.is_valid():
            raise serializers.ValidationError(login_form.errors)

        auth_login(request, login_form.get_user())

        # TODO: Return user?
        return Response(status=status.HTTP_200_OK)

class LogoutAPI(BananasAPIViewSet):

    name = "Logout"
    basename = "logout"
    permission_classes = (IsAuthenticated,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        auth_logout(request)
        return Response(status=status.HTTP_202_ACCEPTED)

class ChangePasswordAPI(BananasAPIViewSet):

    name = "Change password"
    basename = "change_password"
    permission_classes = (IsAuthenticated,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        password_form = PasswordChangeForm(request.user, data=request.data)

        if not password_form.is_valid():
            raise serializers.ValidationError(password_form.errors)

        password_form.save()

        return Response(status=status.HTTP_202_ACCEPTED)
<commit_msg>Translate banans api view names<commit_after>from itertools import groupby

from django.contrib.auth import login as auth_login, logout as auth_logout
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm
from django.urls.exceptions import NoReverseMatch
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, status, views, viewsets
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from rest_framework.reverse import reverse
from rest_framework.utils import formatting

from bananas.models import ModelDict

from .permissions import IsAnonymous
from .versioning import BananasVersioning

UNDEFINED = object()

class BananasAPI(object):

    versioning_class = BananasVersioning

    def get_reverse_name(self, url_name="list"):
        name = "{}-{}".format(self.basename, url_name)

        namespace = self.request.resolver_match.namespace
        if namespace:
            name = "{}:{}".format(namespace, name)

        return name

    @classmethod
    def get_admin_meta(cls):
        meta = getattr(cls, "_admin_meta", None)

        if meta is None:
            app_label, __, __ = cls.__module__.lower().partition(".")
            name = cls.get_view_name(cls)

            basename = getattr(cls, "basename", None)
            if basename is None:
                if type(name).__name__ == '__proxy__':
                    # name is lazy, probably gettext, extract basename from class name
                    basename = cls.get_view_name(cls, respect_name=False)
                else:
                    basename = name
                basename = basename.replace(" ", "_").lower()

            meta = ModelDict(
                app_label=app_label,
                basename=basename,
                name=name,
                # verbose_name=name,
                # verbose_name_plural=UNDEFINED,
            )

            admin = getattr(cls, "Admin", None)
            if admin is not None:
                meta.update(
                    {
                        key: getattr(admin, key)
                        for key in filter(
                            lambda key: key in meta, admin.__dict__.keys()
                        )
                    }
                )

            basename = "{}.{}".format(meta.app_label, meta.basename)
            # verbose_name_plural = (
            #     (meta.verbose_name + "s")
            #     if meta.verbose_name_plural is UNDEFINED
            #     else None
            # )
            meta.update(
                dict(
                    basename=basename,
                    # verbose_name_plural=verbose_name_plural,
                )
            )
            cls._admin_meta = meta

        return meta

    def get_view_name(self, respect_name=True):
        """
        Given a view instance, return a textual name to represent the view.
        This name is used in the browsable API, and in OPTIONS responses.
        This function is the default for the `VIEW_NAME_FUNCTION` setting.
        """
        if isinstance(self, type):
            view = self
        else:
            view = self.__class__

        # Name may be set by some Views, such as a ViewSet.
        if respect_name:
            name = getattr(view, 'name', None)
            if name is not None:
                return name

        name = view.__name__
        name = formatting.remove_trailing_string(name, 'View')
        name = formatting.remove_trailing_string(name, 'ViewSet')
        name = formatting.remove_trailing_string(name, 'API')
        name = formatting.camelcase_to_spaces(name)

        # Suffix may be set by some Views, such as a ViewSet.
        suffix = getattr(view, 'suffix', None)
        if suffix:
            name += ' ' + suffix

        return name

class BananasAPIViewSet(BananasAPI, viewsets.ViewSet):
    pass

class NavigationAPIView(views.APIView):
    """
    The root view for BananasRouter
    """

    description = "The root view for BananasRouter, returning user specific endpoints"
    _ignore_model_permissions = True
    schema = None  # exclude from schema
    api_root_dict = None

    def has_permission(self, viewset):
        view = viewset()
        for permission in view.get_permissions():
            if not permission.has_permission(self.request, view):
                return False
        return True

    def get(self, request, *args, **kwargs):
        ret = []
        namespace = request.resolver_match.namespace

        for key, (viewset, url_name) in self.api_root_dict.items():
            if not self.has_permission(viewset):
                continue

            meta = viewset.get_admin_meta()
            if namespace:
                url_name = namespace + ":" + url_name

            try:
                ret.append(
                    {
                        "endpoint": reverse(
                            url_name,
                            args=args,
                            kwargs=kwargs,
                            request=request,
                            format=kwargs.get("format", None),
                        ),
                        **meta,
                    }
                )
            except NoReverseMatch:
                # Don't bail out if eg. no list routes exist, only detail routes.
                continue

        # Sort and group by app_label
        grouper = lambda item: item["app_label"]
        ret = {
            app_label: sorted(items, key=lambda item: item["name"])
            for app_label, items in groupby(sorted(ret, key=grouper), grouper)
        }

        return Response(ret)

class LoginAPI(BananasAPIViewSet):

    name = _("Log in")
    basename = "login"
    permission_classes = (IsAnonymous,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        """
        # TODO: Decorate api with sensitive post parameters as Django admin do?
        # from django.utils.decorators import method_decorator
        # from django.views.decorators.debug import sensitive_post_parameters
        # sensitive_post_parameters_m = method_decorator(sensitive_post_parameters())
        """
        login_form = AuthenticationForm(request, data=request.data)

        if not login_form.is_valid():
            raise serializers.ValidationError(login_form.errors)

        auth_login(request, login_form.get_user())

        # TODO: Return user?
        return Response(status=status.HTTP_200_OK)

class LogoutAPI(BananasAPIViewSet):

    name = _("Log out")
    basename = "logout"
    permission_classes = (IsAuthenticated,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        auth_logout(request)
        return Response(status=status.HTTP_202_ACCEPTED)

class ChangePasswordAPI(BananasAPIViewSet):

    name = _("Change password")
    basename = "change_password"
    permission_classes = (IsAuthenticated,)

    class Admin:
        verbose_name_plural = None

    def create(self, request):
        password_form = PasswordChangeForm(request.user, data=request.data)

        if not password_form.is_valid():
            raise serializers.ValidationError(password_form.errors)

        password_form.save()

        return Response(status=status.HTTP_202_ACCEPTED)
<|endoftext|>


<commit_before>from __future__ import unicode_literals

import mimetypes
from os import path
import unittest

from django.conf.urls.static import static
from django.http import FileResponse, HttpResponseNotModified
from django.test import SimpleTestCase, override_settings
from django.utils.http import http_date
from django.views.static import was_modified_since

from .. import urls
from ..urls import media_dir

@override_settings(DEBUG=True, ROOT_URLCONF='view_tests.urls')
class StaticTests(SimpleTestCase):
    """Tests django views in django/views/static.py"""

    prefix = 'site_media'

    def test_serve(self):
        "The static view can serve static media"
        media_files = ['file.txt', 'file.txt.gz']
        for filename in media_files:
            response = self.client.get('/%s/%s' % (self.prefix, filename))
            response_content = b''.join(response)
            file_path = path.join(media_dir, filename)
            with open(file_path, 'rb') as fp:
                self.assertEqual(fp.read(), response_content)
            self.assertEqual(len(response_content), int(response['Content-Length']))
            self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))

    def test_chunked(self):
        "The static view should stream files in chunks to avoid large memory usage"
        response = self.client.get('/%s/%s' % (self.prefix, 'long-line.txt'))
        first_chunk = next(response.streaming_content)
        self.assertEqual(len(first_chunk), FileResponse.block_size)
        second_chunk = next(response.streaming_content)
        self.assertEqual(len(second_chunk), 1451)

    def test_unknown_mime_type(self):
        response = self.client.get('/%s/file.unknown' % self.prefix)
        self.assertEqual('application/octet-stream', response['Content-Type'])
        response.close()

    def test_copes_with_empty_path_component(self):
        file_name = 'file.txt'
        response = self.client.get('/%s//%s' % (self.prefix, file_name))
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)

    def test_is_modified_since(self):
        file_name = 'file.txt'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
            HTTP_IF_MODIFIED_SINCE='Thu, 1 Jan 1970 00:00:00 GMT')
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)

    def test_not_modified_since(self):
        file_name = 'file.txt'
        response = self.client.get(
            '/%s/%s' % (self.prefix, file_name),
            HTTP_IF_MODIFIED_SINCE='Mon, 18 Jan 2038 05:14:07 GMT'
            # This is 24h before max Unix time. Remember to fix Django and
            # update this test well before 2038 :)
        )
        self.assertIsInstance(response, HttpResponseNotModified)

    def test_invalid_if_modified_since(self):
        """Handle bogus If-Modified-Since values gracefully

        Assume that a file is modified since an invalid timestamp as per RFC
        2616, section 14.25.
        """
        file_name = 'file.txt'
        invalid_date = 'Mon, 28 May 999999999999 28:25:26 GMT'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
                                   HTTP_IF_MODIFIED_SINCE=invalid_date)
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)
        self.assertEqual(len(response_content), int(response['Content-Length']))

    def test_invalid_if_modified_since2(self):
        """Handle even more bogus If-Modified-Since values gracefully

        Assume that a file is modified since an invalid timestamp as per RFC
        2616, section 14.25.
        """
        file_name = 'file.txt'
        invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
                                   HTTP_IF_MODIFIED_SINCE=invalid_date)
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)
        self.assertEqual(len(response_content), int(response['Content-Length']))

    def test_404(self):
        response = self.client.get('/%s/non_existing_resource' % self.prefix)
        self.assertEqual(404, response.status_code)

class StaticHelperTest(StaticTests):
    """
    Test case to make sure the static URL pattern helper works as expected
    """
    def setUp(self):
        super(StaticHelperTest, self).setUp()
        self._old_views_urlpatterns = urls.urlpatterns[:]
        urls.urlpatterns += static('/media/', document_root=media_dir)

    def tearDown(self):
        super(StaticHelperTest, self).tearDown()
        urls.urlpatterns = self._old_views_urlpatterns

class StaticUtilsTests(unittest.TestCase):
    def test_was_modified_since_fp(self):
        """
        Test that a floating point mtime does not disturb was_modified_since.
        (#18675)
        """
        mtime = 1343416141.107817
        header = http_date(mtime)
        self.assertFalse(was_modified_since(header, mtime))
<commit_msg>Fixed a static view test on Windows.<commit_after>from __future__ import unicode_literals

import mimetypes
from os import path
import unittest

from django.conf.urls.static import static
from django.http import FileResponse, HttpResponseNotModified
from django.test import SimpleTestCase, override_settings
from django.utils.http import http_date
from django.views.static import was_modified_since

from .. import urls
from ..urls import media_dir

@override_settings(DEBUG=True, ROOT_URLCONF='view_tests.urls')
class StaticTests(SimpleTestCase):
    """Tests django views in django/views/static.py"""

    prefix = 'site_media'

    def test_serve(self):
        "The static view can serve static media"
        media_files = ['file.txt', 'file.txt.gz']
        for filename in media_files:
            response = self.client.get('/%s/%s' % (self.prefix, filename))
            response_content = b''.join(response)
            file_path = path.join(media_dir, filename)
            with open(file_path, 'rb') as fp:
                self.assertEqual(fp.read(), response_content)
            self.assertEqual(len(response_content), int(response['Content-Length']))
            self.assertEqual(mimetypes.guess_type(file_path)[1], response.get('Content-Encoding', None))

    def test_chunked(self):
        "The static view should stream files in chunks to avoid large memory usage"
        response = self.client.get('/%s/%s' % (self.prefix, 'long-line.txt'))
        first_chunk = next(response.streaming_content)
        self.assertEqual(len(first_chunk), FileResponse.block_size)
        second_chunk = next(response.streaming_content)
        # strip() to prevent OS line endings from causing differences
        self.assertEqual(len(second_chunk.strip()), 1449)

    def test_unknown_mime_type(self):
        response = self.client.get('/%s/file.unknown' % self.prefix)
        self.assertEqual('application/octet-stream', response['Content-Type'])
        response.close()

    def test_copes_with_empty_path_component(self):
        file_name = 'file.txt'
        response = self.client.get('/%s//%s' % (self.prefix, file_name))
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)

    def test_is_modified_since(self):
        file_name = 'file.txt'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
            HTTP_IF_MODIFIED_SINCE='Thu, 1 Jan 1970 00:00:00 GMT')
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)

    def test_not_modified_since(self):
        file_name = 'file.txt'
        response = self.client.get(
            '/%s/%s' % (self.prefix, file_name),
            HTTP_IF_MODIFIED_SINCE='Mon, 18 Jan 2038 05:14:07 GMT'
            # This is 24h before max Unix time. Remember to fix Django and
            # update this test well before 2038 :)
        )
        self.assertIsInstance(response, HttpResponseNotModified)

    def test_invalid_if_modified_since(self):
        """Handle bogus If-Modified-Since values gracefully

        Assume that a file is modified since an invalid timestamp as per RFC
        2616, section 14.25.
        """
        file_name = 'file.txt'
        invalid_date = 'Mon, 28 May 999999999999 28:25:26 GMT'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
                                   HTTP_IF_MODIFIED_SINCE=invalid_date)
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)
        self.assertEqual(len(response_content), int(response['Content-Length']))

    def test_invalid_if_modified_since2(self):
        """Handle even more bogus If-Modified-Since values gracefully

        Assume that a file is modified since an invalid timestamp as per RFC
        2616, section 14.25.
        """
        file_name = 'file.txt'
        invalid_date = ': 1291108438, Wed, 20 Oct 2010 14:05:00 GMT'
        response = self.client.get('/%s/%s' % (self.prefix, file_name),
                                   HTTP_IF_MODIFIED_SINCE=invalid_date)
        response_content = b''.join(response)
        with open(path.join(media_dir, file_name), 'rb') as fp:
            self.assertEqual(fp.read(), response_content)
        self.assertEqual(len(response_content), int(response['Content-Length']))

    def test_404(self):
        response = self.client.get('/%s/non_existing_resource' % self.prefix)
        self.assertEqual(404, response.status_code)

class StaticHelperTest(StaticTests):
    """
    Test case to make sure the static URL pattern helper works as expected
    """
    def setUp(self):
        super(StaticHelperTest, self).setUp()
        self._old_views_urlpatterns = urls.urlpatterns[:]
        urls.urlpatterns += static('/media/', document_root=media_dir)

    def tearDown(self):
        super(StaticHelperTest, self).tearDown()
        urls.urlpatterns = self._old_views_urlpatterns

class StaticUtilsTests(unittest.TestCase):
    def test_was_modified_since_fp(self):
        """
        Test that a floating point mtime does not disturb was_modified_since.
        (#18675)
        """
        mtime = 1343416141.107817
        header = http_date(mtime)
        self.assertFalse(was_modified_since(header, mtime))
<|endoftext|>


<commit_before>#!/usr/bin/env python
# Copyright (c) 2002 Bryce "Zooko" Wilcox-O'Hearn
# mailto:zooko@zooko.com
# See the end of this file for the free software, open source license (BSD-style).

__author__   = 'zooko'
__revision__ = "$Id: test_base32.py,v 1.1 2003/02/06 17:54:00 myers_carpenter Exp $"

import unittest
import random
from base32 import *

class Base32TestCase(unittest.TestCase):
    def _help_test_rands(self, n):
        return string.join(map(chr, map(random.randrange, [0]*n, [256]*n)), '')

    def test_ende(self):
        bs = self._help_test_rands(2**3)
        as=b2a(bs)
        bs2=a2b(as)
        assert bs2 == bs, "bs2: %s, bs: %s" % (`bs2`, `bs`,)

    def test_ende_long(self):
        bs = self._help_test_rands(2**3)
        as=b2a_long(bs)
        bs2=a2b_long(as)
        assert bs2 == bs, "bs2: %s, bs: %s" % (`bs2`, `bs`,)

    def test_both(self):
        bs = self._help_test_rands(2**3)
        as=b2a(bs)
        asl=b2a_long(bs)
        assert as == asl, "as: %s, asl: %s" % (`as`, `asl`,)
        as=b2a(bs)
        bs2=a2b(as)
        bs2l=a2b_long(as)
        assert bs2 == bs2l
        assert bs2 == bs

    def test_big(self):
        bs = self._help_test_rands(2**9)
        as=b2a(bs)
        asl=b2a_long(bs)
        assert as == asl, "as: %s, asl: %s" % (`as`, `asl`,)
        as=b2a(bs)
        bs2=a2b(as)
        bs2l=a2b_long(as)
        assert bs2 == bs2l
        assert bs2 == bs

    def test_odd_sizes_violates_preconditions(self):
        """
        The Python implementation of b2a_l() actually works if you pass any lengthinbits, and if you don't zero out the unused least significant bits.  The precondition assertions are (a) because the high speed C implementation does not work in those cases and (b) because it might help people discover errors in their own code.  Anyway, if you have assertion-checking turned off, then this test should pass, too.
        """
        for j in range(2**6):
            lib = random.randrange(1, 2**8)
            bs = self._help_test_rands(random.randrange(1, 2**5))
            as = b2a_l(bs, lib)
            assert len(as) == (lib+4)/5 # the size of the base-32 encoding must be just right
            asl = b2a_l_long(bs, lib)
            assert len(asl) == (lib+4)/5 # the size of the base-32 encoding must be just right
            assert as == asl
            bs2 = a2b_l(as, lib)
            assert len(bs2) == (lib+7)/8 # the size of the result must be just right
            bs2l = a2b_l_long(as, lib)
            assert len(bs2l) == (lib+7)/8 # the size of the result must be just right
            assert bs2 == bs2l
            assert trimnpad(bs, lib) == bs2, "trimnpad(%s, %s): %s, bs2: %s" % (`bs`, lib, `trimnpad(bs, lib)`, `bs2`,)

    def test_odd_sizes(self):
        for j in range(2**6):
            lib = random.randrange(1, 2**8)
            bs = self._help_test_rands((lib+7)/8)
            # zero-out unused least-sig bits
            if lib%8:
                b=ord(bs[-1])
                b = b >> (8 - (lib%8))
                b = b << (8 - (lib%8))
                bs = bs[:-1] + chr(b)
            as = b2a_l(bs, lib)
            assert len(as) == (lib+4)/5 # the size of the base-32 encoding must be just right
            asl = b2a_l_long(bs, lib)
            assert len(asl) == (lib+4)/5 # the size of the base-32 encoding must be just right
            assert as == asl
            bs2 = a2b_l(as, lib)
            assert len(bs2) == (lib+7)/8 # the size of the result must be just right
            bs2l = a2b_l_long(as, lib)
            assert len(bs2l) == (lib+7)/8 # the size of the result must be just right
            assert bs2 == bs2l
            assert trimnpad(bs, lib) == bs2, "trimnpad(%s, %s): %s, bs2: %s" % (`bs`, lib, `trimnpad(bs, lib)`, `bs2`,)

    def test_could_be(self):
        # base-32 encoded strings could be
        for j in range(2**9):
            rands = self._help_test_rands(random.randrange(1, 2**7))
            randsenc = b2a(rands)
            assert could_be_base32_encoded(randsenc), "rands: %s, randsenc: %s, a2b(randsenc): %s" % (`rands`, `randsenc`, `a2b(randsenc)`,)

        # base-32 encoded strings with unusual bit lengths could be, too
        for j in range(2**9):
            bitl = random.randrange(1, 2**7)
            bs = self._help_test_rands((bitl+7)/8)
            # zero-out unused least-sig bits
            if bitl%8:
                b=ord(bs[-1])
                b = b >> (8 - (bitl%8))
                b = b << (8 - (bitl%8))
                bs = bs[:-1] + chr(b)
            assert could_be_base32_encoded_l(b2a_l(bs, bitl), bitl)

        # anything with a bogus character couldn't be
        s = b2a(self._help_test_rands(random.randrange(3, 2**7)))
        assert not could_be_base32_encoded('\x00' + s)
        assert not could_be_base32_encoded(s + '\x00')
        assert not could_be_base32_encoded(s[:1] + '\x00' + s[1:])
        assert not could_be_base32_encoded(s[:1] + '\x00' + s[2:])

        # a base-32 encoded string with an alleged lengthinbits of 16 but with 1-bits in the 18th, 19th,
        # and 20th location couldn't be.
        assert not could_be_base32_encoded_l('yyz', 16)

def suite():
    suite = unittest.makeSuite(Base32TestCase, 'test')

    # suite2 = module2.TheTestSuite()
    # return unittest.TestSuite((suite1, suite2))

    return suite

if __name__ == "__main__":
    unittest.main()

# Copyright (c) 2002 Bryce "Zooko" Wilcox-O'Hearn
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software to deal in this software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of this software, and to permit
# persons to whom this software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of this software.
#
# THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THIS SOFTWARE.
<commit_msg> * updated test<commit_after>#!/usr/bin/env python
#
# Copyright (c) 2002, 2003 Bryce "Zooko" Wilcox-O'Hearn
# mailto:zooko@zooko.com
# See the end of this file for the free software, open source license (BSD-style).

__author__ = 'Zooko'
__revision__ = '$Id: test_base32.py,v 1.2 2003/02/07 03:09:04 zooko Exp $'

# Python Standard Library modules
import random, string, unittest

# libbase32 modules
from libbase32.base32 import *

def _help_test_rands(n):
    return string.join(map(chr, map(random.randrange, [0]*n, [256]*n)), '')

class base32TestCase(unittest.TestCase):
    def setUp(self):
        pass

    def tearDown(self):
        pass

    def test_ende(self):
        bs = _help_test_rands(2**3)
        as=b2a(bs)
        bs2=a2b(as)
        assert bs2 == bs, "bs2: %s, bs: %s" % (`bs2`, `bs`,)

    def test_ende_long(self):
        bs = _help_test_rands(2**3)
        as=b2a_long(bs)
        bs2=a2b_long(as)
        assert bs2 == bs, "bs2: %s, bs: %s" % (`bs2`, `bs`,)

    def test_both(self):
        bs = _help_test_rands(2**3)
        as=b2a(bs)
        asl=b2a_long(bs)
        assert as == asl, "as: %s, asl: %s" % (`as`, `asl`,)
        as=b2a(bs)
        bs2=a2b(as)
        bs2l=a2b_long(as)
        assert bs2 == bs2l
        assert bs2 == bs

    def test_big(self):
        bs = _help_test_rands(2**9)
        as=b2a(bs)
        asl=b2a_long(bs)
        assert as == asl, "as: %s, asl: %s" % (`as`, `asl`,)
        as=b2a(bs)
        bs2=a2b(as)
        bs2l=a2b_long(as)
        assert bs2 == bs2l
        assert bs2 == bs

    def DISABLED_test_odd_sizes_violates_preconditions(self):
        """
        The Python implementation of b2a_l() actually works if you pass any lengthinbits, and if you don't zero out the unused least significant bits.  The precondition assertions are (a) because the high speed C implementation does not work in those cases and (b) because it might help people discover errors in their own code.  Anyway, if you have assertion-checking turned off, then this test should pass, too.
        """
        for j in range(2**6):
            lib = random.randrange(1, 2**8)
            bs = _help_test_rands(random.randrange(1, 2**5))
            as = b2a_l(bs, lib)
            assert len(as) == (lib+4)/5 # the size of the base-32 encoding must be just right
            asl = b2a_l_long(bs, lib)
            assert len(asl) == (lib+4)/5 # the size of the base-32 encoding must be just right
            assert as == asl
            bs2 = a2b_l(as, lib)
            assert len(bs2) == (lib+7)/8 # the size of the result must be just right
            bs2l = a2b_l_long(as, lib)
            assert len(bs2l) == (lib+7)/8 # the size of the result must be just right
            assert bs2 == bs2l
            assert trimnpad(bs, lib) == bs2, "trimnpad(%s, %s): %s, bs2: %s" % (`bs`, lib, `trimnpad(bs, lib)`, `bs2`,)

    def test_odd_sizes(self):
        for j in range(2**6):
            lib = random.randrange(1, 2**8)
            bs = _help_test_rands((lib+7)/8)
            # zero-out unused least-sig bits
            if lib%8:
                b=ord(bs[-1])
                b = b >> (8 - (lib%8))
                b = b << (8 - (lib%8))
                bs = bs[:-1] + chr(b)
            as = b2a_l(bs, lib)
            assert len(as) == (lib+4)/5 # the size of the base-32 encoding must be just right
            asl = b2a_l_long(bs, lib)
            assert len(asl) == (lib+4)/5 # the size of the base-32 encoding must be just right
            assert as == asl
            bs2 = a2b_l(as, lib)
            assert len(bs2) == (lib+7)/8 # the size of the result must be just right
            bs2l = a2b_l_long(as, lib)
            assert len(bs2l) == (lib+7)/8 # the size of the result must be just right
            assert bs2 == bs2l
            assert trimnpad(bs, lib) == bs2, "trimnpad(%s, %s): %s, bs2: %s" % (`bs`, lib, `trimnpad(bs, lib)`, `bs2`,)

    def test_veqfp_is_an_encoding(self):
        self.failUnless(could_be_base32_encoded_l('veqfp', 25))

    def test_could_be(self):
        # base-32 encoded strings could be
        for j in range(2**9):
            rands = _help_test_rands(random.randrange(1, 2**7))
            randsenc = b2a(rands)
            assert could_be_base32_encoded(randsenc), "rands: %s, randsenc: %s, a2b(randsenc): %s" % (`rands`, `randsenc`, `a2b(randsenc)`,)

        # base-32 encoded strings with unusual bit lengths could be, too
        for j in range(2**9):
            bitl = random.randrange(1, 2**7)
            bs = _help_test_rands((bitl+7)/8)
            # zero-out unused least-sig bits
            if bitl%8:
                b=ord(bs[-1])
                b = b >> (8 - (bitl%8))
                b = b << (8 - (bitl%8))
                bs = bs[:-1] + chr(b)
            assert could_be_base32_encoded_l(b2a_l(bs, bitl), bitl)

        # anything with a bogus character couldn't be
        s = b2a(_help_test_rands(random.randrange(3, 2**7)))
        assert not could_be_base32_encoded('\x00' + s)
        assert not could_be_base32_encoded(s + '\x00')
        assert not could_be_base32_encoded(s[:1] + '\x00' + s[1:])
        assert not could_be_base32_encoded(s[:1] + '\x00' + s[2:])

        # a base-32 encoded string with an alleged lengthinbits of 16 but with 1-bits in the 18th, 19th,
        # and 20th location couldn't be.
        assert not could_be_base32_encoded_l('yyz', 16)

def _help_bench_e(N):
    return b2a(_help_test_rands(N))
def _help_bench_ed(N):
    return a2b(b2a(_help_test_rands(N)))
def _help_bench_e_l(N):
    return b2a_long(_help_test_rands(N))
def _help_bench_ed_l(N):
    return a2b_long(b2a_long(_help_test_rands(N)))

def benchem():
    import benchfunc # from pyutil
    print "e: "
    benchfunc.bench(_help_bench_e, TOPXP=13)
    print "ed: "
    benchfunc.bench(_help_bench_ed, TOPXP=13)
    print "e_l: "
    benchfunc.bench(_help_bench_e_l, TOPXP=13)
    print "ed_l: "
    benchfunc.bench(_help_bench_ed_l, TOPXP=13)

def suite():
    suite = unittest.makeSuite(base32TestCase, 'test')
    return suite

if __name__ == "__main__":
    unittest.main()

# Copyright (c) 2002, 2003 Bryce "Zooko" Wilcox-O'Hearn
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software to deal in this software without restriction, including
# without limitation the rights to use, copy, modify, merge, publish,
# distribute, sublicense, and/or sell copies of this software, and to permit
# persons to whom this software is furnished to do so, subject to the following
# conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of this software.
#
# THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THIS SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THIS SOFTWARE.
<|endoftext|>