🤝 merge with master

This commit is contained in:
chfw 2019-07-15 08:55:54 +01:00
commit 3408497c81
11 changed files with 170 additions and 74 deletions

View File

@ -1,4 +1,3 @@
sudo: false
dist: xenial
language: python
@ -18,32 +17,40 @@ stages:
- lint
.disable_global: &disable_global
addons: false
cache: false
env: {}
python: false
before_install: false
install: true
install: false
before_script: false
script: false
after_success: false
after_failure: false
before_deploy: false
deploy: false
.lint: &lint
<<: *disable_global
git:
submodules: false
python: 3.6
stage: lint
install: pip install flake8
script: make lint
jobs:
include:
- *moban
- *lint
stage: test
script: make test
before_install:
- if [[ -f min_requirements.txt && "$MINREQ" -eq 1 ]]; then
mv min_requirements.txt requirements.txt ;
fi
- test ! -f rnd_requirements.txt || pip install --no-deps -r rnd_requirements.txt
- test ! -f rnd_requirements.txt ||
pip install --no-deps -r rnd_requirements.txt
- test ! -f rnd_requirements.txt || pip install -r rnd_requirements.txt ;
- pip install -r tests/requirements.txt
script:

View File

@ -1,6 +1,24 @@
Change log
================================================================================
0.5.19 - 14.7.2019
--------------------------------------------------------------------------------
updated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. `pyexcel#185 <https://github.com/pyexcel/pyexcel/issues/185>`_: handle stream
conversion if file type(html) needs string content then bytes to handle
0.5.18 - 12.06.2019
--------------------------------------------------------------------------------
updated
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
#. `#69 <https://github.com/pyexcel/pyexcel-io/issues/69>`_: Force file
type(force_file_type) on write
0.5.17 - 04.04.2019
--------------------------------------------------------------------------------

View File

@ -1,6 +1,18 @@
name: pyexcel-io
organisation: pyexcel
releases:
- changes:
- action: updated
details:
- '`pyexcel#185`: handle stream conversion if file type(html) needs string content then bytes to handle'
version: 0.5.19
date: 14.7.2019
- changes:
- action: updated
details:
- '`#69`: Force file type(force_file_type) on write'
version: 0.5.18
date: 12.06.2019
- changes:
- action: updated
details:

View File

@ -22,7 +22,7 @@ author = 'C.W.'
# The short X.Y version
version = '0.6.0'
# The full version, including alpha/beta/rc tags
release = '0.5.17'
release = '0.5.19'
# -- General configuration ---------------------------------------------------
@ -69,4 +69,4 @@ html_static_path = ['static']
# -- Options for intersphinx extension ---------------------------------------
# Example configuration for intersphinx: refer to the Python standard library.
intersphinx_mapping = {'https://docs.python.org/': None}
intersphinx_mapping = {'https://docs.python.org/': None}

View File

@ -1 +1,2 @@
pip install flake8
flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long

View File

@ -4,8 +4,9 @@ name: pyexcel-io
nick_name: io
version: 0.6.0
current_version: 0.6.0
release: 0.5.19
copyright_year: 2015-2019
release: 0.5.17
moban_command: false
dependencies:
- ordereddict;python_version<"2.7"
- lml>=0.0.4

View File

@ -232,6 +232,16 @@ class BookWriter(RWInterface):
def _convert_content_to_stream(file_content, file_type):
stream = manager.get_io(file_type)
if not PY2:
target_content_type = manager.get_io_type(file_type)
needs_encode = (target_content_type == 'bytes' and
not isinstance(file_content, bytes))
needs_decode = (target_content_type == 'string' and
isinstance(file_content, bytes))
if needs_encode:
file_content = file_content.encode('utf-8')
elif needs_decode:
file_content = file_content.decode('utf-8')
stream.write(file_content)
stream.seek(0)
return stream

View File

