[Python-modules-commits] [django-tables] 01/07: Import django-tables_1.2.0.orig.tar.gz

Brian May bam at moszumanska.debian.org
Tue May 3 01:55:24 UTC 2016


This is an automated email from the git hooks/post-receive script.

bam pushed a commit to branch master
in repository django-tables.

commit ef66a89cc2badd78e4e67573e6bfc23c221e6095
Author: Brian May <bam at debian.org>
Date:   Tue May 3 10:37:15 2016 +1000

    Import django-tables_1.2.0.orig.tar.gz
---
 CHANGELOG.md                                       |  19 +-
 CONTRIBUTING.md                                    |  44 ++++
 README.rst                                         |  39 +---
 django_tables2/__init__.py                         |   2 +-
 django_tables2/columns/emailcolumn.py              |  16 +-
 django_tables2/columns/linkcolumn.py               |  54 ++---
 django_tables2/columns/urlcolumn.py                |  18 +-
 django_tables2/config.py                           |   7 +-
 django_tables2/locale/en/LC_MESSAGES/django.mo     | Bin 392 -> 606 bytes
 django_tables2/locale/en/LC_MESSAGES/django.po     |  31 ++-
 django_tables2/locale/it/LC_MESSAGES/django.mo     | Bin 0 -> 762 bytes
 django_tables2/locale/it/LC_MESSAGES/django.po     |  45 ++++
 django_tables2/locale/nl/LC_MESSAGES/django.mo     | Bin 0 -> 776 bytes
 django_tables2/locale/nl/LC_MESSAGES/django.po     |  45 ++++
 django_tables2/rows.py                             |  93 +++++----
 django_tables2/tables.py                           |  72 ++++---
 .../templates/django_tables2/bootstrap.html        |   6 +-
 django_tables2/templates/django_tables2/table.html |   6 +-
 django_tables2/utils.py                            |  77 +++++--
 django_tables2/views.py                            |  29 ++-
 docs/index.rst                                     |   8 +-
 docs/pages/accessors.rst                           |   7 +-
 docs/pages/api-reference.rst                       |  46 +++--
 docs/pages/column-attributes.rst                   |  12 +-
 docs/pages/column-headers.rst                      |  19 +-
 docs/pages/custom-rendering.rst                    |  22 +-
 docs/pages/generic-mixins.rst                      |  10 +-
 docs/pages/glossary.rst                            |   2 +-
 docs/pages/internal.rst                            |   3 +-
 docs/pages/localization-control.rst                |   3 -
 docs/pages/order-by-accessors.rst                  |  15 +-
 docs/pages/pagination.rst                          |   9 +-
 docs/pages/query-string-fields.rst                 |  11 +-
 docs/pages/swapping-columns.rst                    |   6 +-
 docs/pages/table-data.rst                          |   7 +-
 docs/pages/tables-for-models.rst                   |   2 +-
 docs/pages/template-filters.rst                    |   2 +-
 docs/pages/template-tags.rst                       |  13 +-
 docs/pages/tutorial.rst                            |   2 +-
 docs/pages/upgrading-from-v1.rst                   |  10 +-
 setup.py                                           |   2 +-
 tests/app/urls.py                                  |   9 +-
 tests/columns/test_booleancolumn.py                |  30 +--
 tests/columns/test_checkboxcolumn.py               |  59 ++++--
 tests/columns/test_datecolumn.py                   |  39 ++--
 tests/columns/test_datetimecolumn.py               |  44 ++--
 tests/columns/test_emailcolumn.py                  |  28 +--
 tests/columns/test_filecolumn.py                   |   3 +-
 tests/columns/test_general.py                      | 150 +++++++-------
 tests/columns/test_linkcolumn.py                   |  51 +++--
 tests/columns/test_templatecolumn.py               |  31 +--
 tests/columns/test_timecolumn.py                   |  11 +-
 tests/columns/test_urlcolumn.py                    |  34 ++-
 tests/test_core.py                                 | 228 +++++++++++++--------
 tests/test_models.py                               |  34 +--
 tests/test_rows.py                                 |  16 +-
 tests/test_templates.py                            |  22 ++
 tests/test_utils.py                                | 110 ++++++++--
 tests/test_views.py                                |  71 +++++--
 59 files changed, 1131 insertions(+), 653 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index e34e9f9..7188759 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,7 +1,24 @@
 # Change log
 
