Skip to content

Commit

Permalink
Merge branch 'master' of
Browse files Browse the repository at this point in the history
git@github.com:collective/collective.excelexport.git

Conflicts:
	src/collective/excelexport/datasources/eeafaceted/datasource.py
  • Loading branch information
tdesvenain committed Jul 2, 2014
2 parents be7bfa1 + 3d04524 commit 6e2322e
Show file tree
Hide file tree
Showing 14 changed files with 143 additions and 81 deletions.
5 changes: 5 additions & 0 deletions .coveragerc
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[report]
include =
src/collective/*
omit =
*/test*
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@ parts/
src/*
!src/collective
var/
.coverage
htmlcov/
4 changes: 4 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ install:
- bin/buildout -Nc travis.cfg
script:
- bin/test
- bin/createcoverage
after_success:
- pip install coveralls
- coveralls
notifications:
email:
- travis-reports@ecreall.com
13 changes: 12 additions & 1 deletion buildout.d/base.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ package-name = collective.excelexport
package-extras = [test]

extends =
https://raw.github.com/collective/buildout.plonetest/master/plone-4.3.x.cfg
https://raw.github.com/collective/buildout.plonetest/master/test-4.3.x.cfg
https://raw.github.com/collective/buildout.plonetest/master/qa.cfg
checkouts.cfg
sources.cfg
versions.cfg
Expand All @@ -13,3 +14,13 @@ develop = .
eggs +=
Pillow
ipdb

parts += createcoverage

[code-analysis]
recipe = plone.recipe.codeanalysis
directory = src/collective
# ignore lines too long and indentation warnings
# todo: remove C901,F401
flake8-ignore = E123,E124,E501,E126,E127,E128

24 changes: 23 additions & 1 deletion buildout.d/versions.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,26 @@ robotframework-ride = 1.1
robotframework-selenium2library = 1.2.0
robotsuite = 1.3.3
selenium = 2.34.0
plone.app.vocabularies = 2.1.14
plone.app.vocabularies = 2.1.14

Products.DocFinderTab = 1.0.5
Products.PDBDebugMode = 1.3.1
PyYAML = 3.11
argh = 0.24.1
aws.zope2zcmldoc = 1.1.0
collective.profiler = 0.3
ecreall.helpers.testing = 1.7
flake8 = 2.2.1
ipdb = 0.8
ipython = 2.1.0
mccabe = 0.2.1
pathtools = 0.1.2
pep8 = 1.5.7
plone.recipe.codeanalysis = 1.0rc1
profilehooks = 1.7
pyflakes = 0.8.1
watchdog = 0.7.1
xlrd = 0.9.3

plone.api = 1.2.1
xlwt = 0.7.5
54 changes: 30 additions & 24 deletions src/collective/excelexport/datasources/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,31 @@ def filter_exportables(self, exportables):
"""
return exportables

def get_factories(self, p_type_fti):
factories = getAdapters((p_type_fti, self.context, self.request),
IExportableFactory)
filtered_factories = []
for factory in sorted(factories, key=lambda f: f[1].weight):
factory_name, factory = factory
if factory.portal_types and p_type_fti.id not in factory.portal_types:
# filter on content types if it is set
continue
elif self.excluded_factories and factory_name in self.excluded_factories:
# exclude factory if there is a factory filter
continue
elif factory.behaviors:
# filter on behaviors if it is set
for behavior_id in p_type_fti.behaviors:
behavior = getUtility(IBehavior, behavior_id).interface
if behavior in factory.behaviors:
break
else:
continue

filtered_factories.append(factory)

return filtered_factories

def get_sheets_data(self):
"""Gets a list of dictionaries with three keys :
title: the title of the sheet
Expand All @@ -53,36 +78,17 @@ def get_sheets_data(self):
for p_type in sorted(p_types_objects.keys()):
# get exportables for each content type
p_type_fti = ttool[p_type]
factories = getAdapters((p_type_fti, self.context, self.request),
IExportableFactory)
filtered_factories = []
for factory in sorted(factories, key=lambda f:f[1].weight):
factory_name, factory = factory
if factory.portal_types and p_type not in factory.portal_types:
# filter on content types if it is set
continue
if self.excluded_factories and factory_name in self.excluded_factories:
continue

if factory.behaviors:
# filter on behaviors if it is set
for behavior_id in p_type_fti.behaviors:
behavior = getUtility(IBehavior, behavior_id).interface
if behavior in factory.behaviors:
break
else:
continue

filtered_factories.append(factory)
factories = self.get_factories(p_type_fti)

# get the list of exportables from factories
exportables = []
for factory in filtered_factories:
for factory in factories:
exportables.extend(factory.get_exportables())

title = p_type_fti.Title()
title = p_type_fti.Title()
data.append({'title': title,
'objects': p_types_objects[p_type],
'exportables': self.filter_exportables(exportables)})
'exportables': self.filter_exportables(exportables)
})

return data
1 change: 1 addition & 0 deletions src/collective/excelexport/datasources/eeafaceted/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import urllib
from eea.facetednavigation.criteria.interfaces import ICriteria


class ExportUrl(object):

def export_url(self):
Expand Down
1 change: 1 addition & 0 deletions src/collective/excelexport/exportables/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from zope.interface import implements
from collective.excelexport.interfaces import IExportableFactory


class BaseExportableFactory(object):
implements(IExportableFactory)

Expand Down
3 changes: 2 additions & 1 deletion src/collective/excelexport/exportables/dexterityfields.py
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,6 @@ def get_exportable(field, context, request):
return exportable



class DexterityFieldsExportableFactory(BaseExportableFactory):
"""Get fields content schema
"""
Expand Down Expand Up @@ -274,6 +273,7 @@ def render_value(self, obj):
try:
from z3c.relationfield.interfaces import IRelation
HAS_RELATIONFIELD = True

class RelationFieldRenderer(BaseFieldRenderer):
adapts(IRelation, Interface, Interface)

Expand All @@ -291,6 +291,7 @@ def render_collection_entry(self, obj, value):
try:
from collective.z3cform.datagridfield.interfaces import IRow
HAS_DATAGRIDFIELD = True

class DictRowFieldRenderer(BaseFieldRenderer):
adapts(IRow, Interface, Interface)

Expand Down
4 changes: 2 additions & 2 deletions src/collective/excelexport/setuphandlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ def isNotCurrentProfile(context):

def post_install(context):
"""Post install script"""
if isNotCurrentProfile(context): return
portal = context.getSite()
if isNotCurrentProfile(context):
return
2 changes: 1 addition & 1 deletion src/collective/excelexport/styles.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,4 @@ def __init__(self, context, request):
'align: wrap on, vert centre, horiz center; '
'borders: top thin, bottom thin, left thin, right thin; '
'pattern: pattern solid, back_colour light_orange, fore_colour light_orange; '
)
)
8 changes: 5 additions & 3 deletions src/collective/excelexport/tests/test_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

TEST_IMAGE = os.path.join(os.path.dirname(__file__), 'logoplone.png')


class TestInstall(IntegrationTestCase):
"""Test installation of collective.excelexport into Plone."""

Expand All @@ -23,7 +24,7 @@ def setUp(self):
container = api.content.create(self.portal, type='Folder', id='container')
self.content1 = api.content.create(container, type='member', id='johndoe',
name="John Doe",
birth_date=datetime.date(1980,07,24),
birth_date=datetime.date(1980, 07, 24),
amount=100,
subscription='silver',
languages=('en', 'fr'),
Expand All @@ -32,7 +33,7 @@ def setUp(self):
filename=u'logoplone.png'))
self.content2 = api.content.create(container, type='member', id='johnsmith',
name="John Smith",
birth_date=datetime.date(1981,07,24),
birth_date=datetime.date(1981, 07, 24),
amount=100,
languages=('en', 'es'),
photo=None)
Expand Down Expand Up @@ -89,4 +90,5 @@ def test_searchpolicy_export(self):
self.assertEqual(row1, [u'John Doe', 29426.0, 'silver', 100.0, u'English\nFran\xe7ais', u'logoplone.png'])
with self.assertRaises(IndexError):
sheet.row_values(2)
os.remove(generated_path)

os.remove(generated_path)
100 changes: 54 additions & 46 deletions src/collective/excelexport/view.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,70 +18,78 @@ class ExcelExport(BrowserView):
"""
sheet = NotImplemented

def __call__(self):
self.request.RESPONSE.setHeader('Cache-Control', 'no-cache')
self.request.RESPONSE.setHeader('Pragma', 'no-cache')

string_buffer = StringIO()
xlDoc = xlwt.Workbook(encoding='utf-8')
def set_headers(self, datasource):
self.request.response.setHeader('Cache-Control', 'no-cache')
self.request.response.setHeader('Pragma', 'no-cache')
self.request.response.setHeader(
'Content-type', 'application/vnd.ms-excel;charset=windows-1252')
self.request.response.setHeader(
'Content-disposition',
'attachment; filename="%s"' % datasource.get_filename()
)

# get all values to display, one value by sheet
policy = self.request.get('excelexport.policy', '')
datasource = getMultiAdapter((self.context, self.request),
interface=IDataSource, name=policy)
sheetsinfo = datasource.get_sheets_data()
def write_sheet(self, sheet, sheetinfo, styles):
# headers
for exportablenum, exportable in enumerate(sheetinfo['exportables']):
render = exportable.render_header()
if isinstance(render, Message):
render = translate(render, context=self.request)
sheet.write(0, exportablenum, render, styles.headers)

try:
styles = getMultiAdapter((self.context, self.request),
interface=IStyles, name=policy)
except ComponentLookupError:
styles = getMultiAdapter((self.context, self.request),
interface=IStyles)
# values
for rownum, obj in enumerate(sheetinfo['objects']):
for exportablenum, exportable in enumerate(sheetinfo['exportables']):
render = exportable.render_value(obj)
if isinstance(render, Message):
render = translate(render, context=self.request)
sheet.write(rownum + 1, exportablenum, render,
exportable.render_style(obj, copy(styles.content)))

def get_xldoc(self, sheetsinfo, styles):
xldoc = xlwt.Workbook(encoding='utf-8')
empty_doc = True
for sheetnum, sheetinfo in enumerate(sheetsinfo):
if len(sheetinfo['exportables']) == 0:
continue

# sheet
empty_doc = False
sheet_title = sheetinfo['title'].replace("'", " ").replace(':', '-').replace('/', '-')[:31]

try:
sheet = xlDoc.add_sheet(sheet_title)
sheet = xldoc.add_sheet(sheet_title)
except Exception:
sheet = xlDoc.add_sheet(sheet_title + ' ' + str(sheetnum))
sheet = xldoc.add_sheet(sheet_title + ' ' + str(sheetnum))

for exportablenum, exportable in enumerate(sheetinfo['exportables']):
render = exportable.render_header()
if isinstance(render, Message):
render = translate(render, context=self.request)
sheet.write(0, exportablenum,
translate(render, context=self.request),
styles.headers)

for rownum, obj in enumerate(sheetinfo['objects']):
for exportablenum, exportable in enumerate(sheetinfo['exportables']):
render = exportable.render_value(obj)
if isinstance(render, Message):
render = translate(render, context=self.request)
sheet.write(rownum + 1, exportablenum, render,
exportable.render_style(obj, copy(styles.content)))
self.write_sheet(sheet, sheetinfo, styles)

if empty_doc:
# empty doc
sheet = xlDoc.add_sheet('sheet 1')
sheet.write(0, 0,
"",
styles.content)
sheet = xldoc.add_sheet('sheet 1')
sheet.write(0, 0, "", styles.content)

return xldoc

def __call__(self):

string_buffer = StringIO()

# get all values to display, one value by sheet
policy = self.request.get('excelexport.policy', '')
datasource = getMultiAdapter((self.context, self.request),
interface=IDataSource, name=policy)
self.set_headers(datasource)
sheetsinfo = datasource.get_sheets_data()

try:
styles = getMultiAdapter((self.context, self.request),
interface=IStyles, name=policy)
except ComponentLookupError:
styles = getMultiAdapter((self.context, self.request),
interface=IStyles)

xldoc = self.get_xldoc(sheetsinfo, styles)
doc = CompoundDoc.XlsDoc()
data = xlDoc.get_biff_data()
data = xldoc.get_biff_data()
doc.save(string_buffer, data)

self.request.response.setHeader(
'Content-type', 'application/vnd.ms-excel;charset=windows-1252')
self.request.response.setHeader(
'Content-disposition',
'attachment; filename="%s"' % datasource.get_filename()
)
return string_buffer.getvalue()
3 changes: 1 addition & 2 deletions travis.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,4 @@
extends =
https://raw.github.com/collective/buildout.plonetest/master/travis-4.3.x.cfg
buildout.d/base.cfg
parts = download install test

parts = download install test coverage-sh createcoverage

0 comments on commit 6e2322e

Please sign in to comment.