Skip to content

Commit

Permalink
Merge pull request #19 from pytroll/python3-support
Browse files Browse the repository at this point in the history
Add Python3 support
  • Loading branch information
alexmaul authored Nov 8, 2018
2 parents 2cb328e + 25c0377 commit 9c2f9fe
Show file tree
Hide file tree
Showing 19 changed files with 251 additions and 165 deletions.
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,14 @@ Command-line interface created by setup-py.
* Encoding JSON-formated values to BUFR.

## News
`Vers. 0.10.0`
All code supports Python2 *and* Python3, without code-conversion (i.e. by 2to3).

With Python3 the `setup.py` installs the command-line script with a different
name `trollbufr3`, to reflect its usage of Python3 and to have both versions
callable.

`Vers. 0.6.0`
With version 0.6.0 a feature for encoding a JSON formatted file into binary BUFR
is added.

Expand All @@ -38,5 +46,4 @@ New is `-j` to write any output in a JSON format.
## To-Do
There are still things to do:

* Support Python3
* Implement the remaining obscure operators
77 changes: 49 additions & 28 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,32 +29,53 @@

version = imp.load_source("trollbufr.version", "trollbufr/version.py")

requires = ["bitstring"]
requires = ["bitstring", "six"]

if sys.version_info < (2, 7):
requires.append("argparse")

