<commit_before>from __future__ import absolute_import, unicode_literals

import csv

import django
import six
from django.http.response import HttpResponse
from openpyxl import Workbook
from openpyxl.writer.excel import save_virtual_workbook
from openpyxl.writer.write_only import WriteOnlyCell

if django.VERSION >= (1, 9):
    from django.db.models.query import QuerySet
else:
    from django.db.models.query import QuerySet, ValuesQuerySet


ROW_LIMIT = 1048576
COL_LIMIT = 16384


class ExcelResponse(HttpResponse):
    """
    This class provides an HTTP Response in the form of an Excel spreadsheet, or CSV file.
    """

    def __init__(self, data, output_filename='excel_data', worksheet_name=None, force_csv=False, header_font=None,
                 data_font=None, *args, **kwargs):
        # We do not initialize this with streaming_content, as that gets generated when needed
        super(ExcelResponse, self).__init__(*args, **kwargs)
        self._raw_data = data
        self.output_filename = output_filename
        self.worksheet_name = worksheet_name or 'Sheet 1'
        self.header_font = header_font
        self.data_font = data_font
        self.force_csv = force_csv

    @property
    def content(self):
        workbook = None
        if isinstance(self._raw_data, list):
            workbook = self._serialize_list(self._raw_data)
        elif isinstance(self._raw_data, QuerySet):
            workbook = self._serialize_queryset(self._raw_data)
        if django.VERSION < (1, 9):
            if isinstance(self._raw_data, ValuesQuerySet):
                workbook = self._serialize_values_queryset(self._raw_data)
        if workbook is None:
            raise ValueError('ExcelResponse accepts the following data types: list, dict, QuerySet, ValuesQuerySet')

        if self.force_csv:
            self['Content-Type'] = 'text/csv; charset=utf8'
            self['Content-Disposition'] = 'attachment;filename={}.csv'.format(self.output_filename)
            workbook.seek(0)
            workbook = self.make_bytes(workbook.getvalue())
        else:
            self['Content-Type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            self['Content-Disposition'] = 'attachment; filename={}.xlsx'.format(self.output_filename)
            workbook = save_virtual_workbook(workbook)
        self._container = [self.make_bytes(workbook)]
        return b''.join(self._container)

    @content.setter
    def content(self, value):
        self._raw_data = value

    def _serialize_list(self, data):
        workbook = None
        if isinstance(data[0], dict):  # If we're dealing with a list of dicationaries, generate the headers
            headers = [key for key in data[0]]
        else:
            headers = data[0]
        if len(data) > ROW_LIMIT or len(headers) > COL_LIMIT or self.force_csv:
            self.force_csv = True
            workbook = six.StringIO()
            csvwriter = csv.writer(workbook, dialect='excel')
            append = getattr(csvwriter, 'writerow')<commit_msg>Fix a bug with streaming content<commit_after>from __future__ import absolute_import, unicode_literals

import csv

import django
import six
from django.http.response import HttpResponse
from openpyxl import Workbook
from openpyxl.writer.excel import save_virtual_workbook
from openpyxl.writer.write_only import WriteOnlyCell

if django.VERSION >= (1, 9):
    from django.db.models.query import QuerySet
else:
    from django.db.models.query import QuerySet, ValuesQuerySet


ROW_LIMIT = 1048576
COL_LIMIT = 16384


class ExcelResponse(HttpResponse):
    """
    This class provides an HTTP Response in the form of an Excel spreadsheet, or CSV file.
    """

    def __init__(self, data, output_filename='excel_data', worksheet_name=None, force_csv=False, header_font=None,
                 data_font=None, *args, **kwargs):
        # We do not initialize this with streaming_content, as that gets generated when needed
        self.output_filename = output_filename
        self.worksheet_name = worksheet_name or 'Sheet 1'
        self.header_font = header_font
        self.data_font = data_font
        self.force_csv = force_csv
        super(ExcelResponse, self).__init__(data, *args, **kwargs)

    @property
    def content(self):
        return b''.join(self._container)

    @content.setter
    def content(self, value):
        workbook = None
        if isinstance(value, list):
            workbook = self._serialize_list(value)
        elif isinstance(value, QuerySet):
            workbook = self._serialize_queryset(value)
        if django.VERSION < (1, 9):
            if isinstance(value, ValuesQuerySet):
                workbook = self._serialize_values_queryset(value)
        if workbook is None:
            raise ValueError('ExcelResponse accepts the following data types: list, dict, QuerySet, ValuesQuerySet')

        if self.force_csv:
            self['Content-Type'] = 'text/csv; charset=utf8'
            self['Content-Disposition'] = 'attachment;filename={}.csv'.format(self.output_filename)
            workbook.seek(0)
            workbook = self.make_bytes(workbook.getvalue())
        else:
            self['Content-Type'] = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
            self['Content-Disposition'] = 'attachment; filename={}.xlsx'.format(self.output_filename)
            workbook = save_virtual_workbook(workbook)
        self._container = [self.make_bytes(workbook)]

    def _serialize_list(self, data):
        workbook = None
        if isinstance(data[0], dict):  # If we're dealing with a list of dicationaries, generate the headers
            headers = [key for key in data[0]]
        else:
            headers = data[0]
        if len(data) > ROW_LIMIT or len(headers) > COL_LIMIT or self.force_csv:
            self.force_csv = True
            workbook = six.StringIO()
            csvwriter = csv.writer(workbook, dialect='excel')
            append = getattr(csvwriter, 'writerow')
{'fraction_non_alphanumeric': 0.09173855341738553, 'fraction_numerical': 0.0072992700729927005, 'mean_word_length': 2.91239454899416, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 2}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2329676', 'n_tokens_mistral': 1748, 'n_tokens_neox': 1683, 'n_words': 435}