[Debian-astro-commits] [python-cpl] 01/03: New upstream version 0.7.2

Ole Streicher olebole at moszumanska.debian.org
Tue Feb 23 08:13:09 UTC 2016


This is an automated email from the git hooks/post-receive script.

olebole pushed a commit to branch debian
in repository python-cpl.

commit 38774b8b6e3de0d5cc5d1d8b55defce8e2bc74ea
Author: Ole Streicher <ole at aip.de>
Date:   Mon Feb 22 09:47:19 2016 +0100

    New upstream version 0.7.2
---
 PKG-INFO                          |   7 +-
 README.rst                        |  16 +++--
 cpl/CPL_library.c                 |   2 +
 cpl/CPL_library.h                 |   4 +-
 cpl/cpl_api.h                     |   2 +-
 cpl/dfs.py                        |  30 ++-------
 cpl/esorex.py                     |   2 +-
 cpl/frames.py                     |   5 +-
 cpl/logger.py                     |   3 -
 cpl/md5sum.py                     |  15 ++---
 cpl/recipe.py                     |  15 +++--
 cpl/result.py                     |  47 +++++++-------
 cpl/run.py                        | 130 --------------------------------------
 cpl/version.py                    |   2 +-
 doc/install.rst                   |   9 +--
 doc/{install.rst => install.rst~} |   0
 setup.py                          |   4 +-
 test/TestRecipe.py                | 120 ++++++++++++++++++++++++-----------
 18 files changed, 157 insertions(+), 256 deletions(-)

diff --git a/PKG-INFO b/PKG-INFO
index 0cedee7..f80ec8d 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,12 +1,12 @@
 Metadata-Version: 1.1
 Name: python-cpl
-Version: 0.7
+Version: 0.7.2
 Summary: Python interface for the ESO Common Pipeline Library
-Home-page: https://pypi.python.org/pypi/python-cpl/0.7
+Home-page: https://pypi.python.org/pypi/python-cpl/0.7.2
 Author: Ole Streicher
 Author-email: python-cpl at liska.ath.cx
 License: GPL
-Download-URL: http://pypi.python.org/packages/source/p/python-cpl/python-cpl-0.7.tar.gz
+Download-URL: http://pypi.python.org/packages/source/p/python-cpl/python-cpl-0.7.2.tar.gz
 Description: This module can list, configure and execute CPL-based recipes from Python
         (python2 and python3).  The input, calibration and output data can be
         specified as FITS files or as ``astropy.io.fits`` objects in memory.
@@ -31,5 +31,4 @@ Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 3
 Classifier: Topic :: Scientific/Engineering :: Astronomy
-Requires: astropy
 Provides: cpl
diff --git a/README.rst b/README.rst
index a9306f2..577ca4e 100644
--- a/README.rst
+++ b/README.rst
@@ -3,13 +3,15 @@ python-cpl
 
 *Python interface for the Common Pipeline Library*
 
-.. image:: https://pypip.in/v/python-cpl/badge.png
+.. image:: https://img.shields.io/pypi/v/python-cpl.svg
     :target: https://pypi.python.org/pypi/python-cpl
 
-.. image:: https://pypip.in/d/python-cpl/badge.png
+.. image:: https://img.shields.io/pypi/dm/python-cpl.svg
     :target: https://pypi.python.org/pypi/python-cpl
 
-This module can list, configure and execute CPL-based recipes from Python
+Python-cpl is an `Astropy Affiliated Package <http://www.astropy.org/affiliated/>`_ 
+that can list, configure and execute recipes from `ESO data reduction
+pipelines <http://www.eso.org/sci/software/pipelines/>`_ from Python
 (python2 and python3).  The input, calibration and output data can be
 specified as FITS files or as ``astropy.io.fits`` objects in memory.
 
@@ -21,13 +23,12 @@ the CPL is the ability to create data-reduction algorithms that run as plugins
 (dynamic libraries). These are called "recipes" and are one of the main
 aspects of the CPL data-reduction development environment.
 
-Python-cpl releases are `registered on PyPI
+Python-CPL releases are `registered on PyPI
 <http://pypi.python.org/pypi/python-cpl>`_, and development is occurring at
 the `project's github page <http://github.com/olebole/python-cpl>`_.
 
 For installation instructions, see the 
-`online documentation <http://cpl-python.readthedocs.org/en/master/install.html>`_
-or ``docs/install.rst`` in this source distribution.
+`online documentation <http://python-cpl.readthedocs.org/en/latest/install.html>`_.
 The travis test status, coverage, and documentation build status
 of the github repository is:
 
@@ -37,6 +38,9 @@ of the github repository is:
 .. image:: https://coveralls.io/repos/olebole/python-cpl/badge.svg?branch=master
   :target: https://coveralls.io/r/olebole/python-cpl?branch=master
 
+.. image:: https://landscape.io/github/olebole/python-cpl/master/landscape.svg?style=flat
+   :target: https://landscape.io/github/olebole/python-cpl/master
+	   
 .. image:: https://readthedocs.org/projects/python-cpl/badge/?version=latest
     :target: https://readthedocs.org/projects/python-cpl/?badge=latest
 