-## v1.1.5 (2016-04-02)
+## v1.2.0 (2016-05-02)
+- Allow custom attributes for rows (fixes #47)
+
+## v1.1.8 (2016-05-02)
+- Pass the table instance into `SingleTableMixin.get_table_pagination()` (#320 by
+(@georgema1982)[https://github.com/georgema1982])
+- Ability to change the body of the `<a>`-tag, by passing `text` kwarg to the columns inheriting from BaseLinkColumn (#318 by [@desecho](https://github.com/desecho), #322)
+- Non-field based LinkColumn only renders default value if lookup fails and text is not set. (#322, fixes #257)
+
+## v1.1.7 (2016-04-26)
+- Added Italian translation (#315 by [@paolodina](https://github.com/paolodina)
+- Added Dutch translation.
+- Fixed {% blocktrans %} template whitespace issues
+- Fixed errors when using a column named `items` (#316)
+- Obey `paginate_by` (from `MultipleObjectMixin`) if no later pagination is defined (#242)
+
+## v1.1.6 (2016-04-02)
 - Correct error message about request context processors for current Django (#314)
+- Skipped 1.1.5 due to an error while creating the tag.
 
 ## v1.1.4 (2016-03-22)
 - Fix broken `setup.py` if Django is not installed before django-tables2 (fixes #312)
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000..d8f22b1
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,44 @@
+# Contributing to django-tables2
+
+You are welcome to contribute to the development of `django-tables2` in various ways:
+
+- Discover and [report bugs](https://github.com/bradleyayers/django-tables2/issues/new).
+  Make sure to include a minimal example to show your problem.
+- Propose features or fix bugs by [opening a Pull Request](https://github.com/bradleyayers/django-tables2/compare)
+- Fix documenation or translations
+
+When contributing code or making bug fixes, we need to have unit tests to verify the expected behaviour.
+
+## Running the tests
+
+With `tox` installed, you can run the test suite by typing `tox`.
+It will take care of installing the correct dependencies. During development,
+you might not want to wait for the tests to run in all environments.
+In that case, use the `-e` argument to specify an environment:
+`tox -e py27-1.9` to run the tests in python 2.7 with Django 1.9,
+or `PYTHONPATH=. py.test` to run the tests against your current environment (which is even quicker).
+
+## Code coverage
+
+To generate a html coverage report:
+```
+PYTHONPATH=. py.test -s --cov=django_tables2 --cov-report html
+```
+
+## Building the documentation
+
+If you want to build the docs from within a virtualenv, and Sphinx is installed
+globally, use:
+
+```
+cd docs/
+make html SPHINXBUILD="python $(which sphinx-build)"
+```
+
+Publishing a release
+--------------------
+
+1. Bump the version in `django-tables2/__init__.py`.
+2. Update CHANGELOG.md`.
+3. Create a tag git tag -a v1.0.6 -m 'tagging v1.0.6'`
+4. Run `python setup.py sdist upload --sign --identity=<your gpg identity>`.
diff --git a/README.rst b/README.rst
index bec4686..e0d64dd 100644
--- a/README.rst
+++ b/README.rst
@@ -34,7 +34,7 @@ Its features include:
 Example
 -------
 
-Start by adding "django_tables2" to your INSTALLED_APPS setting like this:
+Start by adding ``django_tables2`` to your ``INSTALLED_APPS`` setting like this:
 
 .. code:: python
 
@@ -69,38 +69,5 @@ And finally in the template:
     {% load django_tables2 %}
     {% render_table table %}
 
-This example shows one of the simplest cases, but django-tables2 can do a lot
-more! Check out the _documentation: http://django-tables2.readthedocs.org/en/latest/ for more details.
-
-Running the tests
------------------
-
-With ``tox`` installed, you can run the test suite by typing ``tox``. It will take
-care of installing the correct dependencies. During development, you might not
-want to wait for the tests to run in all environments. In that case, use the ``-e``
-argument to specify an environment:
-
-``tox -e py27-1.9`` to run the tests in python 2.7 with Django 1.9.
-
-To generate a html coverage report:
-
-    PYTHONPATH=. py.test -s --cov=django_tables2 --cov-report html
-
-
-Building the documentation
---------------------------
-
-If you want to build the docs from within a virtualenv, and Sphinx is installed
-globally, use:
-
-    cd docs/
-    make html SPHINXBUILD="python $(which sphinx-build)"
-
-
-Publishing a release
---------------------
-
-1. Bump the version in ``django-tables2/__init__.py``.
-2. Update ``CHANGELOG.md``.
-3. Create a tag ``git tag -a v1.0.6 -m 'tagging v1.0.6'``
-4. Run ``python setup.py sdist upload --sign --identity=<your gpg identity>``.
+This example shows one of the simplest cases, but django-tables2 can do a lot more! 
+Check out the _documentation: http://django-tables2.readthedocs.org/en/latest/ for more details.
diff --git a/django_tables2/__init__.py b/django_tables2/__init__.py
index bd7b4f5..88962c7 100644
--- a/django_tables2/__init__.py
+++ b/django_tables2/__init__.py
@@ -8,4 +8,4 @@ from .utils import A
 from .views import SingleTableMixin, SingleTableView
 
 
-__version__ = "1.1.6"
+__version__ = '1.2.0'
diff --git a/django_tables2/columns/emailcolumn.py b/django_tables2/columns/emailcolumn.py
index b6804f8..be164bd 100644
--- a/django_tables2/columns/emailcolumn.py
+++ b/django_tables2/columns/emailcolumn.py
@@ -12,10 +12,12 @@ class EmailColumn(BaseLinkColumn):
     """
     A subclass of `.BaseLinkColumn` that renders the cell value as a hyperlink.
 
-    It's common to have a email value in a row hyperlinked to other page.
+    It's common to have a email value in a row hyperlinked to another page.
 
-    :param  attrs: a `dict` of HTML attributes that are added to
-                   the rendered ``<a href="...">...</a>`` tag
+    :param  attrs: a `dict` of HTML attributes that are added to the rendered
+                   ``<a href="...">...</a>`` tag
+    :param   text: Either static text, or a callable. If set, this value will be
+                   used to render the text inside link instead of value (default)
 
     Example:
 
@@ -32,8 +34,12 @@ class EmailColumn(BaseLinkColumn):
             email = tables.EmailColumn()
 
     """
-    def render(self, value):
-        return self.render_link('mailto:%s' % value, text=value)
+    def render(self, record, value):
+        return self.render_link(
+            uri='mailto:{}'.format(value),
+            record=record,
+            value=value
+        )
 
     @classmethod
     def from_field(cls, field):
diff --git a/django_tables2/columns/linkcolumn.py b/django_tables2/columns/linkcolumn.py
index 2e3488c..37304ac 100644
--- a/django_tables2/columns/linkcolumn.py
+++ b/django_tables2/columns/linkcolumn.py
@@ -13,20 +13,29 @@ class BaseLinkColumn(Column):
     """
     The base for other columns that render links.
 
-    Adds support for an ``a`` key in *attrs** which is added to the rendered
-    ``<a href="...">`` tag.
+    :param  text: Either static text, or a callable. If set, this value will be
+                  used to render the text inside link instead of value (default).
+                  The calleble gets the record being rendered as argument.
+    :param attrs: Additional attributes for the ``<a>`` tag
     """
-    def __init__(self, attrs=None, *args, **kwargs):
+    def __init__(self, attrs=None, text=None, *args, **kwargs):
         kwargs['attrs'] = attrs
+        self.text = text
         super(BaseLinkColumn, self).__init__(*args, **kwargs)
 
-    def render_link(self, uri, text, attrs=None):
+    def text_value(self, record, value):
+        if self.text is None:
+            return value
+        return self.text(record) if callable(self.text) else self.text
+
+    def render_link(self, uri, record, value, attrs=None):
         """
         Render a hyperlink.
 
-        :param   uri: URI for the hyperlink
-        :param  text: value wrapped in ``<a></a>``
-        :param attrs: ``<a>`` tag attributes
+        :param    uri: URI for the hyperlink
+        :param record: record currently being rendered
+        :param  value: value wrapped in ``<a></a>``, might be overridden by ``self.text``
+        :param  attrs: ``<a>`` tag attributes
         """
         attrs = AttributeDict(attrs if attrs is not None else
                               self.attrs.get('a', {}))
@@ -35,7 +44,7 @@ class BaseLinkColumn(Column):
         return format_html(
             '<a {attrs}>{text}</a>',
             attrs=attrs.as_html(),
-            text=text
+            text=self.text_value(record, value)
         )
 
 
@@ -60,11 +69,12 @@ class LinkColumn(BaseLinkColumn):
     :param        args: See `~django.core.urlresolvers.reverse`. **
     :param      kwargs: See `~django.core.urlresolvers.reverse`. **
     :param current_app: See `~django.core.urlresolvers.reverse`.
-    :param       attrs: a `dict` of HTML attributes that are added to
-                        the rendered ``<input type="checkbox" .../>`` tag
-    :param        text: Either static text, or a callable. If set, this
-                        value will be used to render the text inside link
-                        instead of value (default)
+    :param       attrs: a `dict` of HTML attributes that are added to the
+                        rendered ``<a ...>...</a>`` tag.
+    :param        text: Either static text, or a callable. If set, this value
+                        will be used to render the text inside link instead of
+                        value (default).
+                        The calleble gets the record being rendered as argument.
 
     ** In order to create a link to a URL that relies on information in the
     current row, `.Accessor` objects can be used in the *args* or
@@ -112,14 +122,13 @@ class LinkColumn(BaseLinkColumn):
     - *a* -- ``<a>`` elements in ``<td>``.
     """
     def __init__(self, viewname=None, urlconf=None, args=None, kwargs=None,
-                 current_app=None, attrs=None, text=None, **extra):
+                 current_app=None, attrs=None, **extra):
         super(LinkColumn, self).__init__(attrs, **extra)
         self.viewname = viewname
         self.urlconf = urlconf
         self.args = args
         self.kwargs = kwargs
         self.current_app = current_app
-        self.text_value = text
 
     def compose_url(self, record, *args, **kwargs):
         '''Compose the url if the column is constructed with a viewname.'''
@@ -148,19 +157,18 @@ class LinkColumn(BaseLinkColumn):
         return reverse(viewname, **params)
 
     def render(self, value, record, bound_column):
-        text_value = value
-        if self.text_value:
-            text_value = self.text_value
-            if callable(text_value):
-                text_value = text_value(record)
-
-        return self.render_link(self.compose_url(record, bound_column), text=text_value)
+        return self.render_link(
+            self.compose_url(record, bound_column),
+            record=record,
+            value=value
+        )
 
 
 @library.register
 class RelatedLinkColumn(LinkColumn):
     '''
-    Render a link to a related object using related object's ``get_absolute_url``
+    Render a link to a related object using related object's ``get_absolute_url``,
+    same parameters as ``LinkColumn``
     '''
 
     def compose_url(self, record, bound_column):
diff --git a/django_tables2/columns/urlcolumn.py b/django_tables2/columns/urlcolumn.py
index 1ed7fd6..958c2f4 100644
--- a/django_tables2/columns/urlcolumn.py
+++ b/django_tables2/columns/urlcolumn.py
@@ -1,6 +1,8 @@
 # coding: utf-8
 from __future__ import absolute_import, unicode_literals
+
 from django.db import models
+
 from .base import library
 from .linkcolumn import BaseLinkColumn
 
@@ -10,21 +12,23 @@ class URLColumn(BaseLinkColumn):
     """
     Renders URL values as hyperlinks.
 
+    :param text: Either static text, or a callable. If set, this
+                 value will be used to render the text inside link
+                 instead of value (default)
+    :param attrs: Additional attributes for the ``<a>`` tag
+
     Example::
 
         >>> class CompaniesTable(tables.Table):
         ...     www = tables.URLColumn()
         ...
-        >>> table = CompaniesTable([{"www": "http://google.com"}])
-        >>> table.rows[0]["www"]
+        >>> table = CompaniesTable([{'www': 'http://google.com'}])
+        >>> table.rows[0].get_cell('www')
         u'<a href="http://google.com">http://google.com</a>'
 
-    Additional attributes for the ``<a>`` tag can be specified via
-    ``attrs['a']``.
-
     """
-    def render(self, value):
-        return self.render_link(value, value)
+    def render(self, record, value):
+        return self.render_link(value, record=record, value=value)
 
     @classmethod
     def from_field(cls, field):
diff --git a/django_tables2/config.py b/django_tables2/config.py
index 8c548aa..4348a5b 100644
--- a/django_tables2/config.py
+++ b/django_tables2/config.py
@@ -1,5 +1,6 @@
 # coding: utf-8
 from __future__ import unicode_literals
+
 from django.core.paginator import EmptyPage, PageNotAnInteger
 
 
@@ -37,13 +38,13 @@ class RequestConfig(object):
         if order_by:
             table.order_by = order_by
         if self.paginate:
-            if hasattr(self.paginate, "items"):
+            if hasattr(self.paginate, 'items'):
                 kwargs = dict(self.paginate)
             else:
                 kwargs = {}
             # extract some options from the request
-            for arg in ("page", "per_page"):
-                name = getattr(table, "prefixed_%s_field" % arg)
+            for arg in ('page', 'per_page'):
+                name = getattr(table, 'prefixed_%s_field' % arg)
                 try:
                     kwargs[arg] = int(self.request.GET[name])
                 except (ValueError, KeyError):
diff --git a/django_tables2/locale/en/LC_MESSAGES/django.mo b/django_tables2/locale/en/LC_MESSAGES/django.mo
index 030119f..8468d9b 100644
Binary files a/django_tables2/locale/en/LC_MESSAGES/django.mo and b/django_tables2/locale/en/LC_MESSAGES/django.mo differ
diff --git a/django_tables2/locale/en/LC_MESSAGES/django.po b/django_tables2/locale/en/LC_MESSAGES/django.po
index b446f74..7e74f77 100644
--- a/django_tables2/locale/en/LC_MESSAGES/django.po
+++ b/django_tables2/locale/en/LC_MESSAGES/django.po
@@ -4,7 +4,7 @@ msgid ""
 msgstr ""
 "Project-Id-Version: django-tables2\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2012-09-18 03:12+0200\n"
+"POT-Creation-Date: 2016-04-19 10:22+0200\n"
 "PO-Revision-Date: 2011-11-06 10:41+1000\n"
 "Last-Translator: Bradley Ayers <bradley.ayers at gmail.com>\n"
 "Language-Team: English <en at li.org>\n"
@@ -13,20 +13,35 @@ msgstr ""
 "Content-Type: text/plain; charset=UTF-8\n"
 "Content-Transfer-Encoding: 8bit\n"
 
-#: templates/django_tables2/table.html:55
-msgid "Previous"
+#: templates/django_tables2/bootstrap.html:35
+msgid "no results"
 msgstr ""
 
-#: templates/django_tables2/table.html:59
+#: templates/django_tables2/bootstrap.html:55
+#, fuzzy
+#| msgid "Previous"
+msgid "previous"
+msgstr "Previous"
+
+#: templates/django_tables2/bootstrap.html:59
+#: templates/django_tables2/table.html:64
 #, python-format
 msgid "Page %(current)s of %(total)s"
+msgstr "Page %(current)s of %(total)s"
+
+#: templates/django_tables2/bootstrap.html:64
+msgid "next"
 msgstr ""
 
-#: templates/django_tables2/table.html:63
+#: templates/django_tables2/table.html:56
+msgid "Previous"
+msgstr "Previous"
+
+#: templates/django_tables2/table.html:72
 msgid "Next"
-msgstr ""
+msgstr "Next"
 
-#: templates/django_tables2/table.html:66
+#: templates/django_tables2/table.html:78
 #, python-format
 msgid "%(count)s of %(total)s"
-msgstr ""
+msgstr "%(count)s of %(total)s"
diff --git a/django_tables2/locale/it/LC_MESSAGES/django.mo b/django_tables2/locale/it/LC_MESSAGES/django.mo
new file mode 100644
index 0000000..55b4ba7
Binary files /dev/null and b/django_tables2/locale/it/LC_MESSAGES/django.mo differ
diff --git a/django_tables2/locale/it/LC_MESSAGES/django.po b/django_tables2/locale/it/LC_MESSAGES/django.po
new file mode 100644
index 0000000..7a2ee7a
--- /dev/null
+++ b/django_tables2/locale/it/LC_MESSAGES/django.po
@@ -0,0 +1,45 @@
+# This file is distributed under the same license as the django-tables2 package
+msgid ""
+msgstr ""
+"Project-Id-Version: django-tables2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-04-19 10:23+0200\n"
+"PO-Revision-Date: 2016-04-14 11:21+0200\n"
+"Last-Translator: Paolo Dina <paolo at php3.it>\n"
+"Language-Team: Italian <it at li.org>\n"
+"Language: it\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: templates/django_tables2/bootstrap.html:35
+msgid "no results"
+msgstr "nessun risultato"
+
+#: templates/django_tables2/bootstrap.html:55
+msgid "previous"
+msgstr "indietro"
+
+#: templates/django_tables2/bootstrap.html:59
+#: templates/django_tables2/table.html:64
+#, python-format
+msgid "Page %(current)s of %(total)s"
+msgstr "Pagina %(current)s di %(total)s"
+
+#: templates/django_tables2/bootstrap.html:64
+msgid "next"
+msgstr "avanti"
+
+#: templates/django_tables2/table.html:56
+msgid "Previous"
+msgstr "Indietro"
+
+#: templates/django_tables2/table.html:72
+msgid "Next"
+msgstr "Avanti"
+
+#: templates/django_tables2/table.html:78
+#, python-format
+msgid "%(count)s of %(total)s"
+msgstr "%(count)s di %(total)s"
diff --git a/django_tables2/locale/nl/LC_MESSAGES/django.mo b/django_tables2/locale/nl/LC_MESSAGES/django.mo
new file mode 100644
index 0000000..0434b6b
Binary files /dev/null and b/django_tables2/locale/nl/LC_MESSAGES/django.mo differ
diff --git a/django_tables2/locale/nl/LC_MESSAGES/django.po b/django_tables2/locale/nl/LC_MESSAGES/django.po
new file mode 100644
index 0000000..959eb5e
--- /dev/null
+++ b/django_tables2/locale/nl/LC_MESSAGES/django.po
@@ -0,0 +1,45 @@
+# This file is distributed under the same license as the django-tables2 package
+msgid ""
+msgstr ""
+"Project-Id-Version: django-tables2\n"
+"Report-Msgid-Bugs-To: \n"
+"POT-Creation-Date: 2016-04-19 10:23+0200\n"
+"PO-Revision-Date: 2016-04-19 10:21+0200\n"
+"Last-Translator: Jan Pieter Waagmeester <jieter at jieter.nl>\n"
+"Language-Team: Dutch <nl at li.org>\n"
+"Language: nl\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=UTF-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Plural-Forms: nplurals=2; plural=(n != 1);\n"
+
+#: templates/django_tables2/bootstrap.html:35
+msgid "no results"
+msgstr "geen resultaten"
+
+#: templates/django_tables2/bootstrap.html:55
+msgid "previous"
+msgstr "vorige"
+
+#: templates/django_tables2/bootstrap.html:59
+#: templates/django_tables2/table.html:64
+#, python-format
+msgid "Page %(current)s of %(total)s"
+msgstr "Pagina %(current)s van %(total)s"
+
+#: templates/django_tables2/bootstrap.html:64
+msgid "next"
+msgstr "volgende"
+
+#: templates/django_tables2/table.html:56
+msgid "Previous"
+msgstr "Vorige"
+
+#: templates/django_tables2/table.html:72
+msgid "Next"
+msgstr "Volgende"
+
+#: templates/django_tables2/table.html:78
+#, python-format
+msgid "%(count)s of %(total)s"
+msgstr "%(count)s van %(total)s"
diff --git a/django_tables2/rows.py b/django_tables2/rows.py
index ebae191..add767b 100644
--- a/django_tables2/rows.py
+++ b/django_tables2/rows.py
@@ -1,9 +1,12 @@
 # coding: utf-8
+
+
 from django.db import models
 from django.db.models.fields import FieldDoesNotExist
 from django.utils import six
 
-from .utils import A, getargspec
+from .columns.linkcolumn import BaseLinkColumn
+from .utils import A, AttributeDict, computed_values, signature
 
 
 class BoundRow(object):
@@ -32,31 +35,27 @@ class BoundRow(object):
         1
         <input type="checkbox" name="my_chkbox" value="2" />
 
-    Alternatively you can treat it like a list and use indexing to retrieve a
-    specific cell. It should be noted that this will raise an IndexError on
-    failure.
+    Alternatively you can use row.get_cell() to retrieve a specific cell.
 
     .. code-block:: python
 
-        >>> row[0]
+        >>> row.get_cell(0)
         1
-        >>> row[1]
+        >>> row.get_cell(1)
         u'<input type="checkbox" name="my_chkbox" value="2" />'
-        >>> row[2]
+        >>> row.get_cell(2)
         ...
         IndexError: list index out of range
 
-    Finally you can also treat it like a dictionary and use column names as the
-    keys. This will raise KeyError on failure (unlike the above indexing using
-    integers).
+    Finally you can also use the column names to retrieve a specific cell:
 
     .. code-block:: python
 
-        >>> row['a']
+        >>> row.get_cell('a')
         1
-        >>> row['b']
+        >>> row.get_cell('b')
         u'<input type="checkbox" name="my_chkbox" value="2" />'
-        >>> row['c']
+        >>> row.get_cell('c')
         ...
         KeyError: 'c'
 
@@ -76,6 +75,20 @@ class BoundRow(object):
         return self._table
 
     @property
+    def attrs(self):
+        '''Return the attributes for a certain row.'''
+        cssClass = 'even' if next(self._table._counter) % 2 == 0 else 'odd'
+
+        row_attrs = computed_values(self._table.row_attrs, self._record)
+
+        if 'class' in row_attrs:
+            row_attrs['class'] += ' ' + cssClass
+        else:
+            row_attrs['class'] = cssClass
+
+        return AttributeDict(row_attrs)
+
+    @property
     def record(self):
         """
         The data record from the data source which is used to populate this row
@@ -95,7 +108,7 @@ class BoundRow(object):
             # is correct – it's what __getitem__ expects.
             yield value
 
-    def __getitem__(self, name):
+    def get_cell(self, name):
         """
         Returns the final rendered value for a cell in the row, given the name
         of a column.
@@ -103,30 +116,42 @@ class BoundRow(object):
         bound_column = self.table.columns[name]
 
         value = None
+        accessor = A(bound_column.accessor)
+
         # We need to take special care here to allow get_FOO_display()
         # methods on a model to be used if available. See issue #30.
-        path, _, remainder = bound_column.accessor.rpartition('.')
-        penultimate = A(path).resolve(self.record, quiet=True)
+        penultimate, remainder = accessor.penultimate(self.record)
+
         # If the penultimate is a model and the remainder is a field
         # using choices, use get_FOO_display().
         if isinstance(penultimate, models.Model):
             try:
-                field = penultimate._meta.get_field(remainder)
-                display = getattr(penultimate, 'get_%s_display' % remainder, None)
-                if getattr(field, "choices", ()) and display:
-                    value = display()
+                field = accessor.get_field(self.record)
+                display_fn = getattr(penultimate, 'get_%s_display' % remainder, None)
+                if getattr(field, 'choices', ()) and display_fn:
+                    value = display_fn()
                     remainder = None
             except FieldDoesNotExist:
                 pass
-        # Fall back to just using the original accessor (we just need
-        # to follow the remainder).
+
+        # Fall back to just using the original accessor
         if remainder:
-            value = A(remainder).resolve(penultimate, quiet=True)
+            try:
+                value = accessor.resolve(self.record)
+            except Exception:
+                # we need to account for non-field based columns (issue #257)
+                is_linkcolumn = isinstance(bound_column.column, BaseLinkColumn)
+                if is_linkcolumn and bound_column.column.text is not None:
+                    return self._call_render(bound_column)
 
         if value in bound_column.column.empty_values:
             return bound_column.default
 
-        available = {
+        return self._call_render(bound_column, value)
+
+    def _call_render(self, bound_column, value=None):
+        '''Call the column's render method with appropriate kwargs'''
+        kwargs = {
             'value': value,
             'record': self.record,
             'column': bound_column.column,
@@ -134,19 +159,15 @@ class BoundRow(object):
             'bound_row': self,
             'table': self._table,
         }
-        expected = {}
 
-        # provide only the arguments expected by `render`
-        argspec = getargspec(bound_column.render)
-        args, varkw = argspec[0], argspec[2]
-        if varkw:
-            expected = available
-        else:
-            for key, value in available.items():
-                if key in args[1:]:
-                    expected[key] = value
+        # inspect signature of the render()-method. If the **kwargs argument is
+        # defined, pass all arguments, else provide exactly the kwargs wanted.
+        args, keywords = signature(bound_column.render)
+
+        if keywords is None:
+            kwargs = {key: kwargs[key] for key in kwargs if key in args}
 
-        return bound_column.render(**expected)
+        return bound_column.render(**kwargs)
 
     def __contains__(self, item):
         """Check by both row object and column name."""
@@ -163,7 +184,7 @@ class BoundRow(object):
         ``rendered within ``<td>``.
         """
         for column in self.table.columns:
-            yield (column, self[column.name])
+            yield (column, self.get_cell(column.name))
 
 
 class BoundRows(object):
diff --git a/django_tables2/tables.py b/django_tables2/tables.py
index 9fc5ebe..ebeca98 100644
--- a/django_tables2/tables.py
+++ b/django_tables2/tables.py
@@ -3,6 +3,7 @@ from __future__ import unicode_literals
 
 import copy
 from collections import OrderedDict
+from itertools import count
 
 from django.core.paginator import Paginator
 from django.db.models.fields import FieldDoesNotExist
@@ -154,7 +155,7 @@ class DeclarativeColumnsMetaclass(type):
     ``base_columns`` as well.
     """
     def __new__(mcs, name, bases, attrs):
-        attrs["_meta"] = opts = TableOptions(attrs.get("Meta", None))
+        attrs['_meta'] = opts = TableOptions(attrs.get('Meta', None))
         # extract declared columns
         cols, remainder = [], {}
         for attr_name, attr in attrs.items():
@@ -171,10 +172,10 @@ class DeclarativeColumnsMetaclass(type):
         # necessary to preserve the correct order of columns.
         parent_columns = []
         for base in bases[::-1]:
-            if hasattr(base, "base_columns"):
+            if hasattr(base, 'base_columns'):
                 parent_columns = list(base.base_columns.items()) + parent_columns
         # Start with the parent columns
-        attrs["base_columns"] = OrderedDict(parent_columns)
+        attrs['base_columns'] = OrderedDict(parent_columns)
         # Possibly add some generated columns based on a model
         if opts.model:
             extra = OrderedDict()
@@ -193,23 +194,23 @@ class DeclarativeColumnsMetaclass(type):
             else:
                 for field in opts.model._meta.fields:
                     extra[field.name] = columns.library.column_for_field(field)
-            attrs["base_columns"].update(extra)
+            attrs['base_columns'].update(extra)
 
         # Explicit columns override both parent and generated columns
-        attrs["base_columns"].update(OrderedDict(cols))
+        attrs['base_columns'].update(OrderedDict(cols))
         # Apply any explicit exclude setting
         for exclusion in opts.exclude:
-            if exclusion in attrs["base_columns"]:
-                attrs["base_columns"].pop(exclusion)
+            if exclusion in attrs['base_columns']:
+                attrs['base_columns'].pop(exclusion)
         # Now reorder the columns based on explicit sequence
         if opts.sequence:
-            opts.sequence.expand(attrs["base_columns"].keys())
+            opts.sequence.expand(attrs['base_columns'].keys())
             # Table's sequence defaults to sequence declared in Meta
             # attrs['_sequence'] = opts.sequence
-            attrs["base_columns"] = OrderedDict(((x, attrs["base_columns"][x]) for x in opts.sequence))
+            attrs['base_columns'] = OrderedDict(((x, attrs['base_columns'][x]) for x in opts.sequence))
 
         # set localize on columns
-        for col_name in attrs["base_columns"].keys():
+        for col_name in attrs['base_columns'].keys():
             localize_column = None
             if col_name in opts.localize:
                 localize_column = True
@@ -218,7 +219,7 @@ class DeclarativeColumnsMetaclass(type):
                 localize_column = False
 
             if localize_column is not None:
-                attrs["base_columns"][col_name].localize = localize_column
+                attrs['base_columns'][col_name].localize = localize_column
 
         return super(DeclarativeColumnsMetaclass, mcs).__new__(mcs, name, bases, attrs)
 
@@ -234,27 +235,28 @@ class TableOptions(object):
     """
     def __init__(self, options=None):
         super(TableOptions, self).__init__()
-        self.attrs = AttributeDict(getattr(options, "attrs", {}))
-        self.default = getattr(options, "default", "—")
-        self.empty_text = getattr(options, "empty_text", None)
-        self.fields = getattr(options, "fields", None)
-        self.exclude = getattr(options, "exclude", ())
-        order_by = getattr(options, "order_by", None)
+        self.attrs = AttributeDict(getattr(options, 'attrs', {}))
+        self.row_attrs = getattr(options, 'row_attrs', {})
+        self.default = getattr(options, 'default', '—')
+        self.empty_text = getattr(options, 'empty_text', None)
+        self.fields = getattr(options, 'fields', None)
+        self.exclude = getattr(options, 'exclude', ())
+        order_by = getattr(options, 'order_by', None)
         if isinstance(order_by, six.string_types):
             order_by = (order_by, )
         self.order_by = OrderByTuple(order_by) if order_by is not None else None
-        self.order_by_field = getattr(options, "order_by_field", "sort")
-        self.page_field = getattr(options, "page_field", "page")
-        self.per_page = getattr(options, "per_page", 25)
-        self.per_page_field = getattr(options, "per_page_field", "per_page")
-        self.prefix = getattr(options, "prefix", "")
-        self.show_header = getattr(options, "show_header", True)
-        self.sequence = Sequence(getattr(options, "sequence", ()))
-        self.orderable = getattr(options, "orderable", True)
-        self.model = getattr(options, "model", None)
-        self.template = getattr(options, "template", "django_tables2/table.html")
-        self.localize = getattr(options, "localize", ())
-        self.unlocalize = getattr(options, "unlocalize", ())
+        self.order_by_field = getattr(options, 'order_by_field', 'sort')
+        self.page_field = getattr(options, 'page_field', 'page')
+        self.per_page = getattr(options, 'per_page', 25)
+        self.per_page_field = getattr(options, 'per_page_field', 'per_page')
+        self.prefix = getattr(options, 'prefix', '')
+        self.show_header = getattr(options, 'show_header', True)
+        self.sequence = Sequence(getattr(options, 'sequence', ()))
+        self.orderable = getattr(options, 'orderable', True)
+        self.model = getattr(options, 'model', None)
+        self.template = getattr(options, 'template', 'django_tables2/table.html')
+        self.localize = getattr(options, 'localize', ())
+        self.unlocalize = getattr(options, 'unlocalize', ())
 
 
 class TableBase(object):
@@ -390,9 +392,10 @@ class TableBase(object):
     TableDataClass = TableData
 
     def __init__(self, data, order_by=None, orderable=None, empty_text=None,
-                 exclude=None, attrs=None, sequence=None, prefix=None,
-                 order_by_field=None, page_field=None, per_page_field=None,
-                 template=None, default=None, request=None, show_header=None):
+                 exclude=None, attrs=None, row_attrs=None, sequence=None,
+                 prefix=None, order_by_field=None, page_field=None,
+                 per_page_field=None, template=None, default=None, request=None,
+                 show_header=None):
         super(TableBase, self).__init__()
         self.exclude = exclude or ()
         self.sequence = sequence
@@ -403,6 +406,7 @@ class TableBase(object):
         self.rows = BoundRows(data=self.data, table=self)
         attrs = computed_values(attrs if attrs is not None else self._meta.attrs)
         self.attrs = AttributeDict(attrs)
+        self.row_attrs = AttributeDict(row_attrs or self._meta.row_attrs)
         self.empty_text = empty_text if empty_text is not None else self._meta.empty_text
         self.orderable = orderable
         self.prefix = prefix
@@ -451,10 +455,14 @@ class TableBase(object):
         if request:
             RequestConfig(request).configure(self)
 
+        self._counter = count()
+
     def as_html(self, request):
         """
         Render the table to a simple HTML table, adding `request` to the context.
         """
+        # reset counter for new rendering
+        self._counter = count()
         template = get_template(self.template)
 
         context = {
diff --git a/django_tables2/templates/django_tables2/bootstrap.html b/django_tables2/templates/django_tables2/bootstrap.html
index f15078c..68589a4 100644
--- a/django_tables2/templates/django_tables2/bootstrap.html
+++ b/django_tables2/templates/django_tables2/bootstrap.html
@@ -24,7 +24,7 @@
                 <tbody>
                 {% for row in table.page.object_list|default:table.rows %} {# support pagination #}
                     {% block table.tbody.row %}
-                        <tr class="{% cycle "odd" "even" %}">
+                        <tr {{ row.attrs.as_html }}>
                             {% for column, cell in row.items %}
                                 <td {{ column.attrs.td.as_html }}>{{ cell }}</td>
                             {% endfor %}
@@ -56,9 +56,7 @@
                 </a>
             {% endif %}
             <li class="cardinality">
-                {% blocktrans with table.page.number as current and table.paginator.num_pages as total %}
-                    Page {{ current }} of {{ total }}
-                {% endblocktrans %}
+                {% blocktrans with table.page.number as current and table.paginator.num_pages as total %}Page {{ current }} of {{ total }}{% endblocktrans %}
             </li>
             {% if table.page.has_next %}
             <li class="next">
diff --git a/django_tables2/templates/django_tables2/table.html b/django_tables2/templates/django_tables2/table.html
index ee5a0f4..f011ae6 100644
--- a/django_tables2/templates/django_tables2/table.html
+++ b/django_tables2/templates/django_tables2/table.html
@@ -23,7 +23,7 @@
     <tbody>
         {% for row in table.page.object_list|default:table.rows %} {# support pagination #}
         {% block table.tbody.row %}
-        <tr class="{% cycle 'even' 'odd' %}">
+        <tr {{ row.attrs.as_html }}>
             {% for column, cell in row.items %}
                 <td {{ column.attrs.td.as_html }}>{% if column.localize == None %}{{ cell }}{% else %}{% if column.localize %}{{ cell|localize }}{% else %}{{ cell|unlocalize }}{% endif %}{% endif %}</td>
             {% endfor %}
@@ -61,9 +61,7 @@
     {% if table.page.has_previous or table.page.has_next %}
         {% block pagination.current %}
             <li class="current">
-                {% blocktrans with table.page.number as current and table.paginator.num_pages as total %}
-                    Page {{ current }} of {{ total }}
-                {% endblocktrans %}
+                {% blocktrans with table.page.number as current and table.paginator.num_pages as total %}Page {{ current }} of {{ total }}{% endblocktrans %}
             </li>
         {% endblock pagination.current %}
     {% endif %}
diff --git a/django_tables2/utils.py b/django_tables2/utils.py
index 654293c..f503163 100644
--- a/django_tables2/utils.py
+++ b/django_tables2/utils.py
@@ -1,7 +1,6 @@
 # coding: utf-8
 from __future__ import absolute_import, unicode_literals
 
-import inspect
 from functools import total_ordering
 from itertools import chain
 
@@ -109,7 +108,8 @@ class OrderBy(six.text_type):
 
 @six.python_2_unicode_compatible
 class OrderByTuple(tuple):
-    """Stores ordering as (as `.OrderBy` objects). The
+    """
+    Stores ordering as (as `.OrderBy` objects). The
... 2764 lines suppressed ...

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/django-tables.git



More information about the Python-modules-commits mailing list