[Python-modules-commits] [python-dbfread] 01/03: New upstream version 2.0.7
Ghislain Vaillant
ghisvail-guest at moszumanska.debian.org
Wed Mar 15 18:52:33 UTC 2017
This is an automated email from the git hooks/post-receive script.
ghisvail-guest pushed a commit to branch master
in repository python-dbfread.
commit 31b19d5b1b90efea9dd8452c665e5b20ed4bb8b2
Author: Ghislain Antony Vaillant <ghisvail at gmail.com>
Date: Wed Mar 15 14:09:25 2017 +0000
New upstream version 2.0.7
---
LICENSE | 22 +++
MANIFEST.in | 9 +
PKG-INFO | 130 +++++++++++++
README.rst | 120 ++++++++++++
dbfread.egg-info/PKG-INFO | 130 +++++++++++++
dbfread.egg-info/SOURCES.txt | 57 ++++++
dbfread.egg-info/dependency_links.txt | 1 +
dbfread.egg-info/top_level.txt | 1 +
dbfread.egg-info/zip-safe | 1 +
dbfread/__init__.py | 27 +++
dbfread/codepages.py | 76 ++++++++
dbfread/dbf.py | 347 ++++++++++++++++++++++++++++++++++
dbfread/dbversions.py | 26 +++
dbfread/deprecated_dbf.py | 54 ++++++
dbfread/exceptions.py | 9 +
dbfread/field_parser.py | 258 +++++++++++++++++++++++++
dbfread/ifiles.py | 61 ++++++
dbfread/memo.py | 183 ++++++++++++++++++
dbfread/struct_parser.py | 41 ++++
dbfread/test_field_parser.py | 180 ++++++++++++++++++
dbfread/test_ifiles.py | 11 ++
dbfread/test_invalid_value.py | 7 +
dbfread/test_memo.py | 14 ++
dbfread/test_read_and_length.py | 42 ++++
dbfread/version.py | 17 ++
docs/Makefile | 153 +++++++++++++++
docs/_static/PLACEHOLDER | 2 +
docs/acknowledgements.rst | 5 +
docs/api_changes.rst | 22 +++
docs/changes.rst | 234 +++++++++++++++++++++++
docs/conf.py | 249 ++++++++++++++++++++++++
docs/dbf_objects.rst | 156 +++++++++++++++
docs/exporting_data.rst | 68 +++++++
docs/field_types.rst | 136 +++++++++++++
docs/index.rst | 62 ++++++
docs/installing.rst | 16 ++
docs/introduction.rst | 194 +++++++++++++++++++
docs/license.rst | 24 +++
docs/make.bat | 190 +++++++++++++++++++
docs/resources.rst | 25 +++
examples/custom_field_type.py | 13 ++
examples/dbf2sqlite | 126 ++++++++++++
examples/dbfinfo.py | 27 +++
examples/files/invalid_value.dbf | Bin 0 -> 173 bytes
examples/files/make_example_files.py | 55 ++++++
examples/files/people.dbf | Bin 0 -> 173 bytes
examples/namedtuples.py | 19 ++
examples/pandas_dataframe.py | 13 ++
examples/print_csv.py | 11 ++
examples/print_invalid_values.py | 18 ++
examples/record_objects.py | 13 ++
examples/using_dataset.py | 17 ++
run_tests.py | 25 +++
setup.cfg | 13 ++
setup.py | 40 ++++
testcases/memotest.FPT | Bin 0 -> 2560 bytes
testcases/memotest.dbf | Bin 0 -> 480 bytes
testcases/no_memofile.dbf | Bin 0 -> 480 bytes
58 files changed, 3750 insertions(+)
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..ca24e3e
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,22 @@
+The MIT License
+
+Copyright (c) Ole Martin Bjørndalen / UiT The Arctic University of Norway
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/MANIFEST.in b/MANIFEST.in
new file mode 100644
index 0000000..f0c825d
--- /dev/null
+++ b/MANIFEST.in
@@ -0,0 +1,9 @@
+include README.rst LICENSE run_tests.py
+include examples/dbf2sqlite
+recursive-include examples *.dbf *.py
+recursive-include testcases *.dbf *.FPT
+recursive-include docs *.bat
+recursive-include docs *.py
+recursive-include docs *.rst
+recursive-include docs Makefile
+include docs/_static/PLACEHOLDER
diff --git a/PKG-INFO b/PKG-INFO
new file mode 100644
index 0000000..554fc14
--- /dev/null
+++ b/PKG-INFO
@@ -0,0 +1,130 @@
+Metadata-Version: 1.0
+Name: dbfread
+Version: 2.0.7
+Summary: Read DBF Files with Python
+Home-page: https://dbfread.readthedocs.io/
+Author: Ole Martin Bjorndalen
+Author-email: ombdalen at gmail.com
+License: MIT
+Description: dbfread - Read DBF Files with Python
+ ====================================
+
+ DBF is a file format used by databases such dBase, Visual FoxPro, and
+ FoxBase+. This library reads DBF files and returns the data as native
+ Python data types for further processing. It is primarily intended for
+ batch jobs and one-off scripts.
+
+ ::
+
+ >>> from dbfread import DBF
+ >>> for record in DBF('people.dbf'):
+ ... print(record)
+ OrderedDict([('NAME', 'Alice'), ('BIRTHDATE', datetime.date(1987, 3, 1))])
+ OrderedDict([('NAME', 'Bob'), ('BIRTHDATE', datetime.date(1980, 11, 12))])
+
+ By default records are streamed directly from the file. If you have
+ enough memory you can instead load them into a list. This allows for
+ random access::
+
+ >>> table = DBF('people.dbf', load=True)
+ >>> print(table.records[1]['NAME'])
+ Bob
+ >>> print(table.records[0]['NAME'])
+ Alice
+
+ Full documentation at https://dbfread.readthedocs.io/
+
+ See docs/changes.rst for a full list of changes in each version.
+
+
+ Main Features
+ -------------
+
+ * written for Python 3, but also works in 2.7
+
+ * simple but flexible API
+
+ * data is returned as native Python data types
+
+ * records are ordered dictionaries, but can be reconfigured to be of
+ any type
+
+ * aims to handle all variants of DBF files. (Currently only widely
+ tested with Visual FoxPro, but should work well with other
+ variants.)
+
+ * support for 18 field types. Custom types can be added by subclassing
+ ``FieldParser``
+
+ * reads ``FPT`` and ``DBT`` memo files, both text and binary data
+
+ * handles mixed case file names gracefully on case sensitive file systems
+
+ * can retrieve deleted records
+
+
+ Installing
+ ----------
+
+ Requires Python 3.2 or 2.7.
+
+ ::
+
+ pip install dbfread
+
+ ``dbfread`` is a pure Python module and doesn't depend on any packages
+ outside the standard library.
+
+ To build documentation locally::
+
+ python setup.py docs
+
+ This requires Sphinx. The resulting files can be found in
+ ``docs/_build/``.
+
+
+ Source code
+ ------------
+
+ Latest stable release: http://github.com/olemb/dbfread/
+
+ Development version: http://github.com/olemb/dbfread/tree/develop/
+
+
+ API Changes
+ -----------
+
+ ``dbfread.open()`` and ``dbfread.read()`` are deprecated as of version
+ ``2.0``, and will be removed in ``2.2``.
+
+ The ``DBF`` class is no longer a subclass of ``list``. This makes the
+ API a lot cleaner and easier to understand, but old code that relied
+ on this behaviour will be broken. Iteration and record counting works
+ the same as before. Other list operations can be rewritten using the
+ ``record`` attribute. For example::
+
+ table = dbfread.read('people.dbf')
+ print(table[1])
+
+ can be rewritten as::
+
+ table = DBF('people.dbf', load=True)
+ print(table.records[1])
+
+ ``open()`` and ``read()`` both return ``DeprecatedDBF``, which is a
+ subclass of ``DBF`` and ``list`` and thus backward compatible.
+
+
+ License
+ -------
+
+ dbfread is released under the terms of the `MIT license
+ <http://en.wikipedia.org/wiki/MIT_License>`_.
+
+
+ Contact
+ -------
+
+ Ole Martin Bjorndalen - ombdalen at gmail.com
+
+Platform: UNKNOWN
diff --git a/README.rst b/README.rst
new file mode 100644
index 0000000..ed03696
--- /dev/null
+++ b/README.rst
@@ -0,0 +1,120 @@
+dbfread - Read DBF Files with Python
+====================================
+
+DBF is a file format used by databases such dBase, Visual FoxPro, and
+FoxBase+. This library reads DBF files and returns the data as native
+Python data types for further processing. It is primarily intended for
+batch jobs and one-off scripts.
+
+::
+
+ >>> from dbfread import DBF
+ >>> for record in DBF('people.dbf'):
+ ... print(record)
+ OrderedDict([('NAME', 'Alice'), ('BIRTHDATE', datetime.date(1987, 3, 1))])
+ OrderedDict([('NAME', 'Bob'), ('BIRTHDATE', datetime.date(1980, 11, 12))])
+
+By default records are streamed directly from the file. If you have
+enough memory you can instead load them into a list. This allows for
+random access::
+
+ >>> table = DBF('people.dbf', load=True)
+ >>> print(table.records[1]['NAME'])
+ Bob
+ >>> print(table.records[0]['NAME'])
+ Alice
+
+Full documentation at https://dbfread.readthedocs.io/
+
+See docs/changes.rst for a full list of changes in each version.
+
+
+Main Features
+-------------
+
+* written for Python 3, but also works in 2.7
+
+* simple but flexible API
+
+* data is returned as native Python data types
+
+* records are ordered dictionaries, but can be reconfigured to be of
+ any type
+
+* aims to handle all variants of DBF files. (Currently only widely
+ tested with Visual FoxPro, but should work well with other
+ variants.)
+
+* support for 18 field types. Custom types can be added by subclassing
+ ``FieldParser``
+
+* reads ``FPT`` and ``DBT`` memo files, both text and binary data
+
+* handles mixed case file names gracefully on case sensitive file systems
+
+* can retrieve deleted records
+
+
+Installing
+----------
+
+Requires Python 3.2 or 2.7.
+
+::
+
+ pip install dbfread
+
+``dbfread`` is a pure Python module and doesn't depend on any packages
+outside the standard library.
+
+To build documentation locally::
+
+ python setup.py docs
+
+This requires Sphinx. The resulting files can be found in
+``docs/_build/``.
+
+
+Source code
+------------
+
+Latest stable release: http://github.com/olemb/dbfread/
+
+Development version: http://github.com/olemb/dbfread/tree/develop/
+
+
+API Changes
+-----------
+
+``dbfread.open()`` and ``dbfread.read()`` are deprecated as of version
+``2.0``, and will be removed in ``2.2``.
+
+The ``DBF`` class is no longer a subclass of ``list``. This makes the
+API a lot cleaner and easier to understand, but old code that relied
+on this behaviour will be broken. Iteration and record counting works
+the same as before. Other list operations can be rewritten using the
+``record`` attribute. For example::
+
+ table = dbfread.read('people.dbf')
+ print(table[1])
+
+can be rewritten as::
+
+ table = DBF('people.dbf', load=True)
+ print(table.records[1])
+
+``open()`` and ``read()`` both return ``DeprecatedDBF``, which is a
+subclass of ``DBF`` and ``list`` and thus backward compatible.
+
+
+License
+-------
+
+dbfread is released under the terms of the `MIT license
+<http://en.wikipedia.org/wiki/MIT_License>`_.
+
+
+Contact
+-------
+
+Ole Martin Bjorndalen - ombdalen at gmail.com
diff --git a/dbfread.egg-info/PKG-INFO b/dbfread.egg-info/PKG-INFO
new file mode 100644
index 0000000..554fc14
--- /dev/null
+++ b/dbfread.egg-info/PKG-INFO
@@ -0,0 +1,130 @@
+Metadata-Version: 1.0
+Name: dbfread
+Version: 2.0.7
+Summary: Read DBF Files with Python
+Home-page: https://dbfread.readthedocs.io/
+Author: Ole Martin Bjorndalen
+Author-email: ombdalen at gmail.com
+License: MIT
+Description: dbfread - Read DBF Files with Python
+ ====================================
+
+ DBF is a file format used by databases such dBase, Visual FoxPro, and
+ FoxBase+. This library reads DBF files and returns the data as native
+ Python data types for further processing. It is primarily intended for
+ batch jobs and one-off scripts.
+
+ ::
+
+ >>> from dbfread import DBF
+ >>> for record in DBF('people.dbf'):
+ ... print(record)
+ OrderedDict([('NAME', 'Alice'), ('BIRTHDATE', datetime.date(1987, 3, 1))])
+ OrderedDict([('NAME', 'Bob'), ('BIRTHDATE', datetime.date(1980, 11, 12))])
+
+ By default records are streamed directly from the file. If you have
+ enough memory you can instead load them into a list. This allows for
+ random access::
+
+ >>> table = DBF('people.dbf', load=True)
+ >>> print(table.records[1]['NAME'])
+ Bob
+ >>> print(table.records[0]['NAME'])
+ Alice
+
+ Full documentation at https://dbfread.readthedocs.io/
+
+ See docs/changes.rst for a full list of changes in each version.
+
+
+ Main Features
+ -------------
+
+ * written for Python 3, but also works in 2.7
+
+ * simple but flexible API
+
+ * data is returned as native Python data types
+
+ * records are ordered dictionaries, but can be reconfigured to be of
+ any type
+
+ * aims to handle all variants of DBF files. (Currently only widely
+ tested with Visual FoxPro, but should work well with other
+ variants.)
+
+ * support for 18 field types. Custom types can be added by subclassing
+ ``FieldParser``
+
+ * reads ``FPT`` and ``DBT`` memo files, both text and binary data
+
+ * handles mixed case file names gracefully on case sensitive file systems
+
+ * can retrieve deleted records
+
+
+ Installing
+ ----------
+
+ Requires Python 3.2 or 2.7.
+
+ ::
+
+ pip install dbfread
+
+ ``dbfread`` is a pure Python module and doesn't depend on any packages
+ outside the standard library.
+
+ To build documentation locally::
+
+ python setup.py docs
+
+ This requires Sphinx. The resulting files can be found in
+ ``docs/_build/``.
+
+
+ Source code
+ ------------
+
+ Latest stable release: http://github.com/olemb/dbfread/
+
+ Development version: http://github.com/olemb/dbfread/tree/develop/
+
+
+ API Changes
+ -----------
+
+ ``dbfread.open()`` and ``dbfread.read()`` are deprecated as of version
+ ``2.0``, and will be removed in ``2.2``.
+
+ The ``DBF`` class is no longer a subclass of ``list``. This makes the
+ API a lot cleaner and easier to understand, but old code that relied
+ on this behaviour will be broken. Iteration and record counting works
+ the same as before. Other list operations can be rewritten using the
+ ``record`` attribute. For example::
+
+ table = dbfread.read('people.dbf')
+ print(table[1])
+
+ can be rewritten as::
+
+ table = DBF('people.dbf', load=True)
+ print(table.records[1])
+
+ ``open()`` and ``read()`` both return ``DeprecatedDBF``, which is a
+ subclass of ``DBF`` and ``list`` and thus backward compatible.
+
+
+ License
+ -------
+
+ dbfread is released under the terms of the `MIT license
+ <http://en.wikipedia.org/wiki/MIT_License>`_.
+
+
+ Contact
+ -------
+
+ Ole Martin Bjorndalen - ombdalen at gmail.com
+
+Platform: UNKNOWN
diff --git a/dbfread.egg-info/SOURCES.txt b/dbfread.egg-info/SOURCES.txt
new file mode 100644
index 0000000..d3e4701
--- /dev/null
+++ b/dbfread.egg-info/SOURCES.txt
@@ -0,0 +1,57 @@
+LICENSE
+MANIFEST.in
+README.rst
+run_tests.py
+setup.cfg
+setup.py
+dbfread/__init__.py
+dbfread/codepages.py
+dbfread/dbf.py
+dbfread/dbversions.py
+dbfread/deprecated_dbf.py
+dbfread/exceptions.py
+dbfread/field_parser.py
+dbfread/ifiles.py
+dbfread/memo.py
+dbfread/struct_parser.py
+dbfread/test_field_parser.py
+dbfread/test_ifiles.py
+dbfread/test_invalid_value.py
+dbfread/test_memo.py
+dbfread/test_read_and_length.py
+dbfread/version.py
+dbfread.egg-info/PKG-INFO
+dbfread.egg-info/SOURCES.txt
+dbfread.egg-info/dependency_links.txt
+dbfread.egg-info/top_level.txt
+dbfread.egg-info/zip-safe
+docs/Makefile
+docs/acknowledgements.rst
+docs/api_changes.rst
+docs/changes.rst
+docs/conf.py
+docs/dbf_objects.rst
+docs/exporting_data.rst
+docs/field_types.rst
+docs/index.rst
+docs/installing.rst
+docs/introduction.rst
+docs/license.rst
+docs/make.bat
+docs/resources.rst
+docs/_static/PLACEHOLDER
+examples/custom_field_type.py
+examples/dbf2sqlite
+examples/dbfinfo.py
+examples/namedtuples.py
+examples/pandas_dataframe.py
+examples/print_csv.py
+examples/print_invalid_values.py
+examples/record_objects.py
+examples/using_dataset.py
+examples/files/invalid_value.dbf
+examples/files/make_example_files.py
+examples/files/people.dbf
+testcases/memotest.FPT
+testcases/memotest.dbf
+testcases/no_memofile.dbf
\ No newline at end of file
diff --git a/dbfread.egg-info/dependency_links.txt b/dbfread.egg-info/dependency_links.txt
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/dbfread.egg-info/dependency_links.txt
@@ -0,0 +1 @@
+
diff --git a/dbfread.egg-info/top_level.txt b/dbfread.egg-info/top_level.txt
new file mode 100644
index 0000000..9d3aaeb
--- /dev/null
+++ b/dbfread.egg-info/top_level.txt
@@ -0,0 +1 @@
+dbfread
diff --git a/dbfread.egg-info/zip-safe b/dbfread.egg-info/zip-safe
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/dbfread.egg-info/zip-safe
@@ -0,0 +1 @@
+
diff --git a/dbfread/__init__.py b/dbfread/__init__.py
new file mode 100644
index 0000000..cd7b46f
--- /dev/null
+++ b/dbfread/__init__.py
@@ -0,0 +1,27 @@
+"""
+Read DBF files with Python.
+
+Example:
+
+ >>> from dbfread import DBF
+ >>> for record in DBF('people.dbf'):
+ ... print(record)
+ OrderedDict([('NAME', 'Alice'), ('BIRTHDATE', datetime.date(1987, 3, 1))])
+ OrderedDict([('NAME', 'Bob'), ('BIRTHDATE', datetime.date(1980, 11, 12))])
+
+Full documentation at https://dbfread.readthedocs.io/
+
+"""
+__author__ = 'Ole Martin Bjorndalen'
+__email__ = 'ombdalen at gmail.com'
+__url__ = 'https://dbfread.readthedocs.io/'
+__license__ = 'MIT'
+
+from .dbf import DBF
+from .deprecated_dbf import open, read
+from .exceptions import *
+from .field_parser import FieldParser, InvalidValue
+from .version import version_info, version as __version__
+
+# Prevent splat import.
+__all__ = []
diff --git a/dbfread/codepages.py b/dbfread/codepages.py
new file mode 100644
index 0000000..1b67f0d
--- /dev/null
+++ b/dbfread/codepages.py
@@ -0,0 +1,76 @@
+# Table from dbf.py by Ethan Furman
+codepages = {
+ 0x00: ('ascii', "plain ol' ascii"),
+ 0x01: ('cp437', 'U.S. MS-DOS'),
+ 0x02: ('cp850', 'International MS-DOS'),
+ 0x03: ('cp1252', 'Windows ANSI'),
+ 0x04: ('mac_roman', 'Standard Macintosh'),
+ 0x08: ('cp865', 'Danish OEM'),
+ 0x09: ('cp437', 'Dutch OEM'),
+ 0x0A: ('cp850', 'Dutch OEM (secondary)'),
+ 0x0B: ('cp437', 'Finnish OEM'),
+ 0x0D: ('cp437', 'French OEM'),
+ 0x0E: ('cp850', 'French OEM (secondary)'),
+ 0x0F: ('cp437', 'German OEM'),
+ 0x10: ('cp850', 'German OEM (secondary)'),
+ 0x11: ('cp437', 'Italian OEM'),
+ 0x12: ('cp850', 'Italian OEM (secondary)'),
+ 0x13: ('cp932', 'Japanese Shift-JIS'),
+ 0x14: ('cp850', 'Spanish OEM (secondary)'),
+ 0x15: ('cp437', 'Swedish OEM'),
+ 0x16: ('cp850', 'Swedish OEM (secondary)'),
+ 0x17: ('cp865', 'Norwegian OEM'),
+ 0x18: ('cp437', 'Spanish OEM'),
+ 0x19: ('cp437', 'English OEM (Britain)'),
+ 0x1A: ('cp850', 'English OEM (Britain) (secondary)'),
+ 0x1B: ('cp437', 'English OEM (U.S.)'),
+ 0x1C: ('cp863', 'French OEM (Canada)'),
+ 0x1D: ('cp850', 'French OEM (secondary)'),
+ 0x1F: ('cp852', 'Czech OEM'),
+ 0x22: ('cp852', 'Hungarian OEM'),
+ 0x23: ('cp852', 'Polish OEM'),
+ 0x24: ('cp860', 'Portuguese OEM'),
+ 0x25: ('cp850', 'Portuguese OEM (secondary)'),
+ 0x26: ('cp866', 'Russian OEM'),
+ 0x37: ('cp850', 'English OEM (U.S.) (secondary)'),
+ 0x40: ('cp852', 'Romanian OEM'),
+ 0x4D: ('cp936', 'Chinese GBK (PRC)'),
+ 0x4E: ('cp949', 'Korean (ANSI/OEM)'),
+ 0x4F: ('cp950', 'Chinese Big 5 (Taiwan)'),
+ 0x50: ('cp874', 'Thai (ANSI/OEM)'),
+ 0x57: ('cp1252', 'ANSI'),
+ 0x58: ('cp1252', 'Western European ANSI'),
+ 0x59: ('cp1252', 'Spanish ANSI'),
+ 0x64: ('cp852', 'Eastern European MS-DOS'),
+ 0x65: ('cp866', 'Russian MS-DOS'),
+ 0x66: ('cp865', 'Nordic MS-DOS'),
+ 0x67: ('cp861', 'Icelandic MS-DOS'),
+ # 0x68: (None, 'Kamenicky (Czech) MS-DOS'),
+ # 0x69: (None, 'Mazovia (Polish) MS-DOS'),
+ 0x6a: ('cp737', 'Greek MS-DOS (437G)'),
+ 0x6b: ('cp857', 'Turkish MS-DOS'),
+ 0x78: ('cp950', 'Traditional Chinese '
+ '(Hong Kong SAR, Taiwan) Windows'),
+ 0x79: ('cp949', 'Korean Windows'),
+ 0x7a: ('cp936', 'Chinese Simplified (PRC, Singapore) Windows'),
+ 0x7b: ('cp932', 'Japanese Windows'),
+ 0x7c: ('cp874', 'Thai Windows'),
+ 0x7d: ('cp1255', 'Hebrew Windows'),
+ 0x7e: ('cp1256', 'Arabic Windows'),
+ 0xc8: ('cp1250', 'Eastern European Windows'),
+ 0xc9: ('cp1251', 'Russian Windows'),
+ 0xca: ('cp1254', 'Turkish Windows'),
+ 0xcb: ('cp1253', 'Greek Windows'),
+ 0x96: ('mac_cyrillic', 'Russian Macintosh'),
+ 0x97: ('mac_latin2', 'Macintosh EE'),
+ 0x98: ('mac_greek', 'Greek Macintosh'),
+}
+
+
+def guess_encoding(language_driver):
+ if language_driver in codepages:
+ return codepages[language_driver][0]
+ else:
+ raise LookupError('Unable to guess encoding '
+ 'for languager driver byte '
+ '0x{:x}'.format(language_driver))
diff --git a/dbfread/dbf.py b/dbfread/dbf.py
new file mode 100644
index 0000000..5793530
--- /dev/null
+++ b/dbfread/dbf.py
@@ -0,0 +1,347 @@
+"""
+Class to read DBF files.
+"""
+import os
+import sys
+import datetime
+import collections
+
+from .ifiles import ifind
+from .struct_parser import StructParser
+from .field_parser import FieldParser
+from .memo import find_memofile, open_memofile, FakeMemoFile, BinaryMemo
+from .codepages import guess_encoding
+from .dbversions import get_dbversion_string
+from .exceptions import *
+
+DBFHeader = StructParser(
+ 'DBFHeader',
+ '<BBBBLHHHBBLLLBBH',
+ ['dbversion',
+ 'year',
+ 'month',
+ 'day',
+ 'numrecords',
+ 'headerlen',
+ 'recordlen',
+ 'reserved1',
+ 'incomplete_transaction',
+ 'encryption_flag',
+ 'free_record_thread',
+ 'reserved2',
+ 'reserved3',
+ 'mdx_flag',
+ 'language_driver',
+ 'reserved4',
+ ])
+
+DBFField = StructParser(
+ 'DBFField',
+ '<11scLBBHBBBB7sB',
+ ['name',
+ 'type',
+ 'address',
+ 'length',
+ 'decimal_count',
+ 'reserved1',
+ 'workarea_id',
+ 'reserved2',
+ 'reserved3',
+ 'set_fields_flag',
+ 'reserved4',
+ 'index_field_flag',
+ ])
+
+
+def expand_year(year):
+ """Convert 2-digit year to 4-digit year."""
+
+ if year < 80:
+ return 2000 + year
+ else:
+ return 1900 + year
+
+
+class RecordIterator(object):
+ def __init__(self, table, record_type):
+ self._record_type = record_type
+ self._table = table
+
+ def __iter__(self):
+ return self._table._iter_records(self._record_type)
+
+ def __len__(self):
+ return self._table._count_records(self._record_type)
+
+
+class DBF(object):
+ """DBF table."""
+ def __init__(self, filename, encoding=None, ignorecase=True,
+ lowernames=False,
+ parserclass=FieldParser,
+ recfactory=collections.OrderedDict,
+ load=False,
+ raw=False,
+ ignore_missing_memofile=False,
+ char_decode_errors='strict'):
+
+ self.encoding = encoding
+ self.ignorecase = ignorecase
+ self.lowernames = lowernames
+ self.parserclass = parserclass
+ self.raw = raw
+ self.ignore_missing_memofile = ignore_missing_memofile
+ self.char_decode_errors = char_decode_errors
+
+ if recfactory is None:
+ self.recfactory = lambda items: items
+ else:
+ self.recfactory = recfactory
+
+ # Name part before .dbf is the table name
+ self.name = os.path.basename(filename)
+ self.name = os.path.splitext(self.name)[0].lower()
+ self._records = None
+ self._deleted = None
+
+ if ignorecase:
+ self.filename = ifind(filename)
+ if not self.filename:
+ raise DBFNotFound('could not find file {!r}'.format(filename))
+ else:
+ self.filename = filename
+
+ # Filled in by self._read_headers()
+ self.memofilename = None
+ self.header = None
+ self.fields = [] # namedtuples
+ self.field_names = [] # strings
+
+ with open(self.filename, mode='rb') as infile:
+ self._read_header(infile)
+ self._read_field_headers(infile)
+ self._check_headers()
+
+ try:
+ self.date = datetime.date(expand_year(self.header.year),
+ self.header.month,
+ self.header.day)
+ except ValueError:
+ # Invalid date or '\x00\x00\x00'.
+ self.date = None
+
+ self.memofilename = self._get_memofilename()
+
+ if load:
+ self.load()
+
+ @property
+ def dbversion(self):
+ return get_dbversion_string(self.header.dbversion)
+
+ def _get_memofilename(self):
+ # Does the table have a memo field?
+ field_types = [field.type for field in self.fields]
+ if not set(field_types) & set('MGPB'):
+ # No memo fields.
+ return None
+
+ path = find_memofile(self.filename)
+ if path is None:
+ if self.ignore_missing_memofile:
+ return None
+ else:
+ raise MissingMemoFile('missing memo file for {}'.format(
+ self.filename))
+ else:
+ return path
+
+ @property
+ def loaded(self):
+ """``True`` if records are loaded into memory."""
+ return self._records is not None
+
+ def load(self):
+ """Load records into memory.
+
+ This loads both records and deleted records. The ``records``
+ and ``deleted`` attributes will now be lists of records.
+
+ """
+ if not self.loaded:
+ self._records = list(self._iter_records(b' '))
+ self._deleted = list(self._iter_records(b'*'))
+
+ def unload(self):
+ """Unload records from memory.
+
+ The records and deleted attributes will now be instances of
+ ``RecordIterator``, which streams records from disk.
+ """
+ self._records = None
+ self._deleted = None
+
+ @property
+ def records(self):
+ """Records (not included deleted ones). When loaded a list of records,
+ when not loaded a new ``RecordIterator`` object.
+ """
+ if self.loaded:
+ return self._records
+ else:
+ return RecordIterator(self, b' ')
+
+ @property
+ def deleted(self):
+ """Deleted records. When loaded a list of records, when not loaded a
+ new ``RecordIterator`` object.
+ """
+ if self.loaded:
+ return self._deleted
+ else:
+ return RecordIterator(self, b'*')
+
+ def _read_header(self, infile):
+ # Todo: more checks?
+ self.header = DBFHeader.read(infile)
+
+ if self.encoding is None:
+ try:
+ self.encoding = guess_encoding(self.header.language_driver)
+ except LookupError as err:
+ self.encoding = 'ascii'
+
+ def _decode_text(self, data):
+ return data.decode(self.encoding, errors=self.char_decode_errors)
+
+ def _read_field_headers(self, infile):
+ while True:
+ sep = infile.read(1)
+ if sep in (b'\r', b'\n', b''):
+ # End of field headers
+ break
+
+ field = DBFField.unpack(sep + infile.read(DBFField.size - 1))
+
+ field.type = chr(ord(field.type))
+
+ # For character fields > 255 bytes the high byte
+ # is stored in decimal_count.
+ if field.type in 'C':
+ field.length |= field.decimal_count << 8
+ field.decimal_count = 0
+
+ # Field name is b'\0' terminated.
+ field.name = self._decode_text(field.name.split(b'\0')[0])
+ if self.lowernames:
+ field.name = field.name.lower()
+
+ self.field_names.append(field.name)
+
+ self.fields.append(field)
+
+ def _open_memofile(self):
+ if self.memofilename and not self.raw:
+ return open_memofile(self.memofilename, self.header.dbversion)
+ else:
+ return FakeMemoFile(self.memofilename)
+
+ def _check_headers(self):
+ field_parser = self.parserclass(self)
+
+ """Check headers for possible format errors."""
+ for field in self.fields:
+
+ if field.type == 'I' and field.length != 4:
+ message = 'Field type I must have length 4 (was {})'
+ raise ValueError(message.format(field.length))
+
+ elif field.type == 'L' and field.length != 1:
+ message = 'Field type L must have length 1 (was {})'
+ raise ValueError(message.format(field.length))
+
+ elif not field_parser.field_type_supported(field.type):
+ # Todo: return as byte string?
+ raise ValueError('Unknown field type: {!r}'.format(field.type))
+
+ def _skip_record(self, infile):
+ # -1 for the record separator which was already read.
+ infile.seek(self.header.recordlen - 1, 1)
+
+ def _count_records(self, record_type=b' '):
+ count = 0
+
+ with open(self.filename, 'rb') as infile:
+ # Skip to first record.
+ infile.seek(self.header.headerlen, 0)
+
+ while True:
+ sep = infile.read(1)
+ if sep == record_type:
+ count += 1
+ self._skip_record(infile)
+ elif sep in (b'\x1a', b''):
+ # End of records.
+ break
+ else:
+ self._skip_record(infile)
... 3155 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-dbfread.git
More information about the Python-modules-commits
mailing list