[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