You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
calculate-utils-3-lib/pym/calculate/contrib/spyne/protocol/html/table/row.py

217 lines
9.1 KiB

# -*- coding: utf-8 -*-
#
# spyne - Copyright (C) Spyne contributors.
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
#
import logging
logger = logging.getLogger(__name__)
from inspect import isgenerator
from lxml.html.builder import E
from spyne import ModelBase, ByteArray, ComplexModelBase, Array, AnyUri, \
ImageUri
from spyne.util import coroutine, Break
from spyne.util.cdict import cdict
from spyne.protocol.html.table import HtmlTableBase
class HtmlRowTable(HtmlTableBase):
"""Protocol that returns the response object as a html table.
The simple flavour is like the HtmlMicroFormatprotocol, but returns data
as a html table using the <table> tag.
Returns one record per table in a table with two columns.
:param app: A spyne.application.Application instance.
:param header: Boolean value to determine whether to show field
names in the beginning of the table or not. Defaults to True. Set to
False to skip headers.
:param table_name_attr: The name of the attribute that will contain the
response name of the complex object in the table tag. Set to None to
disable.
:param table_name: When not none, overrides what goes in `table_name_attr`.
:param table_class: When not none, specifies what goes in `class` attribute
in the `<table>` tag. Table name gets appended when
`table_name_attr == 'class'`
:param field_name_attr: The name of the attribute that will contain the
field names of the complex object children for every table cell. Set
to None to disable.
:param row_class: value that goes inside the <tr class="">
:param cell_class: value that goes inside the <td class="">
:param header_cell_class: value that goes inside the <th class="">
"""
def __init__(self, *args, **kwargs):
super(HtmlRowTable, self).__init__(*args, **kwargs)
self.serialization_handlers = cdict({
ModelBase: self.model_base_to_parent,
AnyUri: self.any_uri_to_parent,
ImageUri: self.imageuri_to_parent,
ByteArray: self.not_supported,
ComplexModelBase: self.complex_model_to_parent,
Array: self.array_to_parent,
})
def model_base_to_parent(self, ctx, cls, inst, parent, name, from_arr=False,
**kwargs):
if from_arr:
td_attrib = {}
if False and self.field_name_attr:
td_attrib[self.field_name_attr] = name
parent.write(E.tr(E.td(self.to_unicode(cls, inst), **td_attrib)))
else:
parent.write(self.to_unicode(cls, inst))
@coroutine
def complex_model_to_parent(self, ctx, cls, inst, parent, name,
from_arr=False, **kwargs):
attrib = {}
if self.table_name_attr is not None:
attrib[self.table_name_attr] = cls.get_type_name()
if self.table_width is not None:
attrib['width'] = self.table_width
with parent.element('table', attrib):
with parent.element('tbody'):
for k, v in self.sort_fields(cls):
sub_attrs = self.get_cls_attrs(v)
if sub_attrs.exc:
logger.debug("\tExclude table cell %r type %r for %r",
k, v, cls)
continue
try:
sub_value = getattr(inst, k, None)
except: # e.g. SQLAlchemy could throw NoSuchColumnError
sub_value = None
sub_name = v.Attributes.sub_name
if sub_name is None:
sub_name = k
tr_attrs = {}
if self.row_class is not None:
self.add_html_attr('class', tr_attrs, self.row_class)
with parent.element('tr', tr_attrs):
th_attrs = {}
if self.header_cell_class is not None:
self.add_html_attr('class', th_attrs,
self.header_cell_class)
self.add_field_attrs(th_attrs, sub_name, v)
if sub_attrs.hidden:
self.add_style(th_attrs, 'display:None')
if self.header:
parent.write(E.th(
self.trc(v, ctx.locale, sub_name),
**th_attrs
))
td_attrs = {}
if self.cell_class is not None:
self.add_html_attr('class', td_attrs,
self.cell_class)
self.add_field_attrs(td_attrs, sub_name, v)
if sub_attrs.hidden:
self.add_style(td_attrs, 'display:None')
with parent.element('td', td_attrs):
ret = self.to_parent(ctx, v, sub_value, parent,
sub_name, **kwargs)
if isgenerator(ret):
try:
while True:
sv2 = (yield)
ret.send(sv2)
except Break as b:
try:
ret.throw(b)
except StopIteration:
pass
@coroutine
def array_to_parent(self, ctx, cls, inst, parent, name, **kwargs):
with parent.element('div'):
if issubclass(cls, ComplexModelBase):
ret = super(HtmlRowTable, self).array_to_parent(
ctx, cls, inst, parent, name, **kwargs)
if isgenerator(ret):
try:
while True:
sv2 = (yield)
ret.send(sv2)
except Break as b:
try:
ret.throw(b)
except StopIteration:
pass
else:
table_attrib = {}
if self.table_name_attr:
table_attrib = {self.table_name_attr: name}
if self.table_width is not None:
table_attrib['width'] = self.table_width
with parent.element('table', table_attrib):
tr_attrib = {}
if self.row_class is not None:
tr_attrib['class'] = self.row_class
with parent.element('tr', tr_attrib):
if self.header:
parent.write(E.th(self.trc(cls, ctx.locale,
cls.get_type_name())))
td_attrs = {}
if self.cell_class is not None:
self.add_html_attr('class', td_attrs,
self.cell_class)
self.add_field_attrs(td_attrs, name, cls)
cls_attrs = self.get_cls_attrs(cls)
if cls_attrs.hidden:
self.add_style(td_attrs, 'display:None')
with parent.element('td', td_attrs):
with parent.element('table'):
ret = super(HtmlRowTable, self) \
.array_to_parent(ctx, cls, inst, parent,
name, **kwargs)
if isgenerator(ret):
try:
while True:
sv2 = (yield)
ret.send(sv2)
except Break as b:
try:
ret.throw(b)
except StopIteration:
pass