setup(name="trollbufr",
version=version.__version__,
description="Reading meteorological data format BUFR in pure Python",
author="Alexander Maul",
author_email="alexander.maul@dwd.de",
classifiers=["Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU Lesser General Public License v3 " +
"or later (LGPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Programming Language :: Python :: 2.7",
"Topic :: Scientific/Engineering"
],
test_suite="bufr.tests.suite",
entry_points={
"console_scripts": ["trollbufr = trollbufr.bufr_main:run",
"trollbufr_update = trollbufr.update:run"]},
packages=["trollbufr", "trollbufr.coder"],
install_requires=requires,
python_requires=">=2.6, <3",
zip_safe=False,
)
if sys.version_info >= (3, 0):
setup(name="trollbufr",
version=version.version,
description="Reading meteorological data format BUFR in pure Python",
author="Alexander Maul",
author_email="alexander.maul@dwd.de",
classifiers=["Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU Lesser General Public License v3 " +
"or later (LGPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.4",
"Topic :: Scientific/Engineering"
],
test_suite="bufr.tests.suite",
entry_points={
"console_scripts": ["trollbufr3 = trollbufr.bufr_main:run",
"trollbufr3_update = trollbufr.update:run"]},
packages=["trollbufr", "trollbufr.coder"],
install_requires=requires,
python_requires=">=3.4",
zip_safe=False,
)
else:
setup(name="trollbufr",
version=version.version,
description="Reading meteorological data format BUFR in pure Python",
author="Alexander Maul",
author_email="alexander.maul@dwd.de",
classifiers=["Development Status :: 4 - Beta",
"Intended Audience :: Science/Research",
"License :: OSI Approved :: GNU Lesser General Public License v3 " +
"or later (LGPLv3+)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 2",
"Programming Language :: Python :: 2.6",
"Topic :: Scientific/Engineering"
],
test_suite="bufr.tests.suite",
entry_points={
"console_scripts": ["trollbufr = trollbufr.bufr_main:run",
"trollbufr_update = trollbufr.update:run"]},
packages=["trollbufr", "trollbufr.coder"],
install_requires=requires,
python_requires=">=2.6, <3",
zip_safe=False,
)
24 changes: 13 additions & 11 deletions trollbufr/bufr.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#
# Copyright (c) 2016-2018 Alexander Maul
#
# Ported to Py3 09/2018
#
# Author(s):
#
# Alexander Maul <alexander.maul@dwd.de>
Expand Down Expand Up @@ -30,15 +32,15 @@
which has the iterator function `next_data()` to iterate over all bin_data elements
in this subset.
"""
from coder.load_tables import TableCache
import coder.bufr_sect as sect
from coder.subset import SubsetReader, SubsetWriter
from coder.bdata import Blob
from coder.tables import TabBElem
from coder.functions import (descr_is_data, descr_is_loop, descr_is_oper,
descr_is_seq, descr_is_nil, get_descr_list)
from coder.errors import (SUPPORTED_BUFR_EDITION, BufrDecodeError,
BufrDecodeWarning, BufrTableError, BufrEncodeError)
from trollbufr.coder.load_tables import TableCache
from trollbufr.coder import bufr_sect as sect
from trollbufr.coder.subset import SubsetReader, SubsetWriter
from trollbufr.coder.bdata import Blob
from trollbufr.coder.tables import TabBElem
from trollbufr.coder.functions import (descr_is_data, descr_is_loop, descr_is_oper,
descr_is_seq, descr_is_nil, get_descr_list)
from trollbufr.coder.errors import (SUPPORTED_BUFR_EDITION, BufrDecodeError,
BufrDecodeWarning, BufrTableError, BufrEncodeError)
import logging

logger = logging.getLogger("trollbufr")
Expand Down Expand Up @@ -321,7 +323,7 @@ def decode_meta(self, bin_data, load_tables=True):
if load_tables:
try:
self._tables = self.load_tables()
except StandardError or Warning as exc:
except Exception or Warning as exc:
tables_fail = exc
#
# Section 2
Expand Down Expand Up @@ -525,7 +527,7 @@ def encode(self, json_data, load_tables=True):
if load_tables and not self._tables:
try:
self._tables = self.load_tables()
except StandardError or Warning as exc:
except Exception or Warning as exc:
raise exc
#
# Section 2
Expand Down
45 changes: 24 additions & 21 deletions trollbufr/bufr_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#
# Copyright (c) 2016,2017 Alexander Maul
#
# Ported to Py3 09/2018
#
# Author(s):
#
# Alexander Maul <alexander.maul@dwd.de>
Expand All @@ -26,15 +28,16 @@
if present) from file(s) and writes human-readable to stdout.
'''
from __future__ import print_function
from __future__ import absolute_import

import sys
import os
from argparse import ArgumentParser, RawDescriptionHelpFormatter
from version import __version__
from bufr import Bufr
from coder.bufr_types import TabBType
import load_file
import coder.load_tables
from trollbufr.version import version
from trollbufr.bufr import Bufr
from trollbufr.coder.bufr_types import TabBType
from trollbufr import load_file
from trollbufr.coder import load_tables

import logging
logger = logging.getLogger("trollbufr")
Expand All @@ -48,7 +51,7 @@ def read_bufr_data(args):
per all subsets at once, which improves performance for compressed BUFR.
"""
try:
fh_out = open(args.out_file, "wb")
fh_out = open(args.out_file, "w")
except:
fh_out = sys.stdout
bufr = Bufr(args.tables_type, args.tables_path)
Expand Down Expand Up @@ -137,7 +140,7 @@ def read_bufr_data(args):
d_name,
str(descr_entry.value),
d_unit), file=fh_out)
except StandardError as e:
except Exception as e:
print("ERROR\t%s" % e, file=fh_out)
if logger.isEnabledFor(logging.DEBUG):
logger.exception(e)
Expand Down Expand Up @@ -169,7 +172,7 @@ def read_bufr_to_json(args):
json_bufr = bufr.decode(blob,
load_tables=True,
as_array=args.array)
except StandardError as e:
except Exception as e:
logger.error(e, exc_info=1 and logger.isEnabledFor(logging.DEBUG))
json_data_item["error"] = str(e)
else:
Expand All @@ -178,7 +181,7 @@ def read_bufr_to_json(args):
finally:
json_data.append(json_data_item)
import json
out_fh = open(args.out_file, "wb") or sys.stdout
out_fh = open(args.out_file, "w") or sys.stdout
with out_fh as fh_out:
if args.sparse:
json.dump(json_data, fh_out)
Expand All @@ -190,7 +193,7 @@ def read_bufr_desc(args):
"""Read BUFR(s), decode meta-data and descriptor list, write to file-handle.
"""
try:
fh_out = open(args.out_file, "wb")
fh_out = open(args.out_file, "w")
except:
fh_out = sys.stdout
for fn_in in args.in_file:
Expand All @@ -212,7 +215,7 @@ def read_bufr_desc(args):
else:
d = bufr.get_descr_full()
print("DESC :\n%s" % "\n".join(d), file=fh_out)
except StandardError as e:
except Exception as e:
print("ERROR\t%s" % e, file=fh_out)
if logger.isEnabledFor(logging.DEBUG):
logger.exception(e)
Expand All @@ -230,7 +233,7 @@ def write_bufr(args):
fh_out = sys.stdout
multi_bul = False
for fn_in in args.in_file:
with open(fn_in, "rb") as fh_in:
with open(fn_in, "r") as fh_in:
json_data = json.load(fh_in)
for json_data_msg in json_data:
if not "bufr" in json_data_msg or json_data_msg["bufr"] is None:
Expand All @@ -240,9 +243,9 @@ def write_bufr(args):
bin_data = bufr.encode(json_data_msg["bufr"],
load_tables=True)
if json_data_msg["heading"] is not None:
multi_bul and print("\r\r\n\r\r\n", end="", file=fh_out)
print("%s\r\r" % json_data_msg["heading"], file=fh_out)
print(bin_data, end="", file=fh_out)
multi_bul and fh_out.write(b"\r\r\n\r\r\n")
fh_out.write(("%s\r\r\n" % json_data_msg["heading"]).encode())
fh_out.write(bin_data)
multi_bul = True
if fh_out is not sys.stdout:
fh_out.close()
Expand All @@ -254,7 +257,7 @@ def run(argv=None):
argv = sys.argv
else:
sys.argv.extend(argv)
program_version = __version__
program_version = version
try:
# Setup argument parser
parser = ArgumentParser(description=__import__('__main__').__doc__,
Expand Down Expand Up @@ -306,11 +309,11 @@ def run(argv=None):
metavar="path"
)
group_tab.add_argument("-T", "--tables_type",
default=coder.load_tables.list_parser()[0],
choices=coder.load_tables.list_parser(),
default=load_tables.list_parser()[0],
choices=load_tables.list_parser(),
help="type of table format [%s], default: %s" % (
"|".join(coder.load_tables.list_parser()),
coder.load_tables.list_parser()[0]
"|".join(load_tables.list_parser()),
load_tables.list_parser()[0]
),
metavar="name"
)
Expand Down Expand Up @@ -375,7 +378,7 @@ def run(argv=None):

except KeyboardInterrupt:
return 0
except StandardError as e:
except Exception as e:
if logger.isEnabledFor(logging.DEBUG):
logger.exception(e)
else:
Expand Down
6 changes: 4 additions & 2 deletions trollbufr/coder/bdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
#
# Copyright (c) 2016 Alexander Maul
#
# Ported to Py3 09/2018
#
# Author(s):
#
# Alexander Maul <alexander.maul@dwd.de>
Expand Down Expand Up @@ -48,7 +50,7 @@ def __init__(self, bin_data=None, rw=False):
self.reset()

def __str__(self):
return "%dB %d/%d" % (len(self._data) / 8, self._data.pos // 8, self._data.pos % 8)
return "%dB %d/%d" % (len(self._data) // 8, self._data.pos // 8, self._data.pos % 8)

def __len__(self):
return len(self._data)
Expand Down Expand Up @@ -93,7 +95,7 @@ def writelist(self, fmt, json_data):
def read_align(self, even=False):
p = self._data.pos
self._data.bytealign()
if even and (self._data.pos / 8) & 1:
if even and (self._data.pos // 8) & 1:
self._data.pos += 8
return self._data.pos - p

Expand Down
Loading

0 comments on commit 9c2f9fe

Please sign in to comment.