diff --git a/cpl/CPL_library.c b/cpl/CPL_library.c
index 3dd9541..aadd353 100644
--- a/cpl/CPL_library.c
+++ b/cpl/CPL_library.c
@@ -4,6 +4,8 @@
 #include "CPL_library.h"
 
 unsigned long supported_versions[] = {
+    CPL_VERSION(7,0,0),
+    CPL_VERSION(6,6,1),
     CPL_VERSION(6,6,0),
     CPL_VERSION(6,5,1),
     CPL_VERSION(6,5,0),
diff --git a/cpl/CPL_library.h b/cpl/CPL_library.h
index fa42970..9880742 100644
--- a/cpl/CPL_library.h
+++ b/cpl/CPL_library.h
@@ -16,8 +16,8 @@
 #if CPL_VERSION_CODE < CPL_VERSION(6,3,0)
 #error CPL version too old. Minimum required version is 6.3.0.
 #endif
-#if CPL_VERSION_CODE > CPL_VERSION(6,3,0)
-#warning Newer CPL version: check API compability with 6.3.0 at http://upstream-tracker.org/versions/cpl.html
+#if CPL_VERSION_CODE > CPL_VERSION(7,0,0)
+#warning Newer CPL version: check API compability with 7.0.0 at http://upstream-tracker.org/versions/cpl.html
 #endif
 
 extern unsigned long supported_versions[];
diff --git a/cpl/cpl_api.h b/cpl/cpl_api.h
index 6ce173a..bd303ab 100644
--- a/cpl/cpl_api.h
+++ b/cpl/cpl_api.h
@@ -36,7 +36,7 @@
 #define CPL_VERSION_MINOR_CODE(code) (((code) >> 8) & 0xff)
 #define CPL_VERSION_MICRO_CODE(code) ((code) & 0xff)
 
-#define CPL_VERSION_CODE CPL_VERSION(6,3,0)
+#define CPL_VERSION_CODE CPL_VERSION(7,0,0)
 
 typedef int cpl_error_code, cpl_errorstate, cpl_boolean, cpl_frame_group,
     cpl_parameter_mode, cpl_parameter_class, cpl_type, cpl_msg_severity;
diff --git a/cpl/dfs.py b/cpl/dfs.py
index ec3cb18..1300ebe 100644
--- a/cpl/dfs.py
+++ b/cpl/dfs.py
@@ -1,9 +1,7 @@
-import itertools
-import os
 import sys
-try:
+try: # pragma: no cover
     from astropy.io import fits
-except:
+except ImportError:
     import pyfits as fits
 
 import cpl
@@ -87,7 +85,7 @@ class ProcessingInfo(object):
           accompanied with the MD5 sum.
     '''
 
-    def __init__(self, source, recno = -1, md5sums = None):
+    def __init__(self, source, recno = -1):
         '''
         :param source: Object pointing to the result file header
         :type source: :class:`str` or :class:`astropy.io.fits.HDUList`
@@ -96,10 +94,6 @@ class ProcessingInfo(object):
         :param recno: Record number. Optional. If not given, the last record
                       (with the highest record number) is used.
         :type recno: :class:`int`
-        :param md5sums: Dictionary with md5 sums as keys and complete file names
-                        as values to provide a full path for the raw and
-                        calibration frames. Optional.
-        :type md5sums: :class:`dict`
         '''
         if isinstance(source, str):
             header = fits.open(source)[0].header
@@ -133,8 +127,6 @@ class ProcessingInfo(object):
             self.version = None
         self.cpl_version = header.get('HIERARCH ESO PRO REC{0} DRS ID'.format(recno))
         self.md5sum = header.get('DATAMD5')
-        if md5sums and self.md5sum in md5sums:
-            self.orig_filename = md5sums[self.md5sum]
         self.md5sums = {}
         self.calib = ProcessingInfo._get_rec_keys(header, recno, 'CAL', 'CATG', 'NAME')
         for cat, md5 in ProcessingInfo._get_rec_keys(header, recno, 'CAL', 'CATG',
@@ -142,12 +134,8 @@ class ProcessingInfo(object):
             if isinstance(md5, list):
                 for i, m in enumerate(md5):
                     if m is not None:
-                        if md5sums and m in md5sums:
-                            self.calib[cat][i] = md5sums[m]
                         self.md5sums[self.calib[cat][i]] = m
             elif md5 is not None:
-                if md5sums and md5 in md5sums:
-                    self.calib[cat] = md5sums[md5]
                 self.md5sums[self.calib[cat]] = md5
         raw = ProcessingInfo._get_rec_keys(header, recno, 'RAW', 'CATG', 'NAME')
         if raw:
@@ -158,12 +146,8 @@ class ProcessingInfo(object):
             if isinstance(md5, list):
                 for i, m in enumerate(md5):
                     if m is not None: 
-                        if md5sums and m in md5sums:
-                            self.raw[i] = md5sums[m]
                         self.md5sums[self.raw[i]] = m
             elif md5 is not None:
-                if md5sums and md5 in md5sums:
-                    self.raw = md5sums[md5]
                 self.md5sums[self.raw] = md5
         else:
             self.tag = None
@@ -224,7 +208,7 @@ class ProcessingInfo(object):
             else:
                 m = max(len(n) for n in v)
                 for n in v:
-                    s += ' {0:<{width}} {1}\n'.format(n, m, k, width = m)
+                    s += ' {0:<{width}} {1}\n'.format(n, m, width = m)
         if self.raw is not None:
             s += 'Input frames:\n'
             if isinstance(self.raw, (str, unicode)):
@@ -304,7 +288,7 @@ class ProcessingInfo(object):
         return {'true':True, 'false':False}.get(value, value)
 
     @staticmethod
-    def list(source, md5sums = None):
+    def list(source):
         '''Get a list of all `ProcessingInfo` objects in the FITS header. The
         list is sorted by the execution order.
 
@@ -316,14 +300,12 @@ class ProcessingInfo(object):
         pi = []
         for i in range(1, 2**16):
             try:
-                pi.append(ProcessingInfo(source, i, md5sums))
+                pi.append(ProcessingInfo(source, i))
             except KeyError:
                 break
         return pi
 
 if __name__ == '__main__':
-    import sys
-
     for arg in sys.argv[1:]:
         print('{0}\nfile: {1}'.format('-' * 72, arg))
         pi = cpl.dfs.ProcessingInfo(arg)
diff --git a/cpl/esorex.py b/cpl/esorex.py
index 677c0b1..1ecd62f 100644
--- a/cpl/esorex.py
+++ b/cpl/esorex.py
@@ -169,7 +169,7 @@ class CplLogger(object):
 
     @format.setter
     def format(self, fmt):
-        if fmt == None:
+        if fmt is None:
             fmt = '%(asctime)s ' if self._time else ''
             fmt += '[%(levelname)7s]'
             fmt += '[%(threadName)s] ' if self._threadid else ' '
diff --git a/cpl/frames.py b/cpl/frames.py
index aba18e6..b54d2aa 100644
--- a/cpl/frames.py
+++ b/cpl/frames.py
@@ -1,9 +1,8 @@
 from __future__ import absolute_import
 import os
-import tempfile
-try:
+try: # pragma: no cover
     from astropy.io import fits
-except:
+except ImportError:
     import pyfits as fits
 
 from . import md5sum
diff --git a/cpl/logger.py b/cpl/logger.py
index 7129ac9..658a353 100644
--- a/cpl/logger.py
+++ b/cpl/logger.py
@@ -3,12 +3,9 @@ import datetime
 import logging
 import os
 import re
-import sys
 import tempfile
 import threading
 
-from . import CPL_recipe
-
 class NullHandler(logging.Handler):
     def emit(self, record):
         pass
diff --git a/cpl/md5sum.py b/cpl/md5sum.py
index 90df125..d681c55 100644
--- a/cpl/md5sum.py
+++ b/cpl/md5sum.py
@@ -1,21 +1,20 @@
-import os 
 import hashlib
 
 def datamd5(hdulist):
     '''Calculate the MD5SUM of all data regions of a HDUList.
     '''
-    sum = hashlib.md5()
+    md5sum = hashlib.md5()
     for hdu in hdulist:
         if hdu.data is not None:
-            sum.update(bytes(hdu.data.data))
+            md5sum.update(bytes(hdu.data.data))
             pad = b'\0' * (2880 - hdu.data.nbytes % 2880)
-            sum.update(pad)
-    return sum.hexdigest()
+            md5sum.update(pad)
+    return md5sum.hexdigest()
 
 def verify_md5(hdulist):
     return hdulist[0].header.get('DATAMD5') == datamd5(hdulist)
 
 def update_md5(hdulist):
-    sum = datamd5(hdulist)
-    hdulist[0].header['DATAMD5'] =  (sum, 'MD5 checksum')
-    return sum
+    md5sum = datamd5(hdulist)
+    hdulist[0].header['DATAMD5'] =  (md5sum, 'MD5 checksum')
+    return md5sum
diff --git a/cpl/recipe.py b/cpl/recipe.py
index 9cdc556..dbaba54 100644
--- a/cpl/recipe.py
+++ b/cpl/recipe.py
@@ -7,9 +7,9 @@ import collections
 import warnings
 import textwrap
 
-try:
+try: # pragma: no cover
     from astropy.io import fits
-except:
+except ImportError:
     import pyfits as fits
 
 from . import CPL_recipe
@@ -280,7 +280,8 @@ class Recipe(object):
     @calib.setter
     def calib(self, source = None):
         if isinstance(source, str) or hasattr(source, 'read'):
-            source = esorex.load_sof(source)
+            from .esorex import load_sof
+            source = load_sof(source)
         self._calib = FrameList(self, source) 
 
     @calib.deleter
@@ -345,7 +346,8 @@ class Recipe(object):
     @param.setter
     def param(self, source = None):
         if isinstance(source, str) or hasattr(source, 'read'):
-            source = esorex.load_rc(source)
+            from .esorex import load_rc
+            source = load_rc(source)
         self._param = ParameterList(self, source)
 
     @param.deleter
@@ -407,7 +409,6 @@ class Recipe(object):
             (``threaded = True``) and an exception occurs, this exception is 
             raised whenever result fields are accessed.
         '''
-        tmpfiles = []
         threaded = ndata.get('threaded', self.threaded)
         mtrace = ndata.get('mtrace', self.mtrace)
         loglevel = ndata.get('loglevel')
@@ -451,7 +452,7 @@ class Recipe(object):
     def _exec(self, output_dir, parlist, framelist, runenv,
               input_len, logger, output_format, delete, mtrace):
         try:
-            return Result(self._recipe.frameConfig(), output_dir,
+            return Result(output_dir,
                           self._recipe.run(output_dir, parlist, framelist,
                                            list(runenv.items()), 
                                            logger.logfile, logger.level,
@@ -567,7 +568,7 @@ class Recipe(object):
         libs = [ ]
         path = Recipe.path.split(':') if isinstance(Recipe.path, str) else Recipe.path
         for p in path:
-            for root, dir, files in os.walk(p):
+            for root, d, files in os.walk(p):
                 libs += [ os.path.join(root, f) 
                            for f in files if f.endswith('.so') ]
         return libs
diff --git a/cpl/result.py b/cpl/result.py
index 86f90c6..dbd3623 100644
--- a/cpl/result.py
+++ b/cpl/result.py
@@ -3,13 +3,13 @@ import os
 import signal
 import logging
 
-try:
+try: # pragma: no cover
     from astropy.io import fits
-except:
+except ImportError:
     import pyfits as fits
 
 class Result(object):
-    def __init__(self, recipedefs, dir, res, input_len = 0, logger = None, 
+    def __init__(self, directory, res, input_len = 0, logger = None, 
                  output_format = fits.HDUList):
         '''Build an object containing all result frames.
 
@@ -45,7 +45,7 @@ class Result(object):
            more sophisticated. And this is not usable for non-MUSE recipes
            anyway. So, we will skip this to probably some distant future.
         '''
-        self.dir = os.path.abspath(dir)
+        self.dir = os.path.abspath(directory)
         logger.join()
         if res[2][0]:
             raise CplError(res[2][0], res[1], logger)
@@ -142,7 +142,7 @@ class CplError(Exception):
 
        .. seealso:: :class:`cpl.logger.LogList`
 
-    .. attribute:: next
+    .. attribute:: next_error
      
        Next error, or :obj:`None`.
 
@@ -150,7 +150,7 @@ class CplError(Exception):
     def __init__(self, retval, res, logger = None):
         self.retval = retval
         self.log = logger.entries if logger else None
-        self.next = None
+        self.next_error = None
         if not res:
             self.code, self.msg, self.file, self.line, self.function = (
                 None, None, None, None, None)
@@ -158,18 +158,20 @@ class CplError(Exception):
             self.code, self.msg, self.file, self.line, self.function = res[0]
             o = self
             for r in res[1:]:
-                o.next = CplError(retval, [ r ], logger)
-                o = o.next
+                o.next_error = CplError(retval, [ r ], logger)
+                o = o.next_error
     
     def __iter__(self):
-        class Iter:
+        class Iter(object):
             current = self
-            def next(self):
+            def __next__(self):
                 if Iter.current is None:
                     raise StopIteration
                 s = Iter.current
-                Iter.current = Iter.current.next
+                Iter.current = Iter.current.next_error
                 return s
+            def next(self):
+                return self.__next__()
         return Iter()
 
     def __str__(self):
@@ -179,8 +181,8 @@ class CplError(Exception):
             s = "%s (%i) in %s() (%s:%i)" % (self.msg, self.code, 
                                              self.function, self.file, 
                                              self.line) 
-        if self.next:
-            for e in self.next:
+        if self.next_error:
+            for e in self.next_error:
                 s += "\n    %s (%i) in %s() (%s:%i)" % (e.msg, e.code, 
                                                         e.function, e.file, 
                                                         e.line) 
@@ -286,10 +288,10 @@ class RecipeCrash(Exception):
                           for e in self.elements ]
         Exception.__init__(self, str(self))
 
-    def _add_variable(self, vars, line):
+    def _add_variable(self, variables, line):
         s = line.strip().split('=', 1)
         if len(s) > 1:
-            vars[s[0].strip()] = s[1].strip()
+            variables[s[0].strip()] = s[1].strip()
 
     def _parse_function_line(self, line):
         s = line.split()
@@ -317,21 +319,20 @@ class RecipeCrash(Exception):
         log.error('Recipe crashed. Traceback (most recent call last):')
         for e in self.elements:
             logc = logging.getLogger('%s.%s' % (logger.name, e.func))
-            logc.error('  File "%s", %sin %s\n' % (
-                    e.filename, 
-                    'line %i, ' % e.line if e.line else '', 
-                    e.func))
+            logc.error('  File "%s", %sin %s\n',e.filename, 
+                       'line %i, ' % e.line if e.line else '', 
+                       e.func)
             if os.path.exists(e.filename) and e.line:
-                logc.error('    %s\n' 
-                           % open(e.filename).readlines()[e.line-1].strip())
+                logc.error('    %s\n',
+                           open(e.filename).readlines()[e.line-1].strip())
             if e.params:
                 logc.error('  Parameters:')
                 for p, v in e.params.items():
-                    logc.error('    %s = %s' % (p, v))
+                    logc.error('    %s = %s', p, v)
             if e.localvars:
                 logc.error('  Local variables:')
                 for p, v in e.localvars.items():
-                    logc.error('    %s = %s' % (p, v))
+                    logc.error('    %s = %s', p, v)
         log.error(RecipeCrash.signals.get(self.signal, 
                                           '%s: Unknown' % str(self.signal)))
 
diff --git a/cpl/run.py b/cpl/run.py
deleted file mode 100644
index 04c113c..0000000
--- a/cpl/run.py
+++ /dev/null
@@ -1,130 +0,0 @@
-import cpl
-import sys
-import logging
-
-from optparse import OptionParser, OptionGroup
-
-cpl.esorex.init()
-    
-for i in range(1, len(sys.argv)):
-    if not sys.argv[i].startswith('--'):
-        recipe = cpl.Recipe(sys.argv[i])
-        recipe.output_dir = '.'
-        del sys.argv[i]
-        break
-else:
-    recipe = None
-
-parser = OptionParser(prog='%s %s' % (sys.argv[0], recipe.__name__),
-                      version = recipe.__version__, 
-                      description=recipe.description[0],
-                      epilog=recipe.description[1] + '\n') if recipe else \
-         OptionParser(prog=sys.argv[0], 
-                      version=cpl.__version__)
-    
-def output_dir_callback(option, opt, value, parser):
-    recipe.output_dir = value
-
-parser.add_option('--output-dir', action = 'callback',
-                  type='str', help = 
-                  'The directory where the product files will be written',
-                  callback = output_dir_callback)
-
-log = logging.getLogger()
-log.setLevel(logging.INFO)
-cpl.esorex.msg.level = logging.ERROR
-    
-def logfile_callback(option, opt, value, parser):
-    ch = logging.FileHandler(value)
-    ch.setLevel(logging.DEBUG)
-    ch.setFormatter(logging.Formatter(
-            "%(asctime)s [%(levelname)s] %(name)s: %(message)s"))
-    log.addHandler(ch)
-
-parser.add_option('--log-file', action = 'callback',
-                  type='str', help = 'Filename of logfile',
-                  callback = logfile_callback)
-
-def loglevel_callback(option, opt, value, parser):
-    levels = {'debug':logging.DEBUG, 'info':logging.INFO, 
-              'warning':logging.warning, 'error':logging.ERROR }
-    log.setLevel(levels[value])
-    
-parser.add_option('--log-level', action = 'callback',
-                  type='str', help = 'Controls the severity level of '
-                  'messages that will be printed to the logfile.',
-                  callback = loglevel_callback)
-
-def msglevel_callback(option, opt, value, parser):
-    levels = {'debug':logging.DEBUG, 'info':logging.INFO, 
-              'warning':logging.warning, 'error':logging.ERROR }
-    cpl.esorex.msg.level = levels[value]
-
-parser.add_option('--msg-level', action = 'callback',
-                  type='str', help = 'Controls the severity level of '
-                  'messages that will be printed to the terminal.',
-                  callback = msglevel_callback)
-
-def tag_callback(option, opt, value, parser):
-    recipe.tag = value
-
-
-def param_callback(option, opt, value, parser, p):
-    p.value = value
-
-def calib_callback(option, opt, value, parser, c):
-    p.frame = value
-
-types = { bool:'string', str:'string', int:'int', float:'float' }
-
-if recipe:
-    parser.add_option('--tag', action = 'callback',
-                      type='str', help = 
-                      'Input file tag %s' % repr(recipe.tags),
-                      callback = tag_callback)
-
-    group = OptionGroup(parser, 'Recipe parameters')
-    for p in recipe.param:
-        group.add_option('--%s' % p.name, action = 'callback', 
-                         type=types.get(p.default.__class__),
-                         help = '%s [%s]' % (p.__doc__, p.default),
-                         callback = param_callback, callback_args = (p,))
-    parser.add_option_group(group)
-
-    if len(recipe.calib) > 0:
-        group = OptionGroup(parser, 'Calibration frames')
-            
-        for f in recipe.calib:
-            help = ''
-            if f.min < 1:
-                help = 'optional'
-            elif f.min > 1:
-                help = 'min %i' % f.min
-            else:
-                help = 'required'
-            if f.max != 1:
-                if help:
-                    help += ', '
-                help += 'may be repeated'
-            group.add_option('--%s' % f.tag, action='callback', 
-                             type = 'string', help = help,
-                             callback = calib_callback, 
-                             callback_args = (f,))
-        parser.add_option_group(group)
-
-(option, args) = parser.parse_args(sys.argv)
-
-if not args[1:]:
-    parser.print_help()
-    sys.exit()
-    
-try: 
-    recipe(args[1:])
-except cpl.result.RecipeCrash as ex:
-    log.exception(ex)
-    print(repr(ex))
-except cpl.result.CplError as ex:
-    log.exception(ex)
-    print(repr(ex))
-    
-    
diff --git a/cpl/version.py b/cpl/version.py
index 3df35ae..7b26f93 100644
--- a/cpl/version.py
+++ b/cpl/version.py
@@ -1,4 +1,4 @@
-version = '0.7'
+version = '0.7.2'
 author = 'Ole Streicher'
 email = 'python-cpl at liska.ath.cx'
 license_ = 'GPL'
diff --git a/doc/install.rst b/doc/install.rst
index 9d052b0..9a06e09 100644
--- a/doc/install.rst
+++ b/doc/install.rst
@@ -17,10 +17,11 @@ On Debian and debian-based systems (Ubuntu, Mint), python-cpl can be installed w
 
   apt-get install python-cpl
 
-Python CPL comes with the Ubuntu distribution since 12.04.
-Debian packages are in `Wheezy (Debian 7) <http://packages.debian.org/wheezy/python-cpl>`_, 
-`Wheezy (Debian 8) <http://packages.debian.org/jessie/python-cpl>`_, and 
-`Testing <http://packages.debian.org/testing/python-cpl>`_
+Python CPL comes with the `Ubuntu <packages.ubuntu.com/python-cpl>`_
+distribution since 12.04.  Debian packages are in `Wheezy (Debian 7)
+<http://packages.debian.org/wheezy/python-cpl>`_, `Squeeze (Debian 8)
+<http://packages.debian.org/jessie/python-cpl>`_, and `Testing
+<http://packages.debian.org/testing/python-cpl>`_
 
 Source code
 -----------
diff --git a/doc/install.rst b/doc/install.rst~
similarity index 100%
copy from doc/install.rst
copy to doc/install.rst~
diff --git a/setup.py b/setup.py
index 6a4b3ba..4369ed8 100644
--- a/setup.py
+++ b/setup.py
@@ -5,7 +5,7 @@ from pkg_resources import require, DistributionNotFound
 author = 'Ole Streicher'
 email = 'python-cpl at liska.ath.cx'
 license_ = 'GPL'
-cpl_version = '0.7'
+cpl_version = '0.7.2'
 description = "Python interface for the ESO Common Pipeline Library"
 long_description = '''This module can list, configure and execute CPL-based recipes from Python
 (python2 and python3).  The input, calibration and output data can be
@@ -67,7 +67,7 @@ setup(
     url = 'https://pypi.python.org/pypi/%s/%s' % (pkgname, cpl_version),
     download_url = '%s/%s-%s.tar.gz' % (baseurl, pkgname, cpl_version),
     classifiers = classifiers,
-    requires = [ required ],
+    install_requires = [ required ],
     provides = ['cpl'],
     packages = ['cpl'],
     ext_modules = [module1]
diff --git a/test/TestRecipe.py b/test/TestRecipe.py
index 799fd35..3586c87 100644
--- a/test/TestRecipe.py
+++ b/test/TestRecipe.py
@@ -14,35 +14,45 @@ cpl.Recipe.memory_mode = 0
 
 recipe_name = 'rtest'
 raw_tag = 'RRRECIPE_DOCATG_RAW'
-
-def create_recipe(name):
-    cname = name + ".c"
-    oname = name + '.o'
-    soname = name + '.so'
-    env = {
+rtest_esorexrc = '''# example RC file
+iiinstrument.rtest.string_option = more
+iiinstrument.rtest.bool_option = False
+iiinstrument.rtest.float_option = 1.125
+iiinstrument.rtest.int_option = -2
+iiinstrument.rtest.enum_option = second
+iiinstrument.rtest.range_option = 0.5
+iiinstrument.rtest.dotted.opt = 1
+'''
+
+def create_recipe(name, builddir):
+    var = {
         'CC':  os.getenv("CC", "gcc"),
         'CPPFLAGS': os.getenv("CPPFLAGS", ""),
         'CFLAGS': os.getenv("CFLAGS", ""),
         'LDFLAGS': os.getenv("LDFLAGS", ""),
         'LIBS': "-lcplcore -lcpldfs",
-        'cname': cname,
-        'oname': oname,
-        'soname': soname,
+        'cname': os.path.join(os.path.dirname(__file__), name + ".c"),
+        'oname': os.path.join(builddir, name + '.o'),
+        'soname': os.path.join(builddir, name + '.so'),
     }
-    if (not os.path.exists(soname) or
-        os.path.getmtime(soname) <= os.path.getmtime(cname)):
-        os.system("{CC} {CPPFLAGS} {CFLAGS} -fPIC -c {cname}".format(**env))
-        os.system("{CC} {LDFLAGS} -shared -o {soname} {oname} {LIBS}".format(**env))
-        os.remove(oname)
-        
+    os.system("{CC} {CPPFLAGS} {CFLAGS} -fPIC -c -o {oname} {cname}".format(**var))
+    os.system("{CC} {LDFLAGS} -shared -o {soname} {oname} {LIBS}".format(**var))
+    os.remove(var['oname'])
+
 class CplTestCase(unittest.TestCase):
     def setUp(self):
-        cpl.Recipe.path = os.path.dirname(os.path.abspath(__file__))
+        unittest.TestCase.setUp(self)
+        self.temp_dir = tempfile.mkdtemp()
+        create_recipe(recipe_name, self.temp_dir)
+        cpl.Recipe.path = self.temp_dir
+
+    def tearDown(self):
+        unittest.TestCase.tearDown(self)
+        shutil.rmtree(self.temp_dir)
 
 class RecipeTestCase(CplTestCase):
     def setUp(self):
         CplTestCase.setUp(self)
-        self.temp_dir = tempfile.mkdtemp()
         self.recipe = cpl.Recipe(recipe_name)
         self.recipe.temp_dir = self.temp_dir
         self.recipe.tag = raw_tag
@@ -53,9 +63,6 @@ class RecipeTestCase(CplTestCase):
         self.raw_frame[0].header['HIERARCH ESO DET DIT'] = 0.0
         self.raw_frame[0].header['HIERARCH ESO PRO CATG'] = raw_tag
 
-    def tearDown(self):
-        shutil.rmtree(self.temp_dir)
-
 class RecipeStatic(CplTestCase):
     def test_list(self):
         '''List available recipes'''
@@ -84,8 +91,8 @@ class RecipeStatic(CplTestCase):
 
     def test_create_recipe_filename(self):
         '''Create a recipe specified by a the name and the filename'''
-        recipe = cpl.Recipe(recipe_name, filename = os.path.join(
-            os.path.dirname(os.path.abspath(__file__)),'rtest.so'))
+        recipe = cpl.Recipe(recipe_name,
+                            filename = os.path.join(self.temp_dir, 'rtest.so'))
         self.assertTrue(isinstance(recipe, cpl.Recipe))
 
     def test_create_recipe_wrong_filename(self):
@@ -240,6 +247,17 @@ class RecipeParams(RecipeTestCase):
         self.assertEqual(self.recipe.param.floatopt.value, 1.5)
         self.assertEqual(self.recipe.param.boolopt.value, True)
 
+    def test_param_load_from_esorexrc(self):
+        '''Load parameters from an Esorex .rc file'''
+        self.recipe.param = rtest_esorexrc
+        self.assertEqual(self.recipe.param.stropt.value, 'more')
+        self.assertEqual(self.recipe.param.boolopt.value, False)
+        self.assertEqual(self.recipe.param.floatopt.value, 1.125)
+        self.assertEqual(self.recipe.param.intopt.value, -2)
+        self.assertEqual(self.recipe.param.enumopt.value, 'second')
+        self.assertEqual(self.recipe.param.rangeopt.value, 0.5)
+        self.assertEqual(self.recipe.param.dot.opt.value, 1)
+
     def test_delete(self):
         '''Delete all parameter values to reset to default'''
         self.recipe.param.boolopt.value = True
@@ -269,6 +287,11 @@ class RecipeCalib(RecipeTestCase):
         self.recipe.calib = { 'FLAT':'flat2.fits' }
         self.assertEqual(self.recipe.calib.FLAT.frames, 'flat2.fits')
 
+    def test_param_load_from_esorexsof(self):
+        '''Load calibration from an Esorex SOF file'''
+        self.recipe.calib = 'flat.fits   FLAT\n'
+        self.assertEqual(self.recipe.calib.FLAT.frames, 'flat.fits')
+
     def test_del(self):
         '''Delete a calibration frame set'''
         self.recipe.calib.FLAT = 'flat.fits'
@@ -578,17 +601,17 @@ class RecipeExec(RecipeTestCase):
                          len('9d123996fa9a7bda315d07e063043454'))
 
 class RecipeCrashing(RecipeTestCase):
-    def test_corrupted(self):
+    def _test_corrupted(self):
         '''Handling of recipe crashes because of corrupted memory'''
         self.recipe.param.crashing = 'free'
         self.assertRaises(cpl.RecipeCrash, self.recipe, self.raw_frame)
 
-    def test_segfault(self):
+    def _test_segfault(self):
         '''Handling of recipe crashes because of segmentation fault'''
         self.recipe.param.crashing = 'segfault'
         self.assertRaises(cpl.RecipeCrash, self.recipe, self.raw_frame)
 
-    def test_cleanup_after_crash(self):
+    def _test_cleanup_after_crash(self):
         '''Test that a second run after a crash will succeed'''
         output_dir = os.path.join(self.temp_dir, 'out')
         self.recipe.output_dir = output_dir
@@ -603,6 +626,7 @@ class RecipeRes(RecipeTestCase):
         self.res = self.recipe(self.raw_frame)
 
     def tearDown(self):
+        RecipeTestCase.tearDown(self)
         try:
             res.THE_PRO_CATG_VALUE.close()
         except:
@@ -618,6 +642,15 @@ class RecipeRes(RecipeTestCase):
         self.assertTrue(isinstance(self.res['THE_PRO_CATG_VALUE'], 
                                    fits.HDUList))
 
+    def test_in(self):
+        '''Check whether a tag is part of the result'''
+        self.assertTrue('THE_PRO_CATG_VALUE' in self.res)
+        self.assertFalse('Anothervalue' in self.res)
+
+    def test_keyerror(self):
+        '''Accessing an inexisting value'''
+        self.assertRaises(KeyError, lambda val: self.res[val], 'Anothervalue')
+
     def test_len(self):
         '''Length of the result'''
         self.assertEqual(len(self.res), 1)
@@ -629,15 +662,10 @@ class RecipeRes(RecipeTestCase):
             self.assertTrue(isinstance(hdu, fits.HDUList))
 
 class RecipeEsorex(CplTestCase):
-    def setUp(self):
-        CplTestCase.setUp(self)
-        self.temp_dir = tempfile.mkdtemp()
-
     def tearDown(self):
         CplTestCase.tearDown(self)
         cpl.esorex.msg.level = cpl.esorex.msg.OFF
         cpl.esorex.log.level = cpl.esorex.msg.OFF
-        shutil.rmtree(self.temp_dir)
 
     def test_read_sof(self):
         '''Read a SOF file'''
@@ -656,12 +684,15 @@ class RecipeEsorex(CplTestCase):
                            
     def test_read_rc(self):
         '''Read an EsoRec .rc file'''
-        rcfile = '# environment variable lambda_low.\n' \
-        'muse.muse_sky.lambda_low=4.65e+03\n' \
-        'muse.muse_sky.lambda_high=9.3e+03\n'
-        self.assertEqual(cpl.esorex.load_rc(rcfile), 
-                         { 'muse.muse_sky.lambda_low': '4.65e+03',
-                           'muse.muse_sky.lambda_high': '9.3e+03'})
+        self.assertEqual(cpl.esorex.load_rc(rtest_esorexrc), 
+                         { 'iiinstrument.rtest.string_option': 'more',
+                           'iiinstrument.rtest.bool_option': 'False',
+                           'iiinstrument.rtest.float_option': '1.125',
+                           'iiinstrument.rtest.int_option': '-2',
+                           'iiinstrument.rtest.enum_option': 'second',
+                           'iiinstrument.rtest.range_option': '0.5',
+                           'iiinstrument.rtest.dotted.opt': '1',
+                       })
         
     def test_esorex_init(self):
         '''Init CPL from an esorex.rc file'''
@@ -880,6 +911,11 @@ class RecipeLog(RecipeTestCase):
         # Check that we can read error messages
         self.assertNotEqual(len(res.log.error), 0)
         self.assertTrue(isinstance(res.log.error[0], str))
+        # Check that we can convert the error to a string
+        self.assertTrue(isinstance(res.__str__(), str))
+        # Check that we can iterate over error messages
+        for r in res:
+            self.assertTrue(isinstance(res, cpl.CplError))
 
 class ProcessingInfo(RecipeTestCase):
     def setUp(self):
@@ -898,6 +934,7 @@ class ProcessingInfo(RecipeTestCase):
         self.pinfo = cpl.dfs.ProcessingInfo(self.res)
 
     def tearDown(self):
+        RecipeTestCase.tearDown(self)
         try:
             self.res.close()
         except:
@@ -946,6 +983,15 @@ class ProcessingInfo(RecipeTestCase):
         md5sum = self.res[0].header.get('HIERARCH ESO PRO REC1 CAL1 DATAMD5')
         self.assertEqual(md5sum, self.pinfo.md5sums[self.pinfo.calib['FLAT']])
 
-create_recipe(recipe_name)
+    def test_recipe(self):
+        '''Recreate and configure the recipe'''
+        recipe = self.pinfo.create_recipe()
+        self.assertTrue(isinstance(recipe, cpl.Recipe))
+        self.assertEqual(len(recipe.calib), 1)
+        self.assertEqual(recipe.calib.FLAT.frames[-5:], '.fits')
+        self.assertEqual(recipe.__name__, self.recipe.__name__)
+        self.assertEqual(recipe.version[0], self.recipe.version[0])
+        self.assertEqual(len(recipe.param), len(self.recipe.param))
+
 if __name__ == '__main__':
     unittest.main()

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-astro/packages/python-cpl.git



More information about the Debian-astro-commits mailing list