diff --git a/.gitignore b/.gitignore index e13e7e6..d09b336 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,8 @@ -# April 2016 -# reference: https://github.com/github/gitignore/blob/master/Python.gitignore +# moban hashes +.moban.hashes + +# Extra rules from https://github.com/github/gitignore/ +# Python rules # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -10,7 +13,6 @@ __pycache__/ # Distribution / packaging .Python -env/ build/ develop-eggs/ dist/ @@ -22,9 +24,11 @@ lib64/ parts/ sdist/ var/ +wheels/ *.egg-info/ .installed.cfg *.egg +MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -44,8 +48,9 @@ htmlcov/ .cache nosetests.xml coverage.xml -*,cover +*.cover .hypothesis/ +.pytest_cache/ # Translations *.mo @@ -54,6 +59,7 @@ coverage.xml # Django stuff: *.log local_settings.py +db.sqlite3 # Flask stuff: instance/ @@ -68,7 +74,7 @@ docs/_build/ # PyBuilder target/ -# IPython Notebook +# Jupyter Notebook .ipynb_checkpoints # pyenv @@ -77,22 +83,388 @@ target/ # celery beat schedule file celerybeat-schedule -# dotenv -.env +# SageMath parsed files +*.sage.py -# virtualenv +# Environments +.env +.venv +env/ venv/ ENV/ +env.bak/ +venv.bak/ # Spyder project settings .spyderproject +.spyproject # Rope project settings .ropeproject -# emacs +# mkdocs documentation +/site + +# mypy +.mypy_cache/ + +# VirtualEnv rules +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json + +# Linux rules *~ -# moban hashes -.moban.hashes -.DS_store +# temporary files which can be created if a process still has a handle open of a deleted file +.fuse_hidden* + +# KDE directory preferences +.directory + +# Linux trash folder which might appear on any partition or disk +.Trash-* + +# .nfs files are created when an open file is removed but is still being accessed +.nfs* + +# Windows rules +# Windows thumbnail cache files +Thumbs.db +ehthumbs.db +ehthumbs_vista.db + +# Dump file +*.stackdump + +# Folder config file +[Dd]esktop.ini + +# Recycle Bin used on file shares +$RECYCLE.BIN/ + +# Windows Installer files +*.cab +*.msi +*.msix +*.msm +*.msp + +# Windows shortcuts +*.lnk + +# macOS rules +# General +.DS_Store +.AppleDouble +.LSOverride + +# Icon must end with two \r +Icon + + +# Thumbnails +._* + +# Files that might appear in the root of a volume +.DocumentRevisions-V100 +.fseventsd +.Spotlight-V100 +.TemporaryItems +.Trashes +.VolumeIcon.icns +.com.apple.timemachine.donotpresent + +# Directories potentially created on remote AFP share +.AppleDB +.AppleDesktop +Network Trash Folder +Temporary Items +.apdisk + +# Emacs rules +# -*- mode: gitignore; -*- +*~ +\#*\# +/.emacs.desktop +/.emacs.desktop.lock +*.elc +auto-save-list +tramp +.\#* + +# Org-mode +.org-id-locations +*_archive + +# flymake-mode +*_flymake.* + +# eshell files +/eshell/history +/eshell/lastdir + +# elpa packages +/elpa/ + +# reftex files +*.rel + +# AUCTeX auto folder +/auto/ + +# cask packages +.cask/ +dist/ + +# Flycheck +flycheck_*.el + +# server auth directory +/server/ + +# projectiles files +.projectile + +# directory configuration +.dir-locals.el + +# Vim rules +# Swap +[._]*.s[a-v][a-z] +[._]*.sw[a-p] +[._]s[a-rt-v][a-z] +[._]ss[a-gi-z] +[._]sw[a-p] + +# Session +Session.vim + +# Temporary +.netrwhist +*~ +# Auto-generated tag files +tags +# Persistent undo +[._]*.un~ + +# JetBrains rules +# Covers JetBrains IDEs: IntelliJ, RubyMine, PhpStorm, AppCode, PyCharm, CLion, Android Studio and WebStorm +# Reference: https://intellij-support.jetbrains.com/hc/en-us/articles/206544839 + +# User-specific stuff +.idea/**/workspace.xml +.idea/**/tasks.xml +.idea/**/usage.statistics.xml +.idea/**/dictionaries +.idea/**/shelf + +# Sensitive or high-churn files +.idea/**/dataSources/ +.idea/**/dataSources.ids +.idea/**/dataSources.local.xml +.idea/**/sqlDataSources.xml +.idea/**/dynamic.xml +.idea/**/uiDesigner.xml +.idea/**/dbnavigator.xml + +# Gradle +.idea/**/gradle.xml +.idea/**/libraries + +# CMake +cmake-build-*/ + +# Mongo Explorer plugin +.idea/**/mongoSettings.xml + +# File-based project format +*.iws + +# IntelliJ +out/ + +# mpeltonen/sbt-idea plugin +.idea_modules/ + +# JIRA plugin +atlassian-ide-plugin.xml + +# Cursive Clojure plugin +.idea/replstate.xml + +# Crashlytics plugin (for Android Studio and IntelliJ) +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties + +# Editor-based Rest Client +.idea/httpRequests + +# SublimeText rules +# Cache files for Sublime Text +*.tmlanguage.cache +*.tmPreferences.cache +*.stTheme.cache + +# Workspace files are user-specific +*.sublime-workspace + +# Project files should be checked into the repository, unless a significant +# proportion of contributors will probably not be using Sublime Text +# *.sublime-project + +# SFTP configuration file +sftp-config.json + +# Package control specific files +Package Control.last-run +Package Control.ca-list +Package Control.ca-bundle +Package Control.system-ca-bundle +Package Control.cache/ +Package Control.ca-certs/ +Package Control.merged-ca-bundle +Package Control.user-ca-bundle +oscrypto-ca-bundle.crt +bh_unicode_properties.cache + +# Sublime-github package stores a github token in this file +# https://packagecontrol.io/packages/sublime-github +GitHub.sublime-settings + +# KDevelop4 rules +*.kdev4 +.kdev4/ + +# Kate rules +# Swap Files # +.*.kate-swp +.swp.* + +# TextMate rules +*.tmproj +*.tmproject +tmtags + +# VisualStudioCode rules +.vscode/* +!.vscode/settings.json +!.vscode/tasks.json +!.vscode/launch.json +!.vscode/extensions.json + +# Xcode rules +# Xcode +# +# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore + +## User settings +xcuserdata/ + +## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) +*.xcscmblueprint +*.xccheckout + +## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) +build/ +DerivedData/ +*.moved-aside +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 + +# Eclipse rules + +.metadata +bin/ +tmp/ +*.tmp +*.bak +*.swp +*~.nib +local.properties +.settings/ +.loadpath +.recommenders + +# External tool builders +.externalToolBuilders/ + +# Locally stored "Eclipse launch configurations" +*.launch + +# PyDev specific (Python IDE for Eclipse) +*.pydevproject + +# CDT-specific (C/C++ Development Tooling) +.cproject + +# CDT- autotools +.autotools + +# Java annotation processor (APT) +.factorypath + +# PDT-specific (PHP Development Tools) +.buildpath + +# sbteclipse plugin +.target + +# Tern plugin +.tern-project + +# TeXlipse plugin +.texlipse + +# STS (Spring Tool Suite) +.springBeans + +# Code Recommenders +.recommenders/ + +# Annotation Processing +.apt_generated/ + +# Scala IDE specific (Scala & Java development for Eclipse) +.cache-main +.scala_dependencies +.worksheet + +# TortoiseGit rules +# Project-level settings +/.tgitconfig + +# Tags rules +# Ignore tags created by etags, ctags, gtags (GNU global) and cscope +TAGS +.TAGS +!TAGS/ +tags +.tags +!tags/ +gtags.files +GTAGS +GRTAGS +GPATH +GSYMS +cscope.files +cscope.out +cscope.in.out +cscope.po.out diff --git a/.moban.d/tests/requirements.txt b/.moban.d/tests/requirements.txt index da5ea12..414637d 100644 --- a/.moban.d/tests/requirements.txt +++ b/.moban.d/tests/requirements.txt @@ -1,4 +1,5 @@ {% extends 'tests/requirements.txt.jj2' %} {%block extras %} pyexcel +xlrd==1.1.0 {%endblock%} diff --git a/.travis.yml b/.travis.yml index 440dd77..5817466 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,7 @@ notifications: email: false python: - pypy-5.3.1 + - 3.7-dev - 3.6 - 3.5 - 3.4 diff --git a/CHANGELOG.rst b/CHANGELOG.rst index 70bb9c2..e4677db 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -1,6 +1,15 @@ Change log ================================================================================ +0.5.8 - 22.08.2018 +-------------------------------------------------------------------------------- + +Added +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +#. `pyexcel#151 `_, read cell + error as #N/A. + 0.5.7 - 15.03.2018 -------------------------------------------------------------------------------- diff --git a/changelog.yml b/changelog.yml index 3734e3c..f25f270 100644 --- a/changelog.yml +++ b/changelog.yml @@ -1,6 +1,12 @@ name: pyexcel-xls organisation: pyexcel releases: +- changes: + - action: Added + details: + - "`pyexcel#151`, read cell error as #N/A." + date: 22.08.2018 + version: 0.5.8 - changes: - action: Added details: diff --git a/docs/source/conf.py b/docs/source/conf.py index 90bf2ea..f3b62db 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -4,39 +4,192 @@ DESCRIPTION = ( ' reads xlsx and xlsm format' + '' ) +# -*- coding: utf-8 -*- +# +# Configuration file for the Sphinx documentation builder. +# +# This file does only contain a selection of the most common options. For a +# full list see the documentation: +# http://www.sphinx-doc.org/en/master/config + +# -- Path setup -------------------------------------------------------------- + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# +# import os +# import sys +# sys.path.insert(0, os.path.abspath('.')) + +# -- Project information ----------------------------------------------------- + +project = u'pyexcel-xls' +copyright = u'2015-2018 Onni Software Ltd.' +author = u'C.W.' + +# The short X.Y version +version = u'0.5.8' +# The full version, including alpha/beta/rc tags +release = u'0.5.8' + + +# -- General configuration --------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +# +# needs_sphinx = '1.0' + +# Add any Sphinx extension module names here, as strings. They can be +# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom +# ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.doctest', 'sphinx.ext.intersphinx', 'sphinx.ext.viewcode', ] -intersphinx_mapping = { - 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), -} + +# Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] + +# The suffix(es) of source filenames. +# You can specify multiple suffix as a list of string: +# +# source_suffix = ['.rst', '.md'] source_suffix = '.rst' + +# The master toctree document. master_doc = 'index' -project = u'pyexcel-xls' -copyright = u'2015-2018 Onni Software Ltd.' -version = '0.5.7' -release = '0.5.7' +# The language for content autogenerated by Sphinx. Refer to documentation +# for a list of supported languages. +# +# This is also used if you do content translation via gettext catalogs. +# Usually you set "language" from the command line for these cases. +language = 'en' + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +# This pattern also affects html_static_path and html_extra_path. exclude_patterns = [] + +# The name of the Pygments (syntax highlighting) style to use. pygments_style = 'sphinx' -html_theme = 'default' + + +# -- Options for HTML output ------------------------------------------------- + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. +# +html_theme = 'alabaster' + +# Theme options are theme-specific and customize the look and feel of a theme +# further. For a list of options available for each theme, see the +# documentation. +# +# html_theme_options = {} + +# Add any paths that contain custom static files (such as style sheets) here, +# relative to this directory. They are copied after the builtin static files, +# so a file named "default.css" will overwrite the builtin "default.css". html_static_path = ['_static'] + +# Custom sidebar templates, must be a dictionary that maps document names +# to template names. +# +# The default sidebars (for documents that don't match any pattern) are +# defined by theme itself. Builtin themes are using these templates by +# default: ``['localtoc.html', 'relations.html', 'sourcelink.html', +# 'searchbox.html']``. +# +# html_sidebars = {} + + +# -- Options for HTMLHelp output --------------------------------------------- + +# Output file base name for HTML help builder. htmlhelp_basename = 'pyexcel-xlsdoc' -latex_elements = {} + + +# -- Options for LaTeX output ------------------------------------------------ + +latex_elements = { + # The paper size ('letterpaper' or 'a4paper'). + # + # 'papersize': 'letterpaper', + + # The font size ('10pt', '11pt' or '12pt'). + # + # 'pointsize': '10pt', + + # Additional stuff for the LaTeX preamble. + # + # 'preamble': '', + + # Latex figure (float) alignment + # + # 'figure_align': 'htbp', +} + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, +# author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'pyexcel-xls.tex', - 'pyexcel-xls Documentation', - 'Onni Software Ltd.', 'manual'), + (master_doc, 'pyexcel-xls.tex', u'pyexcel-xls Documentation', + u'Onni Software Ltd.', 'manual'), ] + + +# -- Options for manual page output ------------------------------------------ + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pyexcel-xls', - 'pyexcel-xls Documentation', - [u'Onni Software Ltd.'], 1) + (master_doc, 'pyexcel-xls', u'pyexcel-xls Documentation', + [author], 1) ] + + +# -- Options for Texinfo output ---------------------------------------------- + +# Grouping the document tree into Texinfo files. List of tuples +# (source start file, target name, title, author, +# dir menu entry, description, category) +texinfo_documents = [ + (master_doc, 'pyexcel-xls', u'pyexcel-xls Documentation', + author, 'pyexcel-xls', 'One line description of project.', + 'Miscellaneous'), +] + + +# -- Options for Epub output ------------------------------------------------- + +# Bibliographic Dublin Core info. +epub_title = project + +# The unique identifier of the text. This can be a ISBN number +# or the project homepage. +# +# epub_identifier = '' + +# A unique identification for the text. +# +# epub_uid = '' + +# A list of files that should not be packed into the epub file. +epub_exclude_files = ['search.html'] + +# -- Extension configuration ------------------------------------------------- +# -- Options for intersphinx extension --------------------------------------- + +# Example configuration for intersphinx: refer to the Python standard library. +intersphinx_mapping = {'https://docs.python.org/': None} +# TODO: html_theme not configurable upstream +html_theme = 'default' + +# TODO: DESCRIPTION not configurable upstream texinfo_documents = [ ('index', 'pyexcel-xls', 'pyexcel-xls Documentation', @@ -44,3 +197,6 @@ texinfo_documents = [ DESCRIPTION, 'Miscellaneous'), ] +intersphinx_mapping.update({ + 'pyexcel': ('http://pyexcel.readthedocs.io/en/latest/', None), +}) diff --git a/pyexcel-xls.yml b/pyexcel-xls.yml new file mode 100644 index 0000000..c620ccb --- /dev/null +++ b/pyexcel-xls.yml @@ -0,0 +1,12 @@ +overrides: "pyexcel.yaml" +name: "pyexcel-xls" +nick_name: xls +version: 0.5.8 +current_version: 0.5.8 +release: 0.5.8 +file_type: xls +dependencies: + - pyexcel-io>=0.5.3 + - xlrd + - xlwt +description: A wrapper library to read, manipulate and write data in xls format. It reads xlsx and xlsm format diff --git a/pyexcel_xls/xlsr.py b/pyexcel_xls/xlsr.py index 8d7345c..0476857 100644 --- a/pyexcel_xls/xlsr.py +++ b/pyexcel_xls/xlsr.py @@ -21,6 +21,7 @@ XLS_KEYWORDS = [ 'file_contents', 'encoding_override', 'formatting_info', 'on_demand', 'ragged_rows' ] +DEFAULT_ERROR_VALUE = '#N/A' class MergedCell(object): @@ -93,6 +94,9 @@ class XLSheet(SheetReader): elif cell_type == xlrd.XL_CELL_NUMBER and self.__auto_detect_int: if has_no_digits_in_float(value): value = int(value) + elif cell_type == xlrd.XL_CELL_ERROR: + value = DEFAULT_ERROR_VALUE + if self.__merged_cells: merged_cell = self.__merged_cells.get("%s-%s" % (row, column)) if merged_cell: diff --git a/setup.py b/setup.py index f18938b..92b2a0e 100644 --- a/setup.py +++ b/setup.py @@ -1,4 +1,6 @@ -# Template by setupmobans +#!/usr/bin/env python3 + +# Template by pypi-mobans import os import sys import codecs @@ -9,7 +11,7 @@ PY26 = PY2 and sys.version_info[1] < 7 NAME = 'pyexcel-xls' AUTHOR = 'C.W.' -VERSION = '0.5.7' +VERSION = '0.5.8' EMAIL = 'wangc_2011@hotmail.com' LICENSE = 'New BSD' DESCRIPTION = ( @@ -17,18 +19,16 @@ DESCRIPTION = ( 'reads xlsx and xlsm format' ) URL = 'https://github.com/pyexcel/pyexcel-xls' -DOWNLOAD_URL = '%s/archive/0.5.7.tar.gz' % URL +DOWNLOAD_URL = '%s/archive/0.5.8.tar.gz' % URL FILES = ['README.rst', 'CHANGELOG.rst'] KEYWORDS = [ 'xls', 'xlsx', - 'xlsm' - 'python' + 'xlsm', + 'python', ] CLASSIFIERS = [ - 'Topic :: Office/Business', - 'Topic :: Utilities', 'Topic :: Software Development :: Libraries', 'Programming Language :: Python', 'Intended Audience :: Developers', @@ -55,8 +55,8 @@ EXTRAS_REQUIRE = { # 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-xls v0.5.7 ' + - "Find 0.5.7 in changelog for more details") +GS_COMMAND = ('gs pyexcel-xls v0.5.8 ' + + "Find 0.5.8 in changelog for more details") NO_GS_MESSAGE = ('Automatic github release is disabled. ' + 'Please install gease to enable it.') UPLOAD_FAILED_MSG = ( @@ -132,7 +132,8 @@ def read_files(*files): def read(afile): """Read a file into setup""" - with codecs.open(afile, 'r', 'utf-8') as opened_file: + the_relative_file = os.path.join(HERE, afile) + 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 diff --git a/test.bat b/test.bat index a09129d..351d266 100644 --- a/test.bat +++ b/test.bat @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long diff --git a/test.sh b/test.sh index a09129d..351d266 100644 --- a/test.sh +++ b/test.sh @@ -1,2 +1,2 @@ pip freeze -nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests --with-doctest --doctest-extension=.rst README.rst tests docs/source pyexcel_xls && flake8 . --exclude=.moban.d --builtins=unicode,xrange,long +nosetests --with-coverage --cover-package pyexcel_xls --cover-package tests tests --with-doctest --doctest-extension=.rst README.rst docs/source pyexcel_xls && flake8 . --exclude=.moban.d,docs --builtins=unicode,xrange,long diff --git a/tests/fixtures/pyexcel_issue_151.xlsx b/tests/fixtures/pyexcel_issue_151.xlsx new file mode 100644 index 0000000..fd2b54a Binary files /dev/null and b/tests/fixtures/pyexcel_issue_151.xlsx differ diff --git a/tests/requirements.txt b/tests/requirements.txt index a29762c..131361c 100644 --- a/tests/requirements.txt +++ b/tests/requirements.txt @@ -4,3 +4,4 @@ codecov coverage flake8 pyexcel +xlrd==1.1.0 diff --git a/tests/test_bug_fixes.py b/tests/test_bug_fixes.py index 35ee894..af8bf42 100644 --- a/tests/test_bug_fixes.py +++ b/tests/test_bug_fixes.py @@ -92,6 +92,14 @@ def test_issue_20(): pe.get_book(url="https://github.com/pyexcel/pyexcel-xls/raw/master/tests/fixtures/file_with_an_empty_sheet.xls"); # flake8: noqa +def test_issue_151(): + s = pe.get_sheet( + file_name=get_fixture('pyexcel_issue_151.xlsx'), + skip_hidden_row_and_column=False, + library='pyexcel-xls') + eq_('#N/A', s[0,0]) + + @raises(NotImplementedError) def test_empty_book_pyexcel_issue_120(): """