@ -4,7 +4,7 @@
The io interface to file extensions
:copyright: (c) 2014-2017 by Onni Software Ltd.
:copyright: (c) 2014-2019 by Onni Software Ltd.
:license: New BSD License, see LICENSE for more details
"""
import os
@ -24,7 +24,7 @@ def iget_data(afile, file_type=None, **keywords):
:param sheet_name: the name of the sheet to be loaded
:param sheet_index: the index of the sheet to be loaded
:param sheets: a list of sheet to be loaded
:param file_type: used only when filename is not a physial file name
:param file_type: used only when filename is not a physical file name
:param force_file_type: used only when filename refers to a physical file
and it is intended to open it as forced file type.
:param streaming: toggles the type of returned data. The values of the
@ -99,6 +99,8 @@ def save_data(afile, data, file_type=None, **keywords):
:param filename: actual file name, a file stream or actual content
:param data: a dictionary but an ordered dictionary is preferred
:param file_type: used only when filename is not a physial file name
:param force_file_type: used only when filename refers to a physical file
and it is intended to open it as forced file type.
:param library: explicitly name a library for use.
e.g. library='pyexcel-ods'
:param keywords: any other parameters that python csv module's
@ -201,7 +203,8 @@ def load_data(
def get_writer(
file_name=None, file_stream=None, file_type=None, library=None, **keywords
file_name=None, file_stream=None, file_type=None,
library=None, force_file_type=None, **keywords
):
"""find a suitable writer"""
inputs = [file_name, file_stream]
@ -211,11 +214,15 @@ def get_writer(
raise IOError(constants.MESSAGE_ERROR_02)
file_type_given = True
if file_type is None and file_name:
try:
file_type = file_name.split(".")[-1]
except AttributeError:
raise Exception("file_name should be a string type")
if force_file_type:
file_type = force_file_type
else:
try:
file_type = file_name.split(".")[-1]
except AttributeError:
raise Exception("file_name should be a string type")
file_type_given = False

120
setup.py
View File

@ -1,14 +1,14 @@
#!/usr/bin/env python3
# Template by pypi-mobans
import os
import sys
import codecs
import locale
import os
import platform
import sys
from shutil import rmtree
from setuptools import Command, setup, find_packages
from setuptools import Command, find_packages, setup
PY2 = sys.version_info[0] == 2
PY26 = PY2 and sys.version_info[1] < 7
@ -22,69 +22,73 @@ PY33 = sys.version_info < (3, 4)
try:
lc = locale.getlocale()
pf = platform.system()
if pf != 'Windows' and lc == (None, None):
locale.setlocale(locale.LC_ALL, 'C.UTF-8')
if pf != "Windows" and lc == (None, None):
locale.setlocale(locale.LC_ALL, "C.UTF-8")
except (ValueError, UnicodeError, locale.Error):
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
locale.setlocale(locale.LC_ALL, "en_US.UTF-8")
NAME = 'pyexcel-io'
AUTHOR = 'C.W.'
VERSION = '0.6.0'
EMAIL = 'info@pyexcel.org'
LICENSE = 'New BSD'
NAME = "pyexcel-io"
AUTHOR = "C.W."
VERSION = "0.6.0"
EMAIL = "info@pyexcel.org"
LICENSE = "New BSD"
DESCRIPTION = (
'A python library to read and write structured data in csv, zipped csv' +
'format and to/from databases'
"A python library to read and write structured data in csv, zipped csv" +
"format and to/from databases"
)
URL = 'https://github.com/pyexcel/pyexcel-io'
DOWNLOAD_URL = '%s/archive/0.5.17.tar.gz' % URL
FILES = ['README.rst', 'CHANGELOG.rst']
URL = "https://github.com/pyexcel/pyexcel-io"
DOWNLOAD_URL = "%s/archive/0.5.19.tar.gz" % URL
FILES = ["README.rst", "CHANGELOG.rst"]
KEYWORDS = [
'python',
'API',
'tsv',
'tsvz',
'csv',
'csvz',
'django',
'sqlalchemy',
"python",
"API",
"tsv",
"tsvz",
"csv",
"csvz",
"django",
"sqlalchemy",
]
CLASSIFIERS = [
'Topic :: Software Development :: Libraries',
'Programming Language :: Python',
'Intended Audience :: Developers',
'Programming Language :: Python :: 2.6',
'Programming Language :: Python :: 2.7',
'Programming Language :: Python :: 3.3',
'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
"Topic :: Software Development :: Libraries",
"Programming Language :: Python",
"Intended Audience :: Developers",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
"Programming Language :: Python :: 3.5",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
'License :: OSI Approved :: BSD License',
'Programming Language :: Python :: Implementation :: PyPy'
]
INSTALL_REQUIRES = [
'lml>=0.0.4',
"lml>=0.0.4",
]
SETUP_COMMANDS = {}
if PY26:
INSTALL_REQUIRES.append('ordereddict')
PACKAGES = find_packages(exclude=['ez_setup', 'examples', 'tests'])
PACKAGES = find_packages(exclude=["ez_setup", "examples", "tests"])
EXTRAS_REQUIRE = {
'xls': ['pyexcel-xls>=0.5.0'],
'xlsx': ['pyexcel-xlsx>=0.5.0'],
'ods': ['pyexcel-ods3>=0.5.0'],
"xls": ['pyexcel-xls>=0.5.0'],
"xlsx": ['pyexcel-xlsx>=0.5.0'],
"ods": ['pyexcel-ods3>=0.5.0'],
}
# You do not need to read beyond this line
PUBLISH_COMMAND = '{0} setup.py sdist bdist_wheel upload -r pypi'.format(
sys.executable)
GS_COMMAND = ('gs pyexcel-io v0.5.17 ' +
"Find 0.5.17 in changelog for more details")
NO_GS_MESSAGE = ('Automatic github release is disabled. ' +
'Please install gease to enable it.')
PUBLISH_COMMAND = "{0} setup.py sdist bdist_wheel upload -r pypi".format(sys.executable)
GS_COMMAND = ("gs pyexcel-io v0.5.19 " +
"Find 0.5.19 in changelog for more details")
NO_GS_MESSAGE = ("Automatic github release is disabled. " +
"Please install gease to enable it.")
UPLOAD_FAILED_MSG = (
'Upload failed. please run "%s" yourself.' % PUBLISH_COMMAND)
HERE = os.path.abspath(os.path.dirname(__file__))
@ -93,13 +97,13 @@ HERE = os.path.abspath(os.path.dirname(__file__))
class PublishCommand(Command):
"""Support setup.py upload."""
description = 'Build and publish the package on github and pypi'
description = "Build and publish the package on github and pypi"
user_options = []
@staticmethod
def status(s):
"""Prints things in bold."""
print('\033[1m{0}\033[0m'.format(s))
print("\033[1m{0}\033[0m".format(s))
def initialize_options(self):
pass
@ -109,14 +113,14 @@ class PublishCommand(Command):
def run(self):
try:
self.status('Removing previous builds...')
rmtree(os.path.join(HERE, 'dist'))
rmtree(os.path.join(HERE, 'build'))
rmtree(os.path.join(HERE, 'pyexcel_io.egg-info'))
self.status("Removing previous builds...")
rmtree(os.path.join(HERE, "dist"))
rmtree(os.path.join(HERE, "build"))
rmtree(os.path.join(HERE, "pyexcel_io.egg-info"))
except OSError:
pass
self.status('Building Source and Wheel (universal) distribution...')
self.status("Building Source and Wheel (universal) distribution...")
run_status = True
if has_gease():
run_status = os.system(GS_COMMAND) == 0
@ -130,7 +134,7 @@ class PublishCommand(Command):
SETUP_COMMANDS.update({
'publish': PublishCommand
"publish": PublishCommand
})
@ -159,7 +163,7 @@ def read_files(*files):
def read(afile):
"""Read a file into setup"""
the_relative_file = os.path.join(HERE, afile)
with codecs.open(the_relative_file, 'r', 'utf-8') as opened_file:
with codecs.open(the_relative_file, "r", "utf-8") as opened_file:
content = filter_out_test_code(opened_file)
content = "".join(list(content))
return content
@ -168,11 +172,11 @@ def read(afile):
def filter_out_test_code(file_handle):
found_test_code = False
for line in file_handle.readlines():
if line.startswith('.. testcode:'):
if line.startswith(".. testcode:"):
found_test_code = True
continue
if found_test_code is True:
if line.startswith(' '):
if line.startswith(" "):
continue
else:
empty_line = line.strip()
@ -182,14 +186,14 @@ def filter_out_test_code(file_handle):
found_test_code = False
yield line
else:
for keyword in ['|version|', '|today|']:
for keyword in ["|version|", "|today|"]:
if keyword in line:
break
else:
yield line
if __name__ == '__main__':
if __name__ == "__main__":
setup(
test_suite="tests",
name=NAME,
@ -203,7 +207,7 @@ if __name__ == '__main__':
license=LICENSE,
keywords=KEYWORDS,
extras_require=EXTRAS_REQUIRE,
tests_require=['nose'],
tests_require=["nose"],
install_requires=INSTALL_REQUIRES,
packages=PACKAGES,
include_package_data=True,

View File

@ -1,6 +1,9 @@
from pyexcel_io.book import BookReader, BookWriter, RWInterface
from nose.tools import raises
from pyexcel_io.book import _convert_content_to_stream
from pyexcel_io._compact import PY2, StringIO, BytesIO
from nose import SkipTest
@raises(NotImplementedError)
@ -31,3 +34,21 @@ def test_book_reader_open_stream():
def test_book_writer():
writer = BookWriter()
writer.open_stream("a string")
def test_convert_to_bytes_stream():
if PY2:
raise SkipTest('No need test in python 2')
else:
file_content = b'test'
stream = _convert_content_to_stream(file_content, 'csv')
assert isinstance(stream, StringIO)
def test_convert_to_string_stream():
if PY2:
raise SkipTest('No need test in python 2')
else:
file_content = 'test'
stream = _convert_content_to_stream(file_content, 'csvz')
assert isinstance(stream, BytesIO)

View File

@ -24,6 +24,21 @@ def test_force_file_type():
eq_(expected, data[test_file])
def test_force_file_type_on_write():
test_file = "force_file_type_on_write.txt"
save_data(
test_file,
{"sheet 1": [[1, 2]]},
force_file_type="csv"
)
data = get_data(
test_file, force_file_type="csv"
)
expected = [[1, 2]]
eq_(expected, data[test_file])
os.unlink(test_file)
@raises(IOError)
def test_invalid_file():
load_data("/something/does/not/exist")