From ee096c4ed2b5636018fb4b034236d3339f1fb73d Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 8 Nov 2016 10:03:34 -0800 Subject: [PATCH 01/54] Initial layout for package --- .gitignore | 56 ++ .gitmodules | 3 + .travis.yml | 134 ++++ MANIFEST.in | 40 + ah_bootstrap.py | 987 +++++++++++++++++++++++++ astropy_helpers | 1 + caom2tools/__init__.py | 15 + caom2tools/_astropy_init.py | 138 ++++ caom2tools/conftest.py | 38 + caom2tools/test/__init__.py | 4 + caom2tools/test/coveragerc | 31 + caom2tools/test/setup_package.py | 3 + docs/Makefile | 133 ++++ docs/_templates/autosummary/base.rst | 2 + docs/_templates/autosummary/class.rst | 2 + docs/_templates/autosummary/module.rst | 2 + docs/conf.py | 172 +++++ docs/index.rst | 0 docs/make.bat | 170 +++++ ez_setup.py | 425 +++++++++++ setup.cfg | 38 + setup.py | 120 +++ 22 files changed, 2514 insertions(+) create mode 100644 .gitignore create mode 100644 .gitmodules create mode 100644 .travis.yml create mode 100644 MANIFEST.in create mode 100644 ah_bootstrap.py create mode 160000 astropy_helpers create mode 100644 caom2tools/__init__.py create mode 100644 caom2tools/_astropy_init.py create mode 100644 caom2tools/conftest.py create mode 100644 caom2tools/test/__init__.py create mode 100644 caom2tools/test/coveragerc create mode 100644 caom2tools/test/setup_package.py create mode 100644 docs/Makefile create mode 100644 docs/_templates/autosummary/base.rst create mode 100644 docs/_templates/autosummary/class.rst create mode 100644 docs/_templates/autosummary/module.rst create mode 100644 docs/conf.py create mode 100644 docs/index.rst create mode 100644 docs/make.bat create mode 100644 ez_setup.py create mode 100644 setup.cfg create mode 100755 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..18969fbd --- /dev/null +++ b/.gitignore @@ -0,0 +1,56 @@ +# Compiled files +*.py[cod] +*.a +*.o +*.so +__pycache__ + +# Ignore .c files by default to avoid including generated code. If you want to +# add a non-generated .c extension, use `git add -f filename.c`. +*.c + +# Other generated files +*/version.py +*/cython_version.py +htmlcov +.coverage +MANIFEST +.ipynb_checkpoints + +# Sphinx +docs/api +docs/_build + +# Eclipse editor project files +.project +.pydevproject +.settings + +# Pycharm editor project files +.idea + +# Packages/installer info +*.egg +*.egg-info +dist +build +eggs +parts +bin +var +sdist +develop-eggs +.installed.cfg +distribute-*.tar.gz + +# Other +.cache +.tox +.*.sw[op] +*~ +.project +.pydevproject +.settings + +# Mac OSX +.DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 00000000..6a20fa6e --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "astropy_helpers"] + path = astropy_helpers + url = https://github.com/astropy/astropy-helpers.git diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 00000000..46d6bd26 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,134 @@ +language: python + +python: + - 2.7 + - 3.4 + - 3.5 + +# Setting sudo to false opts in to Travis-CI container-based builds. +sudo: false + +# The apt packages below are needed for sphinx builds. A full list of packages +# that can be included can be found here: +# +# https://github.com/travis-ci/apt-package-whitelist/blob/master/ubuntu-precise + +#addons: +# apt: +# packages: +# - graphviz +# - texlive-latex-extra +# - dvipng + +env: + global: + + # The following versions are the 'default' for tests, unless + # overridden underneath. They are defined here in order to save having + # to repeat them for all configurations. + - NUMPY_VERSION=stable + - ASTROPY_VERSION=stable + - SETUP_CMD='test' + - PIP_DEPENDENCIES='' + + # For this package-template, we include examples of Cython modules, + # so Cython is required for testing. If your package does not include + # Cython code, you can set CONDA_DEPENDENCIES='' + - CONDA_DEPENDENCIES='Cython' + + # Conda packages for affiliated packages are hosted in channel + # "astropy" while builds for astropy LTS with recent numpy versions + # are in astropy-ci-extras. If your package uses either of these, + # add the channels to CONDA_CHANNELS along with any other channels + # you want to use. + # - CONDA_CHANNELS='astopy-ci-extras astropy' + + # If there are matplotlib or other GUI tests, uncomment the following + # line to use the X virtual framebuffer. + # - SETUP_XVFB=True + + matrix: + # Make sure that egg_info works without dependencies + - SETUP_CMD='egg_info' + # Try all python versions with the latest numpy + - SETUP_CMD='test' + +matrix: + include: + + # Do a coverage test in Python 2. + - python: 2.7 + env: SETUP_CMD='test --coverage' + + # Check for sphinx doc build warnings - we do this first because it + # may run for a long time + - python: 2.7 + env: SETUP_CMD='build_sphinx -w' + + # Try Astropy development version + - python: 2.7 + env: ASTROPY_VERSION=development + - python: 3.5 + env: ASTROPY_VERSION=development + - python: 2.7 + env: ASTROPY_VERSION=lts + - python: 3.5 + env: ASTROPY_VERSION=lts + + # Python 3.3 doesn't have numpy 1.10 in conda, but can be put + # back into the main matrix once the numpy build is available in the + # astropy-ci-extras channel (or in the one provided in the + # CONDA_CHANNELS environmental variable). + + - python: 3.3 + env: SETUP_CMD='egg_info' + - python: 3.3 + env: SETUP_CMD='test' NUMPY_VERSION=1.9 + + # Try older numpy versions + - python: 2.7 + env: NUMPY_VERSION=1.10 + - python: 2.7 + env: NUMPY_VERSION=1.9 + - python: 2.7 + env: NUMPY_VERSION=1.8 + - python: 2.7 + env: NUMPY_VERSION=1.7 + + # Try numpy pre-release + - python: 3.5 + env: NUMPY_VERSION=prerelease + +install: + + # We now use the ci-helpers package to set up our testing environment. + # This is done by using Miniconda and then using conda and pip to install + # dependencies. Which dependencies are installed using conda and pip is + # determined by the CONDA_DEPENDENCIES and PIP_DEPENDENCIES variables, + # which should be space-delimited lists of package names. See the README + # in https://github.com/astropy/ci-helpers for information about the full + # list of environment variables that can be used to customize your + # environment. In some cases, ci-helpers may not offer enough flexibility + # in how to install a package, in which case you can have additional + # commands in the install: section below. + + - git clone git://github.com/astropy/ci-helpers.git + - source ci-helpers/travis/setup_conda_$TRAVIS_OS_NAME.sh + + # As described above, using ci-helpers, you should be able to set up an + # environment with dependencies installed using conda and pip, but in some + # cases this may not provide enough flexibility in how to install a + # specific dependency (and it will not be able to install non-Python + # dependencies). Therefore, you can also include commands below (as + # well as at the start of the install section or in the before_install + # section if they are needed before setting up conda) to install any + # other dependencies. + +script: + - python setup.py $SETUP_CMD + +after_success: + # If coveralls.io is set up for this package, uncomment the line + # below and replace "packagename" with the name of your package. + # The coveragerc file may be customized as needed for your package. + # - if [[ $SETUP_CMD == 'test --coverage' ]]; then coveralls --rcfile='packagename/tests/coveragerc'; fi diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 00000000..c3bf88f0 --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,40 @@ +include README.rst +include CHANGES.rst + +include ez_setup.py +include ah_bootstrap.py +include setup.cfg + +recursive-include packagename *.pyx *.c *.pxd +recursive-include docs * +recursive-include licenses * +recursive-include cextern * +recursive-include scripts * + +prune build +prune docs/_build +prune docs/api + + +# the next few stanzas are for astropy_helpers. It's derived from the +# astropy_helpers/MANIFEST.in, but requires additional includes for the actual +# package directory and egg-info. + +include astropy_helpers/README.rst +include astropy_helpers/CHANGES.rst +include astropy_helpers/LICENSE.rst +recursive-include astropy_helpers/licenses * + +include astropy_helpers/ez_setup.py +include astropy_helpers/ah_bootstrap.py + +recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h +recursive-include astropy_helpers/astropy_helpers.egg-info * +# include the sphinx stuff with "*" because there are css/html/rst/etc. +recursive-include astropy_helpers/astropy_helpers/sphinx * + +prune astropy_helpers/build +prune astropy_helpers/astropy_helpers/tests + + +global-exclude *.pyc *.o diff --git a/ah_bootstrap.py b/ah_bootstrap.py new file mode 100644 index 00000000..0dc50071 --- /dev/null +++ b/ah_bootstrap.py @@ -0,0 +1,987 @@ +""" +This bootstrap module contains code for ensuring that the astropy_helpers +package will be importable by the time the setup.py script runs. It also +includes some workarounds to ensure that a recent-enough version of setuptools +is being used for the installation. + +This module should be the first thing imported in the setup.py of distributions +that make use of the utilities in astropy_helpers. If the distribution ships +with its own copy of astropy_helpers, this module will first attempt to import +from the shipped copy. However, it will also check PyPI to see if there are +any bug-fix releases on top of the current version that may be useful to get +past platform-specific bugs that have been fixed. When running setup.py, use +the ``--offline`` command-line option to disable the auto-upgrade checks. + +When this module is imported or otherwise executed it automatically calls a +main function that attempts to read the project's setup.cfg file, which it +checks for a configuration section called ``[ah_bootstrap]`` the presences of +that section, and options therein, determine the next step taken: If it +contains an option called ``auto_use`` with a value of ``True``, it will +automatically call the main function of this module called +`use_astropy_helpers` (see that function's docstring for full details). +Otherwise no further action is taken (however, +``ah_bootstrap.use_astropy_helpers`` may be called manually from within the +setup.py script). + +Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same +names as the arguments to `use_astropy_helpers`, and can be used to configure +the bootstrap script when ``auto_use = True``. + +See https://github.com/astropy/astropy-helpers for more details, and for the +latest version of this module. +""" + +import contextlib +import errno +import imp +import io +import locale +import os +import re +import subprocess as sp +import sys + +try: + from ConfigParser import ConfigParser, RawConfigParser +except ImportError: + from configparser import ConfigParser, RawConfigParser + + +if sys.version_info[0] < 3: + _str_types = (str, unicode) + _text_type = unicode + PY3 = False +else: + _str_types = (str, bytes) + _text_type = str + PY3 = True + + +# What follows are several import statements meant to deal with install-time +# issues with either missing or misbehaving pacakges (including making sure +# setuptools itself is installed): + + +# Some pre-setuptools checks to ensure that either distribute or setuptools >= +# 0.7 is used (over pre-distribute setuptools) if it is available on the path; +# otherwise the latest setuptools will be downloaded and bootstrapped with +# ``ez_setup.py``. This used to be included in a separate file called +# setuptools_bootstrap.py; but it was combined into ah_bootstrap.py +try: + import pkg_resources + _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') + # This may raise a DistributionNotFound in which case no version of + # setuptools or distribute is properly installed + _setuptools = pkg_resources.get_distribution('setuptools') + if _setuptools not in _setuptools_req: + # Older version of setuptools; check if we have distribute; again if + # this results in DistributionNotFound we want to give up + _distribute = pkg_resources.get_distribution('distribute') + if _setuptools != _distribute: + # It's possible on some pathological systems to have an old version + # of setuptools and distribute on sys.path simultaneously; make + # sure distribute is the one that's used + sys.path.insert(1, _distribute.location) + _distribute.activate() + imp.reload(pkg_resources) +except: + # There are several types of exceptions that can occur here; if all else + # fails bootstrap and use the bootstrapped version + from ez_setup import use_setuptools + use_setuptools() + + +# Note: The following import is required as a workaround to +# https://github.com/astropy/astropy-helpers/issues/89; if we don't import this +# module now, it will get cleaned up after `run_setup` is called, but that will +# later cause the TemporaryDirectory class defined in it to stop working when +# used later on by setuptools +try: + import setuptools.py31compat +except ImportError: + pass + + +# matplotlib can cause problems if it is imported from within a call of +# run_setup(), because in some circumstances it will try to write to the user's +# home directory, resulting in a SandboxViolation. See +# https://github.com/matplotlib/matplotlib/pull/4165 +# Making sure matplotlib, if it is available, is imported early in the setup +# process can mitigate this (note importing matplotlib.pyplot has the same +# issue) +try: + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot +except: + # Ignore if this fails for *any* reason* + pass + + +# End compatibility imports... + + +# In case it didn't successfully import before the ez_setup checks +import pkg_resources + +from setuptools import Distribution +from setuptools.package_index import PackageIndex +from setuptools.sandbox import run_setup + +from distutils import log +from distutils.debug import DEBUG + + +# TODO: Maybe enable checking for a specific version of astropy_helpers? +DIST_NAME = 'astropy-helpers' +PACKAGE_NAME = 'astropy_helpers' + +# Defaults for other options +DOWNLOAD_IF_NEEDED = True +INDEX_URL = 'https://pypi.python.org/simple' +USE_GIT = True +OFFLINE = False +AUTO_UPGRADE = True + +# A list of all the configuration options and their required types +CFG_OPTIONS = [ + ('auto_use', bool), ('path', str), ('download_if_needed', bool), + ('index_url', str), ('use_git', bool), ('offline', bool), + ('auto_upgrade', bool) +] + + +class _Bootstrapper(object): + """ + Bootstrapper implementation. See ``use_astropy_helpers`` for parameter + documentation. + """ + + def __init__(self, path=None, index_url=None, use_git=None, offline=None, + download_if_needed=None, auto_upgrade=None): + + if path is None: + path = PACKAGE_NAME + + if not (isinstance(path, _str_types) or path is False): + raise TypeError('path must be a string or False') + + if PY3 and not isinstance(path, _text_type): + fs_encoding = sys.getfilesystemencoding() + path = path.decode(fs_encoding) # path to unicode + + self.path = path + + # Set other option attributes, using defaults where necessary + self.index_url = index_url if index_url is not None else INDEX_URL + self.offline = offline if offline is not None else OFFLINE + + # If offline=True, override download and auto-upgrade + if self.offline: + download_if_needed = False + auto_upgrade = False + + self.download = (download_if_needed + if download_if_needed is not None + else DOWNLOAD_IF_NEEDED) + self.auto_upgrade = (auto_upgrade + if auto_upgrade is not None else AUTO_UPGRADE) + + # If this is a release then the .git directory will not exist so we + # should not use git. + git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) + if use_git is None and not git_dir_exists: + use_git = False + + self.use_git = use_git if use_git is not None else USE_GIT + # Declared as False by default--later we check if astropy-helpers can be + # upgraded from PyPI, but only if not using a source distribution (as in + # the case of import from a git submodule) + self.is_submodule = False + + @classmethod + def main(cls, argv=None): + if argv is None: + argv = sys.argv + + config = cls.parse_config() + config.update(cls.parse_command_line(argv)) + + auto_use = config.pop('auto_use', False) + bootstrapper = cls(**config) + + if auto_use: + # Run the bootstrapper, otherwise the setup.py is using the old + # use_astropy_helpers() interface, in which case it will run the + # bootstrapper manually after reconfiguring it. + bootstrapper.run() + + return bootstrapper + + @classmethod + def parse_config(cls): + if not os.path.exists('setup.cfg'): + return {} + + cfg = ConfigParser() + + try: + cfg.read('setup.cfg') + except Exception as e: + if DEBUG: + raise + + log.error( + "Error reading setup.cfg: {0!r}\n{1} will not be " + "automatically bootstrapped and package installation may fail." + "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) + return {} + + if not cfg.has_section('ah_bootstrap'): + return {} + + config = {} + + for option, type_ in CFG_OPTIONS: + if not cfg.has_option('ah_bootstrap', option): + continue + + if type_ is bool: + value = cfg.getboolean('ah_bootstrap', option) + else: + value = cfg.get('ah_bootstrap', option) + + config[option] = value + + return config + + @classmethod + def parse_command_line(cls, argv=None): + if argv is None: + argv = sys.argv + + config = {} + + # For now we just pop recognized ah_bootstrap options out of the + # arg list. This is imperfect; in the unlikely case that a setup.py + # custom command or even custom Distribution class defines an argument + # of the same name then we will break that. However there's a catch22 + # here that we can't just do full argument parsing right here, because + # we don't yet know *how* to parse all possible command-line arguments. + if '--no-git' in argv: + config['use_git'] = False + argv.remove('--no-git') + + if '--offline' in argv: + config['offline'] = True + argv.remove('--offline') + + return config + + def run(self): + strategies = ['local_directory', 'local_file', 'index'] + dist = None + + # First, remove any previously imported versions of astropy_helpers; + # this is necessary for nested installs where one package's installer + # is installing another package via setuptools.sandbox.run_setup, as in + # the case of setup_requires + for key in list(sys.modules): + try: + if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): + del sys.modules[key] + except AttributeError: + # Sometimes mysterious non-string things can turn up in + # sys.modules + continue + + # Check to see if the path is a submodule + self.is_submodule = self._check_submodule() + + for strategy in strategies: + method = getattr(self, 'get_{0}_dist'.format(strategy)) + dist = method() + if dist is not None: + break + else: + raise _AHBootstrapSystemExit( + "No source found for the {0!r} package; {0} must be " + "available and importable as a prerequisite to building " + "or installing this package.".format(PACKAGE_NAME)) + + # This is a bit hacky, but if astropy_helpers was loaded from a + # directory/submodule its Distribution object gets a "precedence" of + # "DEVELOP_DIST". However, in other cases it gets a precedence of + # "EGG_DIST". However, when activing the distribution it will only be + # placed early on sys.path if it is treated as an EGG_DIST, so always + # do that + dist = dist.clone(precedence=pkg_resources.EGG_DIST) + + # Otherwise we found a version of astropy-helpers, so we're done + # Just active the found distribution on sys.path--if we did a + # download this usually happens automatically but it doesn't hurt to + # do it again + # Note: Adding the dist to the global working set also activates it + # (makes it importable on sys.path) by default. + + try: + pkg_resources.working_set.add(dist, replace=True) + except TypeError: + # Some (much) older versions of setuptools do not have the + # replace=True option here. These versions are old enough that all + # bets may be off anyways, but it's easy enough to work around just + # in case... + if dist.key in pkg_resources.working_set.by_key: + del pkg_resources.working_set.by_key[dist.key] + pkg_resources.working_set.add(dist) + + @property + def config(self): + """ + A `dict` containing the options this `_Bootstrapper` was configured + with. + """ + + return dict((optname, getattr(self, optname)) + for optname, _ in CFG_OPTIONS if hasattr(self, optname)) + + def get_local_directory_dist(self): + """ + Handle importing a vendored package from a subdirectory of the source + distribution. + """ + + if not os.path.isdir(self.path): + return + + log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( + 'submodule' if self.is_submodule else 'directory', + self.path)) + + dist = self._directory_import() + + if dist is None: + log.warn( + 'The requested path {0!r} for importing {1} does not ' + 'exist, or does not contain a copy of the {1} ' + 'package.'.format(self.path, PACKAGE_NAME)) + elif self.auto_upgrade and not self.is_submodule: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_local_file_dist(self): + """ + Handle importing from a source archive; this also uses setup_requires + but points easy_install directly to the source archive. + """ + + if not os.path.isfile(self.path): + return + + log.info('Attempting to unpack and import astropy_helpers from ' + '{0!r}'.format(self.path)) + + try: + dist = self._do_download(find_links=[self.path]) + except Exception as e: + if DEBUG: + raise + + log.warn( + 'Failed to import {0} from the specified archive {1!r}: ' + '{2}'.format(PACKAGE_NAME, self.path, str(e))) + dist = None + + if dist is not None and self.auto_upgrade: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_index_dist(self): + if not self.download: + log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) + return None + + log.warn( + "Downloading {0!r}; run setup.py with the --offline option to " + "force offline installation.".format(DIST_NAME)) + + try: + dist = self._do_download() + except Exception as e: + if DEBUG: + raise + log.warn( + 'Failed to download and/or install {0!r} from {1!r}:\n' + '{2}'.format(DIST_NAME, self.index_url, str(e))) + dist = None + + # No need to run auto-upgrade here since we've already presumably + # gotten the most up-to-date version from the package index + return dist + + def _directory_import(self): + """ + Import astropy_helpers from the given path, which will be added to + sys.path. + + Must return True if the import succeeded, and False otherwise. + """ + + # Return True on success, False on failure but download is allowed, and + # otherwise raise SystemExit + path = os.path.abspath(self.path) + + # Use an empty WorkingSet rather than the man + # pkg_resources.working_set, since on older versions of setuptools this + # will invoke a VersionConflict when trying to install an upgrade + ws = pkg_resources.WorkingSet([]) + ws.add_entry(path) + dist = ws.by_key.get(DIST_NAME) + + if dist is None: + # We didn't find an egg-info/dist-info in the given path, but if a + # setup.py exists we can generate it + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + with _silence(): + run_setup(os.path.join(path, 'setup.py'), + ['egg_info']) + + for dist in pkg_resources.find_distributions(path, True): + # There should be only one... + return dist + + return dist + + def _do_download(self, version='', find_links=None): + if find_links: + allow_hosts = '' + index_url = None + else: + allow_hosts = None + index_url = self.index_url + + # Annoyingly, setuptools will not handle other arguments to + # Distribution (such as options) before handling setup_requires, so it + # is not straightforward to programmatically augment the arguments which + # are passed to easy_install + class _Distribution(Distribution): + def get_option_dict(self, command_name): + opts = Distribution.get_option_dict(self, command_name) + if command_name == 'easy_install': + if find_links is not None: + opts['find_links'] = ('setup script', find_links) + if index_url is not None: + opts['index_url'] = ('setup script', index_url) + if allow_hosts is not None: + opts['allow_hosts'] = ('setup script', allow_hosts) + return opts + + if version: + req = '{0}=={1}'.format(DIST_NAME, version) + else: + req = DIST_NAME + + attrs = {'setup_requires': [req]} + + try: + if DEBUG: + _Distribution(attrs=attrs) + else: + with _silence(): + _Distribution(attrs=attrs) + + # If the setup_requires succeeded it will have added the new dist to + # the main working_set + return pkg_resources.working_set.by_key.get(DIST_NAME) + except Exception as e: + if DEBUG: + raise + + msg = 'Error retrieving {0} from {1}:\n{2}' + if find_links: + source = find_links[0] + elif index_url != INDEX_URL: + source = index_url + else: + source = 'PyPI' + + raise Exception(msg.format(DIST_NAME, source, repr(e))) + + def _do_upgrade(self, dist): + # Build up a requirement for a higher bugfix release but a lower minor + # release (so API compatibility is guaranteed) + next_version = _next_version(dist.parsed_version) + + req = pkg_resources.Requirement.parse( + '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) + + package_index = PackageIndex(index_url=self.index_url) + + upgrade = package_index.obtain(req) + + if upgrade is not None: + return self._do_download(version=upgrade.version) + + def _check_submodule(self): + """ + Check if the given path is a git submodule. + + See the docstrings for ``_check_submodule_using_git`` and + ``_check_submodule_no_git`` for further details. + """ + + if (self.path is None or + (os.path.exists(self.path) and not os.path.isdir(self.path))): + return False + + if self.use_git: + return self._check_submodule_using_git() + else: + return self._check_submodule_no_git() + + def _check_submodule_using_git(self): + """ + Check if the given path is a git submodule. If so, attempt to initialize + and/or update the submodule if needed. + + This function makes calls to the ``git`` command in subprocesses. The + ``_check_submodule_no_git`` option uses pure Python to check if the given + path looks like a git submodule, but it cannot perform updates. + """ + + cmd = ['git', 'submodule', 'status', '--', self.path] + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except _CommandNotFound: + # The git command simply wasn't found; this is most likely the + # case on user systems that don't have git and are simply + # trying to install the package from PyPI or a source + # distribution. Silently ignore this case and simply don't try + # to use submodules + return False + + stderr = stderr.strip() + + if returncode != 0 and stderr: + # Unfortunately the return code alone cannot be relied on, as + # earlier versions of git returned 0 even if the requested submodule + # does not exist + + # This is a warning that occurs in perl (from running git submodule) + # which only occurs with a malformatted locale setting which can + # happen sometimes on OSX. See again + # https://github.com/astropy/astropy/issues/2749 + perl_warning = ('perl: warning: Falling back to the standard locale ' + '("C").') + if not stderr.strip().endswith(perl_warning): + # Some other unknown error condition occurred + log.warn('git submodule command failed ' + 'unexpectedly:\n{0}'.format(stderr)) + return False + + # Output of `git submodule status` is as follows: + # + # 1: Status indicator: '-' for submodule is uninitialized, '+' if + # submodule is initialized but is not at the commit currently indicated + # in .gitmodules (and thus needs to be updated), or 'U' if the + # submodule is in an unstable state (i.e. has merge conflicts) + # + # 2. SHA-1 hash of the current commit of the submodule (we don't really + # need this information but it's useful for checking that the output is + # correct) + # + # 3. The output of `git describe` for the submodule's current commit + # hash (this includes for example what branches the commit is on) but + # only if the submodule is initialized. We ignore this information for + # now + _git_submodule_status_re = re.compile( + '^(?P[+-U ])(?P[0-9a-f]{40}) ' + '(?P\S+)( .*)?$') + + # The stdout should only contain one line--the status of the + # requested submodule + m = _git_submodule_status_re.match(stdout) + if m: + # Yes, the path *is* a git submodule + self._update_submodule(m.group('submodule'), m.group('status')) + return True + else: + log.warn( + 'Unexpected output from `git submodule status`:\n{0}\n' + 'Will attempt import from {1!r} regardless.'.format( + stdout, self.path)) + return False + + def _check_submodule_no_git(self): + """ + Like ``_check_submodule_using_git``, but simply parses the .gitmodules file + to determine if the supplied path is a git submodule, and does not exec any + subprocesses. + + This can only determine if a path is a submodule--it does not perform + updates, etc. This function may need to be updated if the format of the + .gitmodules file is changed between git versions. + """ + + gitmodules_path = os.path.abspath('.gitmodules') + + if not os.path.isfile(gitmodules_path): + return False + + # This is a minimal reader for gitconfig-style files. It handles a few of + # the quirks that make gitconfig files incompatible with ConfigParser-style + # files, but does not support the full gitconfig syntax (just enough + # needed to read a .gitmodules file). + gitmodules_fileobj = io.StringIO() + + # Must use io.open for cross-Python-compatible behavior wrt unicode + with io.open(gitmodules_path) as f: + for line in f: + # gitconfig files are more flexible with leading whitespace; just + # go ahead and remove it + line = line.lstrip() + + # comments can start with either # or ; + if line and line[0] in (':', ';'): + continue + + gitmodules_fileobj.write(line) + + gitmodules_fileobj.seek(0) + + cfg = RawConfigParser() + + try: + cfg.readfp(gitmodules_fileobj) + except Exception as exc: + log.warn('Malformatted .gitmodules file: {0}\n' + '{1} cannot be assumed to be a git submodule.'.format( + exc, self.path)) + return False + + for section in cfg.sections(): + if not cfg.has_option(section, 'path'): + continue + + submodule_path = cfg.get(section, 'path').rstrip(os.sep) + + if submodule_path == self.path.rstrip(os.sep): + return True + + return False + + def _update_submodule(self, submodule, status): + if status == ' ': + # The submodule is up to date; no action necessary + return + elif status == '-': + if self.offline: + raise _AHBootstrapSystemExit( + "Cannot initialize the {0} submodule in --offline mode; " + "this requires being able to clone the submodule from an " + "online repository.".format(submodule)) + cmd = ['update', '--init'] + action = 'Initializing' + elif status == '+': + cmd = ['update'] + action = 'Updating' + if self.offline: + cmd.append('--no-fetch') + elif status == 'U': + raise _AHBoostrapSystemExit( + 'Error: Submodule {0} contains unresolved merge conflicts. ' + 'Please complete or abandon any changes in the submodule so that ' + 'it is in a usable state, then try again.'.format(submodule)) + else: + log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' + 'attempt to use the submodule as-is, but try to ensure ' + 'that the submodule is in a clean state and contains no ' + 'conflicts or errors.\n{2}'.format(status, submodule, + _err_help_msg)) + return + + err_msg = None + cmd = ['git', 'submodule'] + cmd + ['--', submodule] + log.warn('{0} {1} submodule with: `{2}`'.format( + action, submodule, ' '.join(cmd))) + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except OSError as e: + err_msg = str(e) + else: + if returncode != 0: + err_msg = stderr + + if err_msg is not None: + log.warn('An unexpected error occurred updating the git submodule ' + '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, + _err_help_msg)) + +class _CommandNotFound(OSError): + """ + An exception raised when a command run with run_cmd is not found on the + system. + """ + + +def run_cmd(cmd): + """ + Run a command in a subprocess, given as a list of command-line + arguments. + + Returns a ``(returncode, stdout, stderr)`` tuple. + """ + + try: + p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) + # XXX: May block if either stdout or stderr fill their buffers; + # however for the commands this is currently used for that is + # unlikely (they should have very brief output) + stdout, stderr = p.communicate() + except OSError as e: + if DEBUG: + raise + + if e.errno == errno.ENOENT: + msg = 'Command not found: `{0}`'.format(' '.join(cmd)) + raise _CommandNotFound(msg, cmd) + else: + raise _AHBoostrapSystemExit( + 'An unexpected error occurred when running the ' + '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) + + + # Can fail of the default locale is not configured properly. See + # https://github.com/astropy/astropy/issues/2749. For the purposes under + # consideration 'latin1' is an acceptable fallback. + try: + stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' + except ValueError: + # Due to an OSX oddity locale.getdefaultlocale() can also crash + # depending on the user's locale/language settings. See: + # http://bugs.python.org/issue18378 + stdio_encoding = 'latin1' + + # Unlikely to fail at this point but even then let's be flexible + if not isinstance(stdout, _text_type): + stdout = stdout.decode(stdio_encoding, 'replace') + if not isinstance(stderr, _text_type): + stderr = stderr.decode(stdio_encoding, 'replace') + + return (p.returncode, stdout, stderr) + + +def _next_version(version): + """ + Given a parsed version from pkg_resources.parse_version, returns a new + version string with the next minor version. + + Examples + ======== + >>> _next_version(pkg_resources.parse_version('1.2.3')) + '1.3.0' + """ + + if hasattr(version, 'base_version'): + # New version parsing from setuptools >= 8.0 + if version.base_version: + parts = version.base_version.split('.') + else: + parts = [] + else: + parts = [] + for part in version: + if part.startswith('*'): + break + parts.append(part) + + parts = [int(p) for p in parts] + + if len(parts) < 3: + parts += [0] * (3 - len(parts)) + + major, minor, micro = parts[:3] + + return '{0}.{1}.{2}'.format(major, minor + 1, 0) + + +class _DummyFile(object): + """A noop writeable object.""" + + errors = '' # Required for Python 3.x + encoding = 'utf-8' + + def write(self, s): + pass + + def flush(self): + pass + + +@contextlib.contextmanager +def _silence(): + """A context manager that silences sys.stdout and sys.stderr.""" + + old_stdout = sys.stdout + old_stderr = sys.stderr + sys.stdout = _DummyFile() + sys.stderr = _DummyFile() + exception_occurred = False + try: + yield + except: + exception_occurred = True + # Go ahead and clean up so that exception handling can work normally + sys.stdout = old_stdout + sys.stderr = old_stderr + raise + + if not exception_occurred: + sys.stdout = old_stdout + sys.stderr = old_stderr + + +_err_help_msg = """ +If the problem persists consider installing astropy_helpers manually using pip +(`pip install astropy_helpers`) or by manually downloading the source archive, +extracting it, and installing by running `python setup.py install` from the +root of the extracted source code. +""" + + +class _AHBootstrapSystemExit(SystemExit): + def __init__(self, *args): + if not args: + msg = 'An unknown problem occurred bootstrapping astropy_helpers.' + else: + msg = args[0] + + msg += '\n' + _err_help_msg + + super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) + + +if sys.version_info[:2] < (2, 7): + # In Python 2.6 the distutils log does not log warnings, errors, etc. to + # stderr so we have to wrap it to ensure consistency at least in this + # module + import distutils + + class log(object): + def __getattr__(self, attr): + return getattr(distutils.log, attr) + + def warn(self, msg, *args): + self._log_to_stderr(distutils.log.WARN, msg, *args) + + def error(self, msg): + self._log_to_stderr(distutils.log.ERROR, msg, *args) + + def fatal(self, msg): + self._log_to_stderr(distutils.log.FATAL, msg, *args) + + def log(self, level, msg, *args): + if level in (distutils.log.WARN, distutils.log.ERROR, + distutils.log.FATAL): + self._log_to_stderr(level, msg, *args) + else: + distutils.log.log(level, msg, *args) + + def _log_to_stderr(self, level, msg, *args): + # This is the only truly 'public' way to get the current threshold + # of the log + current_threshold = distutils.log.set_threshold(distutils.log.WARN) + distutils.log.set_threshold(current_threshold) + if level >= current_threshold: + if args: + msg = msg % args + sys.stderr.write('%s\n' % msg) + sys.stderr.flush() + + log = log() + + +BOOTSTRAPPER = _Bootstrapper.main() + + +def use_astropy_helpers(**kwargs): + """ + Ensure that the `astropy_helpers` module is available and is importable. + This supports automatic submodule initialization if astropy_helpers is + included in a project as a git submodule, or will download it from PyPI if + necessary. + + Parameters + ---------- + + path : str or None, optional + A filesystem path relative to the root of the project's source code + that should be added to `sys.path` so that `astropy_helpers` can be + imported from that path. + + If the path is a git submodule it will automatically be initialized + and/or updated. + + The path may also be to a ``.tar.gz`` archive of the astropy_helpers + source distribution. In this case the archive is automatically + unpacked and made temporarily available on `sys.path` as a ``.egg`` + archive. + + If `None` skip straight to downloading. + + download_if_needed : bool, optional + If the provided filesystem path is not found an attempt will be made to + download astropy_helpers from PyPI. It will then be made temporarily + available on `sys.path` as a ``.egg`` archive (using the + ``setup_requires`` feature of setuptools. If the ``--offline`` option + is given at the command line the value of this argument is overridden + to `False`. + + index_url : str, optional + If provided, use a different URL for the Python package index than the + main PyPI server. + + use_git : bool, optional + If `False` no git commands will be used--this effectively disables + support for git submodules. If the ``--no-git`` option is given at the + command line the value of this argument is overridden to `False`. + + auto_upgrade : bool, optional + By default, when installing a package from a non-development source + distribution ah_boostrap will try to automatically check for patch + releases to astropy-helpers on PyPI and use the patched version over + any bundled versions. Setting this to `False` will disable that + functionality. If the ``--offline`` option is given at the command line + the value of this argument is overridden to `False`. + + offline : bool, optional + If `False` disable all actions that require an internet connection, + including downloading packages from the package index and fetching + updates to any git submodule. Defaults to `True`. + """ + + global BOOTSTRAPPER + + config = BOOTSTRAPPER.config + config.update(**kwargs) + + # Create a new bootstrapper with the updated configuration and run it + BOOTSTRAPPER = _Bootstrapper(**config) + BOOTSTRAPPER.run() diff --git a/astropy_helpers b/astropy_helpers new file mode 160000 index 00000000..2732e3a5 --- /dev/null +++ b/astropy_helpers @@ -0,0 +1 @@ +Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e diff --git a/caom2tools/__init__.py b/caom2tools/__init__.py new file mode 100644 index 00000000..fe502a69 --- /dev/null +++ b/caom2tools/__init__.py @@ -0,0 +1,15 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +""" +This is an Astropy affiliated package. +""" + +# Affiliated packages may add whatever they like to this file, but +# should keep this content at the top. +# ---------------------------------------------------------------------------- +from ._astropy_init import * +# ---------------------------------------------------------------------------- + +# For egg_info test builds to pass, put package imports here. +if not _ASTROPY_SETUP_: + from .example_mod import * diff --git a/caom2tools/_astropy_init.py b/caom2tools/_astropy_init.py new file mode 100644 index 00000000..6d94a38b --- /dev/null +++ b/caom2tools/_astropy_init.py @@ -0,0 +1,138 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +__all__ = ['__version__', '__githash__', 'test'] + +# this indicates whether or not we are in the package's setup.py +try: + _ASTROPY_SETUP_ +except NameError: + from sys import version_info + if version_info[0] >= 3: + import builtins + else: + import __builtin__ as builtins + builtins._ASTROPY_SETUP_ = False + +try: + from .version import version as __version__ +except ImportError: + __version__ = '' +try: + from .version import githash as __githash__ +except ImportError: + __githash__ = '' + +# set up the test command +def _get_test_runner(): + import os + from astropy.tests.helper import TestRunner + return TestRunner(os.path.dirname(__file__)) + +def test(package=None, test_path=None, args=None, plugins=None, + verbose=False, pastebin=None, remote_data=False, pep8=False, + pdb=False, coverage=False, open_files=False, **kwargs): + """ + Run the tests using `py.test `__. A proper set + of arguments is constructed and passed to `pytest.main`_. + + .. _py.test: http://pytest.org/latest/ + .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main + + Parameters + ---------- + package : str, optional + The name of a specific package to test, e.g. 'io.fits' or 'utils'. + If nothing is specified all default tests are run. + + test_path : str, optional + Specify location to test by path. May be a single file or + directory. Must be specified absolutely or relative to the + calling directory. + + args : str, optional + Additional arguments to be passed to pytest.main_ in the ``args`` + keyword argument. + + plugins : list, optional + Plugins to be passed to pytest.main_ in the ``plugins`` keyword + argument. + + verbose : bool, optional + Convenience option to turn on verbose output from py.test_. Passing + True is the same as specifying ``'-v'`` in ``args``. + + pastebin : {'failed','all',None}, optional + Convenience option for turning on py.test_ pastebin output. Set to + ``'failed'`` to upload info for failed tests, or ``'all'`` to upload + info for all tests. + + remote_data : bool, optional + Controls whether to run tests marked with @remote_data. These + tests use online data and are not run by default. Set to True to + run these tests. + + pep8 : bool, optional + Turn on PEP8 checking via the `pytest-pep8 plugin + `_ and disable normal + tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. + + pdb : bool, optional + Turn on PDB post-mortem analysis for failing tests. Same as + specifying ``'--pdb'`` in ``args``. + + coverage : bool, optional + Generate a test coverage report. The result will be placed in + the directory htmlcov. + + open_files : bool, optional + Fail when any tests leave files open. Off by default, because + this adds extra run time to the test suite. Requires the + `psutil `_ package. + + parallel : int, optional + When provided, run the tests in parallel on the specified + number of CPUs. If parallel is negative, it will use the all + the cores on the machine. Requires the + `pytest-xdist `_ plugin + installed. Only available when using Astropy 0.3 or later. + + kwargs + Any additional keywords passed into this function will be passed + on to the astropy test runner. This allows use of test-related + functionality implemented in later versions of astropy without + explicitly updating the package template. + + """ + test_runner = _get_test_runner() + return test_runner.run_tests( + package=package, test_path=test_path, args=args, + plugins=plugins, verbose=verbose, pastebin=pastebin, + remote_data=remote_data, pep8=pep8, pdb=pdb, + coverage=coverage, open_files=open_files, **kwargs) + +if not _ASTROPY_SETUP_: + import os + from warnings import warn + from astropy import config + + # add these here so we only need to cleanup the namespace at the end + config_dir = None + + if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): + config_dir = os.path.dirname(__file__) + config_template = os.path.join(config_dir, __package__ + ".cfg") + if os.path.isfile(config_template): + try: + config.configuration.update_default_config( + __package__, config_dir, version=__version__) + except TypeError as orig_error: + try: + config.configuration.update_default_config( + __package__, config_dir) + except config.configuration.ConfigurationDefaultMissingError as e: + wmsg = (e.args[0] + " Cannot install default profile. If you are " + "importing from source, this is expected.") + warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) + del e + except: + raise orig_error diff --git a/caom2tools/conftest.py b/caom2tools/conftest.py new file mode 100644 index 00000000..e0465fef --- /dev/null +++ b/caom2tools/conftest.py @@ -0,0 +1,38 @@ +# this contains imports plugins that configure py.test for astropy tests. +# by importing them here in conftest.py they are discoverable by py.test +# no matter how it is invoked within the source tree. + +from astropy.tests.pytest_plugins import * + +## Uncomment the following line to treat all DeprecationWarnings as +## exceptions +# enable_deprecations_as_exceptions() + +## Uncomment and customize the following lines to add/remove entries from +## the list of packages for which version numbers are displayed when running +## the tests. Making it pass for KeyError is essential in some cases when +## the package uses other astropy affiliated packages. +# try: +# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' +# del PYTEST_HEADER_MODULES['h5py'] +# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 +# pass + +## Uncomment the following lines to display the version number of the +## package rather than the version number of Astropy in the top line when +## running the tests. +import os + +# This is to figure out the affiliated package version, rather than +# using Astropy's +try: + from .version import version +except ImportError: + version = 'dev' + +try: + packagename = os.path.basename(os.path.dirname(__file__)) + TESTED_VERSIONS[packagename] = version +except NameError: # Needed to support Astropy <= 1.0.0 + pass diff --git a/caom2tools/test/__init__.py b/caom2tools/test/__init__.py new file mode 100644 index 00000000..2ff7e2a6 --- /dev/null +++ b/caom2tools/test/__init__.py @@ -0,0 +1,4 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst +""" +This packages contains affiliated package tests. +""" diff --git a/caom2tools/test/coveragerc b/caom2tools/test/coveragerc new file mode 100644 index 00000000..bec7c291 --- /dev/null +++ b/caom2tools/test/coveragerc @@ -0,0 +1,31 @@ +[run] +source = {packagename} +omit = + {packagename}/_astropy_init* + {packagename}/conftest* + {packagename}/cython_version* + {packagename}/setup_package* + {packagename}/*/setup_package* + {packagename}/*/*/setup_package* + {packagename}/tests/* + {packagename}/*/tests/* + {packagename}/*/*/tests/* + {packagename}/version* + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about packages we have installed + except ImportError + + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + + # Don't complain about script hooks + def main\(.*\): + + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} \ No newline at end of file diff --git a/caom2tools/test/setup_package.py b/caom2tools/test/setup_package.py new file mode 100644 index 00000000..f2fd9ed4 --- /dev/null +++ b/caom2tools/test/setup_package.py @@ -0,0 +1,3 @@ +def get_package_data(): + return { + _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} diff --git a/docs/Makefile b/docs/Makefile new file mode 100644 index 00000000..fb03f26e --- /dev/null +++ b/docs/Makefile @@ -0,0 +1,133 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +#This is needed with git because git doesn't create a dir if it's empty +$(shell [ -d "_static" ] || mkdir -p _static) + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf $(BUILDDIR) + -rm -rf api + -rm -rf generated + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + @echo "Run 'python setup.py test' in the root directory to run doctests " \ + @echo "in the documentation." diff --git a/docs/_templates/autosummary/base.rst b/docs/_templates/autosummary/base.rst new file mode 100644 index 00000000..9cabaf52 --- /dev/null +++ b/docs/_templates/autosummary/base.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/base.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/docs/_templates/autosummary/class.rst b/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..6b214a5c --- /dev/null +++ b/docs/_templates/autosummary/class.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/class.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/docs/_templates/autosummary/module.rst b/docs/_templates/autosummary/module.rst new file mode 100644 index 00000000..f38315b2 --- /dev/null +++ b/docs/_templates/autosummary/module.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/module.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py new file mode 100644 index 00000000..78d20fd8 --- /dev/null +++ b/docs/conf.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# +# Astropy documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this file. +# +# All configuration values have a default. Some values are defined in +# the global Astropy configuration which is loaded here before anything else. +# See astropy.sphinx.conf for which values are set there. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('..')) +# IMPORTANT: the above commented section was generated by sphinx-quickstart, but +# is *NOT* appropriate for astropy or Astropy affiliated packages. It is left +# commented out with this explanation to make it clear why this should not be +# done. If the sys.path entry above is added, when the astropy.sphinx.conf +# import occurs, it will import the *source* version of astropy instead of the +# version installed (if invoked as "make html" or directly with sphinx), or the +# version in the build directory (if "python setup.py build_sphinx" is used). +# Thus, any C-extensions that are needed to build the documentation will *not* +# be accessible, and the documentation will not build correctly. + +import datetime +import os +import sys + +try: + import astropy_helpers +except ImportError: + # Building from inside the docs/ directory? + if os.path.basename(os.getcwd()) == 'docs': + a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) + if os.path.isdir(a_h_path): + sys.path.insert(1, a_h_path) + +# Load all of the global Astropy configuration +from astropy_helpers.sphinx.conf import * + +# Get configuration information from setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser +conf = ConfigParser() + +conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) +setup_cfg = dict(conf.items('metadata')) + +# -- General configuration ---------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.2' + +# To perform a Sphinx version check that needs to be more specific than +# major.minor, call `check_sphinx_version("x.y.z")` here. +# check_sphinx_version("1.2.1") + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns.append('_templates') + +# This is added to the end of RST files - a good place to put substitutions to +# be used globally. +rst_epilog += """ +""" + +# -- Project information ------------------------------------------------------ + +# This does not *have* to match the package name, but typically does +project = setup_cfg['package_name'] +author = setup_cfg['author'] +copyright = '{0}, {1}'.format( + datetime.datetime.now().year, setup_cfg['author']) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +__import__(setup_cfg['package_name']) +package = sys.modules[setup_cfg['package_name']] + +# The short X.Y version. +version = package.__version__.split('-', 1)[0] +# The full version, including alpha/beta/rc tags. +release = package.__version__ + + +# -- Options for HTML output -------------------------------------------------- + +# A NOTE ON HTML THEMES +# The global astropy configuration uses a custom theme, 'bootstrap-astropy', +# which is installed along with astropy. A different theme can be used or +# the options for this theme can be modified by overriding some of the +# variables set in the global configuration. The variables set in the +# global configuration are listed below, commented out. + + +# Please update these texts to match the name of your package. +html_theme_options = { + 'logotext1': 'package', # white, semi-bold + 'logotext2': '-template', # orange, light + 'logotext3': ':docs' # white, light + } + +# Add any paths that contain custom themes here, relative to this directory. +# To use a different custom theme, add the directory containing the theme. +#html_theme_path = [] + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. To override the custom theme, set this to the +# name of a builtin theme or the name of a custom theme in html_theme_path. +#html_theme = None + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = '' + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = '{0} v{1}'.format(project, release) + +# Output file base name for HTML help builder. +htmlhelp_basename = project + 'doc' + + +# -- Options for LaTeX output ------------------------------------------------- + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [('index', project + '.tex', project + u' Documentation', + author, 'manual')] + + +# -- Options for manual page output ------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [('index', project.lower(), project + u' Documentation', + [author], 1)] + + +# -- Options for the edit_on_github extension --------------------------------- + +if eval(setup_cfg.get('edit_on_github')): + extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] + + versionmod = __import__(setup_cfg['package_name'] + '.version') + edit_on_github_project = setup_cfg['github_project'] + if versionmod.version.release: + edit_on_github_branch = "v" + versionmod.version.version + else: + edit_on_github_branch = "master" + + edit_on_github_source_root = "" + edit_on_github_doc_root = "docs" + +# -- Resolving issue number to links in changelog ----------------------------- +github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) + diff --git a/docs/index.rst b/docs/index.rst new file mode 100644 index 00000000..e69de29b diff --git a/docs/make.bat b/docs/make.bat new file mode 100644 index 00000000..93dfe92b --- /dev/null +++ b/docs/make.bat @@ -0,0 +1,170 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/ez_setup.py b/ez_setup.py new file mode 100644 index 00000000..fc22046b --- /dev/null +++ b/ez_setup.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python + +""" +Setuptools bootstrapping installer. + +Maintained at https://github.com/pypa/setuptools/tree/bootstrap. + +Run this script to install or upgrade setuptools. +""" + +import os +import shutil +import sys +import tempfile +import zipfile +import optparse +import subprocess +import platform +import textwrap +import contextlib +import json +import codecs + +from distutils import log + +try: + from urllib.request import urlopen + from urllib.parse import urljoin +except ImportError: + from urllib2 import urlopen + from urlparse import urljoin + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +LATEST = object() +DEFAULT_VERSION = LATEST +DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" +DEFAULT_SAVE_DIR = os.curdir + + +def _python_cmd(*args): + """ + Execute a command. + + Return True if the command succeeded. + """ + args = (sys.executable,) + args + return subprocess.call(args) == 0 + + +def _install(archive_filename, install_args=()): + """Install Setuptools.""" + with archive_context(archive_filename): + # installing + log.warn('Installing Setuptools') + if not _python_cmd('setup.py', 'install', *install_args): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + # exitcode will be 2 + return 2 + + +def _build_egg(egg, archive_filename, to_dir): + """Build Setuptools egg.""" + with archive_context(archive_filename): + # building an egg + log.warn('Building a Setuptools egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +class ContextualZipFile(zipfile.ZipFile): + + """Supplement ZipFile class to support context manager for Python 2.6.""" + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def __new__(cls, *args, **kwargs): + """Construct a ZipFile or ContextualZipFile as appropriate.""" + if hasattr(zipfile.ZipFile, '__exit__'): + return zipfile.ZipFile(*args, **kwargs) + return super(ContextualZipFile, cls).__new__(cls) + + +@contextlib.contextmanager +def archive_context(filename): + """ + Unzip filename to a temporary directory, set to the cwd. + + The unzipped target is cleaned up after. + """ + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + with ContextualZipFile(filename) as archive: + archive.extractall() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + yield + + finally: + os.chdir(old_wd) + shutil.rmtree(tmpdir) + + +def _do_download(version, download_base, to_dir, download_delay): + """Download Setuptools.""" + egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + archive = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, archive, to_dir) + sys.path.insert(0, egg) + + # Remove previously-imported pkg_resources if present (see + # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). + if 'pkg_resources' in sys.modules: + _unload_pkg_resources() + + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, download_delay=15): + """ + Ensure that a setuptools version is installed. + + Return None. Raise SystemExit if the requested version + or later cannot be installed. + """ + version = _resolve_version(version) + to_dir = os.path.abspath(to_dir) + + # prior to importing, capture the module state for + # representative modules. + rep_modules = 'pkg_resources', 'setuptools' + imported = set(sys.modules).intersection(rep_modules) + + try: + import pkg_resources + pkg_resources.require("setuptools>=" + version) + # a suitable version is already installed + return + except ImportError: + # pkg_resources not available; setuptools is not installed; download + pass + except pkg_resources.DistributionNotFound: + # no version of setuptools was found; allow download + pass + except pkg_resources.VersionConflict as VC_err: + if imported: + _conflict_bail(VC_err, version) + + # otherwise, unload pkg_resources to allow the downloaded version to + # take precedence. + del pkg_resources + _unload_pkg_resources() + + return _do_download(version, download_base, to_dir, download_delay) + + +def _conflict_bail(VC_err, version): + """ + Setuptools was imported prior to invocation, so it is + unsafe to unload it. Bail out. + """ + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) + msg = conflict_tmpl.format(**locals()) + sys.stderr.write(msg) + sys.exit(2) + + +def _unload_pkg_resources(): + sys.meta_path = [ + importer + for importer in sys.meta_path + if importer.__class__.__module__ != 'pkg_resources.extern' + ] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] + + +def _clean_check(cmd, target): + """ + Run the command to download target. + + If the command fails, clean up before re-raising the error. + """ + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + if os.access(target, os.F_OK): + os.unlink(target) + raise + + +def download_file_powershell(url, target): + """ + Download the file at url to target using Powershell. + + Powershell will validate trust. + Raise an exception if the command cannot complete. + """ + target = os.path.abspath(target) + ps_cmd = ( + "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " + "[System.Net.CredentialCache]::DefaultCredentials; " + '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' + % locals() + ) + cmd = [ + 'powershell', + '-Command', + ps_cmd, + ] + _clean_check(cmd, target) + + +def has_powershell(): + """Determine if Powershell is available.""" + if platform.system() != 'Windows': + return False + cmd = ['powershell', '-Command', 'echo test'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_powershell.viable = has_powershell + + +def download_file_curl(url, target): + cmd = ['curl', url, '--location', '--silent', '--output', target] + _clean_check(cmd, target) + + +def has_curl(): + cmd = ['curl', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_curl.viable = has_curl + + +def download_file_wget(url, target): + cmd = ['wget', url, '--quiet', '--output-document', target] + _clean_check(cmd, target) + + +def has_wget(): + cmd = ['wget', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_wget.viable = has_wget + + +def download_file_insecure(url, target): + """Use Python to download the file, without connection authentication.""" + src = urlopen(url) + try: + # Read all the data in one block. + data = src.read() + finally: + src.close() + + # Write all the data in one block to avoid creating a partial file. + with open(target, "wb") as dst: + dst.write(data) +download_file_insecure.viable = lambda: True + + +def get_best_downloader(): + downloaders = ( + download_file_powershell, + download_file_curl, + download_file_wget, + download_file_insecure, + ) + viable_downloaders = (dl for dl in downloaders if dl.viable()) + return next(viable_downloaders, None) + + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, delay=15, + downloader_factory=get_best_downloader): + """ + Download setuptools from a specified location and return its filename. + + `version` should be a valid setuptools version number that is available + as an sdist for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + + ``downloader_factory`` should be a function taking no arguments and + returning a function for downloading a URL to a target. + """ + version = _resolve_version(version) + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + zip_name = "setuptools-%s.zip" % version + url = download_base + zip_name + saveto = os.path.join(to_dir, zip_name) + if not os.path.exists(saveto): # Avoid repeated downloads + log.warn("Downloading %s", url) + downloader = downloader_factory() + downloader(url, saveto) + return os.path.realpath(saveto) + + +def _resolve_version(version): + """ + Resolve LATEST version + """ + if version is not LATEST: + return version + + meta_url = urljoin(DEFAULT_URL, '/pypi/setuptools/json') + resp = urlopen(meta_url) + with contextlib.closing(resp): + try: + charset = resp.info().get_content_charset() + except Exception: + # Python 2 compat; assume UTF-8 + charset = 'UTF-8' + reader = codecs.getreader(charset) + doc = json.load(reader(resp)) + + return str(doc['info']['version']) + + +def _build_install_args(options): + """ + Build the arguments to 'python setup.py install' on the setuptools package. + + Returns list of command line arguments. + """ + return ['--user'] if options.user_install else [] + + +def _parse_args(): + """Parse the command line for options.""" + parser = optparse.OptionParser() + parser.add_option( + '--user', dest='user_install', action='store_true', default=False, + help='install in user site package') + parser.add_option( + '--download-base', dest='download_base', metavar="URL", + default=DEFAULT_URL, + help='alternative URL from where to download the setuptools package') + parser.add_option( + '--insecure', dest='downloader_factory', action='store_const', + const=lambda: download_file_insecure, default=get_best_downloader, + help='Use internal, non-validating downloader' + ) + parser.add_option( + '--version', help="Specify which version to download", + default=DEFAULT_VERSION, + ) + parser.add_option( + '--to-dir', + help="Directory to save (and re-use) package", + default=DEFAULT_SAVE_DIR, + ) + options, args = parser.parse_args() + # positional arguments are ignored + return options + + +def _download_args(options): + """Return args for download_setuptools function from cmdline args.""" + return dict( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + to_dir=options.to_dir, + ) + + +def main(): + """Install or upgrade setuptools and EasyInstall.""" + options = _parse_args() + archive = download_setuptools(**_download_args(options)) + return _install(archive, _build_install_args(options)) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/setup.cfg b/setup.cfg new file mode 100644 index 00000000..8dc9df27 --- /dev/null +++ b/setup.cfg @@ -0,0 +1,38 @@ +[build_sphinx] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[build_docs] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[upload_docs] +upload-dir = docs/_build/html +show-response = 1 + +[pytest] +minversion = 2.2 +norecursedirs = build docs/_build +doctest_plus = enabled + +[ah_bootstrap] +auto_use = True + +[metadata] +package_name = caom2tools +description = Astropy affiliated package +long_description = This is a package for handling Common Archive Observation Model (CAOM2). CAOM2 is a general +purpose data model for use as the core data model of an astronomical data centre. +author = Canadian Astronomy Data Centre +author_email = cadc@nrc-cnrc.gc.ca +license = BSD +url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 +edit_on_github = False +github_project = opencadc/caom2tools +# version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +version = 0.1.dev + +[entry_points] +astropy-package-template-example = caom2tools.example_mod:main diff --git a/setup.py b/setup.py new file mode 100755 index 00000000..e3f4adc0 --- /dev/null +++ b/setup.py @@ -0,0 +1,120 @@ +#!/usr/bin/env python +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +import glob +import os +import sys + +import ah_bootstrap +from setuptools import setup + +#A dirty hack to get around some early import/configurations ambiguities +if sys.version_info[0] >= 3: + import builtins +else: + import __builtin__ as builtins +builtins._ASTROPY_SETUP_ = True + +from astropy_helpers.setup_helpers import (register_commands, get_debug_option, + get_package_info) +from astropy_helpers.git_helpers import get_git_devstr +from astropy_helpers.version_helpers import generate_version_py + +# Get some values from the setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser + +conf = ConfigParser() +conf.read(['setup.cfg']) +metadata = dict(conf.items('metadata')) + +PACKAGENAME = metadata.get('package_name', 'packagename') +DESCRIPTION = metadata.get('description', 'Astropy affiliated package') +AUTHOR = metadata.get('author', '') +AUTHOR_EMAIL = metadata.get('author_email', '') +LICENSE = metadata.get('license', 'unknown') +URL = metadata.get('url', 'http://astropy.org') + +# Get the long description from the package's docstring +__import__(PACKAGENAME) +package = sys.modules[PACKAGENAME] +LONG_DESCRIPTION = package.__doc__ + +# Store the package name in a built-in variable so it's easy +# to get from other parts of the setup infrastructure +builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME + +# VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +VERSION = metadata.get('version', '0.0.dev') + +# Indicates if this version is a release version +RELEASE = 'dev' not in VERSION + +if not RELEASE: + VERSION += get_git_devstr(False) + +# Populate the dict of setup command overrides; this should be done before +# invoking any other functionality from distutils since it can potentially +# modify distutils' behavior. +cmdclassd = register_commands(PACKAGENAME, VERSION, RELEASE) + +# Freeze build information in version.py +generate_version_py(PACKAGENAME, VERSION, RELEASE, + get_debug_option(PACKAGENAME)) + +# Treat everything in scripts except README.rst as a script to be installed +scripts = [fname for fname in glob.glob(os.path.join('scripts', '*')) + if os.path.basename(fname) != 'README.rst'] + + +# Get configuration information from all of the various subpackages. +# See the docstring for setup_helpers.update_package_files for more +# details. +package_info = get_package_info() + +# Add the project-global data +package_info['package_data'].setdefault(PACKAGENAME, []) +package_info['package_data'][PACKAGENAME].append('data/*') + +# Define entry points for command-line scripts +entry_points = {'console_scripts': []} + +entry_point_list = conf.items('entry_points') +for entry_point in entry_point_list: + entry_points['console_scripts'].append('{0} = {1}'.format(entry_point[0], + entry_point[1])) + +# Include all .c files, recursively, including those generated by +# Cython, since we can not do this in MANIFEST.in with a "dynamic" +# directory name. +c_files = [] +for root, dirs, files in os.walk(PACKAGENAME): + for filename in files: + if filename.endswith('.c'): + c_files.append( + os.path.join( + os.path.relpath(root, PACKAGENAME), filename)) +package_info['package_data'][PACKAGENAME].extend(c_files) + +# Note that requires and provides should not be included in the call to +# ``setup``, since these are now deprecated. See this link for more details: +# https://groups.google.com/forum/#!topic/astropy-dev/urYO8ckB2uM + +setup(name=PACKAGENAME, + version=VERSION, + description=DESCRIPTION, + scripts=scripts, + install_requires=['astropy'], + author=AUTHOR, + author_email=AUTHOR_EMAIL, + license=LICENSE, + url=URL, + long_description=LONG_DESCRIPTION, + cmdclass=cmdclassd, + zip_safe=False, + use_2to3=False, + entry_points=entry_points, + **package_info +) From ba6dd1f9a02dedfcfe7ff4a0bb9d87ba163eda89 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 8 Nov 2016 10:46:47 -0800 Subject: [PATCH 02/54] Initial layout for package --- caom2tools/__init__.py | 3 ++- setup.cfg | 3 +-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/caom2tools/__init__.py b/caom2tools/__init__.py index fe502a69..e7359a5f 100644 --- a/caom2tools/__init__.py +++ b/caom2tools/__init__.py @@ -12,4 +12,5 @@ # For egg_info test builds to pass, put package imports here. if not _ASTROPY_SETUP_: - from .example_mod import * +# from .caom2tools import * + pass diff --git a/setup.cfg b/setup.cfg index 8dc9df27..8eef705f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -23,8 +23,7 @@ auto_use = True [metadata] package_name = caom2tools description = Astropy affiliated package -long_description = This is a package for handling Common Archive Observation Model (CAOM2). CAOM2 is a general -purpose data model for use as the core data model of an astronomical data centre. +long_description = This is a package for handling Common Archive Observation Model (CAOM2). CAOM2 is a general purpose data model for use as the core data model of an astronomical data centre. author = Canadian Astronomy Data Centre author_email = cadc@nrc-cnrc.gc.ca license = BSD From f56fa0aa140cdb26810d9666bb8d8ba02ef936f0 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 8 Nov 2016 13:01:48 -0800 Subject: [PATCH 03/54] Renamed pyCAOM2 to caom2 --- {pyCAOM2 => caom2tools/caom2}/COPYING | 0 {pyCAOM2 => caom2tools/caom2}/Dependencies.txt | 0 {pyCAOM2 => caom2tools/caom2}/MANIFEST.in | 0 {pyCAOM2 => caom2tools/caom2}/build.xml | 0 {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.0.xsd | 0 {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.1.xsd | 0 {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.2.xsd | 0 {pyCAOM2 => caom2tools/caom2}/caom2/__init__.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_algorithm.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_artifact.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_chunk.py | 0 .../caom2}/caom2/caom2_composite_observation.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_data_quality.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_energy.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_energy_transition.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_entity.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_enums.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_environment.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_exceptions.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_instrument.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_metrics.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_object.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_observation.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_observation_uri.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_part.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_plane.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_plane_uri.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_polarization.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_position.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_proposal.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_provenance.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_requirements.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_simple_observation.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_target.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_target_position.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_telescope.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/caom2_time.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/enum.py | 0 .../caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/CompleteCompositeCircle.xml | 0 .../caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/CompleteCompositePolygon.xml | 0 .../caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/CompleteSimpleCircle.xml | 0 .../caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/CompleteSimplePolygon.xml | 0 .../caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/MinimalCompositeCircle.xml | 0 .../caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/MinimalCompositePolygon.xml | 0 .../caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/MinimalSimpleCircle.xml | 0 .../caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../caom2}/caom2/test/data/MinimalSimplePolygon.xml | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_algorithm.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_artifact.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_axis.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_entity.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_enums.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_util.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2instances.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_chunk.py | 0 .../caom2}/caom2/test/test_composite_observation.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_axis1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_axis2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_bounds1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_bounds2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_circle2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_error.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_function1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_function2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_polygon2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_range1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_range2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_data_quality.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_dimension2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_energy.py | 0 .../caom2}/caom2/test/test_energy_transition.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_environment.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_instrument.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_metrics.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observable_axis.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observation.py | 0 .../caom2}/caom2/test/test_observation_reader_writer.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observation_uri.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_part.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_plane.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_plane_uri.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_point.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_polarization.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_polarization_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_position.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_proposal.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_provenance.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_ref_coord.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_requirements.py | 0 .../caom2}/caom2/test/test_simple_observation.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_slice.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_spatial_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_spectral_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_target.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_target_position.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_telescope.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_temporal_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_time.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/test/test_value_coord2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/__init__.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_box.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_circle.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_interval.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_point.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_polygon.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_vertex.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/util/__init__.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/util/caom2_util.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/util/caom2_validator.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/__init__.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_axis.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_axis1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_axis2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_bounds1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_bounds2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_circle2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_error.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_function1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_function2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_polygon2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_range1d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_range2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_dimension2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_observable_axis.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_polarization_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_ref_coord.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_slice.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_spatial_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_spectral_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_temporal_wcs.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_value_coord2d.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/xml/__init__.py | 0 .../caom2}/caom2/xml/caom2_observation_reader.py | 0 .../caom2}/caom2/xml/caom2_observation_writer.py | 0 {pyCAOM2 => caom2tools/caom2}/caom2/xml/caom2_xml_constants.py | 0 {pyCAOM2 => caom2tools/caom2}/requirements.txt | 0 {pyCAOM2 => caom2tools/caom2}/setup.cfg | 0 {pyCAOM2 => caom2tools/caom2}/setup.py | 0 {pyCAOM2/test => caom2tools/caom2/tests}/test_roundtrip.py | 0 caom2tools/{test => tests}/__init__.py | 0 caom2tools/{test => tests}/coveragerc | 0 caom2tools/{test => tests}/setup_package.py | 0 159 files changed, 0 insertions(+), 0 deletions(-) rename {pyCAOM2 => caom2tools/caom2}/COPYING (100%) rename {pyCAOM2 => caom2tools/caom2}/Dependencies.txt (100%) rename {pyCAOM2 => caom2tools/caom2}/MANIFEST.in (100%) rename {pyCAOM2 => caom2tools/caom2}/build.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.0.xsd (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.1.xsd (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/CAOM-2.2.xsd (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/__init__.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_algorithm.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_artifact.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_chunk.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_composite_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_data_quality.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_energy.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_energy_transition.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_entity.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_enums.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_environment.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_exceptions.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_instrument.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_metrics.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_object.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_observation_uri.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_part.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_plane.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_plane_uri.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_polarization.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_position.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_proposal.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_provenance.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_requirements.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_simple_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_target.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_target_position.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_telescope.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/caom2_time.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/enum.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositeCircle.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteCompositePolygon.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimpleCircle.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/CompleteSimplePolygon.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositeCircle.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalCompositePolygon.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimpleCircle.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/data/MinimalSimplePolygon.xml (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_algorithm.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_artifact.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_axis.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_entity.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_enums.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2_util.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_caom2instances.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_chunk.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_composite_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_axis1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_axis2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_bounds1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_bounds2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_circle2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_error.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_function1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_function2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_polygon2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_range1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_coord_range2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_data_quality.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_dimension2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_energy.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_energy_transition.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_environment.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_instrument.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_metrics.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observable_axis.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observation_reader_writer.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_observation_uri.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_part.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_plane.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_plane_uri.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_point.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_polarization.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_polarization_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_position.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_proposal.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_provenance.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_ref_coord.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_requirements.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_simple_observation.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_slice.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_spatial_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_spectral_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_target.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_target_position.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_telescope.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_temporal_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_time.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/test/test_value_coord2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/__init__.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_box.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_circle.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_interval.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_point.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_polygon.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/types/caom2_vertex.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/util/__init__.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/util/caom2_util.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/util/caom2_validator.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/__init__.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_axis.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_axis1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_axis2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_bounds1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_bounds2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_circle2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_error.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_function1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_function2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_polygon2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_range1d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_coord_range2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_dimension2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_observable_axis.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_polarization_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_ref_coord.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_slice.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_spatial_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_spectral_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_temporal_wcs.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/wcs/caom2_value_coord2d.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/xml/__init__.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/xml/caom2_observation_reader.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/xml/caom2_observation_writer.py (100%) rename {pyCAOM2 => caom2tools/caom2}/caom2/xml/caom2_xml_constants.py (100%) rename {pyCAOM2 => caom2tools/caom2}/requirements.txt (100%) rename {pyCAOM2 => caom2tools/caom2}/setup.cfg (100%) rename {pyCAOM2 => caom2tools/caom2}/setup.py (100%) rename {pyCAOM2/test => caom2tools/caom2/tests}/test_roundtrip.py (100%) rename caom2tools/{test => tests}/__init__.py (100%) rename caom2tools/{test => tests}/coveragerc (100%) rename caom2tools/{test => tests}/setup_package.py (100%) diff --git a/pyCAOM2/COPYING b/caom2tools/caom2/COPYING similarity index 100% rename from pyCAOM2/COPYING rename to caom2tools/caom2/COPYING diff --git a/pyCAOM2/Dependencies.txt b/caom2tools/caom2/Dependencies.txt similarity index 100% rename from pyCAOM2/Dependencies.txt rename to caom2tools/caom2/Dependencies.txt diff --git a/pyCAOM2/MANIFEST.in b/caom2tools/caom2/MANIFEST.in similarity index 100% rename from pyCAOM2/MANIFEST.in rename to caom2tools/caom2/MANIFEST.in diff --git a/pyCAOM2/build.xml b/caom2tools/caom2/build.xml similarity index 100% rename from pyCAOM2/build.xml rename to caom2tools/caom2/build.xml diff --git a/pyCAOM2/caom2/CAOM-2.0.xsd b/caom2tools/caom2/caom2/CAOM-2.0.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.0.xsd rename to caom2tools/caom2/caom2/CAOM-2.0.xsd diff --git a/pyCAOM2/caom2/CAOM-2.1.xsd b/caom2tools/caom2/caom2/CAOM-2.1.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.1.xsd rename to caom2tools/caom2/caom2/CAOM-2.1.xsd diff --git a/pyCAOM2/caom2/CAOM-2.2.xsd b/caom2tools/caom2/caom2/CAOM-2.2.xsd similarity index 100% rename from pyCAOM2/caom2/CAOM-2.2.xsd rename to caom2tools/caom2/caom2/CAOM-2.2.xsd diff --git a/pyCAOM2/caom2/__init__.py b/caom2tools/caom2/caom2/__init__.py similarity index 100% rename from pyCAOM2/caom2/__init__.py rename to caom2tools/caom2/caom2/__init__.py diff --git a/pyCAOM2/caom2/caom2_algorithm.py b/caom2tools/caom2/caom2/caom2_algorithm.py similarity index 100% rename from pyCAOM2/caom2/caom2_algorithm.py rename to caom2tools/caom2/caom2/caom2_algorithm.py diff --git a/pyCAOM2/caom2/caom2_artifact.py b/caom2tools/caom2/caom2/caom2_artifact.py similarity index 100% rename from pyCAOM2/caom2/caom2_artifact.py rename to caom2tools/caom2/caom2/caom2_artifact.py diff --git a/pyCAOM2/caom2/caom2_chunk.py b/caom2tools/caom2/caom2/caom2_chunk.py similarity index 100% rename from pyCAOM2/caom2/caom2_chunk.py rename to caom2tools/caom2/caom2/caom2_chunk.py diff --git a/pyCAOM2/caom2/caom2_composite_observation.py b/caom2tools/caom2/caom2/caom2_composite_observation.py similarity index 100% rename from pyCAOM2/caom2/caom2_composite_observation.py rename to caom2tools/caom2/caom2/caom2_composite_observation.py diff --git a/pyCAOM2/caom2/caom2_data_quality.py b/caom2tools/caom2/caom2/caom2_data_quality.py similarity index 100% rename from pyCAOM2/caom2/caom2_data_quality.py rename to caom2tools/caom2/caom2/caom2_data_quality.py diff --git a/pyCAOM2/caom2/caom2_energy.py b/caom2tools/caom2/caom2/caom2_energy.py similarity index 100% rename from pyCAOM2/caom2/caom2_energy.py rename to caom2tools/caom2/caom2/caom2_energy.py diff --git a/pyCAOM2/caom2/caom2_energy_transition.py b/caom2tools/caom2/caom2/caom2_energy_transition.py similarity index 100% rename from pyCAOM2/caom2/caom2_energy_transition.py rename to caom2tools/caom2/caom2/caom2_energy_transition.py diff --git a/pyCAOM2/caom2/caom2_entity.py b/caom2tools/caom2/caom2/caom2_entity.py similarity index 100% rename from pyCAOM2/caom2/caom2_entity.py rename to caom2tools/caom2/caom2/caom2_entity.py diff --git a/pyCAOM2/caom2/caom2_enums.py b/caom2tools/caom2/caom2/caom2_enums.py similarity index 100% rename from pyCAOM2/caom2/caom2_enums.py rename to caom2tools/caom2/caom2/caom2_enums.py diff --git a/pyCAOM2/caom2/caom2_environment.py b/caom2tools/caom2/caom2/caom2_environment.py similarity index 100% rename from pyCAOM2/caom2/caom2_environment.py rename to caom2tools/caom2/caom2/caom2_environment.py diff --git a/pyCAOM2/caom2/caom2_exceptions.py b/caom2tools/caom2/caom2/caom2_exceptions.py similarity index 100% rename from pyCAOM2/caom2/caom2_exceptions.py rename to caom2tools/caom2/caom2/caom2_exceptions.py diff --git a/pyCAOM2/caom2/caom2_instrument.py b/caom2tools/caom2/caom2/caom2_instrument.py similarity index 100% rename from pyCAOM2/caom2/caom2_instrument.py rename to caom2tools/caom2/caom2/caom2_instrument.py diff --git a/pyCAOM2/caom2/caom2_metrics.py b/caom2tools/caom2/caom2/caom2_metrics.py similarity index 100% rename from pyCAOM2/caom2/caom2_metrics.py rename to caom2tools/caom2/caom2/caom2_metrics.py diff --git a/pyCAOM2/caom2/caom2_object.py b/caom2tools/caom2/caom2/caom2_object.py similarity index 100% rename from pyCAOM2/caom2/caom2_object.py rename to caom2tools/caom2/caom2/caom2_object.py diff --git a/pyCAOM2/caom2/caom2_observation.py b/caom2tools/caom2/caom2/caom2_observation.py similarity index 100% rename from pyCAOM2/caom2/caom2_observation.py rename to caom2tools/caom2/caom2/caom2_observation.py diff --git a/pyCAOM2/caom2/caom2_observation_uri.py b/caom2tools/caom2/caom2/caom2_observation_uri.py similarity index 100% rename from pyCAOM2/caom2/caom2_observation_uri.py rename to caom2tools/caom2/caom2/caom2_observation_uri.py diff --git a/pyCAOM2/caom2/caom2_part.py b/caom2tools/caom2/caom2/caom2_part.py similarity index 100% rename from pyCAOM2/caom2/caom2_part.py rename to caom2tools/caom2/caom2/caom2_part.py diff --git a/pyCAOM2/caom2/caom2_plane.py b/caom2tools/caom2/caom2/caom2_plane.py similarity index 100% rename from pyCAOM2/caom2/caom2_plane.py rename to caom2tools/caom2/caom2/caom2_plane.py diff --git a/pyCAOM2/caom2/caom2_plane_uri.py b/caom2tools/caom2/caom2/caom2_plane_uri.py similarity index 100% rename from pyCAOM2/caom2/caom2_plane_uri.py rename to caom2tools/caom2/caom2/caom2_plane_uri.py diff --git a/pyCAOM2/caom2/caom2_polarization.py b/caom2tools/caom2/caom2/caom2_polarization.py similarity index 100% rename from pyCAOM2/caom2/caom2_polarization.py rename to caom2tools/caom2/caom2/caom2_polarization.py diff --git a/pyCAOM2/caom2/caom2_position.py b/caom2tools/caom2/caom2/caom2_position.py similarity index 100% rename from pyCAOM2/caom2/caom2_position.py rename to caom2tools/caom2/caom2/caom2_position.py diff --git a/pyCAOM2/caom2/caom2_proposal.py b/caom2tools/caom2/caom2/caom2_proposal.py similarity index 100% rename from pyCAOM2/caom2/caom2_proposal.py rename to caom2tools/caom2/caom2/caom2_proposal.py diff --git a/pyCAOM2/caom2/caom2_provenance.py b/caom2tools/caom2/caom2/caom2_provenance.py similarity index 100% rename from pyCAOM2/caom2/caom2_provenance.py rename to caom2tools/caom2/caom2/caom2_provenance.py diff --git a/pyCAOM2/caom2/caom2_requirements.py b/caom2tools/caom2/caom2/caom2_requirements.py similarity index 100% rename from pyCAOM2/caom2/caom2_requirements.py rename to caom2tools/caom2/caom2/caom2_requirements.py diff --git a/pyCAOM2/caom2/caom2_simple_observation.py b/caom2tools/caom2/caom2/caom2_simple_observation.py similarity index 100% rename from pyCAOM2/caom2/caom2_simple_observation.py rename to caom2tools/caom2/caom2/caom2_simple_observation.py diff --git a/pyCAOM2/caom2/caom2_target.py b/caom2tools/caom2/caom2/caom2_target.py similarity index 100% rename from pyCAOM2/caom2/caom2_target.py rename to caom2tools/caom2/caom2/caom2_target.py diff --git a/pyCAOM2/caom2/caom2_target_position.py b/caom2tools/caom2/caom2/caom2_target_position.py similarity index 100% rename from pyCAOM2/caom2/caom2_target_position.py rename to caom2tools/caom2/caom2/caom2_target_position.py diff --git a/pyCAOM2/caom2/caom2_telescope.py b/caom2tools/caom2/caom2/caom2_telescope.py similarity index 100% rename from pyCAOM2/caom2/caom2_telescope.py rename to caom2tools/caom2/caom2/caom2_telescope.py diff --git a/pyCAOM2/caom2/caom2_time.py b/caom2tools/caom2/caom2/caom2_time.py similarity index 100% rename from pyCAOM2/caom2/caom2_time.py rename to caom2tools/caom2/caom2/caom2_time.py diff --git a/pyCAOM2/caom2/enum.py b/caom2tools/caom2/caom2/enum.py similarity index 100% rename from pyCAOM2/caom2/enum.py rename to caom2tools/caom2/caom2/enum.py diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/CompleteCompositeCircle.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositeCircle.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositeCircle.xml diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/CompleteCompositePolygon.xml b/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteCompositePolygon.xml rename to caom2tools/caom2/caom2/test/data/CompleteCompositePolygon.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimpleCircle.xml b/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimpleCircle.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimpleCircle.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/CompleteSimplePolygon.xml b/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/CompleteSimplePolygon.xml rename to caom2tools/caom2/caom2/test/data/CompleteSimplePolygon.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositeCircle.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositeCircle.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositeCircle.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalCompositePolygon.xml b/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalCompositePolygon.xml rename to caom2tools/caom2/caom2/test/data/MinimalCompositePolygon.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimpleCircle.xml b/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimpleCircle.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimpleCircle.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/pyCAOM2/caom2/test/data/MinimalSimplePolygon.xml b/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon.xml similarity index 100% rename from pyCAOM2/caom2/test/data/MinimalSimplePolygon.xml rename to caom2tools/caom2/caom2/test/data/MinimalSimplePolygon.xml diff --git a/pyCAOM2/caom2/test/test_algorithm.py b/caom2tools/caom2/caom2/test/test_algorithm.py similarity index 100% rename from pyCAOM2/caom2/test/test_algorithm.py rename to caom2tools/caom2/caom2/test/test_algorithm.py diff --git a/pyCAOM2/caom2/test/test_artifact.py b/caom2tools/caom2/caom2/test/test_artifact.py similarity index 100% rename from pyCAOM2/caom2/test/test_artifact.py rename to caom2tools/caom2/caom2/test/test_artifact.py diff --git a/pyCAOM2/caom2/test/test_axis.py b/caom2tools/caom2/caom2/test/test_axis.py similarity index 100% rename from pyCAOM2/caom2/test/test_axis.py rename to caom2tools/caom2/caom2/test/test_axis.py diff --git a/pyCAOM2/caom2/test/test_caom2_entity.py b/caom2tools/caom2/caom2/test/test_caom2_entity.py similarity index 100% rename from pyCAOM2/caom2/test/test_caom2_entity.py rename to caom2tools/caom2/caom2/test/test_caom2_entity.py diff --git a/pyCAOM2/caom2/test/test_caom2_enums.py b/caom2tools/caom2/caom2/test/test_caom2_enums.py similarity index 100% rename from pyCAOM2/caom2/test/test_caom2_enums.py rename to caom2tools/caom2/caom2/test/test_caom2_enums.py diff --git a/pyCAOM2/caom2/test/test_caom2_util.py b/caom2tools/caom2/caom2/test/test_caom2_util.py similarity index 100% rename from pyCAOM2/caom2/test/test_caom2_util.py rename to caom2tools/caom2/caom2/test/test_caom2_util.py diff --git a/pyCAOM2/caom2/test/test_caom2instances.py b/caom2tools/caom2/caom2/test/test_caom2instances.py similarity index 100% rename from pyCAOM2/caom2/test/test_caom2instances.py rename to caom2tools/caom2/caom2/test/test_caom2instances.py diff --git a/pyCAOM2/caom2/test/test_chunk.py b/caom2tools/caom2/caom2/test/test_chunk.py similarity index 100% rename from pyCAOM2/caom2/test/test_chunk.py rename to caom2tools/caom2/caom2/test/test_chunk.py diff --git a/pyCAOM2/caom2/test/test_composite_observation.py b/caom2tools/caom2/caom2/test/test_composite_observation.py similarity index 100% rename from pyCAOM2/caom2/test/test_composite_observation.py rename to caom2tools/caom2/caom2/test/test_composite_observation.py diff --git a/pyCAOM2/caom2/test/test_coord2d.py b/caom2tools/caom2/caom2/test/test_coord2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord2d.py rename to caom2tools/caom2/caom2/test/test_coord2d.py diff --git a/pyCAOM2/caom2/test/test_coord_axis1d.py b/caom2tools/caom2/caom2/test/test_coord_axis1d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_axis1d.py rename to caom2tools/caom2/caom2/test/test_coord_axis1d.py diff --git a/pyCAOM2/caom2/test/test_coord_axis2d.py b/caom2tools/caom2/caom2/test/test_coord_axis2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_axis2d.py rename to caom2tools/caom2/caom2/test/test_coord_axis2d.py diff --git a/pyCAOM2/caom2/test/test_coord_bounds1d.py b/caom2tools/caom2/caom2/test/test_coord_bounds1d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_bounds1d.py rename to caom2tools/caom2/caom2/test/test_coord_bounds1d.py diff --git a/pyCAOM2/caom2/test/test_coord_bounds2d.py b/caom2tools/caom2/caom2/test/test_coord_bounds2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_bounds2d.py rename to caom2tools/caom2/caom2/test/test_coord_bounds2d.py diff --git a/pyCAOM2/caom2/test/test_coord_circle2d.py b/caom2tools/caom2/caom2/test/test_coord_circle2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_circle2d.py rename to caom2tools/caom2/caom2/test/test_coord_circle2d.py diff --git a/pyCAOM2/caom2/test/test_coord_error.py b/caom2tools/caom2/caom2/test/test_coord_error.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_error.py rename to caom2tools/caom2/caom2/test/test_coord_error.py diff --git a/pyCAOM2/caom2/test/test_coord_function1d.py b/caom2tools/caom2/caom2/test/test_coord_function1d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_function1d.py rename to caom2tools/caom2/caom2/test/test_coord_function1d.py diff --git a/pyCAOM2/caom2/test/test_coord_function2d.py b/caom2tools/caom2/caom2/test/test_coord_function2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_function2d.py rename to caom2tools/caom2/caom2/test/test_coord_function2d.py diff --git a/pyCAOM2/caom2/test/test_coord_polygon2d.py b/caom2tools/caom2/caom2/test/test_coord_polygon2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_polygon2d.py rename to caom2tools/caom2/caom2/test/test_coord_polygon2d.py diff --git a/pyCAOM2/caom2/test/test_coord_range1d.py b/caom2tools/caom2/caom2/test/test_coord_range1d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_range1d.py rename to caom2tools/caom2/caom2/test/test_coord_range1d.py diff --git a/pyCAOM2/caom2/test/test_coord_range2d.py b/caom2tools/caom2/caom2/test/test_coord_range2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_coord_range2d.py rename to caom2tools/caom2/caom2/test/test_coord_range2d.py diff --git a/pyCAOM2/caom2/test/test_data_quality.py b/caom2tools/caom2/caom2/test/test_data_quality.py similarity index 100% rename from pyCAOM2/caom2/test/test_data_quality.py rename to caom2tools/caom2/caom2/test/test_data_quality.py diff --git a/pyCAOM2/caom2/test/test_dimension2d.py b/caom2tools/caom2/caom2/test/test_dimension2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_dimension2d.py rename to caom2tools/caom2/caom2/test/test_dimension2d.py diff --git a/pyCAOM2/caom2/test/test_energy.py b/caom2tools/caom2/caom2/test/test_energy.py similarity index 100% rename from pyCAOM2/caom2/test/test_energy.py rename to caom2tools/caom2/caom2/test/test_energy.py diff --git a/pyCAOM2/caom2/test/test_energy_transition.py b/caom2tools/caom2/caom2/test/test_energy_transition.py similarity index 100% rename from pyCAOM2/caom2/test/test_energy_transition.py rename to caom2tools/caom2/caom2/test/test_energy_transition.py diff --git a/pyCAOM2/caom2/test/test_environment.py b/caom2tools/caom2/caom2/test/test_environment.py similarity index 100% rename from pyCAOM2/caom2/test/test_environment.py rename to caom2tools/caom2/caom2/test/test_environment.py diff --git a/pyCAOM2/caom2/test/test_instrument.py b/caom2tools/caom2/caom2/test/test_instrument.py similarity index 100% rename from pyCAOM2/caom2/test/test_instrument.py rename to caom2tools/caom2/caom2/test/test_instrument.py diff --git a/pyCAOM2/caom2/test/test_metrics.py b/caom2tools/caom2/caom2/test/test_metrics.py similarity index 100% rename from pyCAOM2/caom2/test/test_metrics.py rename to caom2tools/caom2/caom2/test/test_metrics.py diff --git a/pyCAOM2/caom2/test/test_observable_axis.py b/caom2tools/caom2/caom2/test/test_observable_axis.py similarity index 100% rename from pyCAOM2/caom2/test/test_observable_axis.py rename to caom2tools/caom2/caom2/test/test_observable_axis.py diff --git a/pyCAOM2/caom2/test/test_observation.py b/caom2tools/caom2/caom2/test/test_observation.py similarity index 100% rename from pyCAOM2/caom2/test/test_observation.py rename to caom2tools/caom2/caom2/test/test_observation.py diff --git a/pyCAOM2/caom2/test/test_observation_reader_writer.py b/caom2tools/caom2/caom2/test/test_observation_reader_writer.py similarity index 100% rename from pyCAOM2/caom2/test/test_observation_reader_writer.py rename to caom2tools/caom2/caom2/test/test_observation_reader_writer.py diff --git a/pyCAOM2/caom2/test/test_observation_uri.py b/caom2tools/caom2/caom2/test/test_observation_uri.py similarity index 100% rename from pyCAOM2/caom2/test/test_observation_uri.py rename to caom2tools/caom2/caom2/test/test_observation_uri.py diff --git a/pyCAOM2/caom2/test/test_part.py b/caom2tools/caom2/caom2/test/test_part.py similarity index 100% rename from pyCAOM2/caom2/test/test_part.py rename to caom2tools/caom2/caom2/test/test_part.py diff --git a/pyCAOM2/caom2/test/test_plane.py b/caom2tools/caom2/caom2/test/test_plane.py similarity index 100% rename from pyCAOM2/caom2/test/test_plane.py rename to caom2tools/caom2/caom2/test/test_plane.py diff --git a/pyCAOM2/caom2/test/test_plane_uri.py b/caom2tools/caom2/caom2/test/test_plane_uri.py similarity index 100% rename from pyCAOM2/caom2/test/test_plane_uri.py rename to caom2tools/caom2/caom2/test/test_plane_uri.py diff --git a/pyCAOM2/caom2/test/test_point.py b/caom2tools/caom2/caom2/test/test_point.py similarity index 100% rename from pyCAOM2/caom2/test/test_point.py rename to caom2tools/caom2/caom2/test/test_point.py diff --git a/pyCAOM2/caom2/test/test_polarization.py b/caom2tools/caom2/caom2/test/test_polarization.py similarity index 100% rename from pyCAOM2/caom2/test/test_polarization.py rename to caom2tools/caom2/caom2/test/test_polarization.py diff --git a/pyCAOM2/caom2/test/test_polarization_wcs.py b/caom2tools/caom2/caom2/test/test_polarization_wcs.py similarity index 100% rename from pyCAOM2/caom2/test/test_polarization_wcs.py rename to caom2tools/caom2/caom2/test/test_polarization_wcs.py diff --git a/pyCAOM2/caom2/test/test_position.py b/caom2tools/caom2/caom2/test/test_position.py similarity index 100% rename from pyCAOM2/caom2/test/test_position.py rename to caom2tools/caom2/caom2/test/test_position.py diff --git a/pyCAOM2/caom2/test/test_proposal.py b/caom2tools/caom2/caom2/test/test_proposal.py similarity index 100% rename from pyCAOM2/caom2/test/test_proposal.py rename to caom2tools/caom2/caom2/test/test_proposal.py diff --git a/pyCAOM2/caom2/test/test_provenance.py b/caom2tools/caom2/caom2/test/test_provenance.py similarity index 100% rename from pyCAOM2/caom2/test/test_provenance.py rename to caom2tools/caom2/caom2/test/test_provenance.py diff --git a/pyCAOM2/caom2/test/test_ref_coord.py b/caom2tools/caom2/caom2/test/test_ref_coord.py similarity index 100% rename from pyCAOM2/caom2/test/test_ref_coord.py rename to caom2tools/caom2/caom2/test/test_ref_coord.py diff --git a/pyCAOM2/caom2/test/test_requirements.py b/caom2tools/caom2/caom2/test/test_requirements.py similarity index 100% rename from pyCAOM2/caom2/test/test_requirements.py rename to caom2tools/caom2/caom2/test/test_requirements.py diff --git a/pyCAOM2/caom2/test/test_simple_observation.py b/caom2tools/caom2/caom2/test/test_simple_observation.py similarity index 100% rename from pyCAOM2/caom2/test/test_simple_observation.py rename to caom2tools/caom2/caom2/test/test_simple_observation.py diff --git a/pyCAOM2/caom2/test/test_slice.py b/caom2tools/caom2/caom2/test/test_slice.py similarity index 100% rename from pyCAOM2/caom2/test/test_slice.py rename to caom2tools/caom2/caom2/test/test_slice.py diff --git a/pyCAOM2/caom2/test/test_spatial_wcs.py b/caom2tools/caom2/caom2/test/test_spatial_wcs.py similarity index 100% rename from pyCAOM2/caom2/test/test_spatial_wcs.py rename to caom2tools/caom2/caom2/test/test_spatial_wcs.py diff --git a/pyCAOM2/caom2/test/test_spectral_wcs.py b/caom2tools/caom2/caom2/test/test_spectral_wcs.py similarity index 100% rename from pyCAOM2/caom2/test/test_spectral_wcs.py rename to caom2tools/caom2/caom2/test/test_spectral_wcs.py diff --git a/pyCAOM2/caom2/test/test_target.py b/caom2tools/caom2/caom2/test/test_target.py similarity index 100% rename from pyCAOM2/caom2/test/test_target.py rename to caom2tools/caom2/caom2/test/test_target.py diff --git a/pyCAOM2/caom2/test/test_target_position.py b/caom2tools/caom2/caom2/test/test_target_position.py similarity index 100% rename from pyCAOM2/caom2/test/test_target_position.py rename to caom2tools/caom2/caom2/test/test_target_position.py diff --git a/pyCAOM2/caom2/test/test_telescope.py b/caom2tools/caom2/caom2/test/test_telescope.py similarity index 100% rename from pyCAOM2/caom2/test/test_telescope.py rename to caom2tools/caom2/caom2/test/test_telescope.py diff --git a/pyCAOM2/caom2/test/test_temporal_wcs.py b/caom2tools/caom2/caom2/test/test_temporal_wcs.py similarity index 100% rename from pyCAOM2/caom2/test/test_temporal_wcs.py rename to caom2tools/caom2/caom2/test/test_temporal_wcs.py diff --git a/pyCAOM2/caom2/test/test_time.py b/caom2tools/caom2/caom2/test/test_time.py similarity index 100% rename from pyCAOM2/caom2/test/test_time.py rename to caom2tools/caom2/caom2/test/test_time.py diff --git a/pyCAOM2/caom2/test/test_value_coord2d.py b/caom2tools/caom2/caom2/test/test_value_coord2d.py similarity index 100% rename from pyCAOM2/caom2/test/test_value_coord2d.py rename to caom2tools/caom2/caom2/test/test_value_coord2d.py diff --git a/pyCAOM2/caom2/types/__init__.py b/caom2tools/caom2/caom2/types/__init__.py similarity index 100% rename from pyCAOM2/caom2/types/__init__.py rename to caom2tools/caom2/caom2/types/__init__.py diff --git a/pyCAOM2/caom2/types/caom2_box.py b/caom2tools/caom2/caom2/types/caom2_box.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_box.py rename to caom2tools/caom2/caom2/types/caom2_box.py diff --git a/pyCAOM2/caom2/types/caom2_circle.py b/caom2tools/caom2/caom2/types/caom2_circle.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_circle.py rename to caom2tools/caom2/caom2/types/caom2_circle.py diff --git a/pyCAOM2/caom2/types/caom2_interval.py b/caom2tools/caom2/caom2/types/caom2_interval.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_interval.py rename to caom2tools/caom2/caom2/types/caom2_interval.py diff --git a/pyCAOM2/caom2/types/caom2_point.py b/caom2tools/caom2/caom2/types/caom2_point.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_point.py rename to caom2tools/caom2/caom2/types/caom2_point.py diff --git a/pyCAOM2/caom2/types/caom2_polygon.py b/caom2tools/caom2/caom2/types/caom2_polygon.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_polygon.py rename to caom2tools/caom2/caom2/types/caom2_polygon.py diff --git a/pyCAOM2/caom2/types/caom2_vertex.py b/caom2tools/caom2/caom2/types/caom2_vertex.py similarity index 100% rename from pyCAOM2/caom2/types/caom2_vertex.py rename to caom2tools/caom2/caom2/types/caom2_vertex.py diff --git a/pyCAOM2/caom2/util/__init__.py b/caom2tools/caom2/caom2/util/__init__.py similarity index 100% rename from pyCAOM2/caom2/util/__init__.py rename to caom2tools/caom2/caom2/util/__init__.py diff --git a/pyCAOM2/caom2/util/caom2_util.py b/caom2tools/caom2/caom2/util/caom2_util.py similarity index 100% rename from pyCAOM2/caom2/util/caom2_util.py rename to caom2tools/caom2/caom2/util/caom2_util.py diff --git a/pyCAOM2/caom2/util/caom2_validator.py b/caom2tools/caom2/caom2/util/caom2_validator.py similarity index 100% rename from pyCAOM2/caom2/util/caom2_validator.py rename to caom2tools/caom2/caom2/util/caom2_validator.py diff --git a/pyCAOM2/caom2/wcs/__init__.py b/caom2tools/caom2/caom2/wcs/__init__.py similarity index 100% rename from pyCAOM2/caom2/wcs/__init__.py rename to caom2tools/caom2/caom2/wcs/__init__.py diff --git a/pyCAOM2/caom2/wcs/caom2_axis.py b/caom2tools/caom2/caom2/wcs/caom2_axis.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_axis.py rename to caom2tools/caom2/caom2/wcs/caom2_axis.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_axis1d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_axis1d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_axis1d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_axis1d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_axis2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_axis2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_axis2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_axis2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_bounds1d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_bounds1d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_bounds1d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_bounds1d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_bounds2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_bounds2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_bounds2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_bounds2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_circle2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_circle2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_circle2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_circle2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_error.py b/caom2tools/caom2/caom2/wcs/caom2_coord_error.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_error.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_error.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_function1d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_function1d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_function1d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_function1d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_function2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_function2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_function2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_function2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_polygon2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_polygon2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_polygon2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_polygon2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_range1d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_range1d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_range1d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_range1d.py diff --git a/pyCAOM2/caom2/wcs/caom2_coord_range2d.py b/caom2tools/caom2/caom2/wcs/caom2_coord_range2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_coord_range2d.py rename to caom2tools/caom2/caom2/wcs/caom2_coord_range2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_dimension2d.py b/caom2tools/caom2/caom2/wcs/caom2_dimension2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_dimension2d.py rename to caom2tools/caom2/caom2/wcs/caom2_dimension2d.py diff --git a/pyCAOM2/caom2/wcs/caom2_observable_axis.py b/caom2tools/caom2/caom2/wcs/caom2_observable_axis.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_observable_axis.py rename to caom2tools/caom2/caom2/wcs/caom2_observable_axis.py diff --git a/pyCAOM2/caom2/wcs/caom2_polarization_wcs.py b/caom2tools/caom2/caom2/wcs/caom2_polarization_wcs.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_polarization_wcs.py rename to caom2tools/caom2/caom2/wcs/caom2_polarization_wcs.py diff --git a/pyCAOM2/caom2/wcs/caom2_ref_coord.py b/caom2tools/caom2/caom2/wcs/caom2_ref_coord.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_ref_coord.py rename to caom2tools/caom2/caom2/wcs/caom2_ref_coord.py diff --git a/pyCAOM2/caom2/wcs/caom2_slice.py b/caom2tools/caom2/caom2/wcs/caom2_slice.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_slice.py rename to caom2tools/caom2/caom2/wcs/caom2_slice.py diff --git a/pyCAOM2/caom2/wcs/caom2_spatial_wcs.py b/caom2tools/caom2/caom2/wcs/caom2_spatial_wcs.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_spatial_wcs.py rename to caom2tools/caom2/caom2/wcs/caom2_spatial_wcs.py diff --git a/pyCAOM2/caom2/wcs/caom2_spectral_wcs.py b/caom2tools/caom2/caom2/wcs/caom2_spectral_wcs.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_spectral_wcs.py rename to caom2tools/caom2/caom2/wcs/caom2_spectral_wcs.py diff --git a/pyCAOM2/caom2/wcs/caom2_temporal_wcs.py b/caom2tools/caom2/caom2/wcs/caom2_temporal_wcs.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_temporal_wcs.py rename to caom2tools/caom2/caom2/wcs/caom2_temporal_wcs.py diff --git a/pyCAOM2/caom2/wcs/caom2_value_coord2d.py b/caom2tools/caom2/caom2/wcs/caom2_value_coord2d.py similarity index 100% rename from pyCAOM2/caom2/wcs/caom2_value_coord2d.py rename to caom2tools/caom2/caom2/wcs/caom2_value_coord2d.py diff --git a/pyCAOM2/caom2/xml/__init__.py b/caom2tools/caom2/caom2/xml/__init__.py similarity index 100% rename from pyCAOM2/caom2/xml/__init__.py rename to caom2tools/caom2/caom2/xml/__init__.py diff --git a/pyCAOM2/caom2/xml/caom2_observation_reader.py b/caom2tools/caom2/caom2/xml/caom2_observation_reader.py similarity index 100% rename from pyCAOM2/caom2/xml/caom2_observation_reader.py rename to caom2tools/caom2/caom2/xml/caom2_observation_reader.py diff --git a/pyCAOM2/caom2/xml/caom2_observation_writer.py b/caom2tools/caom2/caom2/xml/caom2_observation_writer.py similarity index 100% rename from pyCAOM2/caom2/xml/caom2_observation_writer.py rename to caom2tools/caom2/caom2/xml/caom2_observation_writer.py diff --git a/pyCAOM2/caom2/xml/caom2_xml_constants.py b/caom2tools/caom2/caom2/xml/caom2_xml_constants.py similarity index 100% rename from pyCAOM2/caom2/xml/caom2_xml_constants.py rename to caom2tools/caom2/caom2/xml/caom2_xml_constants.py diff --git a/pyCAOM2/requirements.txt b/caom2tools/caom2/requirements.txt similarity index 100% rename from pyCAOM2/requirements.txt rename to caom2tools/caom2/requirements.txt diff --git a/pyCAOM2/setup.cfg b/caom2tools/caom2/setup.cfg similarity index 100% rename from pyCAOM2/setup.cfg rename to caom2tools/caom2/setup.cfg diff --git a/pyCAOM2/setup.py b/caom2tools/caom2/setup.py similarity index 100% rename from pyCAOM2/setup.py rename to caom2tools/caom2/setup.py diff --git a/pyCAOM2/test/test_roundtrip.py b/caom2tools/caom2/tests/test_roundtrip.py similarity index 100% rename from pyCAOM2/test/test_roundtrip.py rename to caom2tools/caom2/tests/test_roundtrip.py diff --git a/caom2tools/test/__init__.py b/caom2tools/tests/__init__.py similarity index 100% rename from caom2tools/test/__init__.py rename to caom2tools/tests/__init__.py diff --git a/caom2tools/test/coveragerc b/caom2tools/tests/coveragerc similarity index 100% rename from caom2tools/test/coveragerc rename to caom2tools/tests/coveragerc diff --git a/caom2tools/test/setup_package.py b/caom2tools/tests/setup_package.py similarity index 100% rename from caom2tools/test/setup_package.py rename to caom2tools/tests/setup_package.py From 0429c50a431629593985c267f655701c7f1cc1f2 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 9 Nov 2016 12:40:23 -0800 Subject: [PATCH 04/54] Fixed problem with structure of code --- caom2tools/caom2/{caom2 => }/CAOM-2.0.xsd | 0 caom2tools/caom2/{caom2 => }/CAOM-2.1.xsd | 0 caom2tools/caom2/{caom2 => }/CAOM-2.2.xsd | 0 caom2tools/caom2/{caom2 => }/__init__.py | 0 .../caom2/{caom2 => }/caom2_algorithm.py | 0 .../caom2/{caom2 => }/caom2_artifact.py | 0 caom2tools/caom2/{caom2 => }/caom2_chunk.py | 0 .../caom2_composite_observation.py | 0 .../caom2/{caom2 => }/caom2_data_quality.py | 0 caom2tools/caom2/{caom2 => }/caom2_energy.py | 0 .../{caom2 => }/caom2_energy_transition.py | 0 caom2tools/caom2/{caom2 => }/caom2_entity.py | 0 caom2tools/caom2/{caom2 => }/caom2_enums.py | 0 .../caom2/{caom2 => }/caom2_environment.py | 0 .../caom2/{caom2 => }/caom2_exceptions.py | 0 .../caom2/{caom2 => }/caom2_instrument.py | 0 caom2tools/caom2/{caom2 => }/caom2_metrics.py | 0 caom2tools/caom2/{caom2 => }/caom2_object.py | 0 .../caom2/{caom2 => }/caom2_observation.py | 0 .../{caom2 => }/caom2_observation_uri.py | 0 caom2tools/caom2/{caom2 => }/caom2_part.py | 0 caom2tools/caom2/{caom2 => }/caom2_plane.py | 0 .../caom2/{caom2 => }/caom2_plane_uri.py | 0 .../caom2/{caom2 => }/caom2_polarization.py | 0 .../caom2/{caom2 => }/caom2_position.py | 0 .../caom2/{caom2 => }/caom2_proposal.py | 0 .../caom2/{caom2 => }/caom2_provenance.py | 0 .../caom2/{caom2 => }/caom2_requirements.py | 0 .../{caom2 => }/caom2_simple_observation.py | 0 caom2tools/caom2/{caom2 => }/caom2_target.py | 0 .../{caom2 => }/caom2_target_position.py | 0 .../caom2/{caom2 => }/caom2_telescope.py | 0 caom2tools/caom2/{caom2 => }/caom2_time.py | 0 caom2tools/caom2/{caom2 => }/enum.py | 0 .../data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../test/data/CompleteCompositeCircle.xml | 0 .../CompleteCompositePolygon-CAOM-2.1.xml | 0 .../CompleteCompositePolygon-CAOM-2.2.xml | 0 .../test/data/CompleteCompositePolygon.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../test/data/CompleteSimpleCircle.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../test/data/CompleteSimplePolygon.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../test/data/MinimalCompositeCircle.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../test/data/MinimalCompositePolygon.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../test/data/MinimalSimpleCircle.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../test/data/MinimalSimplePolygon.xml | 0 caom2tools/caom2/tests/test/setup_package.py | 3 + .../{caom2 => tests}/test/test_algorithm.py | 0 .../{caom2 => tests}/test/test_artifact.py | 0 .../caom2/{caom2 => tests}/test/test_axis.py | 0 .../test/test_caom2_entity.py | 0 .../{caom2 => tests}/test/test_caom2_enums.py | 0 .../{caom2 => tests}/test/test_caom2_util.py | 0 .../test/test_caom2instances.py | 0 .../caom2/{caom2 => tests}/test/test_chunk.py | 0 .../test/test_composite_observation.py | 0 .../{caom2 => tests}/test/test_coord2d.py | 0 .../test/test_coord_axis1d.py | 0 .../test/test_coord_axis2d.py | 0 .../test/test_coord_bounds1d.py | 0 .../test/test_coord_bounds2d.py | 0 .../test/test_coord_circle2d.py | 0 .../{caom2 => tests}/test/test_coord_error.py | 0 .../test/test_coord_function1d.py | 0 .../test/test_coord_function2d.py | 0 .../test/test_coord_polygon2d.py | 0 .../test/test_coord_range1d.py | 0 .../test/test_coord_range2d.py | 0 .../test/test_data_quality.py | 0 .../{caom2 => tests}/test/test_dimension2d.py | 0 .../{caom2 => tests}/test/test_energy.py | 0 .../test/test_energy_transition.py | 0 .../{caom2 => tests}/test/test_environment.py | 0 .../{caom2 => tests}/test/test_instrument.py | 0 .../{caom2 => tests}/test/test_metrics.py | 0 .../test/test_observable_axis.py | 0 .../{caom2 => tests}/test/test_observation.py | 0 .../test/test_observation_reader_writer.py | 0 .../test/test_observation_uri.py | 0 .../caom2/{caom2 => tests}/test/test_part.py | 0 .../caom2/{caom2 => tests}/test/test_plane.py | 0 .../{caom2 => tests}/test/test_plane_uri.py | 0 .../caom2/{caom2 => tests}/test/test_point.py | 0 .../test/test_polarization.py | 0 .../test/test_polarization_wcs.py | 0 .../{caom2 => tests}/test/test_position.py | 0 .../{caom2 => tests}/test/test_proposal.py | 0 .../{caom2 => tests}/test/test_provenance.py | 0 .../{caom2 => tests}/test/test_ref_coord.py | 0 .../test/test_requirements.py | 0 .../caom2/tests/{ => test}/test_roundtrip.py | 0 .../test/test_simple_observation.py | 0 .../caom2/{caom2 => tests}/test/test_slice.py | 0 .../{caom2 => tests}/test/test_spatial_wcs.py | 0 .../test/test_spectral_wcs.py | 0 .../{caom2 => tests}/test/test_target.py | 0 .../test/test_target_position.py | 0 .../{caom2 => tests}/test/test_telescope.py | 0 .../test/test_temporal_wcs.py | 0 .../caom2/{caom2 => tests}/test/test_time.py | 0 caom2tools/caom2/tests/test/test_util.py | 167 ++++++++++++++++++ .../test/test_value_coord2d.py | 0 .../caom2/{caom2 => }/types/__init__.py | 0 .../caom2/{caom2 => }/types/caom2_box.py | 0 .../caom2/{caom2 => }/types/caom2_circle.py | 0 .../caom2/{caom2 => }/types/caom2_interval.py | 0 .../caom2/{caom2 => }/types/caom2_point.py | 0 .../caom2/{caom2 => }/types/caom2_polygon.py | 0 .../caom2/{caom2 => }/types/caom2_vertex.py | 0 caom2tools/caom2/{caom2 => }/util/__init__.py | 0 .../caom2/{caom2 => }/util/caom2_util.py | 0 .../caom2/{caom2 => }/util/caom2_validator.py | 0 caom2tools/caom2/{caom2 => }/wcs/__init__.py | 0 .../caom2/{caom2 => }/wcs/caom2_axis.py | 0 .../caom2/{caom2 => }/wcs/caom2_coord2d.py | 0 .../{caom2 => }/wcs/caom2_coord_axis1d.py | 0 .../{caom2 => }/wcs/caom2_coord_axis2d.py | 0 .../{caom2 => }/wcs/caom2_coord_bounds1d.py | 0 .../{caom2 => }/wcs/caom2_coord_bounds2d.py | 0 .../{caom2 => }/wcs/caom2_coord_circle2d.py | 0 .../{caom2 => }/wcs/caom2_coord_error.py | 0 .../{caom2 => }/wcs/caom2_coord_function1d.py | 0 .../{caom2 => }/wcs/caom2_coord_function2d.py | 0 .../{caom2 => }/wcs/caom2_coord_polygon2d.py | 0 .../{caom2 => }/wcs/caom2_coord_range1d.py | 0 .../{caom2 => }/wcs/caom2_coord_range2d.py | 0 .../{caom2 => }/wcs/caom2_dimension2d.py | 0 .../{caom2 => }/wcs/caom2_observable_axis.py | 0 .../{caom2 => }/wcs/caom2_polarization_wcs.py | 0 .../caom2/{caom2 => }/wcs/caom2_ref_coord.py | 0 .../caom2/{caom2 => }/wcs/caom2_slice.py | 0 .../{caom2 => }/wcs/caom2_spatial_wcs.py | 0 .../{caom2 => }/wcs/caom2_spectral_wcs.py | 0 .../{caom2 => }/wcs/caom2_temporal_wcs.py | 0 .../{caom2 => }/wcs/caom2_value_coord2d.py | 0 caom2tools/caom2/{caom2 => }/xml/__init__.py | 0 .../xml/caom2_observation_reader.py | 0 .../xml/caom2_observation_writer.py | 0 .../{caom2 => }/xml/caom2_xml_constants.py | 0 151 files changed, 170 insertions(+) rename caom2tools/caom2/{caom2 => }/CAOM-2.0.xsd (100%) rename caom2tools/caom2/{caom2 => }/CAOM-2.1.xsd (100%) rename caom2tools/caom2/{caom2 => }/CAOM-2.2.xsd (100%) rename caom2tools/caom2/{caom2 => }/__init__.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_algorithm.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_artifact.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_chunk.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_composite_observation.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_data_quality.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_energy.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_energy_transition.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_entity.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_enums.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_environment.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_exceptions.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_instrument.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_metrics.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_object.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_observation.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_observation_uri.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_part.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_plane.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_plane_uri.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_polarization.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_position.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_proposal.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_provenance.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_requirements.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_simple_observation.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_target.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_target_position.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_telescope.py (100%) rename caom2tools/caom2/{caom2 => }/caom2_time.py (100%) rename caom2tools/caom2/{caom2 => }/enum.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositeCircle.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteCompositePolygon.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimpleCircle.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/CompleteSimplePolygon.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositeCircle.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalCompositePolygon.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimpleCircle.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{caom2 => tests}/test/data/MinimalSimplePolygon.xml (100%) create mode 100644 caom2tools/caom2/tests/test/setup_package.py rename caom2tools/caom2/{caom2 => tests}/test/test_algorithm.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_artifact.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_axis.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_caom2_entity.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_caom2_enums.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_caom2_util.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_caom2instances.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_chunk.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_composite_observation.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_axis1d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_axis2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_bounds1d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_bounds2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_circle2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_error.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_function1d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_function2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_polygon2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_range1d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_coord_range2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_data_quality.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_dimension2d.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_energy.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_energy_transition.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_environment.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_instrument.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_metrics.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_observable_axis.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_observation.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_observation_reader_writer.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_observation_uri.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_part.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_plane.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_plane_uri.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_point.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_polarization.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_polarization_wcs.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_position.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_proposal.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_provenance.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_ref_coord.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_requirements.py (100%) rename caom2tools/caom2/tests/{ => test}/test_roundtrip.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_simple_observation.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_slice.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_spatial_wcs.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_spectral_wcs.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_target.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_target_position.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_telescope.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_temporal_wcs.py (100%) rename caom2tools/caom2/{caom2 => tests}/test/test_time.py (100%) create mode 100644 caom2tools/caom2/tests/test/test_util.py rename caom2tools/caom2/{caom2 => tests}/test/test_value_coord2d.py (100%) rename caom2tools/caom2/{caom2 => }/types/__init__.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_box.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_circle.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_interval.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_point.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_polygon.py (100%) rename caom2tools/caom2/{caom2 => }/types/caom2_vertex.py (100%) rename caom2tools/caom2/{caom2 => }/util/__init__.py (100%) rename caom2tools/caom2/{caom2 => }/util/caom2_util.py (100%) rename caom2tools/caom2/{caom2 => }/util/caom2_validator.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/__init__.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_axis.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_axis1d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_axis2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_bounds1d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_bounds2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_circle2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_error.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_function1d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_function2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_polygon2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_range1d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_coord_range2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_dimension2d.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_observable_axis.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_polarization_wcs.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_ref_coord.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_slice.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_spatial_wcs.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_spectral_wcs.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_temporal_wcs.py (100%) rename caom2tools/caom2/{caom2 => }/wcs/caom2_value_coord2d.py (100%) rename caom2tools/caom2/{caom2 => }/xml/__init__.py (100%) rename caom2tools/caom2/{caom2 => }/xml/caom2_observation_reader.py (100%) rename caom2tools/caom2/{caom2 => }/xml/caom2_observation_writer.py (100%) rename caom2tools/caom2/{caom2 => }/xml/caom2_xml_constants.py (100%) diff --git a/caom2tools/caom2/caom2/CAOM-2.0.xsd b/caom2tools/caom2/CAOM-2.0.xsd similarity index 100% rename from caom2tools/caom2/caom2/CAOM-2.0.xsd rename to caom2tools/caom2/CAOM-2.0.xsd diff --git a/caom2tools/caom2/caom2/CAOM-2.1.xsd b/caom2tools/caom2/CAOM-2.1.xsd similarity index 100% rename from caom2tools/caom2/caom2/CAOM-2.1.xsd rename to caom2tools/caom2/CAOM-2.1.xsd diff --git a/caom2tools/caom2/caom2/CAOM-2.2.xsd b/caom2tools/caom2/CAOM-2.2.xsd similarity index 100% rename from caom2tools/caom2/caom2/CAOM-2.2.xsd rename to caom2tools/caom2/CAOM-2.2.xsd diff --git a/caom2tools/caom2/caom2/__init__.py b/caom2tools/caom2/__init__.py similarity index 100% rename from caom2tools/caom2/caom2/__init__.py rename to caom2tools/caom2/__init__.py diff --git a/caom2tools/caom2/caom2/caom2_algorithm.py b/caom2tools/caom2/caom2_algorithm.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_algorithm.py rename to caom2tools/caom2/caom2_algorithm.py diff --git a/caom2tools/caom2/caom2/caom2_artifact.py b/caom2tools/caom2/caom2_artifact.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_artifact.py rename to caom2tools/caom2/caom2_artifact.py diff --git a/caom2tools/caom2/caom2/caom2_chunk.py b/caom2tools/caom2/caom2_chunk.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_chunk.py rename to caom2tools/caom2/caom2_chunk.py diff --git a/caom2tools/caom2/caom2/caom2_composite_observation.py b/caom2tools/caom2/caom2_composite_observation.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_composite_observation.py rename to caom2tools/caom2/caom2_composite_observation.py diff --git a/caom2tools/caom2/caom2/caom2_data_quality.py b/caom2tools/caom2/caom2_data_quality.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_data_quality.py rename to caom2tools/caom2/caom2_data_quality.py diff --git a/caom2tools/caom2/caom2/caom2_energy.py b/caom2tools/caom2/caom2_energy.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_energy.py rename to caom2tools/caom2/caom2_energy.py diff --git a/caom2tools/caom2/caom2/caom2_energy_transition.py b/caom2tools/caom2/caom2_energy_transition.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_energy_transition.py rename to caom2tools/caom2/caom2_energy_transition.py diff --git a/caom2tools/caom2/caom2/caom2_entity.py b/caom2tools/caom2/caom2_entity.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_entity.py rename to caom2tools/caom2/caom2_entity.py diff --git a/caom2tools/caom2/caom2/caom2_enums.py b/caom2tools/caom2/caom2_enums.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_enums.py rename to caom2tools/caom2/caom2_enums.py diff --git a/caom2tools/caom2/caom2/caom2_environment.py b/caom2tools/caom2/caom2_environment.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_environment.py rename to caom2tools/caom2/caom2_environment.py diff --git a/caom2tools/caom2/caom2/caom2_exceptions.py b/caom2tools/caom2/caom2_exceptions.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_exceptions.py rename to caom2tools/caom2/caom2_exceptions.py diff --git a/caom2tools/caom2/caom2/caom2_instrument.py b/caom2tools/caom2/caom2_instrument.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_instrument.py rename to caom2tools/caom2/caom2_instrument.py diff --git a/caom2tools/caom2/caom2/caom2_metrics.py b/caom2tools/caom2/caom2_metrics.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_metrics.py rename to caom2tools/caom2/caom2_metrics.py diff --git a/caom2tools/caom2/caom2/caom2_object.py b/caom2tools/caom2/caom2_object.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_object.py rename to caom2tools/caom2/caom2_object.py diff --git a/caom2tools/caom2/caom2/caom2_observation.py b/caom2tools/caom2/caom2_observation.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_observation.py rename to caom2tools/caom2/caom2_observation.py diff --git a/caom2tools/caom2/caom2/caom2_observation_uri.py b/caom2tools/caom2/caom2_observation_uri.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_observation_uri.py rename to caom2tools/caom2/caom2_observation_uri.py diff --git a/caom2tools/caom2/caom2/caom2_part.py b/caom2tools/caom2/caom2_part.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_part.py rename to caom2tools/caom2/caom2_part.py diff --git a/caom2tools/caom2/caom2/caom2_plane.py b/caom2tools/caom2/caom2_plane.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_plane.py rename to caom2tools/caom2/caom2_plane.py diff --git a/caom2tools/caom2/caom2/caom2_plane_uri.py b/caom2tools/caom2/caom2_plane_uri.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_plane_uri.py rename to caom2tools/caom2/caom2_plane_uri.py diff --git a/caom2tools/caom2/caom2/caom2_polarization.py b/caom2tools/caom2/caom2_polarization.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_polarization.py rename to caom2tools/caom2/caom2_polarization.py diff --git a/caom2tools/caom2/caom2/caom2_position.py b/caom2tools/caom2/caom2_position.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_position.py rename to caom2tools/caom2/caom2_position.py diff --git a/caom2tools/caom2/caom2/caom2_proposal.py b/caom2tools/caom2/caom2_proposal.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_proposal.py rename to caom2tools/caom2/caom2_proposal.py diff --git a/caom2tools/caom2/caom2/caom2_provenance.py b/caom2tools/caom2/caom2_provenance.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_provenance.py rename to caom2tools/caom2/caom2_provenance.py diff --git a/caom2tools/caom2/caom2/caom2_requirements.py b/caom2tools/caom2/caom2_requirements.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_requirements.py rename to caom2tools/caom2/caom2_requirements.py diff --git a/caom2tools/caom2/caom2/caom2_simple_observation.py b/caom2tools/caom2/caom2_simple_observation.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_simple_observation.py rename to caom2tools/caom2/caom2_simple_observation.py diff --git a/caom2tools/caom2/caom2/caom2_target.py b/caom2tools/caom2/caom2_target.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_target.py rename to caom2tools/caom2/caom2_target.py diff --git a/caom2tools/caom2/caom2/caom2_target_position.py b/caom2tools/caom2/caom2_target_position.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_target_position.py rename to caom2tools/caom2/caom2_target_position.py diff --git a/caom2tools/caom2/caom2/caom2_telescope.py b/caom2tools/caom2/caom2_telescope.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_telescope.py rename to caom2tools/caom2/caom2_telescope.py diff --git a/caom2tools/caom2/caom2/caom2_time.py b/caom2tools/caom2/caom2_time.py similarity index 100% rename from caom2tools/caom2/caom2/caom2_time.py rename to caom2tools/caom2/caom2_time.py diff --git a/caom2tools/caom2/caom2/enum.py b/caom2tools/caom2/enum.py similarity index 100% rename from caom2tools/caom2/caom2/enum.py rename to caom2tools/caom2/enum.py diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositeCircle.xml b/caom2tools/caom2/tests/test/data/CompleteCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositeCircle.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositeCircle.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteCompositePolygon.xml b/caom2tools/caom2/tests/test/data/CompleteCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteCompositePolygon.xml rename to caom2tools/caom2/tests/test/data/CompleteCompositePolygon.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimpleCircle.xml b/caom2tools/caom2/tests/test/data/CompleteSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimpleCircle.xml rename to caom2tools/caom2/tests/test/data/CompleteSimpleCircle.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/CompleteSimplePolygon.xml b/caom2tools/caom2/tests/test/data/CompleteSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/CompleteSimplePolygon.xml rename to caom2tools/caom2/tests/test/data/CompleteSimplePolygon.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositeCircle.xml b/caom2tools/caom2/tests/test/data/MinimalCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositeCircle.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositeCircle.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalCompositePolygon.xml b/caom2tools/caom2/tests/test/data/MinimalCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalCompositePolygon.xml rename to caom2tools/caom2/tests/test/data/MinimalCompositePolygon.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimpleCircle.xml b/caom2tools/caom2/tests/test/data/MinimalSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimpleCircle.xml rename to caom2tools/caom2/tests/test/data/MinimalSimpleCircle.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/caom2/test/data/MinimalSimplePolygon.xml b/caom2tools/caom2/tests/test/data/MinimalSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/caom2/test/data/MinimalSimplePolygon.xml rename to caom2tools/caom2/tests/test/data/MinimalSimplePolygon.xml diff --git a/caom2tools/caom2/tests/test/setup_package.py b/caom2tools/caom2/tests/test/setup_package.py new file mode 100644 index 00000000..3cef2cb5 --- /dev/null +++ b/caom2tools/caom2/tests/test/setup_package.py @@ -0,0 +1,3 @@ +def get_package_data(): + return { + 'caom2tools.caom2.tests': ['coveragerc']} diff --git a/caom2tools/caom2/caom2/test/test_algorithm.py b/caom2tools/caom2/tests/test/test_algorithm.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_algorithm.py rename to caom2tools/caom2/tests/test/test_algorithm.py diff --git a/caom2tools/caom2/caom2/test/test_artifact.py b/caom2tools/caom2/tests/test/test_artifact.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_artifact.py rename to caom2tools/caom2/tests/test/test_artifact.py diff --git a/caom2tools/caom2/caom2/test/test_axis.py b/caom2tools/caom2/tests/test/test_axis.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_axis.py rename to caom2tools/caom2/tests/test/test_axis.py diff --git a/caom2tools/caom2/caom2/test/test_caom2_entity.py b/caom2tools/caom2/tests/test/test_caom2_entity.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_caom2_entity.py rename to caom2tools/caom2/tests/test/test_caom2_entity.py diff --git a/caom2tools/caom2/caom2/test/test_caom2_enums.py b/caom2tools/caom2/tests/test/test_caom2_enums.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_caom2_enums.py rename to caom2tools/caom2/tests/test/test_caom2_enums.py diff --git a/caom2tools/caom2/caom2/test/test_caom2_util.py b/caom2tools/caom2/tests/test/test_caom2_util.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_caom2_util.py rename to caom2tools/caom2/tests/test/test_caom2_util.py diff --git a/caom2tools/caom2/caom2/test/test_caom2instances.py b/caom2tools/caom2/tests/test/test_caom2instances.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_caom2instances.py rename to caom2tools/caom2/tests/test/test_caom2instances.py diff --git a/caom2tools/caom2/caom2/test/test_chunk.py b/caom2tools/caom2/tests/test/test_chunk.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_chunk.py rename to caom2tools/caom2/tests/test/test_chunk.py diff --git a/caom2tools/caom2/caom2/test/test_composite_observation.py b/caom2tools/caom2/tests/test/test_composite_observation.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_composite_observation.py rename to caom2tools/caom2/tests/test/test_composite_observation.py diff --git a/caom2tools/caom2/caom2/test/test_coord2d.py b/caom2tools/caom2/tests/test/test_coord2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord2d.py rename to caom2tools/caom2/tests/test/test_coord2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_axis1d.py b/caom2tools/caom2/tests/test/test_coord_axis1d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_axis1d.py rename to caom2tools/caom2/tests/test/test_coord_axis1d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_axis2d.py b/caom2tools/caom2/tests/test/test_coord_axis2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_axis2d.py rename to caom2tools/caom2/tests/test/test_coord_axis2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_bounds1d.py b/caom2tools/caom2/tests/test/test_coord_bounds1d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_bounds1d.py rename to caom2tools/caom2/tests/test/test_coord_bounds1d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_bounds2d.py b/caom2tools/caom2/tests/test/test_coord_bounds2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_bounds2d.py rename to caom2tools/caom2/tests/test/test_coord_bounds2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_circle2d.py b/caom2tools/caom2/tests/test/test_coord_circle2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_circle2d.py rename to caom2tools/caom2/tests/test/test_coord_circle2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_error.py b/caom2tools/caom2/tests/test/test_coord_error.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_error.py rename to caom2tools/caom2/tests/test/test_coord_error.py diff --git a/caom2tools/caom2/caom2/test/test_coord_function1d.py b/caom2tools/caom2/tests/test/test_coord_function1d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_function1d.py rename to caom2tools/caom2/tests/test/test_coord_function1d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_function2d.py b/caom2tools/caom2/tests/test/test_coord_function2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_function2d.py rename to caom2tools/caom2/tests/test/test_coord_function2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_polygon2d.py b/caom2tools/caom2/tests/test/test_coord_polygon2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_polygon2d.py rename to caom2tools/caom2/tests/test/test_coord_polygon2d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_range1d.py b/caom2tools/caom2/tests/test/test_coord_range1d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_range1d.py rename to caom2tools/caom2/tests/test/test_coord_range1d.py diff --git a/caom2tools/caom2/caom2/test/test_coord_range2d.py b/caom2tools/caom2/tests/test/test_coord_range2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_coord_range2d.py rename to caom2tools/caom2/tests/test/test_coord_range2d.py diff --git a/caom2tools/caom2/caom2/test/test_data_quality.py b/caom2tools/caom2/tests/test/test_data_quality.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_data_quality.py rename to caom2tools/caom2/tests/test/test_data_quality.py diff --git a/caom2tools/caom2/caom2/test/test_dimension2d.py b/caom2tools/caom2/tests/test/test_dimension2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_dimension2d.py rename to caom2tools/caom2/tests/test/test_dimension2d.py diff --git a/caom2tools/caom2/caom2/test/test_energy.py b/caom2tools/caom2/tests/test/test_energy.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_energy.py rename to caom2tools/caom2/tests/test/test_energy.py diff --git a/caom2tools/caom2/caom2/test/test_energy_transition.py b/caom2tools/caom2/tests/test/test_energy_transition.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_energy_transition.py rename to caom2tools/caom2/tests/test/test_energy_transition.py diff --git a/caom2tools/caom2/caom2/test/test_environment.py b/caom2tools/caom2/tests/test/test_environment.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_environment.py rename to caom2tools/caom2/tests/test/test_environment.py diff --git a/caom2tools/caom2/caom2/test/test_instrument.py b/caom2tools/caom2/tests/test/test_instrument.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_instrument.py rename to caom2tools/caom2/tests/test/test_instrument.py diff --git a/caom2tools/caom2/caom2/test/test_metrics.py b/caom2tools/caom2/tests/test/test_metrics.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_metrics.py rename to caom2tools/caom2/tests/test/test_metrics.py diff --git a/caom2tools/caom2/caom2/test/test_observable_axis.py b/caom2tools/caom2/tests/test/test_observable_axis.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_observable_axis.py rename to caom2tools/caom2/tests/test/test_observable_axis.py diff --git a/caom2tools/caom2/caom2/test/test_observation.py b/caom2tools/caom2/tests/test/test_observation.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_observation.py rename to caom2tools/caom2/tests/test/test_observation.py diff --git a/caom2tools/caom2/caom2/test/test_observation_reader_writer.py b/caom2tools/caom2/tests/test/test_observation_reader_writer.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_observation_reader_writer.py rename to caom2tools/caom2/tests/test/test_observation_reader_writer.py diff --git a/caom2tools/caom2/caom2/test/test_observation_uri.py b/caom2tools/caom2/tests/test/test_observation_uri.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_observation_uri.py rename to caom2tools/caom2/tests/test/test_observation_uri.py diff --git a/caom2tools/caom2/caom2/test/test_part.py b/caom2tools/caom2/tests/test/test_part.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_part.py rename to caom2tools/caom2/tests/test/test_part.py diff --git a/caom2tools/caom2/caom2/test/test_plane.py b/caom2tools/caom2/tests/test/test_plane.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_plane.py rename to caom2tools/caom2/tests/test/test_plane.py diff --git a/caom2tools/caom2/caom2/test/test_plane_uri.py b/caom2tools/caom2/tests/test/test_plane_uri.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_plane_uri.py rename to caom2tools/caom2/tests/test/test_plane_uri.py diff --git a/caom2tools/caom2/caom2/test/test_point.py b/caom2tools/caom2/tests/test/test_point.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_point.py rename to caom2tools/caom2/tests/test/test_point.py diff --git a/caom2tools/caom2/caom2/test/test_polarization.py b/caom2tools/caom2/tests/test/test_polarization.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_polarization.py rename to caom2tools/caom2/tests/test/test_polarization.py diff --git a/caom2tools/caom2/caom2/test/test_polarization_wcs.py b/caom2tools/caom2/tests/test/test_polarization_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_polarization_wcs.py rename to caom2tools/caom2/tests/test/test_polarization_wcs.py diff --git a/caom2tools/caom2/caom2/test/test_position.py b/caom2tools/caom2/tests/test/test_position.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_position.py rename to caom2tools/caom2/tests/test/test_position.py diff --git a/caom2tools/caom2/caom2/test/test_proposal.py b/caom2tools/caom2/tests/test/test_proposal.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_proposal.py rename to caom2tools/caom2/tests/test/test_proposal.py diff --git a/caom2tools/caom2/caom2/test/test_provenance.py b/caom2tools/caom2/tests/test/test_provenance.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_provenance.py rename to caom2tools/caom2/tests/test/test_provenance.py diff --git a/caom2tools/caom2/caom2/test/test_ref_coord.py b/caom2tools/caom2/tests/test/test_ref_coord.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_ref_coord.py rename to caom2tools/caom2/tests/test/test_ref_coord.py diff --git a/caom2tools/caom2/caom2/test/test_requirements.py b/caom2tools/caom2/tests/test/test_requirements.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_requirements.py rename to caom2tools/caom2/tests/test/test_requirements.py diff --git a/caom2tools/caom2/tests/test_roundtrip.py b/caom2tools/caom2/tests/test/test_roundtrip.py similarity index 100% rename from caom2tools/caom2/tests/test_roundtrip.py rename to caom2tools/caom2/tests/test/test_roundtrip.py diff --git a/caom2tools/caom2/caom2/test/test_simple_observation.py b/caom2tools/caom2/tests/test/test_simple_observation.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_simple_observation.py rename to caom2tools/caom2/tests/test/test_simple_observation.py diff --git a/caom2tools/caom2/caom2/test/test_slice.py b/caom2tools/caom2/tests/test/test_slice.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_slice.py rename to caom2tools/caom2/tests/test/test_slice.py diff --git a/caom2tools/caom2/caom2/test/test_spatial_wcs.py b/caom2tools/caom2/tests/test/test_spatial_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_spatial_wcs.py rename to caom2tools/caom2/tests/test/test_spatial_wcs.py diff --git a/caom2tools/caom2/caom2/test/test_spectral_wcs.py b/caom2tools/caom2/tests/test/test_spectral_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_spectral_wcs.py rename to caom2tools/caom2/tests/test/test_spectral_wcs.py diff --git a/caom2tools/caom2/caom2/test/test_target.py b/caom2tools/caom2/tests/test/test_target.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_target.py rename to caom2tools/caom2/tests/test/test_target.py diff --git a/caom2tools/caom2/caom2/test/test_target_position.py b/caom2tools/caom2/tests/test/test_target_position.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_target_position.py rename to caom2tools/caom2/tests/test/test_target_position.py diff --git a/caom2tools/caom2/caom2/test/test_telescope.py b/caom2tools/caom2/tests/test/test_telescope.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_telescope.py rename to caom2tools/caom2/tests/test/test_telescope.py diff --git a/caom2tools/caom2/caom2/test/test_temporal_wcs.py b/caom2tools/caom2/tests/test/test_temporal_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_temporal_wcs.py rename to caom2tools/caom2/tests/test/test_temporal_wcs.py diff --git a/caom2tools/caom2/caom2/test/test_time.py b/caom2tools/caom2/tests/test/test_time.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_time.py rename to caom2tools/caom2/tests/test/test_time.py diff --git a/caom2tools/caom2/tests/test/test_util.py b/caom2tools/caom2/tests/test/test_util.py new file mode 100644 index 00000000..f9f4dad8 --- /dev/null +++ b/caom2tools/caom2/tests/test/test_util.py @@ -0,0 +1,167 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2014. (c) 2014. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# +# *********************************************************************** + +""" Defines TestRoundTrip class """ + +import errno +import filecmp +import glob +import os +import shutil +import unittest + +import caom2.xml.caom2_xml_constants +from caom2.xml.caom2_observation_reader import ObservationReader +from caom2.xml.caom2_observation_writer import ObservationWriter + + +class TestRoundTrip(unittest.TestCase): + + TEST_FILE_SOURCE_DIR = '../caom2/test/data' + XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' + XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' + + def makeTestDir(self): + try: + os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + + def copyFiles(self): + for filename in glob.glob(os.path.join(TestRoundTrip. + TEST_FILE_SOURCE_DIR, '*.xml')): + shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) + + def init(self): + self.makeTestDir() + self.copyFiles() + + def cleanup(self): + shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) + + def get_file_list(self): + return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR)\ + if f.endswith('.xml')] + + def do_test(self, reader, writer, filename): + sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + + '/' + filename) + print "test file: " + sourceFilePath + sourceXMLfp = open(sourceFilePath, 'r') + observation = reader.read(sourceFilePath) + sourceXMLfp.close() + destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename + destXMLfp = open(destFilePath, 'w') + writer.write(observation, destXMLfp) + destXMLfp.close() + self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), + 'files are different, ' + + 'file from Java was: ' + sourceFilePath + ' ' + 'file from Python was: ' + destFilePath) + + # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 + # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 + # objects. The two XML files are then compared to ensure that they + # are the same. The test fails if the files are not the same. The + # test/data/*.xml files can be used in this test. + + def test_round_trip(self): + print "Test Round Trip" + + try: + self.init() + files = self.get_file_list() + self.assertTrue(len(files) > 0, 'No XML files in ' + + TestRoundTrip.XML_FILE_SOURCE_DIR) + try: + os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + reader = ObservationReader(True) + writer20 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM20_NAMESPACE) + writer21 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM21_NAMESPACE) + writer22 = ObservationWriter(True, False, "caom2") + for filename in files: + if filename.endswith("CAOM-2.2.xml"): + self.do_test(reader, writer22, filename) + elif filename.endswith("CAOM-2.1.xml"): + self.do_test(reader, writer21, filename) + else: + self.do_test(reader, writer20, filename) + + #finally: + # self.cleanup() + except Exception as e: + #if e.errno != errno.EEXIST: + raise + +suite = unittest.TestLoader().loadTestsFromTestCase(TestRoundTrip) +unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/caom2tools/caom2/caom2/test/test_value_coord2d.py b/caom2tools/caom2/tests/test/test_value_coord2d.py similarity index 100% rename from caom2tools/caom2/caom2/test/test_value_coord2d.py rename to caom2tools/caom2/tests/test/test_value_coord2d.py diff --git a/caom2tools/caom2/caom2/types/__init__.py b/caom2tools/caom2/types/__init__.py similarity index 100% rename from caom2tools/caom2/caom2/types/__init__.py rename to caom2tools/caom2/types/__init__.py diff --git a/caom2tools/caom2/caom2/types/caom2_box.py b/caom2tools/caom2/types/caom2_box.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_box.py rename to caom2tools/caom2/types/caom2_box.py diff --git a/caom2tools/caom2/caom2/types/caom2_circle.py b/caom2tools/caom2/types/caom2_circle.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_circle.py rename to caom2tools/caom2/types/caom2_circle.py diff --git a/caom2tools/caom2/caom2/types/caom2_interval.py b/caom2tools/caom2/types/caom2_interval.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_interval.py rename to caom2tools/caom2/types/caom2_interval.py diff --git a/caom2tools/caom2/caom2/types/caom2_point.py b/caom2tools/caom2/types/caom2_point.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_point.py rename to caom2tools/caom2/types/caom2_point.py diff --git a/caom2tools/caom2/caom2/types/caom2_polygon.py b/caom2tools/caom2/types/caom2_polygon.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_polygon.py rename to caom2tools/caom2/types/caom2_polygon.py diff --git a/caom2tools/caom2/caom2/types/caom2_vertex.py b/caom2tools/caom2/types/caom2_vertex.py similarity index 100% rename from caom2tools/caom2/caom2/types/caom2_vertex.py rename to caom2tools/caom2/types/caom2_vertex.py diff --git a/caom2tools/caom2/caom2/util/__init__.py b/caom2tools/caom2/util/__init__.py similarity index 100% rename from caom2tools/caom2/caom2/util/__init__.py rename to caom2tools/caom2/util/__init__.py diff --git a/caom2tools/caom2/caom2/util/caom2_util.py b/caom2tools/caom2/util/caom2_util.py similarity index 100% rename from caom2tools/caom2/caom2/util/caom2_util.py rename to caom2tools/caom2/util/caom2_util.py diff --git a/caom2tools/caom2/caom2/util/caom2_validator.py b/caom2tools/caom2/util/caom2_validator.py similarity index 100% rename from caom2tools/caom2/caom2/util/caom2_validator.py rename to caom2tools/caom2/util/caom2_validator.py diff --git a/caom2tools/caom2/caom2/wcs/__init__.py b/caom2tools/caom2/wcs/__init__.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/__init__.py rename to caom2tools/caom2/wcs/__init__.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_axis.py b/caom2tools/caom2/wcs/caom2_axis.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_axis.py rename to caom2tools/caom2/wcs/caom2_axis.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord2d.py b/caom2tools/caom2/wcs/caom2_coord2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord2d.py rename to caom2tools/caom2/wcs/caom2_coord2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_axis1d.py b/caom2tools/caom2/wcs/caom2_coord_axis1d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_axis1d.py rename to caom2tools/caom2/wcs/caom2_coord_axis1d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_axis2d.py b/caom2tools/caom2/wcs/caom2_coord_axis2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_axis2d.py rename to caom2tools/caom2/wcs/caom2_coord_axis2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_bounds1d.py b/caom2tools/caom2/wcs/caom2_coord_bounds1d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_bounds1d.py rename to caom2tools/caom2/wcs/caom2_coord_bounds1d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_bounds2d.py b/caom2tools/caom2/wcs/caom2_coord_bounds2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_bounds2d.py rename to caom2tools/caom2/wcs/caom2_coord_bounds2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_circle2d.py b/caom2tools/caom2/wcs/caom2_coord_circle2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_circle2d.py rename to caom2tools/caom2/wcs/caom2_coord_circle2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_error.py b/caom2tools/caom2/wcs/caom2_coord_error.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_error.py rename to caom2tools/caom2/wcs/caom2_coord_error.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_function1d.py b/caom2tools/caom2/wcs/caom2_coord_function1d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_function1d.py rename to caom2tools/caom2/wcs/caom2_coord_function1d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_function2d.py b/caom2tools/caom2/wcs/caom2_coord_function2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_function2d.py rename to caom2tools/caom2/wcs/caom2_coord_function2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_polygon2d.py b/caom2tools/caom2/wcs/caom2_coord_polygon2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_polygon2d.py rename to caom2tools/caom2/wcs/caom2_coord_polygon2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_range1d.py b/caom2tools/caom2/wcs/caom2_coord_range1d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_range1d.py rename to caom2tools/caom2/wcs/caom2_coord_range1d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_coord_range2d.py b/caom2tools/caom2/wcs/caom2_coord_range2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_coord_range2d.py rename to caom2tools/caom2/wcs/caom2_coord_range2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_dimension2d.py b/caom2tools/caom2/wcs/caom2_dimension2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_dimension2d.py rename to caom2tools/caom2/wcs/caom2_dimension2d.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_observable_axis.py b/caom2tools/caom2/wcs/caom2_observable_axis.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_observable_axis.py rename to caom2tools/caom2/wcs/caom2_observable_axis.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_polarization_wcs.py b/caom2tools/caom2/wcs/caom2_polarization_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_polarization_wcs.py rename to caom2tools/caom2/wcs/caom2_polarization_wcs.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_ref_coord.py b/caom2tools/caom2/wcs/caom2_ref_coord.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_ref_coord.py rename to caom2tools/caom2/wcs/caom2_ref_coord.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_slice.py b/caom2tools/caom2/wcs/caom2_slice.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_slice.py rename to caom2tools/caom2/wcs/caom2_slice.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_spatial_wcs.py b/caom2tools/caom2/wcs/caom2_spatial_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_spatial_wcs.py rename to caom2tools/caom2/wcs/caom2_spatial_wcs.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_spectral_wcs.py b/caom2tools/caom2/wcs/caom2_spectral_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_spectral_wcs.py rename to caom2tools/caom2/wcs/caom2_spectral_wcs.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_temporal_wcs.py b/caom2tools/caom2/wcs/caom2_temporal_wcs.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_temporal_wcs.py rename to caom2tools/caom2/wcs/caom2_temporal_wcs.py diff --git a/caom2tools/caom2/caom2/wcs/caom2_value_coord2d.py b/caom2tools/caom2/wcs/caom2_value_coord2d.py similarity index 100% rename from caom2tools/caom2/caom2/wcs/caom2_value_coord2d.py rename to caom2tools/caom2/wcs/caom2_value_coord2d.py diff --git a/caom2tools/caom2/caom2/xml/__init__.py b/caom2tools/caom2/xml/__init__.py similarity index 100% rename from caom2tools/caom2/caom2/xml/__init__.py rename to caom2tools/caom2/xml/__init__.py diff --git a/caom2tools/caom2/caom2/xml/caom2_observation_reader.py b/caom2tools/caom2/xml/caom2_observation_reader.py similarity index 100% rename from caom2tools/caom2/caom2/xml/caom2_observation_reader.py rename to caom2tools/caom2/xml/caom2_observation_reader.py diff --git a/caom2tools/caom2/caom2/xml/caom2_observation_writer.py b/caom2tools/caom2/xml/caom2_observation_writer.py similarity index 100% rename from caom2tools/caom2/caom2/xml/caom2_observation_writer.py rename to caom2tools/caom2/xml/caom2_observation_writer.py diff --git a/caom2tools/caom2/caom2/xml/caom2_xml_constants.py b/caom2tools/caom2/xml/caom2_xml_constants.py similarity index 100% rename from caom2tools/caom2/caom2/xml/caom2_xml_constants.py rename to caom2tools/caom2/xml/caom2_xml_constants.py From a0c86b0dc13e9eb42c322669d84231199a9a299f Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 14 Nov 2016 12:31:16 -0800 Subject: [PATCH 05/54] s1950: initial pyCAOM2 reorg --- caom2tools/{caom2 => }/COPYING | 0 caom2tools/{caom2 => }/Dependencies.txt | 0 caom2tools/{caom2 => }/MANIFEST.in | 0 caom2tools/{caom2 => }/build.xml | 0 caom2tools/caom2/__init__.py | 124 +- .../caom2/{caom2_artifact.py => artifact.py} | 47 +- caom2tools/caom2/caom2_algorithm.py | 111 - caom2tools/caom2/caom2_chunk.py | 361 --- .../caom2/caom2_composite_observation.py | 139 -- caom2tools/caom2/caom2_data_quality.py | 98 - caom2tools/caom2/caom2_energy.py | 193 -- caom2tools/caom2/caom2_energy_transition.py | 101 - caom2tools/caom2/caom2_enums.py | 148 -- caom2tools/caom2/caom2_environment.py | 199 -- caom2tools/caom2/caom2_exceptions.py | 75 - caom2tools/caom2/caom2_instrument.py | 127 -- caom2tools/caom2/caom2_metrics.py | 172 -- caom2tools/caom2/caom2_object.py | 111 - caom2tools/caom2/caom2_observation.py | 435 ---- caom2tools/caom2/caom2_observation_uri.py | 173 -- caom2tools/caom2/caom2_plane.py | 360 --- caom2tools/caom2/caom2_plane_uri.py | 163 -- caom2tools/caom2/caom2_polarization.py | 109 - caom2tools/caom2/caom2_position.py | 161 -- caom2tools/caom2/caom2_proposal.py | 171 -- caom2tools/caom2/caom2_provenance.py | 191 -- caom2tools/caom2/caom2_requirements.py | 98 - caom2tools/caom2/caom2_simple_observation.py | 159 -- caom2tools/caom2/caom2_target.py | 198 -- caom2tools/caom2/caom2_target_position.py | 124 - caom2tools/caom2/caom2_telescope.py | 201 -- caom2tools/caom2/caom2_time.py | 191 -- .../caom2/{caom2_entity.py => caom_object.py} | 53 +- caom2tools/caom2/chunk.py | 916 ++++++++ .../{types/caom2_point.py => data_type.py} | 47 +- caom2tools/caom2/observation.py | 1312 +++++++++++ caom2tools/caom2/{caom2_part.py => part.py} | 19 +- caom2tools/caom2/plane.py | 1103 +++++++++ ...om2instances.py => caom_test_instances.py} | 102 +- .../data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../data/CompleteCompositeCircle.xml | 0 .../CompleteCompositePolygon-CAOM-2.1.xml | 0 .../CompleteCompositePolygon-CAOM-2.2.xml | 0 .../data/CompleteCompositePolygon.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../{test => }/data/CompleteSimpleCircle.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../{test => }/data/CompleteSimplePolygon.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../data/MinimalCompositeCircle.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../data/MinimalCompositePolygon.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../{test => }/data/MinimalSimpleCircle.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../{test => }/data/MinimalSimplePolygon.xml | 0 .../caom2/tests/{test => }/setup_package.py | 0 caom2tools/caom2/tests/test/test_algorithm.py | 87 - caom2tools/caom2/tests/test/test_axis.py | 93 - .../caom2/tests/test/test_caom2_enums.py | 161 -- .../tests/test/test_composite_observation.py | 278 --- caom2tools/caom2/tests/test/test_coord2d.py | 99 - .../caom2/tests/test/test_coord_axis1d.py | 124 - .../caom2/tests/test/test_coord_axis2d.py | 149 -- .../caom2/tests/test/test_coord_bounds1d.py | 99 - .../caom2/tests/test/test_coord_bounds2d.py | 103 - .../caom2/tests/test/test_coord_circle2d.py | 98 - .../caom2/tests/test/test_coord_error.py | 96 - .../caom2/tests/test/test_coord_function1d.py | 110 - .../caom2/tests/test/test_coord_function2d.py | 117 - .../caom2/tests/test/test_coord_polygon2d.py | 95 - .../caom2/tests/test/test_coord_range1d.py | 99 - .../caom2/tests/test/test_coord_range2d.py | 102 - .../caom2/tests/test/test_data_quality.py | 89 - .../caom2/tests/test/test_dimension2d.py | 95 - caom2tools/caom2/tests/test/test_energy.py | 113 - .../tests/test/test_energy_transition.py | 106 - .../caom2/tests/test/test_environment.py | 110 - .../caom2/tests/test/test_instrument.py | 96 - caom2tools/caom2/tests/test/test_metrics.py | 108 - .../caom2/tests/test/test_observable_axis.py | 99 - .../caom2/tests/test/test_observation.py | 195 -- .../caom2/tests/test/test_observation_uri.py | 108 - caom2tools/caom2/tests/test/test_plane.py | 199 -- caom2tools/caom2/tests/test/test_plane_uri.py | 133 -- .../caom2/tests/test/test_polarization.py | 94 - .../caom2/tests/test/test_polarization_wcs.py | 93 - caom2tools/caom2/tests/test/test_position.py | 101 - caom2tools/caom2/tests/test/test_proposal.py | 100 - .../caom2/tests/test/test_provenance.py | 159 -- caom2tools/caom2/tests/test/test_ref_coord.py | 96 - .../caom2/tests/test/test_requirements.py | 89 - caom2tools/caom2/tests/test/test_roundtrip.py | 169 -- .../tests/test/test_simple_observation.py | 239 -- caom2tools/caom2/tests/test/test_slice.py | 99 - .../caom2/tests/test/test_spatial_wcs.py | 110 - .../caom2/tests/test/test_spectral_wcs.py | 150 -- caom2tools/caom2/tests/test/test_target.py | 118 - .../caom2/tests/test/test_target_position.py | 105 - caom2tools/caom2/tests/test/test_telescope.py | 104 - .../caom2/tests/test/test_temporal_wcs.py | 113 - caom2tools/caom2/tests/test/test_time.py | 102 - caom2tools/caom2/tests/test/test_util.py | 167 -- .../caom2/tests/test/test_value_coord2d.py | 95 - .../caom2/tests/{test => }/test_artifact.py | 40 +- ...st_caom2_entity.py => test_caom_object.py} | 19 +- .../caom2/tests/{test => }/test_chunk.py | 187 +- .../{test/test_point.py => test_data_type.py} | 19 +- caom2tools/caom2/tests/test_observation.py | 751 ++++++ .../caom2/tests/{test => }/test_part.py | 6 +- caom2tools/caom2/tests/test_plane.py | 557 +++++ .../{test/test_caom2_util.py => test_util.py} | 50 +- caom2tools/caom2/tests/test_wcs.py | 461 ++++ ...er_writer.py => test_xml_reader_writer.py} | 306 ++- caom2tools/caom2/types/__init__.py | 73 - caom2tools/caom2/types/caom2_box.py | 77 - caom2tools/caom2/types/caom2_circle.py | 77 - caom2tools/caom2/types/caom2_interval.py | 77 - caom2tools/caom2/types/caom2_polygon.py | 77 - caom2tools/caom2/types/caom2_vertex.py | 77 - .../caom2/{util/caom2_util.py => util.py} | 277 ++- caom2tools/caom2/util/__init__.py | 71 - caom2tools/caom2/util/caom2_validator.py | 125 - caom2tools/caom2/wcs.py | 1000 ++++++++ caom2tools/caom2/wcs/__init__.py | 96 - caom2tools/caom2/wcs/caom2_axis.py | 115 - caom2tools/caom2/wcs/caom2_coord2d.py | 112 - caom2tools/caom2/wcs/caom2_coord_axis1d.py | 174 -- caom2tools/caom2/wcs/caom2_coord_axis2d.py | 202 -- caom2tools/caom2/wcs/caom2_coord_bounds1d.py | 108 - caom2tools/caom2/wcs/caom2_coord_bounds2d.py | 103 - caom2tools/caom2/wcs/caom2_coord_circle2d.py | 120 - caom2tools/caom2/wcs/caom2_coord_error.py | 126 -- .../caom2/wcs/caom2_coord_function1d.py | 141 -- .../caom2/wcs/caom2_coord_function2d.py | 188 -- caom2tools/caom2/wcs/caom2_coord_polygon2d.py | 113 - caom2tools/caom2/wcs/caom2_coord_range1d.py | 118 - caom2tools/caom2/wcs/caom2_coord_range2d.py | 116 - caom2tools/caom2/wcs/caom2_dimension2d.py | 122 - caom2tools/caom2/wcs/caom2_observable_axis.py | 151 -- .../caom2/wcs/caom2_polarization_wcs.py | 106 - caom2tools/caom2/wcs/caom2_ref_coord.py | 122 - caom2tools/caom2/wcs/caom2_slice.py | 121 - caom2tools/caom2/wcs/caom2_spatial_wcs.py | 164 -- caom2tools/caom2/wcs/caom2_spectral_wcs.py | 309 --- caom2tools/caom2/wcs/caom2_temporal_wcs.py | 205 -- caom2tools/caom2/wcs/caom2_value_coord2d.py | 102 - caom2tools/caom2/xml/__init__.py | 77 - .../caom2/xml/caom2_observation_reader.py | 1394 ------------ .../caom2/xml/caom2_observation_writer.py | 737 ------ caom2tools/caom2/xml/caom2_xml_constants.py | 86 - caom2tools/caom2/xml_reader_writer.py | 2013 +++++++++++++++++ caom2tools/{caom2 => }/requirements.txt | 0 caom2tools/{caom2 => }/setup.cfg | 0 caom2tools/{caom2 => }/setup.py | 0 162 files changed, 9007 insertions(+), 16817 deletions(-) rename caom2tools/{caom2 => }/COPYING (100%) rename caom2tools/{caom2 => }/Dependencies.txt (100%) rename caom2tools/{caom2 => }/MANIFEST.in (100%) rename caom2tools/{caom2 => }/build.xml (100%) rename caom2tools/caom2/{caom2_artifact.py => artifact.py} (88%) delete mode 100644 caom2tools/caom2/caom2_algorithm.py delete mode 100644 caom2tools/caom2/caom2_chunk.py delete mode 100644 caom2tools/caom2/caom2_composite_observation.py delete mode 100644 caom2tools/caom2/caom2_data_quality.py delete mode 100644 caom2tools/caom2/caom2_energy.py delete mode 100644 caom2tools/caom2/caom2_energy_transition.py delete mode 100644 caom2tools/caom2/caom2_enums.py delete mode 100644 caom2tools/caom2/caom2_environment.py delete mode 100644 caom2tools/caom2/caom2_exceptions.py delete mode 100644 caom2tools/caom2/caom2_instrument.py delete mode 100644 caom2tools/caom2/caom2_metrics.py delete mode 100644 caom2tools/caom2/caom2_object.py delete mode 100644 caom2tools/caom2/caom2_observation.py delete mode 100644 caom2tools/caom2/caom2_observation_uri.py delete mode 100644 caom2tools/caom2/caom2_plane.py delete mode 100644 caom2tools/caom2/caom2_plane_uri.py delete mode 100644 caom2tools/caom2/caom2_polarization.py delete mode 100644 caom2tools/caom2/caom2_position.py delete mode 100644 caom2tools/caom2/caom2_proposal.py delete mode 100644 caom2tools/caom2/caom2_provenance.py delete mode 100644 caom2tools/caom2/caom2_requirements.py delete mode 100644 caom2tools/caom2/caom2_simple_observation.py delete mode 100644 caom2tools/caom2/caom2_target.py delete mode 100644 caom2tools/caom2/caom2_target_position.py delete mode 100644 caom2tools/caom2/caom2_telescope.py delete mode 100644 caom2tools/caom2/caom2_time.py rename caom2tools/caom2/{caom2_entity.py => caom_object.py} (79%) create mode 100644 caom2tools/caom2/chunk.py rename caom2tools/caom2/{types/caom2_point.py => data_type.py} (86%) create mode 100644 caom2tools/caom2/observation.py rename caom2tools/caom2/{caom2_part.py => part.py} (93%) create mode 100644 caom2tools/caom2/plane.py rename caom2tools/caom2/tests/{test/test_caom2instances.py => caom_test_instances.py} (86%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositeCircle.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteCompositePolygon.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimpleCircle.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/CompleteSimplePolygon.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositeCircle.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalCompositePolygon.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimpleCircle.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/tests/{test => }/data/MinimalSimplePolygon.xml (100%) rename caom2tools/caom2/tests/{test => }/setup_package.py (100%) delete mode 100644 caom2tools/caom2/tests/test/test_algorithm.py delete mode 100644 caom2tools/caom2/tests/test/test_axis.py delete mode 100644 caom2tools/caom2/tests/test/test_caom2_enums.py delete mode 100644 caom2tools/caom2/tests/test/test_composite_observation.py delete mode 100644 caom2tools/caom2/tests/test/test_coord2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_axis1d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_axis2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_bounds1d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_bounds2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_circle2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_error.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_function1d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_function2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_polygon2d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_range1d.py delete mode 100644 caom2tools/caom2/tests/test/test_coord_range2d.py delete mode 100644 caom2tools/caom2/tests/test/test_data_quality.py delete mode 100644 caom2tools/caom2/tests/test/test_dimension2d.py delete mode 100644 caom2tools/caom2/tests/test/test_energy.py delete mode 100644 caom2tools/caom2/tests/test/test_energy_transition.py delete mode 100644 caom2tools/caom2/tests/test/test_environment.py delete mode 100644 caom2tools/caom2/tests/test/test_instrument.py delete mode 100644 caom2tools/caom2/tests/test/test_metrics.py delete mode 100644 caom2tools/caom2/tests/test/test_observable_axis.py delete mode 100644 caom2tools/caom2/tests/test/test_observation.py delete mode 100644 caom2tools/caom2/tests/test/test_observation_uri.py delete mode 100644 caom2tools/caom2/tests/test/test_plane.py delete mode 100644 caom2tools/caom2/tests/test/test_plane_uri.py delete mode 100644 caom2tools/caom2/tests/test/test_polarization.py delete mode 100644 caom2tools/caom2/tests/test/test_polarization_wcs.py delete mode 100644 caom2tools/caom2/tests/test/test_position.py delete mode 100644 caom2tools/caom2/tests/test/test_proposal.py delete mode 100644 caom2tools/caom2/tests/test/test_provenance.py delete mode 100644 caom2tools/caom2/tests/test/test_ref_coord.py delete mode 100644 caom2tools/caom2/tests/test/test_requirements.py delete mode 100644 caom2tools/caom2/tests/test/test_roundtrip.py delete mode 100644 caom2tools/caom2/tests/test/test_simple_observation.py delete mode 100644 caom2tools/caom2/tests/test/test_slice.py delete mode 100644 caom2tools/caom2/tests/test/test_spatial_wcs.py delete mode 100644 caom2tools/caom2/tests/test/test_spectral_wcs.py delete mode 100644 caom2tools/caom2/tests/test/test_target.py delete mode 100644 caom2tools/caom2/tests/test/test_target_position.py delete mode 100644 caom2tools/caom2/tests/test/test_telescope.py delete mode 100644 caom2tools/caom2/tests/test/test_temporal_wcs.py delete mode 100644 caom2tools/caom2/tests/test/test_time.py delete mode 100644 caom2tools/caom2/tests/test/test_util.py delete mode 100644 caom2tools/caom2/tests/test/test_value_coord2d.py rename caom2tools/caom2/tests/{test => }/test_artifact.py (79%) rename caom2tools/caom2/tests/{test/test_caom2_entity.py => test_caom_object.py} (92%) rename caom2tools/caom2/tests/{test => }/test_chunk.py (64%) rename caom2tools/caom2/tests/{test/test_point.py => test_data_type.py} (89%) create mode 100644 caom2tools/caom2/tests/test_observation.py rename caom2tools/caom2/tests/{test => }/test_part.py (97%) create mode 100644 caom2tools/caom2/tests/test_plane.py rename caom2tools/caom2/tests/{test/test_caom2_util.py => test_util.py} (92%) create mode 100644 caom2tools/caom2/tests/test_wcs.py rename caom2tools/caom2/tests/{test/test_observation_reader_writer.py => test_xml_reader_writer.py} (75%) delete mode 100755 caom2tools/caom2/types/__init__.py delete mode 100644 caom2tools/caom2/types/caom2_box.py delete mode 100644 caom2tools/caom2/types/caom2_circle.py delete mode 100644 caom2tools/caom2/types/caom2_interval.py delete mode 100644 caom2tools/caom2/types/caom2_polygon.py delete mode 100644 caom2tools/caom2/types/caom2_vertex.py rename caom2tools/caom2/{util/caom2_util.py => util.py} (62%) delete mode 100755 caom2tools/caom2/util/__init__.py delete mode 100644 caom2tools/caom2/util/caom2_validator.py create mode 100644 caom2tools/caom2/wcs.py delete mode 100755 caom2tools/caom2/wcs/__init__.py delete mode 100644 caom2tools/caom2/wcs/caom2_axis.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_axis1d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_axis2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_bounds1d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_bounds2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_circle2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_error.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_function1d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_function2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_polygon2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_range1d.py delete mode 100644 caom2tools/caom2/wcs/caom2_coord_range2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_dimension2d.py delete mode 100644 caom2tools/caom2/wcs/caom2_observable_axis.py delete mode 100644 caom2tools/caom2/wcs/caom2_polarization_wcs.py delete mode 100644 caom2tools/caom2/wcs/caom2_ref_coord.py delete mode 100644 caom2tools/caom2/wcs/caom2_slice.py delete mode 100644 caom2tools/caom2/wcs/caom2_spatial_wcs.py delete mode 100644 caom2tools/caom2/wcs/caom2_spectral_wcs.py delete mode 100644 caom2tools/caom2/wcs/caom2_temporal_wcs.py delete mode 100644 caom2tools/caom2/wcs/caom2_value_coord2d.py delete mode 100644 caom2tools/caom2/xml/__init__.py delete mode 100644 caom2tools/caom2/xml/caom2_observation_reader.py delete mode 100644 caom2tools/caom2/xml/caom2_observation_writer.py delete mode 100644 caom2tools/caom2/xml/caom2_xml_constants.py create mode 100644 caom2tools/caom2/xml_reader_writer.py rename caom2tools/{caom2 => }/requirements.txt (100%) rename caom2tools/{caom2 => }/setup.cfg (100%) rename caom2tools/{caom2 => }/setup.py (100%) diff --git a/caom2tools/caom2/COPYING b/caom2tools/COPYING similarity index 100% rename from caom2tools/caom2/COPYING rename to caom2tools/COPYING diff --git a/caom2tools/caom2/Dependencies.txt b/caom2tools/Dependencies.txt similarity index 100% rename from caom2tools/caom2/Dependencies.txt rename to caom2tools/Dependencies.txt diff --git a/caom2tools/caom2/MANIFEST.in b/caom2tools/MANIFEST.in similarity index 100% rename from caom2tools/caom2/MANIFEST.in rename to caom2tools/MANIFEST.in diff --git a/caom2tools/caom2/build.xml b/caom2tools/build.xml similarity index 100% rename from caom2tools/caom2/build.xml rename to caom2tools/build.xml diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index f35cf4f0..5cb9d73b 100755 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -70,30 +70,100 @@ """ Deines __init__ """ -# from caom2_algorithm import Algorithm -# from caom2_artifact import Artifact -# from caom2_chunk import Chunk -# from caom2_composite_observation import CompositeObservation -# from caom2_energy import Energy -# from caom2_energy_transition import EnergyTransition -# from caom2_entity import AbstractCaom2Entity -# from caom2_environment import Environment -# from caom2_enums import ProductType, ReleaseType -# from caom2_exceptions import ObservationParsingException -# from caom2_instrument import Instrument -# from caom2_metrics import Metrics -# from caom2_object import Caom2Object -# from caom2_observation import Observation -# from caom2_observation_uri import ObservationURI -# from caom2_part import Part -# from caom2_plane import Plane -# from caom2_plane_uri import PlaneURI -# from caom2_polarization import Polarization -# from caom2_position import Position -# from caom2_proposal import Proposal -# from caom2_provenance import Provenance -# from caom2_simple_observation import SimpleObservation -# from caom2_target import Target -# from caom2_target_position import TargetPosition -# from caom2_telescope import Telescope -# from caom2_time import Time +# +from caom_object import CaomObject +from caom_object import AbstractCaomEntity + +# Util classes +from util import Util +from util import TypedList +from util import TypedSet +from util import TypedOrderedDict +from util import ClassProperty +from util import Validator + +# WCS data types +from wcs import Axis +from wcs import Coord2D +from wcs import CoordAxis1D +from wcs import CoordAxis2D +from wcs import CoordBounds1D +from wcs import CoordBounds2D +from wcs import CoordCircle2D +from wcs import CoordError +from wcs import CoordFunction1D +from wcs import CoordFunction2D +from wcs import CoordPolygon2D +from wcs import CoordRange1D +from wcs import CoordRange2D +from wcs import Dimension2D +from wcs import RefCoord +from wcs import Slice +from wcs import ValueCoord2D +from wcs import EnergyTransition + +# Discovery data types +from data_type import Box +from data_type import Circle +from data_type import Interval +from data_type import Point +from data_type import Polygon +from data_type import Vertex + +# Chunk level classes +from chunk import Chunk +from chunk import ObservableAxis +from chunk import SpatialWCS +from chunk import SpectralWCS +from chunk import TemporalWCS +from chunk import PolarizationWCS + +# Part level classes +from part import Part + +# Artifact level classes +from artifact import Artifact + +# Plane level classes +from plane import Plane +from plane import PlaneURI +from plane import DataQuality +from plane import Metrics +from plane import Provenance +from plane import Position +from plane import Energy +from plane import EnergyTransition +from plane import Polarization +from plane import Time + +# Observation level classes +from observation import Observation +from observation import ObservationURI +from observation import SimpleObservation +from observation import CompositeObservation +from observation import Algorithm +from observation import Environment +from observation import Proposal +from observation import Requirements +from observation import Target +from observation import TargetPosition +from observation import Telescope + +# enums +from artifact import ProductType +from artifact import ReleaseType +from plane import CalibrationLevel +from plane import DataProductType +from plane import EnergyBand +from plane import PolarizationState +from plane import Quality +from observation import ObservationIntentType +from observation import Status +from observation import TargetType + +# observation reader and writer +from xml_reader_writer import ObservationReader +from xml_reader_writer import ObservationWriter +from xml_reader_writer import CAOM20_NAMESPACE +from xml_reader_writer import CAOM21_NAMESPACE +from xml_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/caom2/caom2_artifact.py b/caom2tools/caom2/artifact.py similarity index 88% rename from caom2tools/caom2/caom2_artifact.py rename to caom2tools/caom2/artifact.py index 94773df6..70aba8da 100644 --- a/caom2tools/caom2/caom2_artifact.py +++ b/caom2tools/caom2/artifact.py @@ -74,14 +74,29 @@ from urlparse import urlparse -import util.caom2_util as util -from caom2_entity import AbstractCaom2Entity -from caom2_enums import ProductType, ReleaseType -from caom2_part import Part -from util.caom2_util import TypedOrderedDict - - -class Artifact(AbstractCaom2Entity): +from caom_object import AbstractCaomEntity +from enum import Enum +from part import Part +from util import TypedOrderedDict +from util import Util + +ProductType = Enum('ProductType', + SCIENCE="science", + CALIBRATION="calibration", + PREVIEW="preview", + INFO="info", + NOISE="noise", + WEIGHT="weight", + AUXILIARY="auxiliary", + THUMBNAIL="thumbnail", + ) + +ReleaseType = Enum('ReleaseType', + DATA="data", + META="meta") + + +class Artifact(AbstractCaomEntity): """Contains the meta data assocaited with a file. - location of the file (uri) @@ -148,9 +163,9 @@ def uri(self): @uri.setter def uri(self, value): - util.typeCheck(value, str, 'uri') + Util.type_check(value, str, 'uri') uri = urlparse(value).geturl() - util.valueCheck(value, None, None, 'uri', override=uri) + Util.value_check(value, None, None, 'uri', override=uri) self._uri = uri @property @@ -166,7 +181,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - util.typeCheck(value, ProductType, "product_type", False) + Util.type_check(value, ProductType, "product_type", False) self._product_type = value @property @@ -182,7 +197,7 @@ def release_type(self): @release_type.setter def release_type(self, value): - util.typeCheck(value, ReleaseType, "release_type", False) + Util.type_check(value, ReleaseType, "release_type", False) self._release_type = value @property @@ -195,7 +210,7 @@ def content_type(self): @content_type.setter def content_type(self, value): - util.typeCheck(value, str, "content_type") + Util.type_check(value, str, "content_type") self._content_type = value @property @@ -210,8 +225,8 @@ def content_length(self): @content_length.setter def content_length(self, value): - util.typeCheck(value, long, "content_length") - util.valueCheck(value, 0, 1E10, "content_length") + Util.type_check(value, long, "content_length") + Util.value_check(value, 0, 1E10, "content_length") self._content_length = value @property @@ -238,7 +253,7 @@ def parts(self): @parts.setter def parts(self, value): - util.typeCheck(value, + Util.type_check(value, TypedOrderedDict, 'parts', override=False) diff --git a/caom2tools/caom2/caom2_algorithm.py b/caom2tools/caom2/caom2_algorithm.py deleted file mode 100644 index 0fcf7d99..00000000 --- a/caom2tools/caom2/caom2_algorithm.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines Algorithm class""" - -from caom2_object import Caom2Object -from util.caom2_util import typeCheck - - -class Algorithm(Caom2Object): - """ - The concept of Algorithm is to provide a way for users to find all - composite observation sets that have been built using a particular - grouping algorithm (eg. the MegaPipe stacks). For simple - observations the algorithm is 'exposure'. - """ - - def __init__(self, name): - """ - Initializes an Algorithm instance - - Arguments: - name : name of the algorithm. Should be 'exposure' if this is a - simple observation, otherwise name of algorithm that selected - composite members or just 'composite' works too. - """ - typeCheck(name, str, "name", override=False) - self._name = name - - def _key(self): - return (self._name) - - def __ne__(self, y): - return not self.__eq__(y) - - # Properties - - @property - def name(self): - """ - algorithm that defines the composite grouping; 'exposure' for - simple observations - """ - return self._name diff --git a/caom2tools/caom2/caom2_chunk.py b/caom2tools/caom2/caom2_chunk.py deleted file mode 100644 index d93437b2..00000000 --- a/caom2tools/caom2/caom2_chunk.py +++ /dev/null @@ -1,361 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Defines caom2.Chunk class. - -""" - -from caom2_entity import AbstractCaom2Entity -from caom2_enums import ProductType -from wcs.caom2_observable_axis import ObservableAxis -from wcs.caom2_spatial_wcs import SpatialWCS -from wcs.caom2_spectral_wcs import SpectralWCS -from wcs.caom2_polarization_wcs import PolarizationWCS -from wcs.caom2_temporal_wcs import TemporalWCS -import util.caom2_util as util - - -class Chunk(AbstractCaom2Entity): - """A caom2.Chunk object. A chunk is a peice of file part. - - eg. a column in a Table extension of a FITS file. - - The chunk is characterised by world coordinate system (WCS) - metadata plus an extra axis to describe different observables (the - measured values) stored within the data. Different chunks can be - defined which vary only on the range of coordinate values they - include. For example, if a single data array contains different - observable quantities then one can define a chunk (perhaps - representing different slices through a stored array) with each - slice having a different product type. - - Chunks can also be used to define arbitrary tiles in a large data - array; this is useful if there is no WCS solution to describe the - mapping of sky to pixel coordinates but one still wants to be able - to extract smaller sections of the data (e.g. one chunk). - - """ - - def __init__(self, product_type=None, - naxis=None, - position_axis_1=None, - position_axis_2=None, - position=None, - energy_axis=None, - energy=None, - time_axis=None, - time=None, - polarization_axis=None, - polarization=None, - observable_axis=None, - observable=None, - ): - - super(Chunk, self).__init__() - self.product_type = product_type - self.naxis = naxis - self.position_axis_1 = position_axis_1 - self.position_axis_2 = position_axis_2 - self.energy_axis = energy_axis - self.time_axis = time_axis - self.polarization_axis = polarization_axis - self.observable_axis = observable_axis - self.observable = observable - self.position = position - self.energy = energy - self.time = time - self.polarization = polarization - - @property - def product_type(self): - """A word that describes the content of the chunk. - - eg. Chunk.product_type = ProductType('SCIENCE') - - Allowed values: - """ + str(ProductType.names()) + """ - - """ - - return self._product_type - - @product_type.setter - def product_type(self, value): - if isinstance(value, str) and value in ProductType.names(): - ## be helpful - value = ProductType('value') - util.typeCheck(value, ProductType, 'product_type') - self._product_type = value - - @property - def naxis(self): - """There number of dimensions in this chunk. - - type: int - eg: 2 - - """ - return self._naxis - - @naxis.setter - def naxis(self, value): - util.typeCheck(value, int, 'naxis') - util.valueCheck(value, 0, 5, 'naxis') - self._naxis = value - - @property - def position_axis_1(self): - """The first spatial axis (nominally NAXIS1). - - This is the spatial axis whose WCS is connected to CRPIX1, CD1_1, CD2_1 - - eg: position_axis_1 = 1 - type: int - - """ - return self._position_axis_1 - - @position_axis_1.setter - def position_axis_1(self, value): - util.typeCheck(value, int, 'position_axis_1') -# util.valueCheck(value, 0, self.naxis, 'position_axis_1') - self._position_axis_1 = value - - @property - def position_axis_2(self): - """The second spatial axis (nominally NAXIS2). - - This is the spatial axis whose WCS is connected to CRPIX2, - CD2_2, CD1_2 - - eg: position_axis_2 = 2 - type: int - - """ - return self._position_axis_2 - - @position_axis_2.setter - def position_axis_2(self, value): - util.typeCheck(value, int, 'position_axis_2') -# util.valueCheck(value, 0, self.naxis, 'position_axis_2') - self._position_axis_2 = value - - @property - def energy_axis(self): - """The axis in the file that is in the energy direction. - - This should be None if the data does not contain an - energy axis. In this case the energy WCS maps to a - single pixel. - - eg: energy_axis = 3 - type: int - - """ - return self._energy_axis - - @energy_axis.setter - def energy_axis(self, value): - util.typeCheck(value, int, 'energy_axis') -# util.valueCheck(value, 0, self.naxis, 'energy_axis') - self._energy_axis = value - - @property - def time_axis(self): - """The axis in the data chunk that is in the time direction. - - Can and should be None if no time sampling axis exist. - - eg. time_axis = None - type: int - - """ - return self._time_axis - - @time_axis.setter - def time_axis(self, value): - util.typeCheck(value, int, 'polarization_axis') -# util.valueCheck(value, 0, self._naxis, 'polarization_axis') - self._time_axis = value - - @property - def polarization_axis(self): - """The axis in the data chunk that is in the polarization direction. - - Likely None... - - eg. polarization_axis = None - type: int - - """ - return self._polarization_axis - - @polarization_axis.setter - def polarization_axis(self, value): - util.typeCheck(value, int, 'polarization_axis') -# util.valueCheck(value, 0, self._naxis, 'polariztion_axis') - self._polarization_axis = value - - @property - def observable_axis(self): - """Used when on of the dimensions of the file contains?? ? - - type: int - - """ - return self._observable_axis - - @observable_axis.setter - def observable_axis(self, value): - util.typeCheck(value, int, 'obserable_axis') -# util.valueCheck(value, 0, 1E10, 'observable_axis') - self._observable_axis = value - - @property - def observable(self): - """An obserable that is contained in the chunk. - - Observables are quantities that are recorded directly?? - - """ - return self._observable - - @observable.setter - def observable(self, value): - util.typeCheck(value, ObservableAxis, 'observable_axis') - self._observable = value - - @property - def position(self): - """A SpatialWCS object associated with this chunk. - - The spatialWCS describes the relation between the position_axis - values and the world coordinate. - - type: SpatialWCS. - - """ - return self._position - - @position.setter - def position(self, value): - util.typeCheck(value, SpatialWCS, 'position') - self._position = value - - @property - def energy(self): - """A SpectralWCS object associated with this chunk. - - Even if energy_axis is None an SpectralWCS should still - be defined. The SpectalWCS in this case will be one pixel - in dimension. - - type: SpectralWCS - - """ - return self._energy - - @energy.setter - def energy(self, value): - util.typeCheck(value, SpectralWCS, 'energy') - self._energy = value - - @property - def time(self): - """The TemporalWCS object associated with this chunk. - - Even if time_axis is None you should define the TimeWCS - to convey when you observation was taken. - - type: TemporalWCS - - """ - return self._time - - @time.setter - def time(self, value): - util.typeCheck(value, TemporalWCS, 'time') - self._time = value - - @property - def polarization(self): - """The PolarizationWCS of the observation. - - ususally None - - type: PolarizationWCS - - """ - return self._polarization - - @polarization.setter - def polarization(self, value): - util.typeCheck(value, PolarizationWCS, 'polarization') - self._polarization = value diff --git a/caom2tools/caom2/caom2_composite_observation.py b/caom2tools/caom2/caom2_composite_observation.py deleted file mode 100644 index 0e8cfaf8..00000000 --- a/caom2tools/caom2/caom2_composite_observation.py +++ /dev/null @@ -1,139 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.composite_observation class""" - -from caom2_observation import Observation -from caom2_observation_uri import ObservationURI -from caom2_simple_observation import SimpleObservation -from util.caom2_util import TypedSet - - -class CompositeObservation(Observation): - """ - Composite Observation - - A CompositeObservation is created by collecting data from multiple - SimpleObservations together. - - """ - - def __init__(self, - collection, - observation_id, - algorithm, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None - ): - if (algorithm == SimpleObservation._ALGORITHM): - raise ValueError( - "E{0} (reserved for SimpleObservation)".format(algorithm)) - super(CompositeObservation, self).__init__(collection, - observation_id, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position - ) - self._members = TypedSet((ObservationURI),) - - @property - def algorithm(self): - return super(CompositeObservation, self).algorithm - - @algorithm.setter - def algorithm(self, value): - if value is None: - raise ValueError - if (value == SimpleObservation._ALGORITHM): - raise ValueError("cannot set CompositeObservation.algorithm to {0}" - " (reserved for SimpleObservation)".format(value)) - self._algorithm = value - - @property - def members(self): - return self._members diff --git a/caom2tools/caom2/caom2_data_quality.py b/caom2tools/caom2/caom2_data_quality.py deleted file mode 100644 index 403350f3..00000000 --- a/caom2tools/caom2/caom2_data_quality.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the DataQuality class""" - -from caom2_object import Caom2Object -from caom2_enums import Quality -import caom2.util.caom2_util as util - - -class DataQuality(Caom2Object): - """ DataQuality """ - - def __init__(self, flag): - """ - Construct an DataQuality instance - - Arguments: - flag - """ - self.flag = flag - - @property - def flag(self): - """ flag """ - return self._flag - - @flag.setter - def flag(self, value): - util.typeCheck(value, Quality, "flag") - self._flag = value diff --git a/caom2tools/caom2/caom2_energy.py b/caom2tools/caom2/caom2_energy.py deleted file mode 100644 index 71f92ac7..00000000 --- a/caom2tools/caom2/caom2_energy.py +++ /dev/null @@ -1,193 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Defines the caom2.Energy object""" - -from caom2_object import Caom2Object -from caom2_energy_transition import EnergyTransition -from caom2_enums import EnergyBand -from types.caom2_interval import Interval - - -class Energy(Caom2Object): - """ Energy """ - - def __init__(self): - """ - Initialize an Energy instance. - - Arguments: - None - """ - self._value = None - self._bounds = None - self._dimension = None - self._resolving_power = None - self._sample_size = None - self._bandpass_name = None - self._em_band = None - self._transition = None - - # Properties - @property - def value(self): - """ Energy value """ - return self._value - - @value.setter - def value(self, value): - if value is not None: - assert isinstance(value, float), ( - "energy value is not a float: {0}".format(value)) - self._value = value - - @property - def bounds(self): - """ Energy bounds """ - return self._bounds - - @bounds.setter - def bounds(self, value): - if value is not None: - assert isinstance(value, Interval), ( - "energy bounds is not an Interval: {0}".format(value)) - self._bounds = value - - @property - def dimension(self): - """DIMENSION (NUMBER OF PIXELS) ALONG ENERGY AXIS.""" - return self._dimension - - @dimension.setter - def dimension(self, value): - if value is not None: - assert isinstance(value, long), ( - "energy dimension is not a long: {0}".format(value)) - self._dimension = value - - @property - def resolving_power(self): - """ Resolving power """ - return self._resolving_power - - @resolving_power.setter - def resolving_power(self, value): - if value is not None: - assert isinstance(value, float), ( - "resolving power is not a float: {0}".format(value)) - self._resolving_power = value - - @property - def sample_size(self): - """ Sample size """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - if value is not None: - assert isinstance(value, float), ( - "sample size is not a float: {0}".format(value)) - self._sample_size = value - - @property - def bandpass_name(self): - """ Bandpass name """ - return self._bandpass_name - - @bandpass_name.setter - def bandpass_name(self, value): - if value is not None: - assert isinstance(value, str), ( - "bandpass name is not str: {0}".format(value)) - self._bandpass_name = value - - @property - def em_band(self): - """ EM Band """ - return self._em_band - - @em_band.setter - def em_band(self, value): - if value is not None: - assert isinstance(value, EnergyBand), ( - "em_Band is not an EnergyBand: {0}".format(value)) - self._em_band = value - - @property - def transition(self): - """ Energy transition """ - return self._transition - - @transition.setter - def transition(self, value): - if value is not None: - assert isinstance(value, EnergyTransition), ( - "transition is not an EnergyTransition: {0}".format(value)) - self._transition = value diff --git a/caom2tools/caom2/caom2_energy_transition.py b/caom2tools/caom2/caom2_energy_transition.py deleted file mode 100644 index 21fcf5aa..00000000 --- a/caom2tools/caom2/caom2_energy_transition.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the EnergyTransition class""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class EnergyTransition(Caom2Object): - """ EnergyTransition """ - - def __init__(self, species, transition): - """ - Construct an EnergyTransition instance - - Arguments: - species - transition - """ - util.typeCheck(species, str, "species", override=False) - util.typeCheck(transition, str, "transition", override=False) - self._species = species - self._transition = transition - - @property - def species(self): - """ Species """ - return self._species - - @property - def transition(self): - """ Transition """ - return self._transition diff --git a/caom2tools/caom2/caom2_enums.py b/caom2tools/caom2/caom2_enums.py deleted file mode 100644 index 871a1f03..00000000 --- a/caom2tools/caom2/caom2_enums.py +++ /dev/null @@ -1,148 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""A set of variables that describe the limited range -of allowed values for various caom2 quantities. """ - - -from enum import Enum - -CalibrationLevel = Enum('CalibrationLevel', - RAW_INSTRUMENT=0, - RAW_STANDARD=1, - CALIBRATED=2, - PRODUCT=3) - -DataProductType = Enum('DataProductType', - IMAGE="image", - CATALOG="catalog", - CUBE="cube", - EVENTLIST="eventlist", - SPECTRUM="spectrum", - TIMESERIES="timeseries", - VISIBILITY="visibility") - -EnergyBand = Enum('EnergyBand', - EUV="EUV", - GAMMARAY="Gamma-ray", - INFRARED="Infrared", - MILLIMETER="Millimeter", - OPTICAL="Optical", - RADIO="Radio", - UV="UV", - XRAY="X-ray") - -ObservationIntentType = Enum('ObservationIntentType', - CALIBRATION="calibration", - SCIENCE="science") - -PolarizationState = Enum('PolarizationState', - I="I", - Q="Q", - U="U", - V="V", - LL="LL", - LR="LR", - RL="RL", - RR="RR", - XX="XX", - XY="XY", - YX="YX", - YY="YY") - -ProductType = Enum('ProductType', - SCIENCE="science", - CALIBRATION="calibration", - PREVIEW="preview", - INFO="info", - NOISE="noise", - WEIGHT="weight", - AUXILIARY="auxiliary", - THUMBNAIL="thumbnail", - ) - -ReleaseType = Enum('ReleaseType', - DATA="data", - META="meta") - -SegmentType = Enum('SegmentType', - CLOSE=0, - LINE=1, - MOVE=2) - -TargetType = Enum('TargetType', - FIELD="field", - OBJECT="object") - -Quality = Enum('Quality', - JUNK="junk") - -Status = Enum('Status', - FAIL="fail") diff --git a/caom2tools/caom2/caom2_environment.py b/caom2tools/caom2/caom2_environment.py deleted file mode 100644 index 5cc02be1..00000000 --- a/caom2tools/caom2/caom2_environment.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" -Defines the caom2.Environment class, populates the caom2_environment values -""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Environment(Caom2Object): - """A CAOM2 Environment Object. - - This object contains the various values that can be set in the environment - table entry. Normally each Observation object will have an associate - Environment Object.""" - - def __init__(self): - """ - Initializes an Environment instance - - Arguments: - """ - self._seeing = None - self._humidity = None - self._elevation = None - self._tau = None - self._wavelength_tau = None - self._ambient_temp = None - self._photometric = None - - # Properties - @property - def seeing(self): - """atmospheric seeing (FWHM) in arcsec. - - units: arcseconds - """ - return self._seeing - - @seeing.setter - def seeing(self, value): - util.typeCheck(value, float, 'seeing') - util.valueCheck(value, 0, 360 * 3600.0, 'seeing') - self._seeing = value - - @property - def humidity(self): - """Relative humidity, expressed as a fraction between 0 and 200. - - units: fraction - """ - return self._humidity - - @humidity.setter - def humidity(self, value): - # set the humidity to value, which must be +ve fraction less than 200 - util.typeCheck(value, float, 'humidity') - util.valueCheck(value, 0, 200, 'humidity') - self._humidity = value - - @property - def elevation(self): - """ Elevation above horizon (0 to 90 deg) at which tau was measured. - - units: deg - """ - return self._elevation - - @elevation.setter - def elevation(self, value): - util.typeCheck(value, float, 'elevation') - util.valueCheck(value, 0, 90, 'elevation') - self._elevation = value - - @property - def tau(self): - """The tau at zennith at the time of observation. - - units: fraction - - This tau can be used, in combination with the elevation, - to determine the actual tau.""" - return self._tau - - @tau.setter - def tau(self, value): - util.typeCheck(value, float, 'tau') - util.valueCheck(value, 0, 1, 'tau') - self._tau = value - - @property - def wavelength_tau(self): - """Wavelength at which tau was measured - (normally 225GHz converted to wavelength). - - units: meters - - """ - return self._wavelength_tau - - @wavelength_tau.setter - def wavelength_tau(self, value): - util.typeCheck(value, float, 'wavelength_tau') - util.valueCheck(value, 0, 1E3, 'wavelength_tau') - self._wavelength_tau = value - - @property - def ambient_temp(self): - """The ambient air temperature at time of observation. - - unit: Celsius degrees - """ - return self._ambient_temp - - @ambient_temp.setter - def ambient_temp(self, value): - util.typeCheck(value, float, 'ambient_temp') - util.valueCheck(value, -100, 100, 'ambient_temp') - self._ambient_temp = value - - @property - def photometric(self): - """A boolean flag (True/False) indicating if - the observational conditions were photometric.""" - return self._photometric - - @photometric.setter - def photometric(self, value): - util.typeCheck(value, bool, 'photometric') - self._photometric = value diff --git a/caom2tools/caom2/caom2_exceptions.py b/caom2tools/caom2/caom2_exceptions.py deleted file mode 100644 index 6dad5bee..00000000 --- a/caom2tools/caom2/caom2_exceptions.py +++ /dev/null @@ -1,75 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""A caom2 exception class for catching""" - - -class ObservationParsingException(Exception): - pass diff --git a/caom2tools/caom2/caom2_instrument.py b/caom2tools/caom2/caom2_instrument.py deleted file mode 100644 index 6b528a37..00000000 --- a/caom2tools/caom2/caom2_instrument.py +++ /dev/null @@ -1,127 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""contains the definition of the caom2.Instrument object""" - -import util.caom2_util as util -from caom2_object import Caom2Object - - -class Instrument(Caom2Object): - """The telescopic instrument that recorded a given observation. - - Each observation should have an associated instrument. - - eg: - inst=caom2.Observation('CFHT','123456p','exposure').Instrument("MEGAPRIME") - - Each instrument can have list of keywords. - eg. - inst.keywords.append("shutter=closed") - """ - - def __init__(self, name): - """ - Initializes a Instrument instance - - Arguments: - name - name of the instrument - """ - util.typeCheck(name, str, 'name', override='none') - self._name = name - self._keywords = set() - - # Properties - @property - def name(self): - """The name of the instrument. - - type: str - """ - return self._name - - @property - def keywords(self): - """A set of strings that are keywords associated with the instrument. - - eg. keywords.append(("ccd=off","hot","shutter broken")) - - Keywords are stored as text in the database and are searched as text, - so in the above example you can search for ccd=off but that is just - matching the text 'ccd=off' and you can not do 'ccd!=on' to find that - key/value pair. - - Also, the list is concated together and inserted into the - model as a single text field, so keywords like 'shutter - broken' will match 'shutter' and 'broken'. If these keywords - appear in a pick list 'shutter' and 'broken' will be seperate - entries. So shutter_broken is a better choice. - """ - return self._keywords diff --git a/caom2tools/caom2/caom2_metrics.py b/caom2tools/caom2/caom2_metrics.py deleted file mode 100644 index 6b7ce616..00000000 --- a/caom2tools/caom2/caom2_metrics.py +++ /dev/null @@ -1,172 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of the caom2.Metrics object""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Metrics(Caom2Object): - """ Metrics """ - - def __init__(self): - """ - Initializes a Metrics instance - - Arguments: - None - """ - self._source_number_density = None - self._background = None - self._background_std_dev = None - self._flux_density_limit = None - self._mag_limit = None - - # Properties - @property - def source_number_density(self): - """The number of sources brighter than mag_limit (flux_density_limit) - - unit: ct/deg2 - type: float - """ - return self._source_number_density - - @source_number_density.setter - def source_number_density(self, value): - util.typeCheck(value, float, "source_number_density") - util.valueCheck(value, 0, 1E10, "source_number_density") - self._source_number_density = value - - @property - def background(self): - """The flux in the sky (background). - - units: Jy/pix - type: float - """ - return self._background - - @background.setter - def background(self, value): - util.typeCheck(value, float, "background") - util.valueCheck(value, 0, 1E10, "background") - self._background = value - - @property - def background_std_dev(self): - """the standard deviation (per pixel) in background flux. - - Likely this only makes sense to define if background is also defined. - units: Jy/pix - type: float - """ - return self._background_std_dev - - @background_std_dev.setter - def background_std_dev(self, value): - util.typeCheck(value, float, "background_std_dev") - util.valueCheck(value, 0, 1E10, "background") - self._background_std_dev = value - - @property - def flux_density_limit(self): - """flux density where S:N=5 for point source. - - this is intended to provide a measure of the limit of detection. - - units: Jy - type: float - """ - return self._flux_density_limit - - @flux_density_limit.setter - def flux_density_limit(self, value): - util.typeCheck(value, float, "flux_denisty_limit") - util.valueCheck(value, 0, 1E10, "flux_density_limit") - self._flux_density_limit = value - - @property - def mag_limit(self): - """AB magnitude limit where S:N=5 for point source. - - Likely specify just mag_limit or flux_density_limit, not both? - - units: AB mag - type: float - """ - return self._mag_limit - - @mag_limit.setter - def mag_limit(self, value): - util.typeCheck(value, float, 'mag_limit') - util.valueCheck(value, 0, 40, 'mag_limit') - self._mag_limit = value diff --git a/caom2tools/caom2/caom2_object.py b/caom2tools/caom2/caom2_object.py deleted file mode 100644 index 14011b07..00000000 --- a/caom2tools/caom2/caom2_object.py +++ /dev/null @@ -1,111 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Caom2Object class""" - -import inspect - - -class Caom2Object(object): - """ - setup all objects with the same generic equality, str and repr methods - """ - - def __init__(self): - pass - - def __str__(self): - args = inspect.getargspec(self.__init__).args[1:] - clsName = self.__class__.__name__ - return "\n".join( - ["{}.{} : {}".format(clsName, - arg, - getattr(self, arg, None)) - for arg in args]) - - def __eq__(self, other): - if type(other) == type(self): - return self.__dict__ == other.__dict__ - else: - return False - - def __repr__(self): - args = inspect.getargspec(self.__init__).args[1:] - clsName = "" - if self.__class__.__module__ != '__main__': - clsName += self.__class__.__module__ + "." - clsName += self.__class__.__name__ - pading = " " * (len(clsName) + 1) - return clsName + "(" + ( - ",\n" + pading).join( - ["%s=%r" % (arg, getattr(self, arg, None) - ) for arg in args - ] - ) + ")" diff --git a/caom2tools/caom2/caom2_observation.py b/caom2tools/caom2/caom2_observation.py deleted file mode 100644 index 6ff2e650..00000000 --- a/caom2tools/caom2/caom2_observation.py +++ /dev/null @@ -1,435 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of the caom2.Observation object.""" - -from datetime import datetime - -from caom2_entity import AbstractCaom2Entity -from caom2_algorithm import Algorithm -from caom2_environment import Environment -from caom2_instrument import Instrument -from caom2_plane import Plane -from caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2_target import Target -from caom2_target_position import TargetPosition -from caom2_telescope import Telescope -from caom2_observation_uri import ObservationURI -from caom2_enums import ObservationIntentType -from util.caom2_util import TypedOrderedDict -from util import caom2_util as util - - -class Observation(AbstractCaom2Entity): - """ - Observation - - An observation describes a set of empirical data. - - The CAOM2 observation is described at: - http://www.cadc.hia.nrc.gc.ca/caom2 - - The Observation object is the top level container for the - meta-data assocaited with an observation. The variaous attributes - described here provide ways of storing the complete set of - associated meta-data as well as links to the actual observation - data. - - Observation -> Target - -> Plane(s) - -> Instrument - -> Telescope - -> Proposal - -> Environment - -> TargetPosition - - Plane -> Artifact(s) - - Artifact -> Part(s) - - Part -> Chunk(s) - - The actual 'chunks' of observational data are reference by Chunk - objects. Information about the Spatial/Frequency/Time aspects of - an Observation are expressed at the Chunk level. - - The Chunk contains refernces to caom2 objects that fully describe - the circumstances of that chunk of observation. Often a 'Chunk' - is a single extension in a FITS image. But can also be a - particular column of values from a FITS Table or some other data - object. - - Chunk -> SpatialWCS - -> TemporalWCS - -> SpectralWCS - -> PolarizationWCS - -> (Observable) - """ - - def __init__(self, - collection, - observation_id, - algorithm, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None, - requirements=None - ): - """ - Initializes an Observation instance - - Arguments: collection : where the observation is from - (eg. 'HST') - - observation_id : a unique identifier within that collection - (eg. '111') - - algorithm : the algorithm used to create the observation. For - a telescope observation this is always 'exposure' - """ - super(Observation, self).__init__() - - self.collection = collection - self.observation_id = observation_id - self.algorithm = algorithm - - self.uri = ObservationURI.get_observation_uri(collection, - observation_id) - - self.sequence_number = sequence_number - self.intent = intent - self.obs_type = obs_type - self.proposal = proposal - self.telescope = telescope - self.instrument = instrument - self.target = target - self.environment = environment - self.target_position = target_position - self.requirements = requirements - self.meta_release = meta_release - if planes is None: - planes = TypedOrderedDict((Plane),) - self.planes = planes - - # Properties - @property - def collection(self): - """The name of the collection of observations, normally a telescope - name. - - type: str - """ - return self._collection - - @collection.setter - def collection(self, value): - util.typeCheck(value, str, 'collection', override=False) - self._collection = value - - @property - def observation_id(self): - """A string that uniquely identifies this obseravtion within the given - collection. - - type: str - """ - return self._observation_id - - @observation_id.setter - def observation_id(self, value): - util.typeCheck(value, str, 'observation_id', override=False) - self._observation_id = value - - @property - def uri(self): - """A URI for this observation referenced in the caom system. - - This attribute is auto geneqrated from the other metadata. - type: str - """ - return self._uri - - @uri.setter - def uri(self, value): - util.typeCheck(value, ObservationURI, 'uri') - self._uri = value - - @property - def planes(self): - """A typed ordered dictionary containing plane objects associated with - this observations. - - see caom2.Plane for details about a creating a plane. - - type: TypedOrderDict((Plane),) - - eg. Observation.planes.add(Plane("SCIENCE")) - """ - return self._planes - - @planes.setter - def planes(self, value): - util.typeCheck(value, TypedOrderedDict, 'planes') - self._planes = value - - @property - def algorithm(self): - """The process that was used to select this observation. - - normally 'exposure' for an observation or the name of a group - process for a composite observation""" - return self._algorithm - - @algorithm.setter - def algorithm(self, value): - if isinstance(value, str): - value = Algorithm(value) - util.typeCheck(value, Algorithm, 'algorithm') - self._algorithm = value - - @property - def intent(self): - """The original intent of having this data. - - type: ObservationIntentType - - see ObservationIntentType.names() for allowed values - - """ - return self._intent - - @intent.setter - def intent(self, value): - if isinstance(value, str): - value = ObservationIntentType(value) - util.typeCheck(value, ObservationIntentType, 'intent') - self._intent = value - - @property - def sequence_number(self): - """An integer counter that reprsents this observation within a - collection. eg. EXPNUM type: int - """ - return self._sequence_number - - @sequence_number.setter - def sequence_number(self, value): - util.typeCheck(value, int, 'sequence_number') - self._sequence_number = value - - @property - def obs_type(self): - """The OBSTYPE of the observation being recorded. - - eg. OBJECT, FLAT, BIAS - type: str - """ - return self._obs_type - - @obs_type.setter - def obs_type(self, value): - util.typeCheck(value, str, 'obs_type') - self._obs_type = value - - @property - def proposal(self): - """Refence to a Proposal object that describe the science proposal - that lead to this observation. - - can be None - see caom2.Proposal for help on building a Proposal object - type: caom2.Proposal - """ - return self._proposal - - @proposal.setter - def proposal(self, value): - util.typeCheck(value, Proposal, "proposal") - self._proposal = value - - @property - def telescope(self): - """Reference to a Telescope object associated with this observation. - - can be None - type: caom2.Telescope - """ - return self._telescope - - @telescope.setter - def telescope(self, value): - util.typeCheck(value, Telescope, 'telescope') - self._telescope = value - - @property - def instrument(self): - """Reference to an Instrument object associated with this observation. - - can be None - type: caom2.Instrument - """ - return self._instrument - - @instrument.setter - def instrument(self, value): - if isinstance(value, str): - value = Instrument(str) - util.typeCheck(value, Instrument, "instrument") - self._instrument = value - - @property - def target(self): - """Reference to a Target object associted with this observation. - - can be None - type: caom2.Target - """ - return self._target - - @target.setter - def target(self, value): - if isinstance(value, str): - value = Target(str) - util.typeCheck(value, Target, 'target') - self._target = value - - @property - def environment(self): - """Reference to an Environment object associated with this - observation. - - can be None - type: caom2.Environment - """ - return self._environment - - @environment.setter - def environment(self, value): - util.typeCheck(value, Environment, 'environment') - self._environment = value - - @property - def target_position(self): - """Reference to a TargetPosition object associated - with this observation. - - can be None - type: caom2.TargetPosition - """ - return self._target_position - - @target_position.setter - def target_position(self, value): - util.typeCheck(value, TargetPosition, 'target_position') - self._target_position = value - - @property - def requirements(self): - """Reference to a Requirements object associated - with this observation. - - can be None - type: caom2.Requirements - """ - return self._requirements - - @requirements.setter - def requirements(self, value): - util.typeCheck(value, Requirements, 'requirements') - self._requirements = value - - @property - def meta_release(self): - """A datetime value indicating when the meta-data of this observation - is publicly accessible. - - This only controls access to the information about the - observation. Access to the observational data is controlled - via the Plane.data_release attribute (see the planes - attribute). - - eg. '2012/11/28 12:00:00' - type: datatime - """ - return self._meta_release - - @meta_release.setter - def meta_release(self, value): - util.typeCheck(value, datetime, 'meta_release') - self._meta_release = value diff --git a/caom2tools/caom2/caom2_observation_uri.py b/caom2tools/caom2/caom2_observation_uri.py deleted file mode 100644 index a7fc6c92..00000000 --- a/caom2tools/caom2/caom2_observation_uri.py +++ /dev/null @@ -1,173 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the ObservationURI class """ - - -from util.caom2_util import validate_path_component -from urlparse import urlsplit -from urlparse import SplitResult -from util import caom2_util as util -from caom2_object import Caom2Object - - -class ObservationURI(Caom2Object): - """ Observation URI """ - - _SCHEME = str("caom") - - def __init__(self, uri): - """ - Initializes an Observation instance - - Arguments: - uri : URI corresponding to observation - """ - tmp = urlsplit(uri) - - if tmp.scheme != ObservationURI._SCHEME: - raise ValueError( - "uri must be have scheme of {}. received: {}" - .format(ObservationURI._SCHEME, uri)) - if tmp.geturl() != uri: - raise ValueError( - "uri parsing failure. received: {}".format(uri)) - - self._uri = tmp.geturl() - (collection, observation_id) = tmp.path.split("/") - if collection is None: - raise ValueError( - "uri did not contain a collection part. received: {}" - .format(uri)) - validate_path_component(self, "collection", collection) - if observation_id is None: - raise ValueError( - "uri did not contain an observation_id part. received: {}" - .format(uri)) - validate_path_component(self, "observation_id", observation_id) - (self._collection, self._observation_id) = (collection, observation_id) - self._print_attributes = ['uri', 'collection', 'observation_id'] - - def _key(self): - return (self.uri) - - def __eq__(self, y): - if (isinstance(y, ObservationURI)): - return self._key() == y._key() - return False - - def __hash__(self): - return hash(self._key()) - - @classmethod - def get_observation_uri(cls, collection, observation_id): - """ - Initializes an Observation URI instance - - Arguments: - collection : collection - observation_id : ID of the observation - """ - - util.typeCheck(collection, str, "collection", override=False) - util.typeCheck(observation_id, str, "observation_id", override=False) - - validate_path_component(cls, "collection", collection) - validate_path_component(cls, "observation_id", - observation_id) - - uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + - observation_id, "", "").geturl() - return cls(uri) - - # Properties - - @property - @classmethod - def SCHEME(cls): - """The SCHEME defines where this Observation can be looked up. - - Only 'caom' is currently supported.""" - return cls._SCHEME - - @property - def uri(self): - """The uri that the caom service can use to find the observation""" - return self._uri - - @property - def collection(self): - """The collection part of this Observations uri""" - return self._collection - - @property - def observation_id(self): - """The observation_id of this Observations uri""" - return self._observation_id diff --git a/caom2tools/caom2/caom2_plane.py b/caom2tools/caom2/caom2_plane.py deleted file mode 100644 index 23e6f182..00000000 --- a/caom2tools/caom2/caom2_plane.py +++ /dev/null @@ -1,360 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Plane class""" - - -from caom2_entity import AbstractCaom2Entity -from caom2_artifact import Artifact -from caom2_metrics import Metrics -from caom2_provenance import Provenance -from caom2_data_quality import DataQuality -from caom2_enums import CalibrationLevel -from caom2_enums import DataProductType -from util.caom2_util import TypedOrderedDict -from datetime import datetime -from caom2.util import caom2_util as util - - -class Plane(AbstractCaom2Entity): - """ Plane class """ - - def __init__(self, product_id, - artifacts=None, - meta_release=None, - data_release=None, - data_product_type=None, - calibration_level=None, - provenance=None, - metrics=None, - quality=None): - """ - Initialize a Plane instance - - Arguments: - product_id : product ID - """ - super(Plane, self).__init__() - self.product_id = product_id - if artifacts is None: - artifacts = TypedOrderedDict((Artifact),) - self.artifacts = artifacts - - self.meta_release = meta_release - self.data_release = data_release - self.data_product_type = data_product_type - self.calibration_level = calibration_level - self.provenance = provenance - self.metrics = metrics - self.quality = quality - - # computed fields - # aggregated from the Chunks during ingestion - self._position = None - self._energy = None - self._time = None - self._polarization = None - - def _key(self): - return (self.product_id) - - def __hash__(self): - return hash(self._key()) - - # Properties - @property - def product_id(self): - """A string that identifies the data product, within a given - observation, that is stored in this plane. - - eg: '1234567p' - type: str - """ - return self._product_id - - @product_id.setter - def product_id(self, value): - util.typeCheck(value, str, 'product_id', override=False) - self._product_id = value - - @property - def key(self): - """ The dictionary key for a plane is product ID """ - return self._product_id - - @property - def artifacts(self): - """A TypeList of artifacts that are part of this plane. - - individual artifacts are constructed and then added to the plane. - - eg. Plane.artifacts.add(Artifact('ad:CFHT/1234567p')), see the - Arifact help for more info on making an Aritfact object return - """ - return self._artifacts - - @artifacts.setter - def artifacts(self, value): - util.typeCheck(value, TypedOrderedDict, 'artifacts', override=False) - self._artifacts = value - - @property - def meta_release(self): - """The date when the metadata describing this observation become - public. - - eg. Plane.meta_releaes=datetime.datetime(2012,1,1,0,0,0) - indicates that the metadata become public at 00:00:00 on - January 1st 2012. - - if there is no meta_release period, set value to None - - unit: calendar date - type: datetime - """ - return self._meta_release - - @meta_release.setter - def meta_release(self, value): - util.typeCheck(value, datetime, 'meta_release') - util.valueCheck(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'meta_release') - self._meta_release = value - - @property - def data_release(self): - """The date when the data contained in this plane become public. - - eg. Plane.data_releaes=datetime.datetime(2012,1,1,0,0,0) - indicates that ar 00:00:00 on January 1st 2012 the data - assocaited with this Plane will become publicly accessible. - - If there is no data_release period, set value to None. - - unit: calendar date - type: datetime - """ - return self._data_release - - @data_release.setter - def data_release(self, value): - util.typeCheck(value, datetime, 'data_release') - util.valueCheck(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'data_release') - self._data_release = value - - @property - def data_product_type(self): - """The type of file structure that this plane contains. - - eg. - Plane.data_product_type = 'EVENTLIST' - - see DataProductType.names() for allowed values - - """ - return self._data_product_type - - @data_product_type.setter - def data_product_type(self, value): - util.typeCheck(value, DataProductType, 'data_product_type') - self._data_product_type = value - - @property - def calibration_level(self): - """a string that represents the level of calibration (aka processing) - the data contained in this plane have received. The string - is converted to an integer during storage. - - eg. Plane.calibration_level = "RAW_STANDARD" - type: str - - Must be one of CalibrationLevel.names() - - """ - return self._calibration_level - - @calibration_level.setter - def calibration_level(self, value): - util.typeCheck(value, CalibrationLevel, "calibration_level") - self._calibration_level = value - - @property - def provenance(self): - """The process that created the data referred to by this Plane. - - eg. Plane.provenance=caom2.Provenance("Elixir") - """ - return self._provenance - - @provenance.setter - def provenance(self, value): - util.typeCheck(value, Provenance, "provenance") - self._provenance = value - - @property - def metrics(self): - """reference to an object that contains metrics of this plane. - - eg. Plane.metrics = caom2.Metrics() - """ - return self._metrics - - @metrics.setter - def metrics(self, value): - util.typeCheck(value, Metrics, 'metrics') - self._metrics = value - - @property - def quality(self): - """reference to an object that describes the quality of the data of this plane. - - eg. Plane.data_quality = caom2.DataQuality() - """ - return self._quality - - @quality.setter - def quality(self, value): - util.typeCheck(value, DataQuality, 'quality') - self._quality = value - - #@property - #def observable(self): - # """ """ - # return self._observable - - @property - def position(self): - """A caom2 Position object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - return self._position - - @property - def energy(self): - """A caom2 Energy object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - """ Energy """ - return self._energy - - @property - def time(self): - """A caom2 Time object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - """ Time """ - return self._time - - @property - def polarization(self): - """A caom2 Polarization object that is developed from - the agregation of the Chunks that are children of - the Plane. - - agregation happens during ingest and is not part - of the python module at this time. - """ - return self._polarization - - # Compute derived fields - - def compute_position(self): - raise NotImplementedError( - "Aggregation of position has not been implemented in this module") - - def compute_energy(self): - raise NotImplementedError( - "Aggregation of energy has not been implemented in this module") - - def compute_time(self): - raise NotImplementedError( - "Aggregation of time has not been implemented in this module") - - def compute_polarization(self): - raise NotImplementedError( - "Aggregation of polarization " + - "has not been implemented in this module") diff --git a/caom2tools/caom2/caom2_plane_uri.py b/caom2tools/caom2/caom2_plane_uri.py deleted file mode 100644 index a943b207..00000000 --- a/caom2tools/caom2/caom2_plane_uri.py +++ /dev/null @@ -1,163 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.PlaneURI class""" - -from caom2_observation_uri import ObservationURI -from util.caom2_util import validate_path_component -from urlparse import urlsplit -from urlparse import SplitResult -from caom2_object import Caom2Object -import util.caom2_util as util - - -class PlaneURI(Caom2Object): - """ Plane URI """ - - def __init__(self, uri): - """ - Initializes an Plane instance - - Arguments: - uri : URI corresponding to the plane - - Throws: - TypeError : if uri is not a string - ValueError : if uri is invalid - ValueError : if the uri is valid but does not contain the expected - fields (collection, observation_id and product_id) - """ - - self.uri = uri - - def _key(self): - return (self.uri) - - def __hash__(self): - return hash(self._key()) - - @classmethod - def get_plane_uri(cls, observation_uri, product_id): - """ - Initializes an Plane URI instance - - Arguments: - observation_uri : the uri of the observation - product_id : ID of the product - """ - util.typeCheck(observation_uri, ObservationURI, "observation_uri", - override=False) - util.typeCheck(product_id, str, "observation_uri", override=False) - validate_path_component(cls, "product_id", product_id) - - path = urlsplit(observation_uri.uri).path - uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + - product_id, "", "").geturl() - return cls(uri) - - # Properties - @property - def uri(self): - """A uri that locates the plane object inside caom""" - return self._uri - - @uri.setter - def uri(self, value): - - util.typeCheck(value, str, "uri", override=False) - tmp = urlsplit(value) - - if tmp.scheme != ObservationURI._SCHEME: - raise ValueError("{} doesn't have an allowed scheme".format(value)) - if tmp.geturl() != value: - raise ValueError("Failed to parse uri correctly: {}".format(value)) - - (collection, observation_id, product_id) = tmp.path.split("/") - - if product_id is None: - raise ValueError("Faield to get product ID from uri: {}" - .format(value)) - - self._product_id = product_id - self._observation_uri = \ - ObservationURI.get_observation_uri(collection, - observation_id) - self._uri = value - - @property - def product_id(self): - """the product_id associated with this plane""" - return self._product_id - - @property - def observation_uri(self): - """The uri that can be used to find the caom2 observation object that - this plane belongs to""" - return self._observation_uri diff --git a/caom2tools/caom2/caom2_polarization.py b/caom2tools/caom2/caom2_polarization.py deleted file mode 100644 index c5c97e3e..00000000 --- a/caom2tools/caom2/caom2_polarization.py +++ /dev/null @@ -1,109 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Polarization class""" - -from caom2_object import Caom2Object -import util.caom2_util as util - - -class Polarization(Caom2Object): - """ Polarization """ - - def __init__(self, - dimension=None, - polarization_states=None): - """ - Initialize a Polarization instance. - - Arguments: - None - """ - self.dimension = dimension - self.polarization_states = polarization_states - - # Properties - @property - def dimension(self): - """number of samples (pixels) along polarization axis. - - unit: pix - type: int - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, int, 'dimension') - util.valueCheck(value, 0, 1E10, 'dimension') - self._dimension = value - - -# TODO implement list of PolarizationState enums diff --git a/caom2tools/caom2/caom2_position.py b/caom2tools/caom2/caom2_position.py deleted file mode 100644 index 8ca74d3b..00000000 --- a/caom2tools/caom2/caom2_position.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Position class""" - -from types.caom2_box import Box -from types.caom2_circle import Circle -from types.caom2_polygon import Polygon -from wcs.caom2_dimension2d import Dimension2D -from caom2_object import Caom2Object - - -class Position(Caom2Object): - """ Position """ - - def __init__(self, bounds=None, - dimension=None, - resolution=None, - sample_size=None, - time_dependent=None - ): - """ - Initialize a Position instance. - - Arguments: - None - """ - self.bounds = bounds - self.dimension = dimension - self.resolution = resolution - self.sample_size = sample_size - self.time_dependent = time_dependent - - # Properties - - @property - def bounds(self): - """ Bounds """ - return self._bounds - - @bounds.setter - def bounds(self, value): - if value is not None: - assert isinstance(value, (Box, Circle, Polygon)), ( - "bounds is not a Shape: {0}".format(value)) - self._bounds = value - - @property - def dimension(self): - """ Dimension """ - return self._dimension - - @dimension.setter - def dimension(self, value): - if value is not None: - assert isinstance(value, Dimension2D), ( - "dimension is not a Dimension2D: {0}".format(value)) - self._dimension = value - - @property - def resolution(self): - """ Resolution """ - return self._resolution - - @resolution.setter - def resolution(self, value): - if value is not None: - assert isinstance(value, float), ( - "resolution is not a float: {0}".format(value)) - self._resolution = value - - @property - def sample_size(self): - """ Sample size """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - if value is not None: - assert isinstance(value, float), ( - "sample size is not a float: {0}".format(value)) - self._sample_size = value - - @property - def time_dependent(self): - """ Time dependent """ - return self._time_dependent - - @time_dependent.setter - def time_dependent(self, value): - if value is not None: - assert isinstance(value, bool), ( - "time dependent is not a bool: {0}".format(value)) - self._time_dependent = value diff --git a/caom2tools/caom2/caom2_proposal.py b/caom2tools/caom2/caom2_proposal.py deleted file mode 100644 index 083e09be..00000000 --- a/caom2tools/caom2/caom2_proposal.py +++ /dev/null @@ -1,171 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Proposal class""" - -from caom2_object import Caom2Object -from util.caom2_util import TypedList -import util.caom2_util as util - - -class Proposal(Caom2Object): - """ Proposal """ - - def __init__(self, - proposal_id, - pi_name=None, - project=None, - title=None): - """ - Initializes a Proposal instance - - Arguments: - myId : id of the proposal - """ - - self.proposal_id = proposal_id - self.pi_name = pi_name - self.project = project - self.title = title - - self.keywords = set() - - # Properties - - @property - def id(self): - """The proposal ID. Sometimes also called a RUNID. - - type: str - """ - return self._proposal_id - - @id.setter - def proposal_id(self, value): - util.typeCheck(value, str, 'id') - self._proposal_id = value - - @property - def keywords(self): - """A Set of keywords connected to this proposal. - - keywords are stored as a string of words and do not need to be - key/value pairs. - - eg. Proposal.keywords.add('galaxies') - - type: set - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def pi_name(self): - """The name (First Last) of the Principle Investigator of the - Proposal. - - type: str - """ - return self._pi_name - - @pi_name.setter - def pi_name(self, value): - util.typeCheck(value, str, 'pi_name') - self._pi_name = value - - @property - def project(self): - """The name of a project associated with this proposal. - - type: str - """ - return self._project - - @project.setter - def project(self, value): - util.typeCheck(value, str, 'project') - self._project = value - - @property - def title(self): - """The title of the proposal. - - type: str - """ - return self._title - - @title.setter - def title(self, value): - util.typeCheck(value, str, 'title') - self._title = value diff --git a/caom2tools/caom2/caom2_provenance.py b/caom2tools/caom2/caom2_provenance.py deleted file mode 100644 index 6869d94e..00000000 --- a/caom2tools/caom2/caom2_provenance.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Provenance class""" - -from datetime import datetime -from urlparse import urlsplit - -from caom2_object import Caom2Object -from caom2_plane_uri import PlaneURI -from util.caom2_util import TypedSet -from util.caom2_util import typeCheck - - -class Provenance(Caom2Object): - """ Provenance """ - - def __init__(self, name, - version=None, - project=None, - producer=None, - run_id=None, - reference=None, - last_executed=None): - """ - Initializes a Provenance instance - - Arguments: - name - name of the provenance - """ - - assert name is not None, "No name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) - self._name = name - - self.version = version - self.project = project - self.producer = producer - self.run_id = run_id - self.reference = reference - self.last_executed = last_executed - - self._keywords = set() - self._inputs = TypedSet((PlaneURI),) - - # Properties - - @property - def name(self): - """ Name """ - return self._name - - @property - def version(self): - """ Version """ - return self._version - - @version.setter - def version(self, value): - typeCheck(value, str, 'version') - self._version = value - - @property - def project(self): - """ Project """ - return self._project - - @project.setter - def project(self, value): - typeCheck(value, str, 'project') - self._project = value - - @property - def producer(self): - """ Producer """ - return self._producer - - @producer.setter - def producer(self, value): - typeCheck(value, str, 'producer') - self._producer = value - - @property - def run_id(self): - """ Run ID """ - return self._run_id - - @run_id.setter - def run_id(self, value): - typeCheck(value, str, 'run_id') - self._run_id = value - - @property - def reference(self): - """ Reference """ - return self._reference - - @reference.setter - def reference(self, value): - typeCheck(value, str, 'version') - if value is not None: - tmp = urlsplit(value) - assert tmp.geturl() == value, "Invalid URI: " + value - self._reference = value - - @property - def last_executed(self): - """ Version """ - return self._last_executed - - @last_executed.setter - def last_executed(self, value): - typeCheck(value, datetime, 'last_executed') - self._last_executed = value - - @property - def keywords(self): - """ Set of keywords as str""" - return self._keywords - - @property - def inputs(self): - """ Set of inputs as PlaneURI""" - return self._inputs diff --git a/caom2tools/caom2/caom2_requirements.py b/caom2tools/caom2/caom2_requirements.py deleted file mode 100644 index dc68ee73..00000000 --- a/caom2tools/caom2/caom2_requirements.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the Requirements class""" - -from caom2_object import Caom2Object -from caom2_enums import Status -import caom2.util.caom2_util as util - - -class Requirements(Caom2Object): - """ Requirements """ - - def __init__(self, flag): - """ - Construct an Requirements instance - - Arguments: - flag - """ - self.flag = flag - - @property - def flag(self): - """ flag """ - return self._flag - - @flag.setter - def flag(self, value): - util.typeCheck(value, Status, "flag") - self._flag = value \ No newline at end of file diff --git a/caom2tools/caom2/caom2_simple_observation.py b/caom2tools/caom2/caom2_simple_observation.py deleted file mode 100644 index cb791b2f..00000000 --- a/caom2tools/caom2/caom2_simple_observation.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SimpleObservation class""" - - -from caom2_algorithm import Algorithm -from caom2_observation import Observation -import util.caom2_util as util - - -class SimpleObservation(Observation): - """A convenience class for biuld Observations where - algorithm='exposure'. - - Simple Observation : an object to store the metadata associated - with a telescopic observation. - - Simple Observations are the basic package for the CAOM2 - model. Each simple observation refers to an observation by a - telescope. - - The metadata content is stored in a variety of objects, see the - caom2_observtion class for details. - - The algorithm value for a simple observation is forced set to - "exposure" - - """ - - _ALGORITHM = Algorithm("exposure") - - def __init__(self, - collection, - observation_id, - algorithm=None, - sequence_number=None, - intent=None, - obs_type=None, - proposal=None, - telescope=None, - instrument=None, - target=None, - meta_release=None, - planes=None, - environment=None, - target_position=None - ): - """ - collection - A name that describes a collection of data, - nominally the name of a telescope - - observation_id - A UNIQUE identifier with in that collection - """ - if (algorithm == None): - algorithm = SimpleObservation._ALGORITHM - if (algorithm != SimpleObservation._ALGORITHM): - raise ValueError( - "E{0} (required for SimpleObservation)".format(algorithm)) - super(SimpleObservation, self).__init__(collection, - observation_id, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position - ) - - @property - def algorithm(self): - """The algorithm that built the observation, for SimpleObservation - this is always 'exposure'""" - - return super(SimpleObservation, self).algorithm - - @algorithm.setter - def algorithm(self, value=_ALGORITHM): - # build an Algorithm type if passed a string... - if isinstance(value, str): - value = Algorithm(value) - util.typeCheck(value, Algorithm, 'algorithm', override=False) - util.valueCheck(value, None, None, - 'algorithm', - override=self._ALGORITHM) - self._algorithm = value diff --git a/caom2tools/caom2/caom2_target.py b/caom2tools/caom2/caom2_target.py deleted file mode 100644 index 4bc05f37..00000000 --- a/caom2tools/caom2/caom2_target.py +++ /dev/null @@ -1,198 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.Target class""" - -import util.caom2_util as util -from caom2_enums import TargetType -from caom2_object import Caom2Object - - -class Target(Caom2Object): - """ Target """ - - def __init__(self, name, - target_type=None, - standard=None, - redshift=None, - keywords=None, - moving=None): - """ - Initializes a Target instance - - Arguments: - name : name of the target - type : type of the target - """ - - self.name = name - self.target_type = target_type - self.standard = standard - self.redshift = redshift - if keywords is None: - keywords = set() - self.keywords = keywords - self.moving = moving - - # Properties - - @property - def name(self): - """A name for the target - - eg 'NGC 3115' - type: str - - """ - return self._name - - @name.setter - def name(self, value): - util.typeCheck(value, str, "name", override=False) - self._name = value - - @property - def target_type(self): - """A keyword describing the type of target. - - must be from the list - """ + ",".join(TargetType.names()) + """ - type: TargetType - - """ - return self._type - - @target_type.setter - def target_type(self, value): - if isinstance(value, str): - value = TargetType(value) - util.typeCheck(value, TargetType, "target_type") - self._type = value - - @property - def keywords(self): - """A set of keywords associated with this target. - - eg. keywords.add('galaxy') - type: set - - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def standard(self): - """Is this a standard field? - - eg True - type: bool - - """ - return self._standard - - @standard.setter - def standard(self, value): - util.typeCheck(value, bool, 'standard') - self._standard = value - - @property - def redshift(self): - """The redshift of the observed target. - - eg 1.2 (can be None) - type: float - - """ - return self._redshift - - @redshift.setter - def redshift(self, value): - util.typeCheck(value, float, 'redshift') - util.valueCheck(value, -0.5, 1200, 'redshift') - self._redshift = value - - @property - def moving(self): - """Is this a moving target? - - eg True - type: bool - - """ - return self._moving - - @moving.setter - def moving(self, value): - util.typeCheck(value, bool, 'moving') - self._moving = value diff --git a/caom2tools/caom2/caom2_target_position.py b/caom2tools/caom2/caom2_target_position.py deleted file mode 100644 index 681f3598..00000000 --- a/caom2tools/caom2/caom2_target_position.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the caom2.TargetPosition class""" - -from caom2_object import Caom2Object -from types.caom2_point import Point -import caom2.util.caom2_util as util - - -class TargetPosition(Caom2Object): - """ TargetPosition """ - - def __init__(self, coordinates, coordsys, equinox=None): - """ - Initialize a TargetPosition instance. - - Arguments: - coordinates : target position as a Point. - coordsys: target coordsys - equinox: target equinox - """ - self.coordinates = coordinates - self.coordsys = coordsys - self.equinox = equinox - - # Properties - - @property - def coordinates(self): - """ Coordinates """ - return self._coordinates - - @coordinates.setter - def coordinates(self, value): - util.typeCheck(value, Point, "coordinates") - self._coordinates = value - - @property - def coordsys(self): - """ Coordsys """ - return self._coordsys - - @coordsys.setter - def coordsys(self, value): - util.typeCheck(value, str, "coordsys") - self._coordsys = value - - @property - def equinox(self): - """ Equinox """ - return self._equinox - - @equinox.setter - def equinox(self, value): - util.typeCheck(value, float, "equinox") - self._equinox = value diff --git a/caom2tools/caom2/caom2_telescope.py b/caom2tools/caom2/caom2_telescope.py deleted file mode 100644 index 508d6354..00000000 --- a/caom2tools/caom2/caom2_telescope.py +++ /dev/null @@ -1,201 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Definition of the caom2.telescope class""" - -import util.caom2_util as util -from caom2_object import Caom2Object - - -class Telescope(Caom2Object): - """ Telescope """ - - def __init__(self, name, - geo_location_x=None, - geo_location_y=None, - geo_location_z=None, - keywords=None - ): - """ - Initializes a Telescope instance - - Arguments: - name : name of the telescope - """ - - assert name is not None, "No telescope name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) - self.name = name - self.geo_location_x = geo_location_x - self.geo_location_y = geo_location_y - self.geo_location_z = geo_location_z - if keywords is None: - keywords = set() - self.keywords = keywords - - # Properties - - @property - def name(self): - """a name for this facility. - - eg. CFHT - type: str - - """ - return self._name - - @name.setter - def name(self, value): - util.typeCheck(value, str, 'name', override=False) - self._name = value - - @property - def keywords(self): - """A set that contains keywords associated with this telescope - - eg. keywords.add('big') - type: set - - """ - return self._keywords - - @keywords.setter - def keywords(self, value): - util.typeCheck(value, set, 'keywords', override=False) - self._keywords = value - - @property - def geo_location_x(self): - """The x geocentric location of the telescope. - - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_x - - @geo_location_x.setter - def geo_location_x(self, value): - util.typeCheck(value, float, 'geo_location_x') - self._geo_location_x = value - - @property - def geo_location_y(self): - """the y geocentric (ECR) location of the telescope. - - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_y - - @geo_location_y.setter - def geo_location_y(self, value): - util.typeCheck(value, float, 'geo_location_y') - self._geo_location_y = value - - @property - def geo_location_z(self): - """the z geocentric (ECR) location of the telescope. - This should be valid at time of MJD-OBS. - - These coordinates should be in the ITRS reference, - basically whatever a GPS device is saying. - - The directions of the x/y/z follow the - Earth Centred Rotation frame. - - units: m - type: float - - """ - return self._geo_location_z - - @geo_location_z.setter - def geo_location_z(self, value): - util.typeCheck(value, float, 'geo_location_z') - self._geo_location_z = value diff --git a/caom2tools/caom2/caom2_time.py b/caom2tools/caom2/caom2_time.py deleted file mode 100644 index dfec3e84..00000000 --- a/caom2tools/caom2/caom2_time.py +++ /dev/null @@ -1,191 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the time class""" - -from caom2_object import Caom2Object -from types.caom2_interval import Interval -import util.caom2_util as util - - -class Time(Caom2Object): - """ Time """ - - def __init__(self, - value=None, - bounds=None, - dimension=None, - resolution=None, - sample_size=None, - exposure=None): - """ - Initialize a Time instance. - - Arguments: - None - """ - self.value = value - self.bounds = bounds - self.dimension = dimension - self.resolution = resolution - self.sample_size = sample_size - self.exposure = exposure - - # Properties - - @property - def value(self): - """ Actual time value, seconds since epoch. - - quesion is, what epoch? - - units: s - """ - return self._value - - @value.setter - def value(self, value): - util.typeCheck(value, float, 'value') - self._value = value - - @property - def bounds(self): - """an interval object that gives start and end of an time interval - - Not actually implemented yet. Likely you want a TemporalWCS - instead - - type: Interval(lower_mjd, upper_mjd) - unit: mjd - - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, Interval, 'bounds') - self._bounds = value - - @property - def dimension(self): - """Number of pixel in the time direction, normally 1. - - eg 1 - type: long - - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, long, 'dimension') - self._dimension = value - - @property - def resolution(self): - """Time resolution of the samples, in seconds. - - normally this is the same as the exposure time, - but in a stack you might have a larger resolution value than - exposure time. - - eg. 1000 - unit: s - type: float - - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - self._resolution = value - - @property - def sample_size(self): - """nominally the exposure time, in seconds. - - """ - return self._sample_size - - @sample_size.setter - def sample_size(self, value): - util.typeCheck(value, float, 'sample_size') - self._sample_size = value - - @property - def exposure(self): - """Duration of the exposure, in seconds""" - return self._exposure - - @exposure.setter - def exposure(self, value): - util.typeCheck(value, float, 'exposure') - self._exposure = value diff --git a/caom2tools/caom2/caom2_entity.py b/caom2tools/caom2/caom_object.py similarity index 79% rename from caom2tools/caom2/caom2_entity.py rename to caom2tools/caom2/caom_object.py index 34bc3a9b..2b57a673 100644 --- a/caom2tools/caom2/caom2_entity.py +++ b/caom2tools/caom2/caom_object.py @@ -68,22 +68,59 @@ #*********************************************************************** # -"""defines the AbstractCaom2Entity class""" - +import inspect import random import time import uuid from datetime import datetime -from caom2_object import Caom2Object -from caom2.util.caom2_util import long2uuid + +from util import Util + + +class CaomObject(object): + """ + setup all objects with the same generic equality, str and repr methods + """ + + def __init__(self): + pass + + def __str__(self): + args = inspect.getargspec(self.__init__).args[1:] + clsName = self.__class__.__name__ + return "\n".join( + ["{}.{} : {}".format(clsName, + arg, + getattr(self, arg, None)) + for arg in args]) + + def __eq__(self, other): + if type(other) == type(self): + return self.__dict__ == other.__dict__ + else: + return False + + def __repr__(self): + args = inspect.getargspec(self.__init__).args[1:] + clsName = "" + if self.__class__.__module__ != '__main__': + clsName += self.__class__.__module__ + "." + clsName += self.__class__.__name__ + pading = " " * (len(clsName) + 1) + return clsName + "(" + ( + ",\n" + pading).join( + ["%s=%r" % (arg, getattr(self, arg, None) + ) for arg in args + ] + ) + ")" -class AbstractCaom2Entity(Caom2Object): +class AbstractCaomEntity(CaomObject): """Class that defines the persistence unique ID and last mod date """ def __init__(self, fulluuid=False): - self._id = AbstractCaom2Entity._gen_id(fulluuid) - self._last_modified = AbstractCaom2Entity._gen_last_modified() + self._id = AbstractCaomEntity._gen_id(fulluuid) + self._last_modified = AbstractCaomEntity._gen_last_modified() @classmethod def _gen_id(cls, fulluuid=False): @@ -105,7 +142,7 @@ def _gen_id(cls, fulluuid=False): rand = vmrandom | randtime if rand & 0x8000000000000000: rand = 0x1000000000000000 + rand - return long2uuid(rand) + return Util.long2uuid(rand) @classmethod def _gen_last_modified(cls): diff --git a/caom2tools/caom2/chunk.py b/caom2tools/caom2/chunk.py new file mode 100644 index 00000000..2eb9622a --- /dev/null +++ b/caom2tools/caom2/chunk.py @@ -0,0 +1,916 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +"""Defines caom2.Chunk class. + +""" + +from artifact import ProductType +from caom_object import AbstractCaomEntity +from caom_object import CaomObject +from plane import EnergyTransition +from util import Util +from wcs import CoordAxis1D +from wcs import CoordAxis2D +from wcs import Slice + + +class Chunk(AbstractCaomEntity): + """A caom2.Chunk object. A chunk is a peice of file part. + + eg. a column in a Table extension of a FITS file. + + The chunk is characterised by world coordinate system (WCS) + metadata plus an extra axis to describe different observables (the + measured values) stored within the data. Different chunks can be + defined which vary only on the range of coordinate values they + include. For example, if a single data array contains different + observable quantities then one can define a chunk (perhaps + representing different slices through a stored array) with each + slice having a different product type. + + Chunks can also be used to define arbitrary tiles in a large data + array; this is useful if there is no WCS solution to describe the + mapping of sky to pixel coordinates but one still wants to be able + to extract smaller sections of the data (e.g. one chunk). + + """ + + def __init__(self, product_type=None, + naxis=None, + position_axis_1=None, + position_axis_2=None, + position=None, + energy_axis=None, + energy=None, + time_axis=None, + time=None, + polarization_axis=None, + polarization=None, + observable_axis=None, + observable=None, + ): + + super(Chunk, self).__init__() + self.product_type = product_type + self.naxis = naxis + self.position_axis_1 = position_axis_1 + self.position_axis_2 = position_axis_2 + self.energy_axis = energy_axis + self.time_axis = time_axis + self.polarization_axis = polarization_axis + self.observable_axis = observable_axis + self.observable = observable + self.position = position + self.energy = energy + self.time = time + self.polarization = polarization + + @property + def product_type(self): + """A word that describes the content of the chunk. + + eg. Chunk.product_type = ProductType('SCIENCE') + + Allowed values: + """ + str(ProductType.names()) + """ + + """ + + return self._product_type + + @product_type.setter + def product_type(self, value): + if isinstance(value, str) and value in ProductType.names(): + ## be helpful + value = ProductType('value') + Util.type_check(value, ProductType, 'product_type') + self._product_type = value + + @property + def naxis(self): + """There number of dimensions in this chunk. + + type: int + eg: 2 + + """ + return self._naxis + + @naxis.setter + def naxis(self, value): + Util.type_check(value, int, 'naxis') + Util.value_check(value, 0, 5, 'naxis') + self._naxis = value + + @property + def position_axis_1(self): + """The first spatial axis (nominally NAXIS1). + + This is the spatial axis whose WCS is connected to CRPIX1, CD1_1, CD2_1 + + eg: position_axis_1 = 1 + type: int + + """ + return self._position_axis_1 + + @position_axis_1.setter + def position_axis_1(self, value): + Util.type_check(value, int, 'position_axis_1') +# util.valueCheck(value, 0, self.naxis, 'position_axis_1') + self._position_axis_1 = value + + @property + def position_axis_2(self): + """The second spatial axis (nominally NAXIS2). + + This is the spatial axis whose WCS is connected to CRPIX2, + CD2_2, CD1_2 + + eg: position_axis_2 = 2 + type: int + + """ + return self._position_axis_2 + + @position_axis_2.setter + def position_axis_2(self, value): + Util.type_check(value, int, 'position_axis_2') +# util.valueCheck(value, 0, self.naxis, 'position_axis_2') + self._position_axis_2 = value + + @property + def energy_axis(self): + """The axis in the file that is in the energy direction. + + This should be None if the data does not contain an + energy axis. In this case the energy WCS maps to a + single pixel. + + eg: energy_axis = 3 + type: int + + """ + return self._energy_axis + + @energy_axis.setter + def energy_axis(self, value): + Util.type_check(value, int, 'energy_axis') +# util.valueCheck(value, 0, self.naxis, 'energy_axis') + self._energy_axis = value + + @property + def time_axis(self): + """The axis in the data chunk that is in the time direction. + + Can and should be None if no time sampling axis exist. + + eg. time_axis = None + type: int + + """ + return self._time_axis + + @time_axis.setter + def time_axis(self, value): + Util.type_check(value, int, 'polarization_axis') +# util.valueCheck(value, 0, self._naxis, 'polarization_axis') + self._time_axis = value + + @property + def polarization_axis(self): + """The axis in the data chunk that is in the polarization direction. + + Likely None... + + eg. polarization_axis = None + type: int + + """ + return self._polarization_axis + + @polarization_axis.setter + def polarization_axis(self, value): + Util.type_check(value, int, 'polarization_axis') +# util.valueCheck(value, 0, self._naxis, 'polariztion_axis') + self._polarization_axis = value + + @property + def observable_axis(self): + """Used when on of the dimensions of the file contains?? ? + + type: int + + """ + return self._observable_axis + + @observable_axis.setter + def observable_axis(self, value): + Util.type_check(value, int, 'obserable_axis') +# util.valueCheck(value, 0, 1E10, 'observable_axis') + self._observable_axis = value + + @property + def observable(self): + """An obserable that is contained in the chunk. + + Observables are quantities that are recorded directly?? + + """ + return self._observable + + @observable.setter + def observable(self, value): + Util.type_check(value, ObservableAxis, 'observable_axis') + self._observable = value + + @property + def position(self): + """A SpatialWCS object associated with this chunk. + + The spatialWCS describes the relation between the position_axis + values and the world coordinate. + + type: SpatialWCS. + + """ + return self._position + + @position.setter + def position(self, value): + Util.type_check(value, SpatialWCS, 'position') + self._position = value + + @property + def energy(self): + """A SpectralWCS object associated with this chunk. + + Even if energy_axis is None an SpectralWCS should still + be defined. The SpectalWCS in this case will be one pixel + in dimension. + + type: SpectralWCS + + """ + return self._energy + + @energy.setter + def energy(self, value): + Util.type_check(value, SpectralWCS, 'energy') + self._energy = value + + @property + def time(self): + """The TemporalWCS object associated with this chunk. + + Even if time_axis is None you should define the TimeWCS + to convey when you observation was taken. + + type: TemporalWCS + + """ + return self._time + + @time.setter + def time(self, value): + Util.type_check(value, TemporalWCS, 'time') + self._time = value + + @property + def polarization(self): + """The PolarizationWCS of the observation. + + ususally None + + type: PolarizationWCS + + """ + return self._polarization + + @polarization.setter + def polarization(self, value): + Util.type_check(value, PolarizationWCS, 'polarization') + self._polarization = value + + +class ObservableAxis(CaomObject): + """The slice through the data structure that provides the thing being + described by this Axis. + + this data structure is used when a file contains data that has set + of measured values (the dependent variable) and might also have + the coordinate at which those values are measured in another Slice + of the file. + + The Slice refers to a column in a FITS image. The bin is the + column index and ctype/cunit for the axis describe what the column + contiains. + + eg. + + NAXIS=2 + NAXIS1=3 + NAXIS2=N + l1 f1 s1 + l2 f2 s2 + l3 f3 s3 + . + . + lN fN sN + + where l? is the wavelength at which a measure of flux f? has been + made and l is the first column of a FITS data structure that is + 3,N in size. s? is a third slice that would be used to define + another observable. When defining the s? obserable the independent + variable must be defined for that ObservableAxis too. + + The l/f obserable would be recorded as + + dependent=Slice(Axis('wave','nm'),bin=1) + independent=Slice(Axis('flux','Jy'),bin=2) + Chunk.observable_axis=ObservableAxis(dependent, independent) + + + """ + def __init__(self, dependent, independent=None): + + self.dependent = dependent + self.independent = independent + + @property + def dependent(self): + """The dependent (y) variable slice. + + A slice provides the bin and the type/unit of the observable axis + """ + + return self._dependent + + @dependent.setter + def dependent(self, value): + Util.type_check(value, Slice, 'dependent', override=False) + self._dependent = value + + @property + def independent(self): + """The dependent (y) variable slice. + + A slice that provides the pixel value and the type/unit for + conversion + + """ + return self._independent + + @independent.setter + def independent(self, value): + Util.type_check(value, Slice, "independent") + self._independent = value + + +class SpatialWCS(CaomObject): + """this object contains the WCS information needed to convert an + astronomical spatial location (ie. RA/DEC) into a pixel location + in the image. + + During ingestion a variety of extra information is created. + + """ + + def __init__(self, + axis, + coordsys=None, + equinox=None, + resolution=None): + + self.axis = axis + self.coordsys = coordsys + self.equinox = equinox + self.resolution = resolution + + @property + def axis(self): + """A CoordAxis2D object that contains + the actual WCS values (crpix etc.) + + type: CoordAxis2D + + """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, CoordAxis2D, 'axis', override=False) + self._axis = value + + @property + def coordsys(self): + """The Coordinate system of the transformation, likely ICRS or FK5. + + eg. SpatialWCS.coordsys="ICRS" + + type: str + + """ + return self._coordsys + + @coordsys.setter + def coordsys(self, value): + Util.type_check(value, str, 'coordsys') + self._coordsys = value + + @property + def equinox(self): + """The Equinox of the coordinate system. + + You might think J2000, but must be expressed as a float, so in years + + unit: years + type: float + + """ + return self._equinox + + @equinox.setter + def equinox(self, value): + Util.type_check(value, float, 'equinox') + Util.value_check(value, 1800, 2500, 'equinox') + self._equinox = value + + @property + def resolution(self): + """The spatial resolution of the image data (account for seeing/beem). + + unit: arcsec + type: float + + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + Util.type_check(value, float, 'resolution') + Util.value_check(value, 0, 360 * 3600.0, 'resolution') + self._resolution = value + + +class SpectralWCS(CaomObject): + """A transformation that maps pixel coordinates to spectral ones. + + Note that a 2D image has implicit 'spectral' (and temporal) + dimension that is one pixel in size. Basically pixels are really + multidimensional voxels. + + Due to FITS standards this pixel starts at 0.5 and runs to 1.5 + with the centre being at 1.0 + + """ + + def __init__(self, + axis, + specsys, + ssysobs=None, + ssyssrc=None, + restfrq=None, + restwav=None, + velosys=None, + zsource=None, + velang=None, + bandpass_name=None, + transition=None, + resolving_power=None + ): + """The SpectralWCS can be defined in a number of different ways, to + define one you must provide a CoordAxis1D object that maps the + pixels to WCS values and a reference specsys. After that the + user can add what ever parts seam useful. More info is more + helpful for searching. + + """ + + self.axis = axis + self.specsys = specsys + self.ssysobs = ssysobs + self.ssyssrc = ssyssrc + self.restfrq = restfrq + self.restwav = restwav + self.velosys = velosys + self.zsource = zsource + self.velang = velang + self.bandpass_name = bandpass_name + self.transition = transition + self.resolving_power = resolving_power + + @property + def axis(self): + """A 1D coordinate axis object that contains the pix/wcs + transformation values. + + eg. CoordAxis1D(Axis('wave','flux'),...) + + """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, CoordAxis1D, 'axis', override=False) + self._axis = value + + @property + def specsys(self): + """describes the reference frame in use for the spectral-axis + coordinate(s). + + eg. BARYCENT + + type: str + """ + return self._specsys + + @specsys.setter + def specsys(self, value): + Util.type_check(value, str, 'specsys', override=False) + self._specsys = value + + @property + def ssysobs(self): + """describes the spectral reference frame that is constant over the + range of the non-spectral world coordinates + + For example, for a large image the the wavelength at the edges + is different from the centres. This refernce frame is one where they + are not different. + + Nominally 'TOPOCENT' + + type: str + """ + return self._ssysobs + + @ssysobs.setter + def ssysobs(self, value): + Util.type_check(value, str, 'ssysobs') + self._ssysobs = value + + @property + def ssyssrc(self): + """The reference frame in which zsource is expressed. + + eg. BARYCENT + type: string + """ + return self._ssyssrc + + @ssyssrc.setter + def ssyssrc(self, value): + Util.type_check(value, str, 'ssyssrc') + self._ssyssrc = value + + @property + def restfrq(self): + """The frequency of the spectal feature being observed. + + unit: Hz + type: float + """ + return self._restfrq + + @restfrq.setter + def restfrq(self, value): + Util.type_check(value, float, 'restfrq') + self._restfrq = value + + @property + def restwav(self): + """The wavelength of spectral feature being observed, + not the wavelength observed but the wavelength of the + feature when at rest.. + + unit: m + type: float + """ + return self._restwav + + @restwav.setter + def restwav(self, value): + Util.type_check(value, float, 'restwav') + self._restwav = value + + @property + def velosys(self): + """Relative radial velocity between the observer and the selected + standard of rest in the direction of the celestial reference + coordinate. + + eg. 26000 m/s + + + unit: m/s + type: float + """ + return self._velosys + + @velosys.setter + def velosys(self, value): + Util.type_check(value, float, 'velosys') + self._velosys = value + + @property + def zsource(self): + """The redshift of the source emitting the photons. + + almost always None + + unit: z + type: float + """ + return self._zsource + + @zsource.setter + def zsource(self, value): + Util.type_check(value, float, 'zsource') + Util.value_check(value, -0.5, 1200, 'zsource') + self._zsource = value + + @property + def velang(self): + """I don't know what this is... angle of the velocity ??? """ + return self._velang + + @velang.setter + def velang(self, value): + Util.type_check(value, float, 'velang') + self._velang = value + + @property + def bandpass_name(self): + """string the represent the bandpass of the observation. + + eg. r' + type: str + """ + return self._bandpass_name + + @bandpass_name.setter + def bandpass_name(self, value): + Util.type_check(value, str, 'bandpass_name') + self._bandpass_name = value + + @property + def transition(self): + """which molecular transition has been observed. + + type: EnergyTransition object (see caom2.EnergyTransition for help) + """ + return self._transition + + @transition.setter + def transition(self, value): + Util.type_check(value, EnergyTransition, "transition") + self._transition = value + + @property + def resolving_power(self): + """The R value of the spectal coverage. + + Normally this is something like dlamda/lamda + + unit: RATIO + type: float + """ + return self._resolving_power + + @resolving_power.setter + def resolving_power(self, value): + Util.type_check(value, float, 'resolving_power') + Util.value_check(value, 0, 1E8, 'resolving_power') + self._resolving_power = value + + +class TemporalWCS(CaomObject): + """Describes the Time variation within the data. + + In the case of a single exposure, define the center of the first + pixel (0.5) as the MJD of the exposure and size of the pixel + as the exposure time.""" + + def __init__(self, + axis, + timesys=None, + trefpos=None, + mjdref=None, + exposure=None, + resolution=None + ): + + self.axis = axis + self.timesys = timesys + self.trefpos = trefpos + self.mjdref = mjdref + self.exposure = exposure + self.resolution = resolution + + @property + def axis(self): + """A CoordAxis1D object that describes the TemporalWCS transform. + + eg. CoordAxis1D(Axis) """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, CoordAxis1D, 'axis', override=False) + self._axis = value + + @property + def timesys(self): + """The time scale that you are using, almost alwasy UTC. + + eg. timesys = "UTC" + type: str + """ + return self._timesys + + @timesys.setter + def timesys(self, value): + Util.type_check(value, str, 'timesys') + self._timesys = value + + @property + def trefpos(self): + """ specifies the spatial location at which the time is valid, either + where the observation was made or the point in space for which + light-time corrections have been applied. + + eg. trefpos = "TOPOCENTER" + type: str + """ + return self._trefpos + + @trefpos.setter + def trefpos(self, value): + Util.type_check(value, str, 'trefpos') + self._trefpos = value + + @property + def mjdref(self): + """The Modified Julian Date of the at the reference location of the + location of the TimeWCS (aka. pixel 0.5). Nominally this the start + of the exposure. + + Why 0.5? FITS: the middle of the first pixel + is defined as pixel value 1.0 so, the start of that pixel + is location 0.5 + + eg. mjdref = 567643.1234 + unit: d + type: float + """ + return self._mjdref + + @mjdref.setter + def mjdref(self, value): + Util.type_check(value, float, 'mjdref') + ### set the limits to be after 1800 but before year 2050 + Util.value_check(value, -22000, 70000, 'mjdref') + self._mjdref = value + + @property + def exposure(self): + """The median exposure time per pixel. + + The exposure time if this not a time cube you are describing. + + eg. exposure = 100.0 + unit: s + type: float + """ + return self._exposure + + @exposure.setter + def exposure(self, value): + Util.type_check(value, float, "exposure") + Util.value_check(value, 0, 30 * 24 * 3600.0, "exposure") + self._exposure = value + + @property + def resolution(self): + """the resolution of the time sampling available. + + Normally this is going to be the same as the exposure above, + but a stack of exposures taken over many months has a very + large value for resolution while the exposure value is just + the sum of the individual exposure times. + + + eg. resolution = 100.0s + unit: s + type: float + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + Util.type_check(value, float, 'resolution') + Util.value_check(value, 0, 100 * 365 * 24 * 3600.0, "resolution") + self._resolution = value + + +class PolarizationWCS(CaomObject): + """A WCS structure that describes the relation ship between a pixel + location and the polarization value. + + """ + + def __init__(self, axis): + """Set up a CoordAxis1D object to represent the Polariation. + + """ + + self.axis = axis + + @property + def axis(self): + """A CoordAxis1D object that describes the pixel/value relation ship + for polarization of the data. + + type: CoordAxis1D + + """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, CoordAxis1D, 'axis', override=False) + if value.axis.ctype != 'STOKES': + raise ValueError('CTYPE must be STOKES') + self._axis = value + + diff --git a/caom2tools/caom2/types/caom2_point.py b/caom2tools/caom2/data_type.py similarity index 86% rename from caom2tools/caom2/types/caom2_point.py rename to caom2tools/caom2/data_type.py index f484ac59..6f8687ff 100644 --- a/caom2tools/caom2/types/caom2_point.py +++ b/caom2tools/caom2/data_type.py @@ -68,13 +68,36 @@ #*********************************************************************** # -""" defines Point class """ +from enum import Enum +from caom_object import CaomObject +from util import Util -import caom2.util.caom2_util as util -from caom2.caom2_object import Caom2Object +SegmentType = Enum('SegmentType', + CLOSE=0, + LINE=1, + MOVE=2) -class Point(Caom2Object): + +class Box(CaomObject): + + def __init__(self): + pass + + +class Circle(CaomObject): + + def __init__(self): + pass + + +class Interval(CaomObject): + + def __init__(self): + pass + + +class Point(CaomObject): def __init__(self, cval1, cval2): @@ -90,7 +113,7 @@ def cval1(self): @cval1.setter def cval1(self, value): - util.typeCheck(value, float, 'cval1', override=False) + Util.type_check(value, float, 'cval1', override=False) self._cval1 = value @property @@ -102,5 +125,17 @@ def cval2(self): @cval2.setter def cval2(self, value): - util.typeCheck(value, float, 'cval2', override=False) + Util.type_check(value, float, 'cval2', override=False) self._cval2 = value + + +class Polygon(CaomObject): + + def __init__(self): + pass + + +class Vertex(CaomObject): + + def __init__(self): + pass diff --git a/caom2tools/caom2/observation.py b/caom2tools/caom2/observation.py new file mode 100644 index 00000000..6e82dcde --- /dev/null +++ b/caom2tools/caom2/observation.py @@ -0,0 +1,1312 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +"""definition of the caom2.Observation object.""" + +from datetime import datetime +from urlparse import SplitResult + +from caom_object import AbstractCaomEntity +from caom_object import CaomObject +from data_type import Point +from enum import Enum +from plane import Plane +from util import TypedOrderedDict +from util import TypedSet +from util import Util + +ObservationIntentType = Enum('ObservationIntentType', + CALIBRATION="calibration", + SCIENCE="science") + +Status = Enum('Status', + FAIL="fail") + +TargetType = Enum('TargetType', + FIELD="field", + OBJECT="object") + + +class Observation(AbstractCaomEntity): + """ + Observation + + An observation describes a set of empirical data. + + The CAOM2 observation is described at: + http://www.cadc.hia.nrc.gc.ca/caom2 + + The Observation object is the top level container for the + meta-data assocaited with an observation. The variaous attributes + described here provide ways of storing the complete set of + associated meta-data as well as links to the actual observation + data. + + Observation -> Target + -> Plane(s) + -> Instrument + -> Telescope + -> Proposal + -> Environment + -> TargetPosition + + Plane -> Artifact(s) + + Artifact -> Part(s) + + Part -> Chunk(s) + + The actual 'chunks' of observational data are reference by Chunk + objects. Information about the Spatial/Frequency/Time aspects of + an Observation are expressed at the Chunk level. + + The Chunk contains refernces to caom2 objects that fully describe + the circumstances of that chunk of observation. Often a 'Chunk' + is a single extension in a FITS image. But can also be a + particular column of values from a FITS Table or some other data + object. + + Chunk -> SpatialWCS + -> TemporalWCS + -> SpectralWCS + -> PolarizationWCS + -> (Observable) + """ + + def __init__(self, + collection, + observation_id, + algorithm, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None, + requirements=None + ): + """ + Initializes an Observation instance + + Arguments: collection : where the observation is from + (eg. 'HST') + + observation_id : a unique identifier within that collection + (eg. '111') + + algorithm : the algorithm used to create the observation. For + a telescope observation this is always 'exposure' + """ + super(Observation, self).__init__() + + self.collection = collection + self.observation_id = observation_id + self.algorithm = algorithm + + self.uri = ObservationURI.get_observation_uri(collection, + observation_id) + + self.sequence_number = sequence_number + self.intent = intent + self.obs_type = obs_type + self.proposal = proposal + self.telescope = telescope + self.instrument = instrument + self.target = target + self.environment = environment + self.target_position = target_position + self.requirements = requirements + self.meta_release = meta_release + if planes is None: + planes = Util.TypedOrderedDict((Plane),) + self.planes = planes + + # Properties + @property + def collection(self): + """The name of the collection of observations, normally a telescope + name. + + type: str + """ + return self._collection + + @collection.setter + def collection(self, value): + Util.type_check(value, str, 'collection', override=False) + self._collection = value + + @property + def observation_id(self): + """A string that uniquely identifies this obseravtion within the given + collection. + + type: str + """ + return self._observation_id + + @observation_id.setter + def observation_id(self, value): + Util.type_check(value, str, 'observation_id', override=False) + self._observation_id = value + + @property + def uri(self): + """A URI for this observation referenced in the caom system. + + This attribute is auto geneqrated from the other metadata. + type: str + """ + return self._uri + + @uri.setter + def uri(self, value): + Util.type_check(value, ObservationURI, 'uri') + self._uri = value + + @property + def planes(self): + """A typed ordered dictionary containing plane objects associated with + this observations. + + see caom2.Plane for details about a creating a plane. + + type: TypedOrderDict((Plane),) + + eg. Observation.planes.add(Plane("SCIENCE")) + """ + return self._planes + + @planes.setter + def planes(self, value): + Util.type_check(value, TypedOrderedDict, 'planes') + self._planes = value + + @property + def algorithm(self): + """The process that was used to select this observation. + + normally 'exposure' for an observation or the name of a group + process for a composite observation""" + return self._algorithm + + @algorithm.setter + def algorithm(self, value): + if isinstance(value, str): + value = Algorithm(value) + Util.type_check(value, Algorithm, 'algorithm') + self._algorithm = value + + @property + def intent(self): + """The original intent of having this data. + + type: ObservationIntentType + + see ObservationIntentType.names() for allowed values + + """ + return self._intent + + @intent.setter + def intent(self, value): + if isinstance(value, str): + value = ObservationIntentType(value) + Util.type_check(value, ObservationIntentType, 'intent') + self._intent = value + + @property + def sequence_number(self): + """An integer counter that reprsents this observation within a + collection. eg. EXPNUM type: int + """ + return self._sequence_number + + @sequence_number.setter + def sequence_number(self, value): + Util.type_check(value, int, 'sequence_number') + self._sequence_number = value + + @property + def obs_type(self): + """The OBSTYPE of the observation being recorded. + + eg. OBJECT, FLAT, BIAS + type: str + """ + return self._obs_type + + @obs_type.setter + def obs_type(self, value): + Util.type_check(value, str, 'obs_type') + self._obs_type = value + + @property + def proposal(self): + """Refence to a Proposal object that describe the science proposal + that lead to this observation. + + can be None + see caom2.Proposal for help on building a Proposal object + type: caom2.Proposal + """ + return self._proposal + + @proposal.setter + def proposal(self, value): + Util.type_check(value, Proposal, "proposal") + self._proposal = value + + @property + def telescope(self): + """Reference to a Telescope object associated with this observation. + + can be None + type: caom2.Telescope + """ + return self._telescope + + @telescope.setter + def telescope(self, value): + Util.type_check(value, Telescope, 'telescope') + self._telescope = value + + @property + def instrument(self): + """Reference to an Instrument object associated with this observation. + + can be None + type: caom2.Instrument + """ + return self._instrument + + @instrument.setter + def instrument(self, value): + if isinstance(value, str): + value = Instrument(str) + Util.type_check(value, Instrument, "instrument") + self._instrument = value + + @property + def target(self): + """Reference to a Target object associted with this observation. + + can be None + type: caom2.Target + """ + return self._target + + @target.setter + def target(self, value): + if isinstance(value, str): + value = Target(str) + Util.type_check(value, Target, 'target') + self._target = value + + @property + def environment(self): + """Reference to an Environment object associated with this + observation. + + can be None + type: caom2.Environment + """ + return self._environment + + @environment.setter + def environment(self, value): + Util.type_check(value, Environment, 'environment') + self._environment = value + + @property + def target_position(self): + """Reference to a TargetPosition object associated + with this observation. + + can be None + type: caom2.TargetPosition + """ + return self._target_position + + @target_position.setter + def target_position(self, value): + Util.type_check(value, TargetPosition, 'target_position') + self._target_position = value + + @property + def requirements(self): + """Reference to a Requirements object associated + with this observation. + + can be None + type: caom2.Requirements + """ + return self._requirements + + @requirements.setter + def requirements(self, value): + Util.type_check(value, Requirements, 'requirements') + self._requirements = value + + @property + def meta_release(self): + """A datetime value indicating when the meta-data of this observation + is publicly accessible. + + This only controls access to the information about the + observation. Access to the observational data is controlled + via the Plane.data_release attribute (see the planes + attribute). + + eg. '2012/11/28 12:00:00' + type: datatime + """ + return self._meta_release + + @meta_release.setter + def meta_release(self, value): + Util.type_check(value, datetime, 'meta_release') + self._meta_release = value + + +class ObservationURI(CaomObject): + """ Observation URI """ + + _SCHEME = str("caom") + + def __init__(self, uri): + """ + Initializes an Observation instance + + Arguments: + uri : URI corresponding to observation + """ + tmp = Util.urlsplit(uri) + + if tmp.scheme != ObservationURI._SCHEME: + raise ValueError( + "uri must be have scheme of {}. received: {}" + .format(ObservationURI._SCHEME, uri)) + if tmp.geturl() != uri: + raise ValueError( + "uri parsing failure. received: {}".format(uri)) + + self._uri = tmp.geturl() + (collection, observation_id) = tmp.path.split("/") + if collection is None: + raise ValueError( + "uri did not contain a collection part. received: {}" + .format(uri)) + Util.validate_path_component(self, "collection", collection) + if observation_id is None: + raise ValueError( + "uri did not contain an observation_id part. received: {}" + .format(uri)) + Util.validate_path_component(self, "observation_id", observation_id) + (self._collection, self._observation_id) = (collection, observation_id) + self._print_attributes = ['uri', 'collection', 'observation_id'] + + def _key(self): + return self.uri + + def __eq__(self, y): + if isinstance(y, ObservationURI): + return self._key() == y._key() + return False + + def __hash__(self): + return hash(self._key()) + + @classmethod + def get_observation_uri(cls, collection, observation_id): + """ + Initializes an Observation URI instance + + Arguments: + collection : collection + observation_id : ID of the observation + """ + + Util.type_check(collection, str, "collection", override=False) + Util.type_check(observation_id, str, "observation_id", override=False) + + Util.validate_path_component(cls, "collection", collection) + Util.validate_path_component(cls, "observation_id", observation_id) + + uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + observation_id, + "", "").geturl() + return cls(uri) + + # Properties + + @property + @classmethod + def SCHEME(cls): + """The SCHEME defines where this Observation can be looked up. + + Only 'caom' is currently supported.""" + return cls._SCHEME + + @property + def uri(self): + """The uri that the caom service can use to find the observation""" + return self._uri + + @property + def collection(self): + """The collection part of this Observations uri""" + return self._collection + + @property + def observation_id(self): + """The observation_id of this Observations uri""" + return self._observation_id + + +class SimpleObservation(Observation): + """A convenience class for building Observations where + algorithm='exposure'. + + Simple Observation : an object to store the metadata associated + with a telescopic observation. + + Simple Observations are the basic package for the CAOM2 + model. Each simple observation refers to an observation by a + telescope. + + The metadata content is stored in a variety of objects, see the + caom2_observtion class for details. + + The algorithm value for a simple observation is forced set to + "exposure" + + """ + + _ALGORITHM = Algorithm("exposure") + + def __init__(self, + collection, + observation_id, + algorithm=None, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None + ): + """ + collection - A name that describes a collection of data, + nominally the name of a telescope + + observation_id - A UNIQUE identifier with in that collection + """ + if algorithm is None: + algorithm = SimpleObservation._ALGORITHM + if algorithm != SimpleObservation._ALGORITHM: + raise ValueError( + "E{0} (required for SimpleObservation)".format(algorithm)) + super(SimpleObservation, self).__init__(collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position + ) + + @property + def algorithm(self): + """The algorithm that built the observation, for SimpleObservation + this is always 'exposure'""" + + return super(SimpleObservation, self).algorithm + + @algorithm.setter + def algorithm(self, value=_ALGORITHM): + # build an Algorithm type if passed a string... + if isinstance(value, str): + value = Algorithm(value) + Util.type_check(value, Algorithm, 'algorithm', override=False) + Util.value_check(value, None, None, + 'algorithm', + override=self._ALGORITHM) + self._algorithm = value + + +class CompositeObservation(Observation): + """ + Composite Observation + + A CompositeObservation is created by collecting data from multiple + SimpleObservations together. + + """ + + def __init__(self, + collection, + observation_id, + algorithm, + sequence_number=None, + intent=None, + obs_type=None, + proposal=None, + telescope=None, + instrument=None, + target=None, + meta_release=None, + planes=None, + environment=None, + target_position=None + ): + if algorithm == SimpleObservation._ALGORITHM: + raise ValueError( + "E{0} (reserved for SimpleObservation)".format(algorithm)) + super(CompositeObservation, self).__init__(collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position + ) + self._members = TypedSet((ObservationURI),) + + @property + def algorithm(self): + return super(CompositeObservation, self).algorithm + + @algorithm.setter + def algorithm(self, value): + if value is None: + raise ValueError + if value == SimpleObservation._ALGORITHM: + raise ValueError("cannot set CompositeObservation.algorithm to {0}" + " (reserved for SimpleObservation)".format(value)) + self._algorithm = value + + @property + def members(self): + return self._members + + +class Algorithm(CaomObject): + """ + The concept of Algorithm is to provide a way for users to find all + composite observation sets that have been built using a particular + grouping algorithm (eg. the MegaPipe stacks). For simple + observations the algorithm is 'exposure'. + """ + + def __init__(self, name): + """ + Initializes an Algorithm instance + + Arguments: + name : name of the algorithm. Should be 'exposure' if this is a + simple observation, otherwise name of algorithm that selected + composite members or just 'composite' works too. + """ + Util.type_check(name, str, "name", override=False) + self._name = name + + def _key(self): + return (self._name) + + def __ne__(self, y): + return not self.__eq__(y) + + # Properties + + @property + def name(self): + """ + algorithm that defines the composite grouping; 'exposure' for + simple observations + """ + return self._name + + +class Environment(CaomObject): + """A CAOM2 Environment Object. + + This object contains the various values that can be set in the environment + table entry. Normally each Observation object will have an associate + Environment Object.""" + + def __init__(self): + """ + Initializes an Environment instance + + Arguments: + """ + self._seeing = None + self._humidity = None + self._elevation = None + self._tau = None + self._wavelength_tau = None + self._ambient_temp = None + self._photometric = None + + # Properties + @property + def seeing(self): + """atmospheric seeing (FWHM) in arcsec. + + units: arcseconds + """ + return self._seeing + + @seeing.setter + def seeing(self, value): + Util.type_check(value, float, 'seeing') + Util.value_check(value, 0, 360 * 3600.0, 'seeing') + self._seeing = value + + @property + def humidity(self): + """Relative humidity, expressed as a fraction between 0 and 200. + + units: fraction + """ + return self._humidity + + @humidity.setter + def humidity(self, value): + # set the humidity to value, which must be +ve fraction less than 200 + Util.type_check(value, float, 'humidity') + Util.value_check(value, 0, 200, 'humidity') + self._humidity = value + + @property + def elevation(self): + """ Elevation above horizon (0 to 90 deg) at which tau was measured. + + units: deg + """ + return self._elevation + + @elevation.setter + def elevation(self, value): + Util.type_check(value, float, 'elevation') + Util.value_check(value, 0, 90, 'elevation') + self._elevation = value + + @property + def tau(self): + """The tau at zennith at the time of observation. + + units: fraction + + This tau can be used, in combination with the elevation, + to determine the actual tau.""" + return self._tau + + @tau.setter + def tau(self, value): + Util.type_check(value, float, 'tau') + Util.value_check(value, 0, 1, 'tau') + self._tau = value + + @property + def wavelength_tau(self): + """Wavelength at which tau was measured + (normally 225GHz converted to wavelength). + + units: meters + + """ + return self._wavelength_tau + + @wavelength_tau.setter + def wavelength_tau(self, value): + Util.type_check(value, float, 'wavelength_tau') + Util.value_check(value, 0, 1E3, 'wavelength_tau') + self._wavelength_tau = value + + @property + def ambient_temp(self): + """The ambient air temperature at time of observation. + + unit: Celsius degrees + """ + return self._ambient_temp + + @ambient_temp.setter + def ambient_temp(self, value): + Util.type_check(value, float, 'ambient_temp') + Util.value_check(value, -100, 100, 'ambient_temp') + self._ambient_temp = value + + @property + def photometric(self): + """A boolean flag (True/False) indicating if + the observational conditions were photometric.""" + return self._photometric + + @photometric.setter + def photometric(self, value): + Util.type_check(value, bool, 'photometric') + self._photometric = value + + +class Instrument(CaomObject): + """The telescopic instrument that recorded a given observation. + + Each observation should have an associated instrument. + + eg: + inst=caom2.Observation('CFHT','123456p','exposure').Instrument("MEGAPRIME") + + Each instrument can have list of keywords. + eg. + inst.keywords.append("shutter=closed") + """ + + def __init__(self, name): + """ + Initializes a Instrument instance + + Arguments: + name - name of the instrument + """ + Util.type_check(name, str, 'name', override='none') + self._name = name + self._keywords = set() + + # Properties + @property + def name(self): + """The name of the instrument. + + type: str + """ + return self._name + + @property + def keywords(self): + """A set of strings that are keywords associated with the instrument. + + eg. keywords.append(("ccd=off","hot","shutter broken")) + + Keywords are stored as text in the database and are searched as text, + so in the above example you can search for ccd=off but that is just + matching the text 'ccd=off' and you can not do 'ccd!=on' to find that + key/value pair. + + Also, the list is concated together and inserted into the + model as a single text field, so keywords like 'shutter + broken' will match 'shutter' and 'broken'. If these keywords + appear in a pick list 'shutter' and 'broken' will be seperate + entries. So shutter_broken is a better choice. + """ + return self._keywords + + +class Proposal(CaomObject): + """ Proposal """ + + def __init__(self, + proposal_id, + pi_name=None, + project=None, + title=None): + """ + Initializes a Proposal instance + + Arguments: + myId : id of the proposal + """ + + self.proposal_id = proposal_id + self.pi_name = pi_name + self.project = project + self.title = title + + self.keywords = set() + + # Properties + + @property + def id(self): + """The proposal ID. Sometimes also called a RUNID. + + type: str + """ + return self._proposal_id + + @id.setter + def proposal_id(self, value): + Util.type_check(value, str, 'id') + self._proposal_id = value + + @property + def keywords(self): + """A Set of keywords connected to this proposal. + + keywords are stored as a string of words and do not need to be + key/value pairs. + + eg. Proposal.keywords.add('galaxies') + + type: set + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + Util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def pi_name(self): + """The name (First Last) of the Principle Investigator of the + Proposal. + + type: str + """ + return self._pi_name + + @pi_name.setter + def pi_name(self, value): + Util.type_check(value, str, 'pi_name') + self._pi_name = value + + @property + def project(self): + """The name of a project associated with this proposal. + + type: str + """ + return self._project + + @project.setter + def project(self, value): + Util.type_check(value, str, 'project') + self._project = value + + @property + def title(self): + """The title of the proposal. + + type: str + """ + return self._title + + @title.setter + def title(self, value): + Util.type_check(value, str, 'title') + self._title = value + + +class Requirements(CaomObject): + """ Requirements """ + + def __init__(self, flag): + """ + Construct an Requirements instance + + Arguments: + flag + """ + self.flag = flag + + @property + def flag(self): + """ flag """ + return self._flag + + @flag.setter + def flag(self, value): + Util.type_check(value, Status, "flag") + self._flag = value + + +class Target(CaomObject): + """ Target """ + + def __init__(self, name, + target_type=None, + standard=None, + redshift=None, + keywords=None, + moving=None): + """ + Initializes a Target instance + + Arguments: + name : name of the target + type : type of the target + """ + + self.name = name + self.target_type = target_type + self.standard = standard + self.redshift = redshift + if keywords is None: + keywords = set() + self.keywords = keywords + self.moving = moving + + # Properties + + @property + def name(self): + """A name for the target + + eg 'NGC 3115' + type: str + + """ + return self._name + + @name.setter + def name(self, value): + Util.type_check(value, str, "name", override=False) + self._name = value + + @property + def target_type(self): + """A keyword describing the type of target. + + must be from the list + """ + ",".join(TargetType.names()) + """ + type: TargetType + + """ + return self._type + + @target_type.setter + def target_type(self, value): + if isinstance(value, str): + value = TargetType(value) + Util.type_check(value, TargetType, "target_type") + self._type = value + + @property + def keywords(self): + """A set of keywords associated with this target. + + eg. keywords.add('galaxy') + type: set + + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + Util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def standard(self): + """Is this a standard field? + + eg True + type: bool + + """ + return self._standard + + @standard.setter + def standard(self, value): + Util.type_check(value, bool, 'standard') + self._standard = value + + @property + def redshift(self): + """The redshift of the observed target. + + eg 1.2 (can be None) + type: float + + """ + return self._redshift + + @redshift.setter + def redshift(self, value): + Util.type_check(value, float, 'redshift') + Util.value_check(value, -0.5, 1200, 'redshift') + self._redshift = value + + @property + def moving(self): + """Is this a moving target? + + eg True + type: bool + + """ + return self._moving + + @moving.setter + def moving(self, value): + Util.type_check(value, bool, 'moving') + self._moving = value + + +class TargetPosition(CaomObject): + """ TargetPosition """ + + def __init__(self, coordinates, coordsys, equinox=None): + """ + Initialize a TargetPosition instance. + + Arguments: + coordinates : target position as a Point. + coordsys: target coordsys + equinox: target equinox + """ + self.coordinates = coordinates + self.coordsys = coordsys + self.equinox = equinox + + # Properties + + @property + def coordinates(self): + """ Coordinates """ + return self._coordinates + + @coordinates.setter + def coordinates(self, value): + Util.type_check(value, Point, "coordinates") + self._coordinates = value + + @property + def coordsys(self): + """ Coordsys """ + return self._coordsys + + @coordsys.setter + def coordsys(self, value): + Util.type_check(value, str, "coordsys") + self._coordsys = value + + @property + def equinox(self): + """ Equinox """ + return self._equinox + + @equinox.setter + def equinox(self, value): + Util.type_check(value, float, "equinox") + self._equinox = value + + +class Telescope(CaomObject): + """ Telescope """ + + def __init__(self, name, + geo_location_x=None, + geo_location_y=None, + geo_location_z=None, + keywords=None + ): + """ + Initializes a Telescope instance + + Arguments: + name : name of the telescope + """ + + assert name is not None, "No telescope name provided" + assert isinstance(name, str), "name is not a str: {0}".format(name) + self.name = name + self.geo_location_x = geo_location_x + self.geo_location_y = geo_location_y + self.geo_location_z = geo_location_z + if keywords is None: + keywords = set() + self.keywords = keywords + + # Properties + + @property + def name(self): + """a name for this facility. + + eg. CFHT + type: str + + """ + return self._name + + @name.setter + def name(self, value): + Util.type_check(value, str, 'name', override=False) + self._name = value + + @property + def keywords(self): + """A set that contains keywords associated with this telescope + + eg. keywords.add('big') + type: set + + """ + return self._keywords + + @keywords.setter + def keywords(self, value): + Util.type_check(value, set, 'keywords', override=False) + self._keywords = value + + @property + def geo_location_x(self): + """The x geocentric location of the telescope. + + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_x + + @geo_location_x.setter + def geo_location_x(self, value): + Util.type_check(value, float, 'geo_location_x') + self._geo_location_x = value + + @property + def geo_location_y(self): + """the y geocentric (ECR) location of the telescope. + + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_y + + @geo_location_y.setter + def geo_location_y(self, value): + Util.type_check(value, float, 'geo_location_y') + self._geo_location_y = value + + @property + def geo_location_z(self): + """the z geocentric (ECR) location of the telescope. + This should be valid at time of MJD-OBS. + + These coordinates should be in the ITRS reference, + basically whatever a GPS device is saying. + + The directions of the x/y/z follow the + Earth Centred Rotation frame. + + units: m + type: float + + """ + return self._geo_location_z + + @geo_location_z.setter + def geo_location_z(self, value): + Util.type_check(value, float, 'geo_location_z') + self._geo_location_z = value diff --git a/caom2tools/caom2/caom2_part.py b/caom2tools/caom2/part.py similarity index 93% rename from caom2tools/caom2/caom2_part.py rename to caom2tools/caom2/part.py index 2974b44d..6124f1d3 100644 --- a/caom2tools/caom2/caom2_part.py +++ b/caom2tools/caom2/part.py @@ -72,13 +72,14 @@ the caom2_Observation_Plane_Artifact_Part object.""" -from caom2_entity import AbstractCaom2Entity -from caom2_chunk import Chunk -from caom2_enums import ProductType -import util.caom2_util as util +from caom_object import AbstractCaomEntity +from chunk import Chunk +from artifact import ProductType +from util import TypedList +from util import Util -class Part(AbstractCaom2Entity): +class Part(AbstractCaomEntity): """A qualitative subsection of an artifact. eg: a extension of a FITS file. @@ -92,7 +93,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = util.TypedList((Chunk),) + chunks = TypedList((Chunk),) self.chunks = chunks def _key(self): @@ -116,7 +117,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - util.typeCheck(value, ProductType, "product_type") + Util.type_check(value, ProductType, "product_type") self._product_type = value @property @@ -129,7 +130,7 @@ def name(self): @name.setter def name(self, value): - util.typeCheck(value, str, 'name', override=False) + Util.type_check(value, str, 'name', override=False) self._name = value @property @@ -144,5 +145,5 @@ def chunks(self): @chunks.setter def chunks(self, value): - util.typeCheck(value, util.TypedList, 'chunks', override=False) + Util.type_check(value, TypedList, 'chunks', override=False) self._chunks = value diff --git a/caom2tools/caom2/plane.py b/caom2tools/caom2/plane.py new file mode 100644 index 00000000..6f4b2163 --- /dev/null +++ b/caom2tools/caom2/plane.py @@ -0,0 +1,1103 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +"""defines the caom2.Plane class""" + +from datetime import datetime +from urlparse import SplitResult +from urlparse import urlsplit + +from artifact import Artifact +from caom_object import AbstractCaomEntity +from caom_object import CaomObject +from data_type import Box +from data_type import Circle +from data_type import Interval +from data_type import Polygon +from enum import Enum +from observation import ObservationURI +from util import TypedOrderedDict +from util import TypedSet +from util import Util +from wcs import Dimension2D + +CalibrationLevel = Enum('CalibrationLevel', + RAW_INSTRUMENT=0, + RAW_STANDARD=1, + CALIBRATED=2, + PRODUCT=3) + +DataProductType = Enum('DataProductType', + IMAGE="image", + CATALOG="catalog", + CUBE="cube", + EVENTLIST="eventlist", + SPECTRUM="spectrum", + TIMESERIES="timeseries", + VISIBILITY="visibility") + +EnergyBand = Enum('EnergyBand', + EUV="EUV", + GAMMARAY="Gamma-ray", + INFRARED="Infrared", + MILLIMETER="Millimeter", + OPTICAL="Optical", + RADIO="Radio", + UV="UV", + XRAY="X-ray") + +PolarizationState = Enum('PolarizationState', + I="I", + Q="Q", + U="U", + V="V", + LL="LL", + LR="LR", + RL="RL", + RR="RR", + XX="XX", + XY="XY", + YX="YX", + YY="YY") + +Quality = Enum('Quality', + JUNK="junk") + + +class Plane(AbstractCaomEntity): + """ Plane class """ + + def __init__(self, product_id, + artifacts=None, + meta_release=None, + data_release=None, + data_product_type=None, + calibration_level=None, + provenance=None, + metrics=None, + quality=None): + """ + Initialize a Plane instance + + Arguments: + product_id : product ID + """ + super(Plane, self).__init__() + self.product_id = product_id + if artifacts is None: + artifacts = TypedOrderedDict((Artifact),) + self.artifacts = artifacts + + self.meta_release = meta_release + self.data_release = data_release + self.data_product_type = data_product_type + self.calibration_level = calibration_level + self.provenance = provenance + self.metrics = metrics + self.quality = quality + + # computed fields + # aggregated from the Chunks during ingestion + self._position = None + self._energy = None + self._time = None + self._polarization = None + + def _key(self): + return self.product_id + + def __hash__(self): + return hash(self._key()) + + # Properties + @property + def product_id(self): + """A string that identifies the data product, within a given + observation, that is stored in this plane. + + eg: '1234567p' + type: str + """ + return self._product_id + + @product_id.setter + def product_id(self, value): + Util.type_check(value, str, 'product_id', override=False) + self._product_id = value + + @property + def key(self): + """ The dictionary key for a plane is product ID """ + return self._product_id + + @property + def artifacts(self): + """A TypeList of artifacts that are part of this plane. + + individual artifacts are constructed and then added to the plane. + + eg. Plane.artifacts.add(Artifact('ad:CFHT/1234567p')), see the + Arifact help for more info on making an Aritfact object return + """ + return self._artifacts + + @artifacts.setter + def artifacts(self, value): + Util.type_check(value, TypedOrderedDict, 'artifacts', override=False) + self._artifacts = value + + @property + def meta_release(self): + """The date when the metadata describing this observation become + public. + + eg. Plane.meta_releaes=datetime.datetime(2012,1,1,0,0,0) + indicates that the metadata become public at 00:00:00 on + January 1st 2012. + + if there is no meta_release period, set value to None + + unit: calendar date + type: datetime + """ + return self._meta_release + + @meta_release.setter + def meta_release(self, value): + Util.type_check(value, datetime, 'meta_release') + Util.value_check(value, + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'meta_release') + self._meta_release = value + + @property + def data_release(self): + """The date when the data contained in this plane become public. + + eg. Plane.data_releaes=datetime.datetime(2012,1,1,0,0,0) + indicates that ar 00:00:00 on January 1st 2012 the data + assocaited with this Plane will become publicly accessible. + + If there is no data_release period, set value to None. + + unit: calendar date + type: datetime + """ + return self._data_release + + @data_release.setter + def data_release(self, value): + Util.type_check(value, datetime, 'data_release') + Util.value_check(value, + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'data_release') + self._data_release = value + + @property + def data_product_type(self): + """The type of file structure that this plane contains. + + eg. + Plane.data_product_type = 'EVENTLIST' + + see DataProductType.names() for allowed values + + """ + return self._data_product_type + + @data_product_type.setter + def data_product_type(self, value): + Util.type_check(value, DataProductType, 'data_product_type') + self._data_product_type = value + + @property + def calibration_level(self): + """a string that represents the level of calibration (aka processing) + the data contained in this plane have received. The string + is converted to an integer during storage. + + eg. Plane.calibration_level = "RAW_STANDARD" + type: str + + Must be one of CalibrationLevel.names() + + """ + return self._calibration_level + + @calibration_level.setter + def calibration_level(self, value): + Util.type_check(value, CalibrationLevel, "calibration_level") + self._calibration_level = value + + @property + def provenance(self): + """The process that created the data referred to by this Plane. + + eg. Plane.provenance=caom2.Provenance("Elixir") + """ + return self._provenance + + @provenance.setter + def provenance(self, value): + Util.type_check(value, Provenance, "provenance") + self._provenance = value + + @property + def metrics(self): + """reference to an object that contains metrics of this plane. + + eg. Plane.metrics = caom2.Metrics() + """ + return self._metrics + + @metrics.setter + def metrics(self, value): + Util.type_check(value, Metrics, 'metrics') + self._metrics = value + + @property + def quality(self): + """reference to an object that describes the quality of the data of this plane. + + eg. Plane.data_quality = caom2.DataQuality() + """ + return self._quality + + @quality.setter + def quality(self, value): + Util.type_check(value, DataQuality, 'quality') + self._quality = value + + #@property + #def observable(self): + # """ """ + # return self._observable + + @property + def position(self): + """A caom2 Position object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + return self._position + + @property + def energy(self): + """A caom2 Energy object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + """ Energy """ + return self._energy + + @property + def time(self): + """A caom2 Time object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + """ Time """ + return self._time + + @property + def polarization(self): + """A caom2 Polarization object that is developed from + the agregation of the Chunks that are children of + the Plane. + + agregation happens during ingest and is not part + of the python module at this time. + """ + return self._polarization + + # Compute derived fields + + def compute_position(self): + raise NotImplementedError( + "Aggregation of position has not been implemented in this module") + + def compute_energy(self): + raise NotImplementedError( + "Aggregation of energy has not been implemented in this module") + + def compute_time(self): + raise NotImplementedError( + "Aggregation of time has not been implemented in this module") + + def compute_polarization(self): + raise NotImplementedError( + "Aggregation of polarization " + + "has not been implemented in this module") + + +class PlaneURI(CaomObject): + """ Plane URI """ + + def __init__(self, uri): + """ + Initializes an Plane instance + + Arguments: + uri : URI corresponding to the plane + + Throws: + TypeError : if uri is not a string + ValueError : if uri is invalid + ValueError : if the uri is valid but does not contain the expected + fields (collection, observation_id and product_id) + """ + + self.uri = uri + + def _key(self): + return self.uri + + def __hash__(self): + return hash(self._key()) + + @classmethod + def get_plane_uri(cls, observation_uri, product_id): + """ + Initializes an Plane URI instance + + Arguments: + observation_uri : the uri of the observation + product_id : ID of the product + """ + Util.type_check(observation_uri, ObservationURI, "observation_uri", + override=False) + Util.type_check(product_id, str, "observation_uri", override=False) + Util.validate_path_component(cls, "product_id", product_id) + + path = urlsplit(observation_uri.uri).path + uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + + product_id, "", "").geturl() + return cls(uri) + + # Properties + @property + def uri(self): + """A uri that locates the plane object inside caom""" + return self._uri + + @uri.setter + def uri(self, value): + + Util.type_check(value, str, "uri", override=False) + tmp = urlsplit(value) + + if tmp.scheme != ObservationURI._SCHEME: + raise ValueError("{} doesn't have an allowed scheme".format(value)) + if tmp.geturl() != value: + raise ValueError("Failed to parse uri correctly: {}".format(value)) + + (collection, observation_id, product_id) = tmp.path.split("/") + + if product_id is None: + raise ValueError("Faield to get product ID from uri: {}" + .format(value)) + + self._product_id = product_id + self._observation_uri = \ + ObservationURI.get_observation_uri(collection, + observation_id) + self._uri = value + + @property + def product_id(self): + """the product_id associated with this plane""" + return self._product_id + + @property + def observation_uri(self): + """The uri that can be used to find the caom2 observation object that + this plane belongs to""" + return self._observation_uri + + +class DataQuality(CaomObject): + """ DataQuality """ + + def __init__(self, flag): + """ + Construct an DataQuality instance + + Arguments: + flag + """ + self.flag = flag + + @property + def flag(self): + """ flag """ + return self._flag + + @flag.setter + def flag(self, value): + Util.type_check(value, Quality, "flag") + self._flag = value + + +class Metrics(CaomObject): + """ Metrics """ + + def __init__(self): + """ + Initializes a Metrics instance + + Arguments: + None + """ + self._source_number_density = None + self._background = None + self._background_std_dev = None + self._flux_density_limit = None + self._mag_limit = None + + # Properties + @property + def source_number_density(self): + """The number of sources brighter than mag_limit (flux_density_limit) + + unit: ct/deg2 + type: float + """ + return self._source_number_density + + @source_number_density.setter + def source_number_density(self, value): + Util.type_check(value, float, "source_number_density") + Util.value_check(value, 0, 1E10, "source_number_density") + self._source_number_density = value + + @property + def background(self): + """The flux in the sky (background). + + units: Jy/pix + type: float + """ + return self._background + + @background.setter + def background(self, value): + Util.type_check(value, float, "background") + Util.value_check(value, 0, 1E10, "background") + self._background = value + + @property + def background_std_dev(self): + """the standard deviation (per pixel) in background flux. + + Likely this only makes sense to define if background is also defined. + units: Jy/pix + type: float + """ + return self._background_std_dev + + @background_std_dev.setter + def background_std_dev(self, value): + Util.type_check(value, float, "background_std_dev") + Util.value_check(value, 0, 1E10, "background") + self._background_std_dev = value + + @property + def flux_density_limit(self): + """flux density where S:N=5 for point source. + + this is intended to provide a measure of the limit of detection. + + units: Jy + type: float + """ + return self._flux_density_limit + + @flux_density_limit.setter + def flux_density_limit(self, value): + Util.type_check(value, float, "flux_denisty_limit") + Util.value_check(value, 0, 1E10, "flux_density_limit") + self._flux_density_limit = value + + @property + def mag_limit(self): + """AB magnitude limit where S:N=5 for point source. + + Likely specify just mag_limit or flux_density_limit, not both? + + units: AB mag + type: float + """ + return self._mag_limit + + @mag_limit.setter + def mag_limit(self, value): + Util.type_check(value, float, 'mag_limit') + Util.value_check(value, 0, 40, 'mag_limit') + self._mag_limit = value + + +class Provenance(CaomObject): + """ Provenance """ + + def __init__(self, name, + version=None, + project=None, + producer=None, + run_id=None, + reference=None, + last_executed=None): + """ + Initializes a Provenance instance + + Arguments: + name - name of the provenance + """ + + assert name is not None, "No name provided" + assert isinstance(name, str), "name is not a str: {0}".format(name) + self._name = name + + self.version = version + self.project = project + self.producer = producer + self.run_id = run_id + self.reference = reference + self.last_executed = last_executed + + self._keywords = set() + self._inputs = TypedSet((PlaneURI),) + + # Properties + + @property + def name(self): + """ Name """ + return self._name + + @property + def version(self): + """ Version """ + return self._version + + @version.setter + def version(self, value): + Util.type_check(value, str, 'version') + self._version = value + + @property + def project(self): + """ Project """ + return self._project + + @project.setter + def project(self, value): + Util.type_check(value, str, 'project') + self._project = value + + @property + def producer(self): + """ Producer """ + return self._producer + + @producer.setter + def producer(self, value): + Util.type_check(value, str, 'producer') + self._producer = value + + @property + def run_id(self): + """ Run ID """ + return self._run_id + + @run_id.setter + def run_id(self, value): + Util.type_check(value, str, 'run_id') + self._run_id = value + + @property + def reference(self): + """ Reference """ + return self._reference + + @reference.setter + def reference(self, value): + Util.type_check(value, str, 'version') + if value is not None: + tmp = urlsplit(value) + assert tmp.geturl() == value, "Invalid URI: " + value + self._reference = value + + @property + def last_executed(self): + """ Version """ + return self._last_executed + + @last_executed.setter + def last_executed(self, value): + Util.type_check(value, datetime, 'last_executed') + self._last_executed = value + + @property + def keywords(self): + """ Set of keywords as str""" + return self._keywords + + @property + def inputs(self): + """ Set of inputs as PlaneURI""" + return self._inputs + + +class Position(CaomObject): + """ Position """ + + def __init__(self, bounds=None, + dimension=None, + resolution=None, + sample_size=None, + time_dependent=None + ): + """ + Initialize a Position instance. + + Arguments: + None + """ + self.bounds = bounds + self.dimension = dimension + self.resolution = resolution + self.sample_size = sample_size + self.time_dependent = time_dependent + + # Properties + + @property + def bounds(self): + """ Bounds """ + return self._bounds + + @bounds.setter + def bounds(self, value): + if value is not None: + assert isinstance(value, (Box, Circle, Polygon)), ( + "bounds is not a Shape: {0}".format(value)) + self._bounds = value + + @property + def dimension(self): + """ Dimension """ + return self._dimension + + @dimension.setter + def dimension(self, value): + if value is not None: + assert isinstance(value, Dimension2D), ( + "dimension is not a Dimension2D: {0}".format(value)) + self._dimension = value + + @property + def resolution(self): + """ Resolution """ + return self._resolution + + @resolution.setter + def resolution(self, value): + if value is not None: + assert isinstance(value, float), ( + "resolution is not a float: {0}".format(value)) + self._resolution = value + + @property + def sample_size(self): + """ Sample size """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + if value is not None: + assert isinstance(value, float), ( + "sample size is not a float: {0}".format(value)) + self._sample_size = value + + @property + def time_dependent(self): + """ Time dependent """ + return self._time_dependent + + @time_dependent.setter + def time_dependent(self, value): + if value is not None: + assert isinstance(value, bool), ( + "time dependent is not a bool: {0}".format(value)) + self._time_dependent = value + + +class Energy(CaomObject): + """ Energy """ + + def __init__(self): + """ + Initialize an Energy instance. + + Arguments: + None + """ + self._value = None + self._bounds = None + self._dimension = None + self._resolving_power = None + self._sample_size = None + self._bandpass_name = None + self._em_band = None + self._transition = None + + # Properties + @property + def value(self): + """ Energy value """ + return self._value + + @value.setter + def value(self, value): + if value is not None: + assert isinstance(value, float), ( + "energy value is not a float: {0}".format(value)) + self._value = value + + @property + def bounds(self): + """ Energy bounds """ + return self._bounds + + @bounds.setter + def bounds(self, value): + if value is not None: + assert isinstance(value, Interval), ( + "energy bounds is not an Interval: {0}".format(value)) + self._bounds = value + + @property + def dimension(self): + """DIMENSION (NUMBER OF PIXELS) ALONG ENERGY AXIS.""" + return self._dimension + + @dimension.setter + def dimension(self, value): + if value is not None: + assert isinstance(value, long), ( + "energy dimension is not a long: {0}".format(value)) + self._dimension = value + + @property + def resolving_power(self): + """ Resolving power """ + return self._resolving_power + + @resolving_power.setter + def resolving_power(self, value): + if value is not None: + assert isinstance(value, float), ( + "resolving power is not a float: {0}".format(value)) + self._resolving_power = value + + @property + def sample_size(self): + """ Sample size """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + if value is not None: + assert isinstance(value, float), ( + "sample size is not a float: {0}".format(value)) + self._sample_size = value + + @property + def bandpass_name(self): + """ Bandpass name """ + return self._bandpass_name + + @bandpass_name.setter + def bandpass_name(self, value): + if value is not None: + assert isinstance(value, str), ( + "bandpass name is not str: {0}".format(value)) + self._bandpass_name = value + + @property + def em_band(self): + """ EM Band """ + return self._em_band + + @em_band.setter + def em_band(self, value): + if value is not None: + assert isinstance(value, EnergyBand), ( + "em_Band is not an EnergyBand: {0}".format(value)) + self._em_band = value + + @property + def transition(self): + """ Energy transition """ + return self._transition + + @transition.setter + def transition(self, value): + if value is not None: + assert isinstance(value, EnergyTransition), ( + "transition is not an EnergyTransition: {0}".format(value)) + self._transition = value + + +class EnergyTransition(CaomObject): + """ EnergyTransition """ + + def __init__(self, species, transition): + """ + Construct an EnergyTransition instance + + Arguments: + species + transition + """ + Util.type_check(species, str, "species", override=False) + Util.type_check(transition, str, "transition", override=False) + self._species = species + self._transition = transition + + @property + def species(self): + """ Species """ + return self._species + + @property + def transition(self): + """ Transition """ + return self._transition + + +class Polarization(CaomObject): + """ Polarization """ + + def __init__(self, + dimension=None, + polarization_states=None): + """ + Initialize a Polarization instance. + + Arguments: + None + """ + self.dimension = dimension + self.polarization_states = polarization_states + + # Properties + @property + def dimension(self): + """number of samples (pixels) along polarization axis. + + unit: pix + type: int + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + Util.type_check(value, int, 'dimension') + Util.value_check(value, 0, 1E10, 'dimension') + self._dimension = value + + +class Time(CaomObject): + """ Time """ + + def __init__(self, + value=None, + bounds=None, + dimension=None, + resolution=None, + sample_size=None, + exposure=None): + """ + Initialize a Time instance. + + Arguments: + None + """ + self.value = value + self.bounds = bounds + self.dimension = dimension + self.resolution = resolution + self.sample_size = sample_size + self.exposure = exposure + + # Properties + + @property + def value(self): + """ Actual time value, seconds since epoch. + + quesion is, what epoch? + + units: s + """ + return self._value + + @value.setter + def value(self, value): + Util.type_check(value, float, 'value') + self._value = value + + @property + def bounds(self): + """an interval object that gives start and end of an time interval + + Not actually implemented yet. Likely you want a TemporalWCS + instead + + type: Interval(lower_mjd, upper_mjd) + unit: mjd + + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + Util.type_check(value, Interval, 'bounds') + self._bounds = value + + @property + def dimension(self): + """Number of pixel in the time direction, normally 1. + + eg 1 + type: long + + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + Util.type_check(value, long, 'dimension') + self._dimension = value + + @property + def resolution(self): + """Time resolution of the samples, in seconds. + + normally this is the same as the exposure time, + but in a stack you might have a larger resolution value than + exposure time. + + eg. 1000 + unit: s + type: float + + """ + return self._resolution + + @resolution.setter + def resolution(self, value): + Util.type_check(value, float, 'resolution') + self._resolution = value + + @property + def sample_size(self): + """nominally the exposure time, in seconds. + + """ + return self._sample_size + + @sample_size.setter + def sample_size(self, value): + Util.type_check(value, float, 'sample_size') + self._sample_size = value + + @property + def exposure(self): + """Duration of the exposure, in seconds""" + return self._exposure + + @exposure.setter + def exposure(self, value): + Util.type_check(value, float, 'exposure') + self._exposure = value + diff --git a/caom2tools/caom2/tests/test/test_caom2instances.py b/caom2tools/caom2/tests/caom_test_instances.py similarity index 86% rename from caom2tools/caom2/tests/test/test_caom2instances.py rename to caom2tools/caom2/tests/caom_test_instances.py index 75043ec1..ad0e1b21 100644 --- a/caom2tools/caom2/tests/test/test_caom2instances.py +++ b/caom2tools/caom2/tests/caom_test_instances.py @@ -73,57 +73,57 @@ import collections from datetime import datetime -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_artifact import Artifact -from caom2.caom2_chunk import Chunk -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_energy_transition import EnergyTransition -from caom2.caom2_enums import CalibrationLevel -from caom2.caom2_enums import DataProductType -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import ProductType -from caom2.caom2_enums import Quality -from caom2.caom2_enums import Status -from caom2.caom2_enums import TargetType -from caom2.caom2_enums import ReleaseType -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_metrics import Metrics -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane -from caom2.caom2_plane_uri import PlaneURI -from caom2.caom2_proposal import Proposal -from caom2.caom2_provenance import Provenance -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedList, TypedSet -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS -from caom2.wcs.caom2_ref_coord import RefCoord -from caom2.wcs.caom2_slice import Slice -from caom2.wcs.caom2_spatial_wcs import SpatialWCS -from caom2.wcs.caom2_spectral_wcs import SpectralWCS -from caom2.wcs.caom2_temporal_wcs import TemporalWCS -from caom2.wcs.caom2_value_coord2d import ValueCoord2D +# from caom2.caom2_algorithm import Algorithm +# from caom2.artifact import Artifact +# from caom2.chunk import Chunk +# from caom2.caom2_composite_observation import CompositeObservation +# from caom2.caom2_data_quality import DataQuality +# from caom2.caom2_energy_transition import EnergyTransition +# from caom2.caom_enums import CalibrationLevel +# from caom2.caom_enums import DataProductType +# from caom2.caom_enums import ObservationIntentType +# from caom2.caom_enums import ProductType +# from caom2.caom_enums import Quality +# from caom2.caom_enums import Status +# from caom2.caom_enums import TargetType +# from caom2.caom_enums import ReleaseType +# from caom2.caom2_environment import Environment +# from caom2.caom2_instrument import Instrument +# from caom2.caom2_metrics import Metrics +# from caom2.caom2_observation_uri import ObservationURI +# from caom2.part import Part +# from caom2.plane import Plane +# from caom2.caom2_plane_uri import PlaneURI +# from caom2.caom2_proposal import Proposal +# from caom2.caom2_provenance import Provenance +# from caom2.caom2_requirements import Requirements +# from caom2.caom2_simple_observation import SimpleObservation +# from caom2.caom2_target import Target +# from caom2.caom2_target_position import TargetPosition +# from caom2.caom2_telescope import Telescope +# from caom2.data_type.caom2_point import Point +# from caom2.util.caom2_util import TypedList, TypedSet +# from caom2.wcs.caom2_axis import Axis +# from caom2.wcs.caom2_coord2d import Coord2D +# from caom2.wcs.caom2_coord_axis1d import CoordAxis1D +# from caom2.wcs.caom2_coord_axis2d import CoordAxis2D +# from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D +# from caom2.wcs.caom2_coord_circle2d import CoordCircle2D +# from caom2.wcs.caom2_coord_error import CoordError +# from caom2.wcs.caom2_coord_function1d import CoordFunction1D +# from caom2.wcs.caom2_coord_function2d import CoordFunction2D +# from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D +# from caom2.wcs.caom2_coord_range1d import CoordRange1D +# from caom2.wcs.caom2_coord_range2d import CoordRange2D +# from caom2.wcs.caom2_dimension2d import Dimension2D +# from caom2.wcs.caom2_observable_axis import ObservableAxis +# from caom2.wcs.caom2_polarization_wcs import PolarizationWCS +# from caom2.wcs.caom2_ref_coord import RefCoord +# from caom2.wcs.caom2_slice import Slice +# from caom2.wcs.caom2_spatial_wcs import SpatialWCS +# from caom2.wcs.caom2_spectral_wcs import SpectralWCS +# from caom2.wcs.caom2_temporal_wcs import TemporalWCS +# from caom2.wcs.caom2_value_coord2d import ValueCoord2D class Caom2TestInstances(object): diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositeCircle.xml b/caom2tools/caom2/tests/data/CompleteCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositeCircle.xml rename to caom2tools/caom2/tests/data/CompleteCompositeCircle.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteCompositePolygon.xml b/caom2tools/caom2/tests/data/CompleteCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteCompositePolygon.xml rename to caom2tools/caom2/tests/data/CompleteCompositePolygon.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimpleCircle.xml b/caom2tools/caom2/tests/data/CompleteSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimpleCircle.xml rename to caom2tools/caom2/tests/data/CompleteSimpleCircle.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/CompleteSimplePolygon.xml b/caom2tools/caom2/tests/data/CompleteSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/CompleteSimplePolygon.xml rename to caom2tools/caom2/tests/data/CompleteSimplePolygon.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositeCircle.xml b/caom2tools/caom2/tests/data/MinimalCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositeCircle.xml rename to caom2tools/caom2/tests/data/MinimalCompositeCircle.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalCompositePolygon.xml b/caom2tools/caom2/tests/data/MinimalCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalCompositePolygon.xml rename to caom2tools/caom2/tests/data/MinimalCompositePolygon.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimpleCircle.xml b/caom2tools/caom2/tests/data/MinimalSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimpleCircle.xml rename to caom2tools/caom2/tests/data/MinimalSimpleCircle.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/test/data/MinimalSimplePolygon.xml b/caom2tools/caom2/tests/data/MinimalSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/test/data/MinimalSimplePolygon.xml rename to caom2tools/caom2/tests/data/MinimalSimplePolygon.xml diff --git a/caom2tools/caom2/tests/test/setup_package.py b/caom2tools/caom2/tests/setup_package.py similarity index 100% rename from caom2tools/caom2/tests/test/setup_package.py rename to caom2tools/caom2/tests/setup_package.py diff --git a/caom2tools/caom2/tests/test/test_algorithm.py b/caom2tools/caom2/tests/test/test_algorithm.py deleted file mode 100644 index 09d5cd19..00000000 --- a/caom2tools/caom2/tests/test/test_algorithm.py +++ /dev/null @@ -1,87 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestAlgorithm class """ - -import unittest - -from caom2.caom2_algorithm import Algorithm - - -class TestAlgorithm(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("myAlgorithm") - self.assertEqual("myAlgorithm", algorithm.name, "Algorithm name") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_axis.py b/caom2tools/caom2/tests/test/test_axis.py deleted file mode 100644 index c36dcb1f..00000000 --- a/caom2tools/caom2/tests/test/test_axis.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestAxis class """ -import unittest - -from caom2.wcs.caom2_axis import Axis - - -class TestAxis(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, Axis, None, None) - self.assertRaises(TypeError, Axis, None, "cunit") - self.assertRaises(TypeError, Axis, "ctype", int(1)) - self.assertRaises(TypeError, Axis, int(1), "cunit") - - axis = Axis("ctype", "cunit") - self.assertEqual(axis.ctype, "ctype") - self.assertEqual(axis.cunit, "cunit") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_caom2_enums.py b/caom2tools/caom2/tests/test/test_caom2_enums.py deleted file mode 100644 index 075a3462..00000000 --- a/caom2tools/caom2/tests/test/test_caom2_enums.py +++ /dev/null @@ -1,161 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCaom2Enums class """ - -import unittest - -from caom2.caom2_enums import EnergyBand, CalibrationLevel, ProductType - - -class TestCaom2Enums(unittest.TestCase): - - # EnergyBand and CalibrationLevel are used to test the open source - # Enum package that the Caom2Enums use. Caom2Enums only use a subset - # of the features provided by the Enum package. Only these subset - # features are tested. - def testToOBject(self): - # test for invalid value - self.assertEqual(EnergyBand.get("no_such_string"), None) - self.assertEqual(EnergyBand.get("g"), None) - self.assertEqual(EnergyBand.get("no_such_string"), None) - self.assertRaises(AttributeError, EnergyBand.get, None) - self.assertRaises(AttributeError, EnergyBand.get, 1) - # test that we can get the object for each enum by name - self.assertEqual(CalibrationLevel.CALIBRATED.name, "CALIBRATED", - "incorrect enum name") - self.assertEqual(CalibrationLevel.get(CalibrationLevel.CALIBRATED.name) - .name, "CALIBRATED") - self.assertEqual(CalibrationLevel.get('CALIBRATED').value, 2) - self.assertEqual(CalibrationLevel.get(CalibrationLevel.CALIBRATED.name) - .value, 2) - self.assertEqual(CalibrationLevel. - getByValue(CalibrationLevel.CALIBRATED.value) - .value, 2) - self.assertEqual(CalibrationLevel. - getByValue(CalibrationLevel.CALIBRATED.value).name, - "CALIBRATED") - self.assertEqual(EnergyBand.get('RADIO').value, "Radio") - self.assertEqual(EnergyBand.get('MILLIMETER').value, "Millimeter") - self.assertEqual(EnergyBand.get('INFRARED').value, "Infrared") - self.assertEqual(EnergyBand.get('OPTICAL').value, "Optical") - self.assertEqual(EnergyBand.get('UV').value, "UV") - self.assertEqual(EnergyBand.get('EUV').value, "EUV") - self.assertEqual(EnergyBand.get('XRAY').value, "X-ray") - self.assertEqual(EnergyBand.get('GAMMARAY').value, "Gamma-ray") - # test that we can get the object for each enum by value - self.assertEqual(EnergyBand.getByValue(EnergyBand.RADIO.value).value, - "Radio") - self.assertEqual(EnergyBand.getByValue(EnergyBand.MILLIMETER.value) - .value, "Millimeter") - self.assertEqual(EnergyBand.getByValue(EnergyBand.INFRARED.value) - .value, "Infrared") - self.assertEqual(EnergyBand.getByValue(EnergyBand.OPTICAL.value) - .value, "Optical") - self.assertEqual(EnergyBand.getByValue(EnergyBand.UV.value).value, - "UV") - self.assertEqual(EnergyBand.getByValue(EnergyBand.EUV.value).value, - "EUV") - self.assertEqual(EnergyBand.getByValue(EnergyBand.XRAY.value).value, - "X-ray") - self.assertEqual(EnergyBand.getByValue(EnergyBand.GAMMARAY.value) - .value, "Gamma-ray") - - def testGetValue(self): - # test that we can get each enum value - self.assertEqual(EnergyBand.RADIO.value, "Radio") - self.assertEqual(EnergyBand.MILLIMETER.value, "Millimeter") - self.assertEqual(EnergyBand.INFRARED.value, "Infrared") - self.assertEqual(EnergyBand.OPTICAL.value, "Optical") - self.assertEqual(EnergyBand.UV.value, "UV") - self.assertEqual(EnergyBand.EUV.value, "EUV") - self.assertEqual(EnergyBand.XRAY.value, "X-ray") - self.assertEqual(EnergyBand.GAMMARAY.value, "Gamma-ray") - - def testSetValue(self): - # test that we cannot change an enum value - self.assertRaises(TypeError, EnergyBand.RADIO.value, "InvalidValue") - self.assertRaises(TypeError, EnergyBand.RADIO.name, "InvalidName") - - def testProductType(self): - # test that we can get each enum value - self.assertEqual(ProductType.AUXILIARY.value, "auxiliary") - self.assertEqual(ProductType.CALIBRATION.value, "calibration") - self.assertEqual(ProductType.INFO.value, "info") - self.assertEqual(ProductType.PREVIEW.value, "preview") - self.assertEqual(ProductType.SCIENCE.value, "science") - self.assertEqual(ProductType.THUMBNAIL.value, "thumbnail") - self.assertEqual(ProductType.NOISE.value, "noise") - self.assertEqual(ProductType.WEIGHT.value, "weight") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_composite_observation.py b/caom2tools/caom2/tests/test/test_composite_observation.py deleted file mode 100644 index 06d96cd1..00000000 --- a/caom2tools/caom2/tests/test/test_composite_observation.py +++ /dev/null @@ -1,278 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCompositeObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedOrderedDict - - -class TestCompositeObservation(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("mozaic") - obs = CompositeObservation("GSA", "A12345", algorithm) - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - obs.algorithm = algorithm - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - # try to set algorithm to an invalid value - exception = False - try: - obs.algorithm = SimpleObservation._ALGORITHM - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - # try to set algorithm to None - exception = False - try: - obs.algorithm = None - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - self.assertEqual(0, len(obs.members), "Members") - observationURI1 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI1) - self.assertEqual(1, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - - observationURI2 = ObservationURI("caom:collection/obsID2") - obs.members.add(observationURI2) - self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) - - #duplicates - observationURI3 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI3) - self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) - - # run the rest of the Observation tests - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, - obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, - obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, - obs.target, "Target") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEquals(requirements, obs.requirements, "requirements") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - # Test the complete constructor - def testCompleteInit(self): - collection = str("CFHT") - observationID = str("543210") - algorithm = str("algo") - sequence_number = int(3) - intent = ObservationIntentType.SCIENCE - obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") - meta_release = datetime.now() - planes = TypedOrderedDict((Plane),) - environment = Environment() - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - - obs = CompositeObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position) - - self.assertIsNotNone(obs.collection, "Collection") - self.assertEqual(collection, obs.collection, "Collection") - - self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") - - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - self.assertIsNotNone(obs.intent, "Observation intent") - self.assertEqual(intent, obs.intent, "Observation intent") - - self.assertIsNotNone(obs.obs_type, "obs type") - self.assertEqual(obs_type, obs.obs_type, "obs type") - - self.assertIsNotNone(obs.proposal, "Proposal") - self.assertEqual(proposal, obs.proposal, "Proposal") - - self.assertIsNotNone(obs.telescope, "Telescope") - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNotNone(obs.instrument, "Instrument") - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNotNone(obs.target, "Target") - self.assertEqual(target, obs.target, "Target") - - self.assertIsNotNone(obs.meta_release, "Metadata release") - self.assertEqual(meta_release, obs.meta_release, "Metadata release") - - self.assertIsNotNone(obs.planes, "Planes") - self.assertEqual(planes, obs.planes, "Planes") - - self.assertIsNotNone(obs.environment, "Environment") - self.assertEqual(environment, obs.environment, "Environment") - - self.assertIsNotNone(obs.target_position, "TargetPosition") - self.assertEqual(target_position, obs.target_position, - "TargetPosition") - - # Try changing the algorithm - algorithm2 = str("new algo") - obs.algorithm = algorithm2 - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertNotEqual(algorithm, obs.algorithm, "Algorithm") - self.assertEqual(algorithm2, obs.algorithm, "Algorithm") - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_coord2d.py b/caom2tools/caom2/tests/test/test_coord2d.py deleted file mode 100644 index df3c2eef..00000000 --- a/caom2tools/caom2/tests/test/test_coord2d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoord2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoord2D(unittest.TestCase): - - def testInit(self): - - coord1 = RefCoord(float(1.0), float(2.0)) - coord2 = RefCoord(float(3.0), float(4.0)) - - self.assertRaises(TypeError, Coord2D, None, None) - self.assertRaises(TypeError, Coord2D, None, coord2) - self.assertRaises(TypeError, Coord2D, coord1, None) - self.assertRaises(TypeError, Coord2D, str("s"), coord2) - self.assertRaises(TypeError, Coord2D, coord1, str("s")) - - coord_2d = Coord2D(coord1, coord2) - self.assertEqual(coord_2d.coord1, coord1) - self.assertEqual(coord_2d.coord2, coord2) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_axis1d.py b/caom2tools/caom2/tests/test/test_coord_axis1d.py deleted file mode 100644 index e8bd5a21..00000000 --- a/caom2tools/caom2/tests/test/test_coord_axis1d.py +++ /dev/null @@ -1,124 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordAxis1D class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordAxis1D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordAxis1D, None) - self.assertRaises(TypeError, CoordAxis1D, int(1)) - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - self.assertEqual(axis_1d.axis, axis) - with self.assertRaises(TypeError): - axis_1d.error = str("s") - axis_1d.bounds = str("s") - axis_1d.function = str("s") - axis_1d.range = str("s") - - error = CoordError(float(1.0), float(2.0)) - axis_1d.error = error - self.assertEqual(axis_1d.error, error) - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - coordRange = CoordRange1D(start, end) - axis_1d.range = coordRange - self.assertEqual(axis_1d.range, coordRange) - - bounds = CoordBounds1D() - axis_1d.bounds = bounds - self.assertEqual(axis_1d.bounds, bounds) - - naxis = long(1) - delta = float(2.5) - ref_coord = RefCoord(float(1.0), float(2.0)) - function = CoordFunction1D(naxis, delta, ref_coord) - axis_1d.function = function - self.assertEqual(axis_1d.function, function) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_axis2d.py b/caom2tools/caom2/tests/test/test_coord_axis2d.py deleted file mode 100644 index 141e25a6..00000000 --- a/caom2tools/caom2/tests/test/test_coord_axis2d.py +++ /dev/null @@ -1,149 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordAxis2D class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_error import CoordError -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_ref_coord import RefCoord -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordAxis2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordAxis2D, None, None) - self.assertRaises(TypeError, CoordAxis2D, None, int(1)) - self.assertRaises(TypeError, CoordAxis2D, int(1), None) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - self.assertEqual(axis_2d.axis1, axis1) - self.assertEqual(axis_2d.axis2, axis2) - with self.assertRaises(TypeError): - axis_2d.error1 = str("s") - axis_2d.error2 = str("s") - axis_2d.bounds = str("s") - axis_2d.function = str("s") - axis_2d.range = str("s") - - error1 = CoordError(float(1.0), float(2.0)) - axis_2d.error1 = error1 - self.assertEqual(axis_2d.error1, error1) - - error2 = CoordError(float(3.0), float(4.0)) - axis_2d.error2 = error2 - self.assertEqual(axis_2d.error2, error2) - - start = Coord2D(RefCoord(float(1.0), float(2.0)), - RefCoord(float(3.0), float(4.0))) - end = Coord2D(RefCoord(float(5.0), float(6.0)), - RefCoord(float(7.0), float(8.0))) - coordRange = CoordRange2D(start, end) - axis_2d.range = coordRange - self.assertEqual(axis_2d.range, coordRange) - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - circle = CoordCircle2D(center, radius) - axis_2d.bounds = circle - self.assertEqual(axis_2d.bounds, circle) - - polygon = CoordPolygon2D() - axis_2d.bounds = polygon - self.assertEqual(axis_2d.bounds, polygon) - - dimension = Dimension2D(long(1), long(2)) - ref_coord = Coord2D(RefCoord(float(9.0), float(10.0)), - RefCoord(float(11.0), float(12.0))) - cd11 = float(1.1) - cd12 = float(1.2) - cd21 = float(2.1) - cd22 = float(2.2) - function = CoordFunction2D(dimension, ref_coord, - cd11, cd12, cd21, cd22) - axis_2d.function = function - self.assertEqual(axis_2d.function, function) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_bounds1d.py b/caom2tools/caom2/tests/test/test_coord_bounds1d.py deleted file mode 100644 index 000ee8b0..00000000 --- a/caom2tools/caom2/tests/test/test_coord_bounds1d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordBounds1D class """ - -import unittest - -from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordBounds1D(unittest.TestCase): - - def testInit(self): - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - coordRange = CoordRange1D(start, end) - - bounds = CoordBounds1D() - bounds.samples.append(coordRange) - self.assertTrue(bounds.samples.count(coordRange) == 1) - self.assertEqual(bounds.samples.pop(), coordRange) - - with self.assertRaises(TypeError): - bounds.samples = [str("s")] - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_bounds2d.py b/caom2tools/caom2/tests/test/test_coord_bounds2d.py deleted file mode 100644 index d19f8f5f..00000000 --- a/caom2tools/caom2/tests/test/test_coord_bounds2d.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordBounds2D class """ - -import unittest - -from caom2.wcs.caom2_coord_bounds2d import CoordBounds2D -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordBounds2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, CoordBounds2D, None) - self.assertRaises(TypeError, CoordBounds2D, float(1.0)) - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - circle = CoordCircle2D(center, radius) - - polygon = CoordPolygon2D() - polygon.vertices.append(ValueCoord2D(float(1.0), float(2.0))) - - bounds = CoordBounds2D(circle) - self.assertEqual(bounds.bounds, circle) - - bounds = CoordBounds2D(polygon) - self.assertEqual(bounds.bounds, polygon) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_coord_circle2d.py b/caom2tools/caom2/tests/test/test_coord_circle2d.py deleted file mode 100644 index 940763da..00000000 --- a/caom2tools/caom2/tests/test/test_coord_circle2d.py +++ /dev/null @@ -1,98 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordCircle2D class """ - -import unittest - -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordCircle2D(unittest.TestCase): - - def testInit(self): - - center = ValueCoord2D(float(1.0), float(2.0)) - radius = float(1.5) - - self.assertRaises(TypeError, CoordCircle2D, None, None) - self.assertRaises(TypeError, CoordCircle2D, None, radius) - self.assertRaises(TypeError, CoordCircle2D, center, None) - self.assertRaises(TypeError, CoordCircle2D, int(1), radius) - self.assertRaises(TypeError, CoordCircle2D, center, int(1)) - - circle = CoordCircle2D(center, radius) - self.assertEqual(circle.center, center) - self.assertEqual(circle.radius, radius) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_coord_error.py b/caom2tools/caom2/tests/test/test_coord_error.py deleted file mode 100644 index ea7d3b12..00000000 --- a/caom2tools/caom2/tests/test/test_coord_error.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordError class """ - -import unittest - -from caom2.wcs.caom2_coord_error import CoordError - - -class TestCoordError(unittest.TestCase): - - def testInit(self): - self.assertRaises(TypeError, CoordError, None, None) - self.assertRaises(TypeError, CoordError, None, float(1.0)) - self.assertRaises(TypeError, CoordError, float(1.0), None) - self.assertRaises(TypeError, CoordError, int(1), float(1.0)) - self.assertRaises(TypeError, CoordError, float(1.0), int(1)) - - error = CoordError(float(1), float(2)) - print error.rnder - self.assertIsNotNone(error) - self.assertEqual(error.syser, float(1)) - self.assertEqual(error.rnder, float(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_function1d.py b/caom2tools/caom2/tests/test/test_coord_function1d.py deleted file mode 100644 index f945084d..00000000 --- a/caom2tools/caom2/tests/test/test_coord_function1d.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordFunction1D class """ - -import unittest - -from caom2.wcs.caom2_coord_function1d import CoordFunction1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordFunction1D(unittest.TestCase): - - def testInit(self): - - naxis = long(1) - delta = float(2.5) - ref_coord = RefCoord(float(1.0), float(2.0)) - - self.assertRaises(TypeError, CoordFunction1D, None, None, - None) - self.assertRaises(TypeError, CoordFunction1D, None, delta, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, None, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, delta, - None) - self.assertRaises(TypeError, CoordFunction1D, int(1), delta, - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, int(1), - ref_coord) - self.assertRaises(TypeError, CoordFunction1D, naxis, delta, - int(1)) - - function = CoordFunction1D(naxis, delta, ref_coord) - self.assertEqual(function.naxis, naxis) - self.assertEqual(function.delta, delta) - self.assertEqual(function.ref_coord, ref_coord) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_function2d.py b/caom2tools/caom2/tests/test/test_coord_function2d.py deleted file mode 100644 index 3115d93d..00000000 --- a/caom2tools/caom2/tests/test/test_coord_function2d.py +++ /dev/null @@ -1,117 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordFunction2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_function2d import CoordFunction2D -from caom2.wcs.caom2_dimension2d import Dimension2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordFunction2D(unittest.TestCase): - - def testInit(self): - - dimension = Dimension2D(long(1), long(2)) - ref_coord = Coord2D(RefCoord(float(9.0), float(10.0)), - RefCoord(float(11.0), float(12.0))) - cd11 = float(1.1) - cd12 = float(1.2) - cd21 = float(2.1) - cd22 = float(2.2) - - self.assertRaises(TypeError, CoordFunction2D, None, - ref_coord, cd11, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - None, cd11, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, None, cd12, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, None, cd21, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, cd12, None, cd22) - self.assertRaises(TypeError, CoordFunction2D, dimension, - ref_coord, cd11, cd12, cd21, None) - - function = CoordFunction2D(dimension, ref_coord, - cd11, cd12, cd21, cd22) - self.assertEqual(function.dimension, dimension) - self.assertEqual(function.ref_coord, ref_coord) - self.assertEqual(function.cd11, cd11) - self.assertEqual(function.cd12, cd12) - self.assertEqual(function.cd21, cd21) - self.assertEqual(function.cd22, cd22) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_coord_polygon2d.py b/caom2tools/caom2/tests/test/test_coord_polygon2d.py deleted file mode 100644 index 53218dbd..00000000 --- a/caom2tools/caom2/tests/test/test_coord_polygon2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordPolygon2D class """ - -import unittest - -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestCoordPolygon2D(unittest.TestCase): - - def testInit(self): - - value_coord2d = ValueCoord2D(float(1.0), float(2.0)) - - polygon = CoordPolygon2D() - polygon.vertices.append(value_coord2d) - self.assertTrue(polygon.vertices.count(value_coord2d) == 1) - self.assertEqual(polygon.vertices.pop(), value_coord2d) - - with self.assertRaises(TypeError): - polygon.vertices = [str("s")] - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_coord_range1d.py b/caom2tools/caom2/tests/test/test_coord_range1d.py deleted file mode 100644 index e057a2c9..00000000 --- a/caom2tools/caom2/tests/test/test_coord_range1d.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordRange1D class """ - -import unittest - -from caom2.wcs.caom2_coord_range1d import CoordRange1D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordRange1D(unittest.TestCase): - - def testInit(self): - - start = RefCoord(float(1.0), float(2.0)) - end = RefCoord(float(3.0), float(4.0)) - - self.assertRaises(TypeError, CoordRange1D, None, None) - self.assertRaises(TypeError, CoordRange1D, None, end) - self.assertRaises(TypeError, CoordRange1D, start, None) - self.assertRaises(TypeError, CoordRange1D, int(1), end) - self.assertRaises(TypeError, CoordRange1D, start, int(1)) - - coordRange = CoordRange1D(start, end) - self.assertEqual(coordRange.start, start) - self.assertEqual(coordRange.end, end) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_coord_range2d.py b/caom2tools/caom2/tests/test/test_coord_range2d.py deleted file mode 100644 index ab88709a..00000000 --- a/caom2tools/caom2/tests/test/test_coord_range2d.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestCoordRange2D class """ - -import unittest - -from caom2.wcs.caom2_coord2d import Coord2D -from caom2.wcs.caom2_coord_range2d import CoordRange2D -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestCoordRange2D(unittest.TestCase): - - def testInit(self): - - start = Coord2D(RefCoord(float(1.0), float(2.0)), - RefCoord(float(3.0), float(4.0))) - end = Coord2D(RefCoord(float(5.0), float(6.0)), - RefCoord(float(7.0), float(8.0))) - - self.assertRaises(TypeError, CoordRange2D, None, None) - self.assertRaises(TypeError, CoordRange2D, None, end) - self.assertRaises(TypeError, CoordRange2D, start, None) - self.assertRaises(TypeError, CoordRange2D, int(1), end) - self.assertRaises(TypeError, CoordRange2D, start, int(1)) - - coordRange = CoordRange2D(start, end) - self.assertEqual(coordRange.start, start) - self.assertEqual(coordRange.end, end) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_data_quality.py b/caom2tools/caom2/tests/test/test_data_quality.py deleted file mode 100644 index b4ebdb4b..00000000 --- a/caom2tools/caom2/tests/test/test_data_quality.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestDataQuality class """ - -import unittest - -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_enums import Quality - - -class TestDataQuality(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, DataQuality, "string") - quality = DataQuality(Quality.JUNK) - self.assertEqual(Quality.JUNK, quality.flag, - "DataQuality flag") - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_dimension2d.py b/caom2tools/caom2/tests/test/test_dimension2d.py deleted file mode 100644 index d666e2b1..00000000 --- a/caom2tools/caom2/tests/test/test_dimension2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestDimension2D class """ - -import unittest - -from caom2.wcs.caom2_dimension2d import Dimension2D - - -class TestDimension2D(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, Dimension2D, None, None) - self.assertRaises(TypeError, Dimension2D, long(1), None) - self.assertRaises(TypeError, Dimension2D, None, long(1)) - self.assertRaises(TypeError, Dimension2D, int(1), long(1)) - self.assertRaises(TypeError, Dimension2D, long(1), int(1)) - - dimension = Dimension2D(long(1), long(2)) - self.assertEqual(dimension.naxis1, long(1)) - self.assertEqual(dimension.naxis2, long(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_energy.py b/caom2tools/caom2/tests/test/test_energy.py deleted file mode 100644 index b233c1d8..00000000 --- a/caom2tools/caom2/tests/test/test_energy.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnergy class """ - -import unittest - -from caom2.caom2_energy import Energy -from caom2.caom2_enums import EnergyBand - - -class TestEnergy(unittest.TestCase): - - def testAll(self): - energy = Energy() - self.assertIsNone(energy.value, "Default energy value") - energy.value = 33.33 - self.assertEqual(33.33, energy.value, "Energy value") - self.assertIsNone(energy.bounds, "Default energy bounds") - #TODO switch to Interval - #energy.bounds = 22 - self.assertIsNone(energy.dimension, "Default energy dimension") - energy.dimension = 1000L - self.assertEqual(1000L, energy.dimension, "Energy dimension") - self.assertIsNone(energy.resolving_power, - "Default energy resolving power") - energy.resolving_power = 123.12 - self.assertEqual(123.12, energy.resolving_power, - "Energy resolving power") - self.assertIsNone(energy.sample_size, "Default energy sample size") - energy.sample_size = 123.321 - self.assertEqual(123.321, energy.sample_size, "Energy sample size") - self.assertIsNone(energy.bandpass_name, "Default energy band pass") - energy.bandpass_name = "EBN" - self.assertEqual("EBN", energy.bandpass_name, "Energy bandpass name") - self.assertIsNone(energy.em_band, "Default energy em band") - energy.em_band = EnergyBand.OPTICAL - self.assertEqual(EnergyBand.OPTICAL, energy.em_band, "Energy band") - self.assertIsNone(energy.transition, "Default energy transition") - #TODO replace with EnergyTransistion - #energy.transition = "BLAH" - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_energy_transition.py b/caom2tools/caom2/tests/test/test_energy_transition.py deleted file mode 100644 index 495e220e..00000000 --- a/caom2tools/caom2/tests/test/test_energy_transition.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnergyTransition class """ - -import unittest - -from caom2.caom2_energy_transition import EnergyTransition - - -class TestEnergyTransition(unittest.TestCase): - - def test__init__(self): - # test for invalid values - self.assertRaises(TypeError, EnergyTransition, None, None) - self.assertRaises(TypeError, EnergyTransition, 'aString', None) - self.assertRaises(TypeError, EnergyTransition, None, 'aString') - self.assertRaises(TypeError, EnergyTransition, 1, 'aString') - self.assertRaises(TypeError, EnergyTransition, 'aString', 2) - # test for happy path - transition = EnergyTransition("aSpecies", "aTransition") - self.assertEqual(transition._species, "aSpecies") - self.assertEqual(transition._transition, "aTransition") - - def test_setters(self): - # test that we cannot change the attribute values - transition = EnergyTransition("aSpecies", "aTransition") - try: - transition.species = "newSpecies" - transition.transition = "newTransition" - except AttributeError: - pass - else: - raise AttributeError("at least one attribute was changed") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_environment.py b/caom2tools/caom2/tests/test/test_environment.py deleted file mode 100644 index 7a6a045f..00000000 --- a/caom2tools/caom2/tests/test/test_environment.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestEnvironment class """ - -import unittest - -from caom2.caom2_environment import Environment - - -class TestEnvironment(unittest.TestCase): - - def testAll(self): - environment = Environment() - - self.assertIsNone(environment.seeing, "Default seeing") - environment.seeing = 123.321 - self.assertEqual(123.321, environment.seeing, "Seeing") - self.assertIsNone(environment.humidity, "Default humidity") - environment.humidity = 0.333 - self.assertEqual(0.333, environment.humidity, "humidity") - self.assertIsNone(environment.elevation, "Default elevation") - environment.elevation = 12.12 - self.assertEqual(12.12, environment.elevation, "Elevation") - self.assertIsNone(environment.tau, "Default tau") - environment.tau = 0.456 - self.assertEqual(0.456, environment.tau, "Tau") - self.assertIsNone(environment.wavelength_tau, "Default wavelength tau") - environment.wavelength_tau = 200.02 - self.assertEqual(200.02, environment.wavelength_tau, "Wavelength tau") - self.assertIsNone(environment.ambient_temp, - "Default ambient temperature") - environment.ambient_temp = 12.44 - self.assertEqual(12.44, environment.ambient_temp, - "Ambient temperature") - self.assertIsNone(environment.photometric, "Default photometric") - environment.photometric = True - self.assertTrue(environment.photometric, "Photometric") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_instrument.py b/caom2tools/caom2/tests/test/test_instrument.py deleted file mode 100644 index ec60ed05..00000000 --- a/caom2tools/caom2/tests/test/test_instrument.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlane class """ - -import unittest - -from caom2.caom2_instrument import Instrument - - -class TestPlane(unittest.TestCase): - - def testAll(self): - instrument = Instrument("myInstrument") - self.assertEqual("myInstrument", instrument.name, "Instrument name") - self.assertEqual(0, len(instrument.keywords), "Default number of keywords") - - instrument.keywords.add("optical") - self.assertEqual(1, len(instrument.keywords), "Number of keywords") - self.assertTrue("optical" in instrument.keywords, "Keyword not found") - - instrument.keywords.add("radio") - self.assertEqual(2, len(instrument.keywords), "Number of keywords") - self.assertTrue("radio" in instrument.keywords, "Keyword not found") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_metrics.py b/caom2tools/caom2/tests/test/test_metrics.py deleted file mode 100644 index 048c32bd..00000000 --- a/caom2tools/caom2/tests/test/test_metrics.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestMetrics class """ - -import unittest - -from caom2.caom2_metrics import Metrics - - -class TestMetrics(unittest.TestCase): - - def testAll(self): - metrics = Metrics() - - self.assertIsNone(metrics.source_number_density, - "Default source number density") - metrics.source_number_density = 22.22 - self.assertEquals(22.22, metrics.source_number_density, - "Source number density") - self.assertIsNone(metrics.background, "Default background") - metrics.background = 12.34 - self.assertEquals(12.34, metrics.background, "Background") - self.assertIsNone(metrics.background_std_dev, - "Default background standard deviation") - metrics.background_std_dev = 34.34 - self.assertEquals(34.34, metrics.background_std_dev, - "Background standard deviation") - self.assertIsNone(metrics.flux_density_limit, - "Default flux density limit") - metrics.flux_density_limit = 55.55 - self.assertEquals(55.55, metrics.flux_density_limit, - "Flux density limit") - self.assertIsNone(metrics.mag_limit, "Default mag limit") - metrics.mag_limit = 20.08 - self.assertEquals(20.08, metrics.mag_limit, "Mag limit") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_observable_axis.py b/caom2tools/caom2/tests/test/test_observable_axis.py deleted file mode 100644 index 6d9f50f6..00000000 --- a/caom2tools/caom2/tests/test/test_observable_axis.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservableAxis class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_slice import Slice - - -class TestObservableAxis(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, ObservableAxis, None) - self.assertRaises(TypeError, ObservableAxis, int(1)) - - dependent = Slice(Axis("ctype1", "cunit1"), long(1)) - independent = Slice(Axis("ctype2", "cunit2"), long(2)) - - observable = ObservableAxis(dependent) - self.assertEqual(observable.dependent, dependent) - - observable.independent = independent - self.assertEqual(observable.independent, independent) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_observation.py b/caom2tools/caom2/tests/test/test_observation.py deleted file mode 100644 index 6fb59459..00000000 --- a/caom2tools/caom2/tests/test/test_observation.py +++ /dev/null @@ -1,195 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_observation import Observation -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point - - -class TestObservation(unittest.TestCase): - - def testAll(self): - algorithm = Algorithm("myAlg") - obs = Observation("GSA", "A12345", algorithm) - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - new_algorithm = Algorithm("myNewAlg") - obs.algorithm = new_algorithm - self.assertEquals(new_algorithm, obs.algorithm, "New algorithm") - - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, obs.target, "Target") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEqual(requirements, - obs.requirements, "Requirements") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - self.assertEqual(0, len(obs.planes), "Default planes") - plane1 = Plane("myPlaneID") - obs.planes["myPlaneID"] = plane1 - self.assertEqual(1, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes.keys()) - - plane2 = Plane("myPlaneID2") - obs.planes["myPlaneID2"] = plane2 - self.assertEqual(2, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes) - self.assertTrue("myPlaneID2" in obs.planes.keys()) - - # test duplicates - plane3 = Plane("myPlaneID2") - obs.planes["myPlaneID2"] = plane3 - self.assertEqual(2, len(obs.planes), "Planes") - self.assertTrue("myPlaneID" in obs.planes) - self.assertTrue("myPlaneID2" in obs.planes.keys()) - - obs2 = Observation(obs.collection, - obs.observation_id, - obs.algorithm, - planes=obs.planes, - sequence_number=obs.sequence_number, - intent=obs.intent, - obs_type=obs.obs_type, - proposal=obs.proposal, - telescope=obs.telescope, - instrument=obs.instrument, - target=obs.target, - meta_release=obs.meta_release, - environment=obs.environment, - target_position=obs.target_position) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_observation_uri.py b/caom2tools/caom2/tests/test/test_observation_uri.py deleted file mode 100644 index e90edd5f..00000000 --- a/caom2tools/caom2/tests/test/test_observation_uri.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestObservationURI class """ - -import unittest - -from caom2.caom2_observation_uri import ObservationURI - - -class TestObservationURI(unittest.TestCase): - - def testAll(self): - obsURI = ObservationURI("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", obsURI.uri, "Observation URI") - self.assertEqual("GEMINI", obsURI.collection, "Collection") - self.assertEqual("12345", obsURI.observation_id, "Observation ID") - - obsURI = ObservationURI.get_observation_uri("CFHT", "654321") - self.assertEqual("caom:CFHT/654321", obsURI.uri, "Observation URI") - self.assertEqual("CFHT", obsURI.collection, "Collection") - self.assertEqual("654321", obsURI.observation_id, "Observation ID") - - exception = False - try: - obsURI = ObservationURI.get_observation_uri(None, "123") - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - obsURI = ObservationURI.get_observation_uri("GEMINI", None) - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_plane.py b/caom2tools/caom2/tests/test/test_plane.py deleted file mode 100644 index 974f1384..00000000 --- a/caom2tools/caom2/tests/test/test_plane.py +++ /dev/null @@ -1,199 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlane class """ - -import unittest -from datetime import datetime - -from caom2.caom2_artifact import Artifact -from caom2.caom2_data_quality import DataQuality -from caom2.caom2_enums import CalibrationLevel -from caom2.caom2_enums import DataProductType -from caom2.caom2_enums import Quality -from caom2.caom2_metrics import Metrics -from caom2.caom2_plane import Plane -from caom2.caom2_provenance import Provenance -from caom2.caom2_enums import ProductType, ReleaseType - - -class TestPlane(unittest.TestCase): - - def testAll(self): - plane = Plane("ProdID") - self.assertEqual("ProdID", plane.product_id, "Product ID") - self.assertEqual(0, len(plane.artifacts), - "Default number of artifacts") - self.assertIsNone(plane.meta_release, "Default meta release date") - date_now = datetime.now() - plane.meta_release = date_now - self.assertEqual(date_now, plane.meta_release, "Metadata release date") - self.assertIsNone(plane.data_release, "Default data release date") - date_now = datetime.now() - plane.data_release = date_now - self.assertEqual(date_now, plane.data_release, "Data release date") - self.assertIsNone(plane.data_product_type, "Default data product type") - plane.data_product_type = DataProductType.IMAGE - self.assertEqual(DataProductType.IMAGE, plane.data_product_type, - "Data product type") - self.assertIsNone(plane.calibration_level, - "Default calibration level") - plane.calibration_level = CalibrationLevel.CALIBRATED - self.assertEqual(CalibrationLevel.CALIBRATED, - plane.calibration_level, "CalibrationLevel") - self.assertIsNone(plane.quality, - "Default quality") - quality = DataQuality(Quality.JUNK) - plane.quality = quality - self.assertEqual(quality, - plane.quality, "Quality") - self.assertIsNone(plane.provenance, "Default provenance") - provenance = Provenance("myProv") - plane.provenance = provenance - self.assertEqual("myProv", plane.provenance.name, "Provenance - name") - self.assertIsNone(plane.metrics, "Default metrics") - metrics = Metrics() - plane.metrics = metrics - self.assertEqual(metrics, plane.metrics, "Provenance - metrics") - #self.assertIsNone(plane.observable, "Default observable") - self.assertIsNone(plane.position, "Default position") - self.assertIsNone(plane.energy, "Default energy") - self.assertIsNone(plane.time, "Default time") - self.assertIsNone(plane.polarization, "Default polarization") - - artifact1 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact1 - self.assertEquals(1, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - - artifact2 = Artifact("caom:CFHT/55/66", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:CFHT/55/66"] = artifact2 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) - - #try to append a duplicate artifact - artifact3 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact3 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) - - #Error cases - exception = False - try: - plane = Plane(None) - except TypeError: - exception = True - self.assertTrue(exception, "Null argument in initialize") - - #exception = False - #try: - # plane.compute_observable() - #except TypeError: - # exception = True - #self.assertTrue(exception, - # "compute_observable implemented - Testing needed") - - #exception = False - #try: - # plane.compute_position() - #except TypeError: - # exception = True - #self.assertTrue(exception, - # "compute_position implemented - Testing needed") - - exception = False - try: - plane.compute_energy() - except NotImplementedError: - exception = True - self.assertTrue(exception, - "compute_energy implemented - Testing needed") - - exception = False - try: - plane.compute_time() - except NotImplementedError: - exception = True - self.assertTrue(exception, "compute_time implemented - Testing needed") - - exception = False - try: - plane.compute_polarization() - except NotImplementedError: - exception = True - self.assertTrue(exception, "compute_polarization implemented" - " - Testing needed") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_plane_uri.py b/caom2tools/caom2/tests/test/test_plane_uri.py deleted file mode 100644 index 25eef54b..00000000 --- a/caom2tools/caom2/tests/test/test_plane_uri.py +++ /dev/null @@ -1,133 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPlaneURI class """ - -import unittest - -from caom2.caom2_observation_uri import ObservationURI -from caom2.caom2_plane_uri import PlaneURI - - -class TestPlaneURI(unittest.TestCase): - - def testAll(self): - planeURI = PlaneURI("caom:GEMINI/12345/3333") - self.assertEqual("caom:GEMINI/12345/3333", planeURI.uri, - "Plane URI") - self.assertEqual("GEMINI", planeURI.observation_uri.collection, - "Collection") - self.assertEqual("12345", planeURI.observation_uri.observation_id, - "Observation ID") - self.assertEqual("3333", planeURI.product_id, "Product ID") - - planeURI = PlaneURI.get_plane_uri(ObservationURI("caom:CFHT/654321"), - "555") - self.assertEqual("caom:CFHT/654321/555", planeURI.uri, - "Observation URI") - self.assertEqual("CFHT", planeURI.observation_uri.collection, - "Collection") - self.assertEqual("654321", planeURI.observation_uri.observation_id, - "Observation ID") - self.assertEqual("555", planeURI.product_id, "Product ID") - - exception = False - try: - planeURI = PlaneURI.get_plane_uri(None, "123") - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - planeURI = PlaneURI.get_plane_uri("GEMINI", None) - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - #wrong scheme - exception = False - try: - planeURI = PlaneURI("somescheme:GEMINI/12345/3333") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - planeURI = PlaneURI("caom:GEMINI/12345") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_polarization.py b/caom2tools/caom2/tests/test/test_polarization.py deleted file mode 100644 index 0d22864f..00000000 --- a/caom2tools/caom2/tests/test/test_polarization.py +++ /dev/null @@ -1,94 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPolarizaton class """ - -import unittest - -from caom2.caom2_energy import Energy -from caom2.caom2_polarization import Polarization - - -class TestPolarizaton(unittest.TestCase): - - def testAll(self): - polarization = Polarization() - - self.assertIsNone(polarization.dimension, - "Default polarization dimension") - energy = Energy() - energy.bandpass_name = '123' - self.assertEqual('123', energy.bandpass_name, "Polarization dimension") - - #TODO add test for state - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_polarization_wcs.py b/caom2tools/caom2/tests/test/test_polarization_wcs.py deleted file mode 100644 index 8cc7426a..00000000 --- a/caom2tools/caom2/tests/test/test_polarization_wcs.py +++ /dev/null @@ -1,93 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPolarizationWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS - - -class TestPolarizationWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, PolarizationWCS, None) - self.assertRaises(TypeError, PolarizationWCS, int(1)) - - axis = Axis('STOKES') - axis_1d = CoordAxis1D(axis) - polarization = PolarizationWCS(axis_1d) - self.assertEqual(polarization.axis, axis_1d) - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_position.py b/caom2tools/caom2/tests/test/test_position.py deleted file mode 100644 index ae3c2bae..00000000 --- a/caom2tools/caom2/tests/test/test_position.py +++ /dev/null @@ -1,101 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestPosition class """ - -import unittest - -from caom2.caom2_position import Position - - -class TestPosition(unittest.TestCase): - - def testAll(self): - position = Position() - - self.assertIsNone(position.bounds, "Default bounds") - #position.bounds = 123 - #self.assertEqual(123, position.bounds, "Bounds") - self.assertIsNone(position.dimension, "Default dimension") - #position.dimension = 123 - #self.assertEqual(123, position.dimension, "Dimension") - self.assertIsNone(position.resolution, "Default resolution") - position.resolution = 123.321 - self.assertEqual(123.321, position.resolution, "Resolution") - self.assertIsNone(position.sample_size, "Default sample size") - position.sample_size = 321.123 - self.assertEqual(321.123, position.sample_size, "Sample size") - self.assertFalse(position.time_dependent, "Default time dependent") - position.time_dependent = True - self.assertTrue(position.time_dependent, "Time dependent") - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_proposal.py b/caom2tools/caom2/tests/test/test_proposal.py deleted file mode 100644 index 300ac24d..00000000 --- a/caom2tools/caom2/tests/test/test_proposal.py +++ /dev/null @@ -1,100 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestProposal class """ - -import unittest - -from caom2.caom2_proposal import Proposal - - -class TestProposal(unittest.TestCase): - - def testAll(self): - proposal = Proposal("myProposal") - self.assertEqual("myProposal", proposal.proposal_id, "Proposal ID") - self.assertEqual(0, len(proposal.keywords), "Default number of keywords") - proposal.keywords.add("optical") - self.assertEqual(1, len(proposal.keywords), "Number of keywords") - self.assertTrue("optical" in proposal.keywords, "Keyword not found") - self.assertIsNone(proposal.pi_name, "Default PI") - proposal.pi_name = "John Doe" - self.assertEqual("John Doe", proposal.pi_name, "PI") - self.assertIsNone(proposal.project, "Default PI") - proposal.project = "Project A" - self.assertEqual("Project A", proposal.project, "Project") - self.assertIsNone(proposal.title, "Default title") - proposal.title = "Something Interesting" - self.assertEqual("Something Interesting", proposal.title, "Title") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_provenance.py b/caom2tools/caom2/tests/test/test_provenance.py deleted file mode 100644 index bbfe4a65..00000000 --- a/caom2tools/caom2/tests/test/test_provenance.py +++ /dev/null @@ -1,159 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestProvenance class """ - -import unittest -from datetime import datetime - -from caom2.caom2_plane_uri import PlaneURI -from caom2.caom2_provenance import Provenance - - -class TestProvenance(unittest.TestCase): - - def testAll(self): - provenance = Provenance("MyProvenance") - self.assertEqual("MyProvenance", provenance.name, "Name") - - self.assertIsNone(provenance.version, "Default version") - provenance.version = "XII" - self.assertEquals("XII", provenance.version, "Version") - self.assertIsNone(provenance.project, "Default project") - provenance.project = "CFHTLS" - self.assertEquals("CFHTLS", provenance.project, "Project") - self.assertIsNone(provenance.producer, "Default producer") - provenance.producer = "prod" - self.assertEquals("prod", provenance.producer, "Producer") - self.assertIsNone(provenance.run_id, "Default run ID") - provenance.run_id = "A23" - self.assertEquals("A23", provenance.run_id, "Run ID") - self.assertIsNone(provenance.reference, "Default reference") - - self.assertEqual(0, len(provenance.inputs), "Default inputs") - planeURI1 = PlaneURI("caom:HST/11/00") - provenance.inputs.add(planeURI1) - self.assertEqual(1, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - - planeURI2 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI2) - self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) - - # testing duplicates - planeURI3 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI3) - self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) - - self.assertIsNone(provenance.last_executed, "Default last executed") - now_date = datetime.now() - provenance.last_executed = now_date - self.assertEquals(now_date, provenance.last_executed, "Last executed") - - self.assertEquals(0, len(provenance.keywords), "0 default keywords") - provenance.keywords.add("keyword1") - self.assertEquals(1, len(provenance.keywords), "1 keyword") - self.assertTrue("keyword1" in provenance.keywords, "Keyword not found") - - provenance.keywords.add("keyword2") - self.assertEquals(2, len(provenance.keywords), "2 keyword") - self.assertTrue("keyword2" in provenance.keywords, "Keyword not found") - - # test the full constructor - provenance = Provenance("MyOtherProvenance", - "Version2.0", - "JCMT", - "Mutt Lang", - "b32", - "caom:JCMT/33/00", - now_date) - - self.assertIsNotNone(provenance.name) - self.assertIsNotNone(provenance.version) - self.assertIsNotNone(provenance.project) - self.assertIsNotNone(provenance.producer) - self.assertIsNotNone(provenance.run_id) - self.assertIsNotNone(provenance.reference) - self.assertIsNotNone(provenance.last_executed) - - self.assertEquals("MyOtherProvenance", provenance.name, "name") - self.assertEquals("Version2.0", provenance.version, "version") - self.assertEquals("JCMT", provenance.project, "project") - self.assertEquals("Mutt Lang", provenance.producer, "producer") - self.assertEquals("b32", provenance.run_id, "run_id") - self.assertEquals("caom:JCMT/33/00", provenance.reference, "reference") - self.assertEquals(now_date, provenance.last_executed, "last_executed") - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_ref_coord.py b/caom2tools/caom2/tests/test/test_ref_coord.py deleted file mode 100644 index ee12da9e..00000000 --- a/caom2tools/caom2/tests/test/test_ref_coord.py +++ /dev/null @@ -1,96 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRefCoord class """ - -import unittest - -from caom2.wcs.caom2_ref_coord import RefCoord - - -class TestRefCoord(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, RefCoord, None, None) - self.assertRaises(TypeError, RefCoord, None, float(1.0)) - self.assertRaises(TypeError, RefCoord, float(1.0), None) - self.assertRaises(TypeError, RefCoord, int(1), float(1.0)) - self.assertRaises(TypeError, RefCoord, float(1.0), int(1)) - - ref_coord = RefCoord(float(1), float(2)) - self.assertIsNotNone(ref_coord) - self.assertEqual(ref_coord.pix, float(1)) - self.assertEqual(ref_coord.val, float(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_requirements.py b/caom2tools/caom2/tests/test/test_requirements.py deleted file mode 100644 index 7b238d95..00000000 --- a/caom2tools/caom2/tests/test/test_requirements.py +++ /dev/null @@ -1,89 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRequirements class """ - -import unittest - -from caom2.caom2_enums import Status -from caom2.caom2_requirements import Requirements - - -class TestRequirements(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, Requirements, "string") - requirements = Requirements(Status.FAIL) - self.assertEqual(Status.FAIL, requirements.flag, - "Requirements flag") - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_roundtrip.py b/caom2tools/caom2/tests/test/test_roundtrip.py deleted file mode 100644 index 4098f841..00000000 --- a/caom2tools/caom2/tests/test/test_roundtrip.py +++ /dev/null @@ -1,169 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestRoundTrip class """ - -import errno -import filecmp -import glob -import os -import shutil -import unittest - -import caom2.xml.caom2_xml_constants -from caom2.xml.caom2_observation_reader import ObservationReader -from caom2.xml.caom2_observation_writer import ObservationWriter - - -class TestRoundTrip(unittest.TestCase): - - TEST_FILE_SOURCE_DIR = '../caom2/test/data' - XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' - - def makeTestDir(self): - try: - os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - - def copyFiles(self): - for filename in glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, '*.xml')): - shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) - - def init(self): - self.makeTestDir() - self.copyFiles() - - def cleanup(self): - shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) - - def get_file_list(self): - return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR)\ - if f.endswith('.xml')] - - def do_test(self, reader, writer, filename): - sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + - '/' + filename) - print "test file: " + sourceFilePath - sourceXMLfp = open(sourceFilePath, 'r') - observation = reader.read(sourceFilePath) - sourceXMLfp.close() - destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename - destXMLfp = open(destFilePath, 'w') - writer.write(observation, destXMLfp) - destXMLfp.close() - self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), - 'files are different, ' + - 'file from Java was: ' + sourceFilePath + ' ' - 'file from Python was: ' + destFilePath) - - # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 - # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 - # objects. The two XML files are then compared to ensure that they - # are the same. The test fails if the files are not the same. The - # test/data/*.xml files can be used in this test. - - def test_round_trip(self): - print "Test Round Trip" - - try: - self.init() - files = self.get_file_list() - self.assertTrue(len(files) > 0, 'No XML files in ' + - TestRoundTrip.XML_FILE_SOURCE_DIR) - try: - os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - reader = ObservationReader(True) - writer20 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM20_NAMESPACE) - writer21 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM21_NAMESPACE) - writer22 = ObservationWriter(True, False, "caom2") - for filename in files: - if filename.endswith("CAOM-2.2.xml"): - self.do_test(reader, writer22, filename) - elif filename.endswith("CAOM-2.1.xml"): - self.do_test(reader, writer21, filename) - else: - self.do_test(reader, writer20, filename) - - #finally: - # self.cleanup() - except Exception as e: - #if e.errno != errno.EEXIST: - raise - -suite = unittest.TestLoader().loadTestsFromTestCase(TestRoundTrip) -unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/caom2tools/caom2/tests/test/test_simple_observation.py b/caom2tools/caom2/tests/test/test_simple_observation.py deleted file mode 100644 index a9706b61..00000000 --- a/caom2tools/caom2/tests/test/test_simple_observation.py +++ /dev/null @@ -1,239 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSimpleObservation class """ - -import unittest -from datetime import datetime - -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_enums import ObservationIntentType -from caom2.caom2_enums import Status -from caom2.caom2_environment import Environment -from caom2.caom2_instrument import Instrument -from caom2.caom2_plane import Plane -from caom2.caom2_proposal import Proposal -from caom2.caom2_requirements import Requirements -from caom2.caom2_simple_observation import SimpleObservation -from caom2.caom2_target import Target -from caom2.caom2_target_position import TargetPosition -from caom2.caom2_telescope import Telescope -from caom2.types.caom2_point import Point -from caom2.util.caom2_util import TypedOrderedDict - - -class TestSimpleObservation(unittest.TestCase): - - def testAll(self): - algorithm = SimpleObservation._ALGORITHM - obs = SimpleObservation("GSA", "A12345") - self.assertEqual("GSA", obs.collection, "Collection") - self.assertEqual("A12345", obs.observation_id, "Observation ID") - - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - obs.algorithm = algorithm - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - # try to set algorithm - exception = False - try: - obs.algorithm = Algorithm("myAlg") - except ValueError: - exception = True - self.assertTrue(exception, "Missing exception") - - # run the rest of the Observation tests - self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, - obs.intent, "Observation intent") - - self.assertIsNone(obs.obs_type, "Default obs_type") - obs.obs_type = "obstype1" - self.assertEqual("obstype1", - obs.obs_type, "obs type") - - self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") - obs.proposal = proposal - self.assertEqual(proposal, - obs.proposal, "Proposal") - - self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") - obs.telescope = telescope - self.assertEqual(telescope, - obs.telescope, "Telescope") - - self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") - obs.instrument = instrument - self.assertEqual(instrument, - obs.instrument, "Instrument") - - self.assertIsNone(obs.target, "Default target") - target = Target("TGT") - obs.target = target - self.assertEqual(target, - obs.target, "Target") - - self.assertIsNone(obs.environment, "Default environment") - environment = Environment() - obs.environment = environment - self.assertEqual(environment, - obs.environment, "Environment") - - self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - obs.target_position = target_position - self.assertEqual(target_position, - obs.target_position, "TargetPosition") - - self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) - obs.requirements = requirements - self.assertEquals(requirements, obs.requirements, "requirements") - - self.assertIsNone(obs.meta_release, "Default metadata release") - date_now = datetime.now() - obs.meta_release = date_now - self.assertEqual(date_now, - obs.meta_release, "Metadata release") - - # Test the complete constructor - def testCompleteInit(self): - collection = str("CFHT") - observationID = str("543210") - algorithm = SimpleObservation._ALGORITHM - sequence_number = int(3) - intent = ObservationIntentType.SCIENCE - obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") - meta_release = datetime.now() - planes = TypedOrderedDict((Plane),) - environment = Environment() - - obs = SimpleObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment) - - self.assertIsNotNone(obs.collection, "Collection") - self.assertEqual(collection, obs.collection, "Collection") - - self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") - - self.assertIsNotNone(obs.algorithm, "Algorithm") - self.assertEqual(algorithm, obs.algorithm, "Algorithm") - - self.assertIsNotNone(obs.intent, "Observation intent") - self.assertEqual(intent, obs.intent, "Observation intent") - - self.assertIsNotNone(obs.obs_type, "obs type") - self.assertEqual(obs_type, obs.obs_type, "obs type") - - self.assertIsNotNone(obs.proposal, "Proposal") - self.assertEqual(proposal, obs.proposal, "Proposal") - - self.assertIsNotNone(obs.telescope, "Telescope") - self.assertEqual(telescope, obs.telescope, "Telescope") - - self.assertIsNotNone(obs.instrument, "Instrument") - self.assertEqual(instrument, obs.instrument, "Instrument") - - self.assertIsNotNone(obs.target, "Target") - self.assertEqual(target, obs.target, "Target") - - self.assertIsNotNone(obs.meta_release, "Metadata release") - self.assertEqual(meta_release, obs.meta_release, "Metadata release") - - self.assertIsNotNone(obs.planes, "Planes") - self.assertEqual(planes, obs.planes, "Planes") - - self.assertIsNotNone(obs.environment, "Environment") - self.assertEqual(environment, obs.environment, "Environment") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_slice.py b/caom2tools/caom2/tests/test/test_slice.py deleted file mode 100644 index 8bf7ac20..00000000 --- a/caom2tools/caom2/tests/test/test_slice.py +++ /dev/null @@ -1,99 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSlice class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_slice import Slice - - -class TestSlice(unittest.TestCase): - - def testInit(self): - - axis = Axis("ctype", "cunit") - myBin = long(1) - - self.assertRaises(TypeError, Slice, None, None) - self.assertRaises(TypeError, Slice, None, myBin) - self.assertRaises(TypeError, Slice, axis, None) - self.assertRaises(TypeError, Slice, str("s"), myBin) - self.assertRaises(TypeError, Slice, axis, int(1)) - - mySlice = Slice(axis, myBin) - self.assertEqual(mySlice.axis, axis) - self.assertEqual(mySlice.bin, long(1)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_spatial_wcs.py b/caom2tools/caom2/tests/test/test_spatial_wcs.py deleted file mode 100644 index 3aac4c67..00000000 --- a/caom2tools/caom2/tests/test/test_spatial_wcs.py +++ /dev/null @@ -1,110 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSpatialWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.wcs.caom2_spatial_wcs import SpatialWCS - - -class TestSpatialWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, SpatialWCS, None) - self.assertRaises(TypeError, SpatialWCS, int(1)) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - position = SpatialWCS(axis_2d) - self.assertEqual(position.axis, axis_2d) - with self.assertRaises(TypeError): - position.coordsys = float(1.0) - position.bounds = str("s") - position.function = str("s") - - position.coordsys = "coordsys" - self.assertEqual(position.coordsys, "coordsys") - - self.assertRaises(ValueError, position.equinox, float(1.0)) - position.equinox = float(2000.0) - self.assertEqual(position.equinox, float(2000.0)) - - position.resolution = float(2.0) - self.assertEqual(position.resolution, float(2.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_spectral_wcs.py b/caom2tools/caom2/tests/test/test_spectral_wcs.py deleted file mode 100644 index 0db774e2..00000000 --- a/caom2tools/caom2/tests/test/test_spectral_wcs.py +++ /dev/null @@ -1,150 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestSpectralWCS class """ - -import unittest - -from caom2.caom2_energy_transition import EnergyTransition -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_spectral_wcs import SpectralWCS - - -class TestSpectralWCS(unittest.TestCase): - - def testInit(self): - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - - self.assertRaises(TypeError, SpectralWCS, None, None) - self.assertRaises(TypeError, SpectralWCS, None, str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, None) - self.assertRaises(TypeError, SpectralWCS, int(1), str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, int(1)) - - energy = SpectralWCS(axis_1d, "specsys") - self.assertEqual(energy.axis, axis_1d) - self.assertEqual(energy.specsys, "specsys") - with self.assertRaises(TypeError): - energy.ssysobs = int(1) - energy.ssyssrc = int(1) - energy.restfrq = int(1) - energy.restwav = int(1) - energy.velosys = int(1) - energy.zsource = int(1) - energy.velang = int(1) - energy.bandpass_name = int(1) - energy.transition = int(1) - energy.resolving_power = int(1) - - with self.assertRaises(ValueError): - energy.zsource = float(-1) - energy.zsource = float(1201) - energy.resolving_power = float(-1) - energy.resolving_power = float(1.1e8) - - - energy.ssysobs = "ssysobs" - self.assertEqual(energy.ssysobs, "ssysobs") - - energy.ssyssrc = "ssyssrc" - self.assertEqual(energy.ssyssrc, "ssyssrc") - - energy.restfrq = float(1.0) - self.assertEqual(energy.restfrq, float(1.0)) - - energy.restwav = float(2.0) - self.assertEqual(energy.restwav, float(2.0)) - - energy.velosys = float(3.0) - self.assertEqual(energy.velosys, float(3.0)) - - energy.zsource = float(4.0) - self.assertEqual(energy.zsource, float(4.0)) - - energy.velang = float(5.0) - self.assertEqual(energy.velang, float(5.0)) - - energy.bandpass_name = "bandpass_name" - self.assertEqual(energy.bandpass_name, "bandpass_name") - - transition = EnergyTransition("species", "transition") - energy.transition = transition - self.assertEqual(energy.transition, transition) - - energy.resolving_power = float(6.0) - self.assertEqual(energy.resolving_power, float(6.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_target.py b/caom2tools/caom2/tests/test/test_target.py deleted file mode 100644 index aacf9051..00000000 --- a/caom2tools/caom2/tests/test/test_target.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTarget class """ - -import unittest - -from caom2.caom2_enums import TargetType -from caom2.caom2_target import Target -from caom2.util.caom2_util import TypedList - - -class TestTarget(unittest.TestCase): - - def testAll(self): - - target = Target("myTarget") - self.assertEqual("myTarget", target.name, "target name") - - target.target_type = TargetType.FIELD - self.assertEqual(TargetType.FIELD, target.target_type, "target type") - - self.assertEqual(0, len(target.keywords), "Default number of keywords") - target.keywords.add("optical") - self.assertEqual(1, len(target.keywords), "Number of keywords") - self.assertTrue("optical" in target.keywords, "Keyword not found") - - self.assertIsNone(target.redshift, "Default redshift") - target.redshift = 123.321 - self.assertEqual(123.321, target.redshift, "Redshift") - - self.assertIsNone(target.standard, "Default standard") - target.standard = True - self.assertTrue(target.standard, "Standard") - - self.assertIsNone(target.moving, "Default moving") - target.moving = True - self.assertTrue(target.moving, "Moving") - - target = Target("myOtherTarget", TargetType.OBJECT, False, 1.2, {"radio"}, False) - self.assertEquals("myOtherTarget", target.name, "target name") - self.assertEquals(TargetType.OBJECT, target.target_type, "target type") - self.assertFalse(target.standard, "Standard") - self.assertEquals(1.2, target.redshift, "Redshift") - self.assertEquals(1, len(target.keywords), "Keywords") - self.assertTrue("radio" in target.keywords, "Keywords") - self.assertFalse(target.moving, "Moving") - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_target_position.py b/caom2tools/caom2/tests/test/test_target_position.py deleted file mode 100644 index 5815c259..00000000 --- a/caom2tools/caom2/tests/test/test_target_position.py +++ /dev/null @@ -1,105 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTargetPosition class """ - -import unittest - -from caom2.caom2_target_position import TargetPosition -from caom2.types.caom2_point import Point - - -class TestTargetPosition(unittest.TestCase): - - def testAll(self): - - self.assertRaises(TypeError, TargetPosition, "string") - point = Point(1.0, 2.0) - target_position = TargetPosition(point, "coordsys") - self.assertIsNotNone(target_position.coordinates, - "target position coordinates") - self.assertEqual(point.cval1, target_position.coordinates.cval1, - "coordinates cval1") - self.assertEqual(point.cval2, target_position.coordinates.cval2, - "coordinates cval2") - self.assertIsNotNone(target_position.coordsys, - "target position coordsys") - self.assertEqual("coordsys", target_position.coordsys, "coordsys") - self.assertIsNone(target_position.equinox, - "target position equinox") - - target_position = TargetPosition(point, "coordsys", 1.0) - self.assertIsNotNone(target_position.equinox, - "target position equinox") - self.assertEqual(1.0, target_position.equinox, - "equinox") - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_telescope.py b/caom2tools/caom2/tests/test/test_telescope.py deleted file mode 100644 index 8ccfeda0..00000000 --- a/caom2tools/caom2/tests/test/test_telescope.py +++ /dev/null @@ -1,104 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTelescope class """ - -import unittest - -from caom2.caom2_telescope import Telescope - - -class TestTelescope(unittest.TestCase): - - def testAll(self): - telescope = Telescope("myTelescope") - self.assertEqual("myTelescope", telescope.name, "telescope name") - self.assertEqual(0, len(telescope.keywords), "Default number of keywords") - - telescope.keywords.add("optical") - self.assertEqual(1, len(telescope.keywords), "Number of keywords") - self.assertTrue("optical" in telescope.keywords, "Keyword not found") - - self.assertIsNone(telescope.geo_location_x, "Default geo location x") - telescope.geo_location_x = 123.321 - self.assertEqual(123.321, telescope.geo_location_x, "Geo location x") - - self.assertIsNone(telescope.geo_location_y, "Default geo location y") - telescope.geo_location_y = 333.33 - self.assertEqual(333.33, telescope.geo_location_y, "Geo location y") - - self.assertIsNone(telescope.geo_location_z, "Default geo location z") - telescope.geo_location_z = 12.12 - self.assertEqual(12.12, telescope.geo_location_z, "Geo location z") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_temporal_wcs.py b/caom2tools/caom2/tests/test/test_temporal_wcs.py deleted file mode 100644 index 5b83fb4f..00000000 --- a/caom2tools/caom2/tests/test/test_temporal_wcs.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTemporalWCS class """ - -import unittest - -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_temporal_wcs import TemporalWCS - - -class TestTemporalWCS(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, TemporalWCS, None) - self.assertRaises(TypeError, TemporalWCS, int(1)) - - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - time = TemporalWCS(axis_1d) - self.assertEqual(time.axis, axis_1d) - with self.assertRaises(TypeError): - time.exposure = str("s") - time.resolution = str("s") - - time.exposure = float(1.0) - self.assertEqual(time.exposure, float(1.0)) - - time.resolution = float(2.0) - self.assertEqual(time.resolution, float(2.0)) - - time.timesys = str("timesys") - self.assertEqual(time.timesys, "timesys") - - time.trefpos = str("trefpos") - self.assertEqual(time.trefpos, "trefpos") - - time.mjdref = float(3.0) - self.assertEqual(time.mjdref, float(3.0)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_time.py b/caom2tools/caom2/tests/test/test_time.py deleted file mode 100644 index 37d545e4..00000000 --- a/caom2tools/caom2/tests/test/test_time.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestTime class """ - -import unittest - -from caom2.caom2_time import Time - - -class TestTime(unittest.TestCase): - - def testAll(self): - time = Time() - self.assertIsNone(time.value, "Default value") - self.assertIsNone(time.bounds, "Default bounds") - self.assertIsNone(time.dimension, "Default dimension") - self.assertIsNone(time.resolution, "Default resolution") - self.assertIsNone(time.sample_size, "Default sample size") - self.assertIsNone(time.exposure, "Default exposure") - - time.value = 34.34 - self.assertEqual(34.34, time.value, "Value") - time.dimension = 777L - self.assertEqual(777L, time.dimension, "Dimension") - time.resolution = 77.777 - self.assertEqual(77.777, time.resolution, "Resolution") - time.sample_size = 12.34 - self.assertEqual(12.34, time.sample_size, "Sample size") - time.exposure = 55.55 - self.assertEqual(55.55, time.exposure, "Exposure") - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_util.py b/caom2tools/caom2/tests/test/test_util.py deleted file mode 100644 index f9f4dad8..00000000 --- a/caom2tools/caom2/tests/test/test_util.py +++ /dev/null @@ -1,167 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -# *********************************************************************** -# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2014. (c) 2014. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# -# *********************************************************************** - -""" Defines TestRoundTrip class """ - -import errno -import filecmp -import glob -import os -import shutil -import unittest - -import caom2.xml.caom2_xml_constants -from caom2.xml.caom2_observation_reader import ObservationReader -from caom2.xml.caom2_observation_writer import ObservationWriter - - -class TestRoundTrip(unittest.TestCase): - - TEST_FILE_SOURCE_DIR = '../caom2/test/data' - XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' - - def makeTestDir(self): - try: - os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - - def copyFiles(self): - for filename in glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, '*.xml')): - shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) - - def init(self): - self.makeTestDir() - self.copyFiles() - - def cleanup(self): - shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) - - def get_file_list(self): - return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR)\ - if f.endswith('.xml')] - - def do_test(self, reader, writer, filename): - sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + - '/' + filename) - print "test file: " + sourceFilePath - sourceXMLfp = open(sourceFilePath, 'r') - observation = reader.read(sourceFilePath) - sourceXMLfp.close() - destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename - destXMLfp = open(destFilePath, 'w') - writer.write(observation, destXMLfp) - destXMLfp.close() - self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), - 'files are different, ' + - 'file from Java was: ' + sourceFilePath + ' ' - 'file from Python was: ' + destFilePath) - - # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 - # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 - # objects. The two XML files are then compared to ensure that they - # are the same. The test fails if the files are not the same. The - # test/data/*.xml files can be used in this test. - - def test_round_trip(self): - print "Test Round Trip" - - try: - self.init() - files = self.get_file_list() - self.assertTrue(len(files) > 0, 'No XML files in ' + - TestRoundTrip.XML_FILE_SOURCE_DIR) - try: - os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) - except OSError as e: - if e.errno != errno.EEXIST: - raise - - reader = ObservationReader(True) - writer20 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM20_NAMESPACE) - writer21 = ObservationWriter(True, False, "caom2", caom2.xml.caom2_xml_constants.CAOM21_NAMESPACE) - writer22 = ObservationWriter(True, False, "caom2") - for filename in files: - if filename.endswith("CAOM-2.2.xml"): - self.do_test(reader, writer22, filename) - elif filename.endswith("CAOM-2.1.xml"): - self.do_test(reader, writer21, filename) - else: - self.do_test(reader, writer20, filename) - - #finally: - # self.cleanup() - except Exception as e: - #if e.errno != errno.EEXIST: - raise - -suite = unittest.TestLoader().loadTestsFromTestCase(TestRoundTrip) -unittest.TextTestRunner(verbosity=2).run(suite) diff --git a/caom2tools/caom2/tests/test/test_value_coord2d.py b/caom2tools/caom2/tests/test/test_value_coord2d.py deleted file mode 100644 index d4cc94c1..00000000 --- a/caom2tools/caom2/tests/test/test_value_coord2d.py +++ /dev/null @@ -1,95 +0,0 @@ -#!/usr/bin/env python -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines TestValueCoord2d class """ - -import unittest - -from caom2.wcs.caom2_value_coord2d import ValueCoord2D - - -class TestValueCoord2d(unittest.TestCase): - - def testInit(self): - - self.assertRaises(TypeError, ValueCoord2D, None, None) - self.assertRaises(TypeError, ValueCoord2D, None, float(1.0)) - self.assertRaises(TypeError, ValueCoord2D, float(1.0), None) - self.assertRaises(TypeError, ValueCoord2D, int(1), float(1.0)) - self.assertRaises(TypeError, ValueCoord2D, float(1.0), int(1)) - - value_coord2d = ValueCoord2D(float(1), float(2)) - self.assertIsNotNone(value_coord2d) - self.assertEqual(value_coord2d.coord1, float(1)) - self.assertEqual(value_coord2d.coord2, float(2)) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test/test_artifact.py b/caom2tools/caom2/tests/test_artifact.py similarity index 79% rename from caom2tools/caom2/tests/test/test_artifact.py rename to caom2tools/caom2/tests/test_artifact.py index d5313ab6..0be92e4a 100644 --- a/caom2tools/caom2/tests/test/test_artifact.py +++ b/caom2tools/caom2/tests/test_artifact.py @@ -73,9 +73,43 @@ import unittest from urlparse import urlparse -from caom2.caom2_artifact import Artifact -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_part import Part +from caom2.artifact import Artifact +from caom2.artifact import ProductType +from caom2.artifact import ReleaseType +from caom2.part import Part + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + self.assertEqual(ProductType.get("no_such_string"), None) + self.assertRaises(AttributeError, ProductType.get, None) + self.assertRaises(AttributeError, ProductType.get, 1) + + self.assertEqual(ReleaseType.get("no_such_string"), None) + self.assertRaises(AttributeError, ReleaseType.get, None) + self.assertRaises(AttributeError, ReleaseType.get, 1) + + # test that we can get the object for each enum by name + self.assertEqual(ProductType.SCIENCE.name, "SCIENCE") + self.assertEqual(ProductType.get(ProductType.SCIENCE.name).name, "SCIENCE") + self.assertEqual(ProductType.get('SCIENCE').value, "science") + self.assertEqual(ProductType.get(ProductType.SCIENCE.name).value, "science") + self.assertEqual(ProductType.getByValue(ProductType.SCIENCE.value).value, "science") + self.assertEqual(ProductType.getByValue(ProductType.CALIBRATED.value).name, "SCIENCE") + + self.assertEqual(ProductType.SCIENCE.value, "science") + self.assertEqual(ProductType.CALIBRATION.value, "calibration") + self.assertEqual(ProductType.PREVIEW.value, "preview") + self.assertEqual(ProductType.INFO.value, "info") + self.assertEqual(ProductType.NOISE.value, "noise") + self.assertEqual(ProductType.WEIGHT.value, "weight") + self.assertEqual(ProductType.AUXILIARY.value, "auxiliary") + self.assertEqual(ProductType.THUMBNAIL.value, "thumbnail") + + self.assertEqual(ReleaseType.DATA.value, "data") + self.assertEqual(ReleaseType.META.value, "meta") class TestArtifact(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test/test_caom2_entity.py b/caom2tools/caom2/tests/test_caom_object.py similarity index 92% rename from caom2tools/caom2/tests/test/test_caom2_entity.py rename to caom2tools/caom2/tests/test_caom_object.py index 4e85cc11..795ee9ce 100644 --- a/caom2tools/caom2/tests/test/test_caom2_entity.py +++ b/caom2tools/caom2/tests/test_caom_object.py @@ -72,21 +72,20 @@ import unittest -from caom2.caom2_algorithm import Algorithm -from caom2.caom2_artifact import Artifact -from caom2.caom2_chunk import Chunk -from caom2.caom2_entity import AbstractCaom2Entity -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_observation import Observation -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane +from caom2.artifact import Artifact, ProductType, ReleaseType +from caom2.caom_object import AbstractCaomEntity +from caom2.chunk import Chunk +from caom2.observation import Algorithm +from caom2.observation import Observation +from caom2.part import Part +from caom2.plane import Plane class TestCaom2IdGenerator(unittest.TestCase): - def testAll(self): + def test_all(self): #Not much for now. Just to make sure that all the clients work - entity = AbstractCaom2Entity() + entity = AbstractCaomEntity() print entity._id, entity._last_modified artifact = Artifact("caom2:/blah/blah", ProductType.SCIENCE, ReleaseType.DATA) print artifact._id, artifact._last_modified diff --git a/caom2tools/caom2/tests/test/test_chunk.py b/caom2tools/caom2/tests/test_chunk.py similarity index 64% rename from caom2tools/caom2/tests/test/test_chunk.py rename to caom2tools/caom2/tests/test_chunk.py index 47a17db1..d0e8bea7 100644 --- a/caom2tools/caom2/tests/test/test_chunk.py +++ b/caom2tools/caom2/tests/test_chunk.py @@ -72,23 +72,23 @@ import unittest -from caom2.caom2_chunk import Chunk -from caom2.caom2_enums import ProductType -from caom2.wcs.caom2_axis import Axis -from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -from caom2.caom2_enums import ProductType -from caom2.wcs.caom2_observable_axis import ObservableAxis -from caom2.wcs.caom2_polarization_wcs import PolarizationWCS -from caom2.wcs.caom2_slice import Slice -from caom2.wcs.caom2_spatial_wcs import SpatialWCS -from caom2.wcs.caom2_spectral_wcs import SpectralWCS -from caom2.wcs.caom2_temporal_wcs import TemporalWCS +from caom2.artifact import ProductType +from caom2.chunk import Chunk +from caom2.chunk import ObservableAxis +from caom2.chunk import PolarizationWCS +from caom2.chunk import SpatialWCS +from caom2.chunk import SpectralWCS +from caom2.chunk import TemporalWCS +from caom2.plane import EnergyTransition +from caom2.wcs import Axis +from caom2.wcs import CoordAxis1D +from caom2.wcs import CoordAxis2D +from caom2.wcs import Slice class TestChunk(unittest.TestCase): - def testInit(self): + def test_init(self): chunk = Chunk() self.assertIsNone(chunk.product_type) @@ -105,7 +105,7 @@ def testInit(self): self.assertIsNone(chunk.time) self.assertIsNone(chunk.polarization) - def testAttributes(self): + def test_attributes(self): chunk = Chunk() with self.assertRaises(TypeError): @@ -173,7 +173,7 @@ def testAttributes(self): chunk.polarization = polarization self.assertEqual(polarization, chunk.polarization) -# def testCompareTo(self): +# def test_compare_to(self): # # test for chunk1 == chunk2 # chunk1 = Chunk() # chunk1.naxis = 1 @@ -265,6 +265,161 @@ def testAttributes(self): # chunk2.polarization = PolarizationWCS() +class TestObservableAxis(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, ObservableAxis, None) + self.assertRaises(TypeError, ObservableAxis, int(1)) + + dependent = Slice(Axis("ctype1", "cunit1"), long(1)) + independent = Slice(Axis("ctype2", "cunit2"), long(2)) + + observable = ObservableAxis(dependent) + self.assertEqual(observable.dependent, dependent) + + observable.independent = independent + self.assertEqual(observable.independent, independent) + + +class TestSpatialWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, SpatialWCS, None) + self.assertRaises(TypeError, SpatialWCS, int(1)) + + axis1 = Axis("ctype1", "cunit1") + axis2 = Axis("ctype2", "cunit2") + axis_2d = CoordAxis2D(axis1, axis2) + position = SpatialWCS(axis_2d) + self.assertEqual(position.axis, axis_2d) + with self.assertRaises(TypeError): + position.coordsys = float(1.0) + position.bounds = str("s") + position.function = str("s") + + position.coordsys = "coordsys" + self.assertEqual(position.coordsys, "coordsys") + + self.assertRaises(ValueError, position.equinox, float(1.0)) + position.equinox = float(2000.0) + self.assertEqual(position.equinox, float(2000.0)) + + position.resolution = float(2.0) + self.assertEqual(position.resolution, float(2.0)) + + +class TestSpectralWCS(unittest.TestCase): + + def test_init(self): + + axis = Axis("ctype", "cunit") + axis_1d = CoordAxis1D(axis) + + self.assertRaises(TypeError, SpectralWCS, None, None) + self.assertRaises(TypeError, SpectralWCS, None, str("s")) + self.assertRaises(TypeError, SpectralWCS, axis_1d, None) + self.assertRaises(TypeError, SpectralWCS, int(1), str("s")) + self.assertRaises(TypeError, SpectralWCS, axis_1d, int(1)) + + energy = SpectralWCS(axis_1d, "specsys") + self.assertEqual(energy.axis, axis_1d) + self.assertEqual(energy.specsys, "specsys") + with self.assertRaises(TypeError): + energy.ssysobs = int(1) + energy.ssyssrc = int(1) + energy.restfrq = int(1) + energy.restwav = int(1) + energy.velosys = int(1) + energy.zsource = int(1) + energy.velang = int(1) + energy.bandpass_name = int(1) + energy.transition = int(1) + energy.resolving_power = int(1) + + with self.assertRaises(ValueError): + energy.zsource = float(-1) + energy.zsource = float(1201) + energy.resolving_power = float(-1) + energy.resolving_power = float(1.1e8) + + + energy.ssysobs = "ssysobs" + self.assertEqual(energy.ssysobs, "ssysobs") + + energy.ssyssrc = "ssyssrc" + self.assertEqual(energy.ssyssrc, "ssyssrc") + + energy.restfrq = float(1.0) + self.assertEqual(energy.restfrq, float(1.0)) + + energy.restwav = float(2.0) + self.assertEqual(energy.restwav, float(2.0)) + + energy.velosys = float(3.0) + self.assertEqual(energy.velosys, float(3.0)) + + energy.zsource = float(4.0) + self.assertEqual(energy.zsource, float(4.0)) + + energy.velang = float(5.0) + self.assertEqual(energy.velang, float(5.0)) + + energy.bandpass_name = "bandpass_name" + self.assertEqual(energy.bandpass_name, "bandpass_name") + + transition = EnergyTransition("species", "transition") + energy.transition = transition + self.assertEqual(energy.transition, transition) + + energy.resolving_power = float(6.0) + self.assertEqual(energy.resolving_power, float(6.0)) + + +class TestTemporalWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, TemporalWCS, None) + self.assertRaises(TypeError, TemporalWCS, int(1)) + + axis = Axis("ctype", "cunit") + axis_1d = CoordAxis1D(axis) + time = TemporalWCS(axis_1d) + self.assertEqual(time.axis, axis_1d) + with self.assertRaises(TypeError): + time.exposure = str("s") + time.resolution = str("s") + + time.exposure = float(1.0) + self.assertEqual(time.exposure, float(1.0)) + + time.resolution = float(2.0) + self.assertEqual(time.resolution, float(2.0)) + + time.timesys = str("timesys") + self.assertEqual(time.timesys, "timesys") + + time.trefpos = str("trefpos") + self.assertEqual(time.trefpos, "trefpos") + + time.mjdref = float(3.0) + self.assertEqual(time.mjdref, float(3.0)) + + +class TestPolarizationWCS(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, PolarizationWCS, None) + self.assertRaises(TypeError, PolarizationWCS, int(1)) + + axis = Axis('STOKES') + axis_1d = CoordAxis1D(axis) + polarization = PolarizationWCS(axis_1d) + self.assertEqual(polarization.axis, axis_1d) + + if __name__ == '__main__': unittest.main() - diff --git a/caom2tools/caom2/tests/test/test_point.py b/caom2tools/caom2/tests/test_data_type.py similarity index 89% rename from caom2tools/caom2/tests/test/test_point.py rename to caom2tools/caom2/tests/test_data_type.py index 18a668de..43e85c52 100644 --- a/caom2tools/caom2/tests/test/test_point.py +++ b/caom2tools/caom2/tests/test_data_type.py @@ -68,15 +68,28 @@ #*********************************************************************** # -""" Defines TestPoint class """ import unittest -from caom2.types.caom2_point import Point +from caom2.data_type import Point +from caom2.data_type import SegmentType + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + self.assertEqual(SegmentType.get(999), None) + self.assertRaises(AttributeError, SegmentType.get, None) + self.assertRaises(AttributeError, SegmentType.get, "foo") + + self.assertEqual(SegmentType.CLOSE.value, 0) + self.assertEqual(SegmentType.LINE.value, 1) + self.assertEqual(SegmentType.MOVE.value, 2) class TestPoint(unittest.TestCase): - def testInit(self): + def test_all(self): self.assertRaises(TypeError, Point, None, None) self.assertRaises(TypeError, Point, None, 1.0) diff --git a/caom2tools/caom2/tests/test_observation.py b/caom2tools/caom2/tests/test_observation.py new file mode 100644 index 00000000..f9bf55c3 --- /dev/null +++ b/caom2tools/caom2/tests/test_observation.py @@ -0,0 +1,751 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestObservation class """ + +import unittest +from datetime import datetime + +from caom2.data_type import Point +from caom2.observation import Algorithm +from caom2.observation import CompositeObservation +from caom2.observation import Environment +from caom2.observation import Instrument +from caom2.observation import Observation +from caom2.observation import ObservationIntentType +from caom2.observation import ObservationURI +from caom2.observation import Proposal +from caom2.observation import Requirements +from caom2.observation import SimpleObservation +from caom2.observation import Status +from caom2.observation import Target +from caom2.observation import TargetPosition +from caom2.observation import TargetType +from caom2.observation import Telescope +from caom2.plane import Plane +from caom2.util import Util + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + self.assertEqual(ObservationIntentType.get("no_such_string"), None) + self.assertRaises(AttributeError, ObservationIntentType.get, None) + self.assertRaises(AttributeError, ObservationIntentType.get, 1) + + self.assertEqual(Status.get("no_such_string"), None) + self.assertRaises(AttributeError, Status.get, None) + self.assertRaises(AttributeError, Status.get, 1) + + self.assertEqual(TargetType.get("no_such_string"), None) + self.assertRaises(AttributeError, TargetType.get, None) + self.assertRaises(AttributeError, TargetType.get, 1) + + # test that we can get the object for each enum by name + self.assertEqual(ObservationIntentType.CALIBRATION.value, "calibration") + self.assertEqual(ObservationIntentType.SCIENCE.value, "science") + + self.assertEqual(Status.FAIL.value, "fail") + + self.assertEqual(TargetType.FIELD.value, "field") + self.assertEqual(TargetType.OBJECT.value, "object") + + +class TestObservation(unittest.TestCase): + + def test_all(self): + algorithm = Algorithm("myAlg") + obs = Observation("GSA", "A12345", algorithm) + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + new_algorithm = Algorithm("myNewAlg") + obs.algorithm = new_algorithm + self.assertEquals(new_algorithm, obs.algorithm, "New algorithm") + + self.assertIsNone(obs.intent, "Default intent") + obs.intent = ObservationIntentType.CALIBRATION + self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = Target("TGT") + obs.target = target + self.assertEqual(target, obs.target, "Target") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = Requirements(Status.FAIL) + obs.requirements = requirements + self.assertEqual(requirements, + obs.requirements, "Requirements") + + self.assertIsNone(obs.environment, "Default environment") + environment = Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + self.assertEqual(0, len(obs.planes), "Default planes") + plane1 = Plane("myPlaneID") + obs.planes["myPlaneID"] = plane1 + self.assertEqual(1, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes.keys()) + + plane2 = Plane("myPlaneID2") + obs.planes["myPlaneID2"] = plane2 + self.assertEqual(2, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes) + self.assertTrue("myPlaneID2" in obs.planes.keys()) + + # test duplicates + plane3 = Plane("myPlaneID2") + obs.planes["myPlaneID2"] = plane3 + self.assertEqual(2, len(obs.planes), "Planes") + self.assertTrue("myPlaneID" in obs.planes) + self.assertTrue("myPlaneID2" in obs.planes.keys()) + + obs2 = Observation(obs.collection, + obs.observation_id, + obs.algorithm, + planes=obs.planes, + sequence_number=obs.sequence_number, + intent=obs.intent, + obs_type=obs.obs_type, + proposal=obs.proposal, + telescope=obs.telescope, + instrument=obs.instrument, + target=obs.target, + meta_release=obs.meta_release, + environment=obs.environment, + target_position=obs.target_position) + + +class TestObservationURI(unittest.TestCase): + + def test_all(self): + obsURI = ObservationURI("caom:GEMINI/12345") + self.assertEqual("caom:GEMINI/12345", obsURI.uri, "Observation URI") + self.assertEqual("GEMINI", obsURI.collection, "Collection") + self.assertEqual("12345", obsURI.observation_id, "Observation ID") + + obsURI = ObservationURI.get_observation_uri("CFHT", "654321") + self.assertEqual("caom:CFHT/654321", obsURI.uri, "Observation URI") + self.assertEqual("CFHT", obsURI.collection, "Collection") + self.assertEqual("654321", obsURI.observation_id, "Observation ID") + + exception = False + try: + obsURI = ObservationURI.get_observation_uri(None, "123") + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + obsURI = ObservationURI.get_observation_uri("GEMINI", None) + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + +class TestSimpleObservation(unittest.TestCase): + + def test_all(self): + algorithm = SimpleObservation._ALGORITHM + obs = SimpleObservation("GSA", "A12345") + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + obs.algorithm = algorithm + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + # try to set algorithm + exception = False + try: + obs.algorithm = Algorithm("myAlg") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + # run the rest of the Observation tests + self.assertIsNone(obs.intent, "Default intent") + obs.intent = ObservationIntentType.CALIBRATION + self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, + obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, + obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = Target("TGT") + obs.target = target + self.assertEqual(target, + obs.target, "Target") + + self.assertIsNone(obs.environment, "Default environment") + environment = Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = Requirements(Status.FAIL) + obs.requirements = requirements + self.assertEquals(requirements, obs.requirements, "requirements") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + # Test the complete constructor + def test_complete_init(self): + collection = str("CFHT") + observationID = str("543210") + algorithm = SimpleObservation._ALGORITHM + sequence_number = int(3) + intent = ObservationIntentType.SCIENCE + obs_type = str("foo") + proposal = Proposal("123") + telescope = Telescope("TEL") + instrument = Instrument("INST") + target = Target("LMC") + meta_release = datetime.now() + planes = Util.TypedOrderedDict((Plane),) + environment = Environment() + + obs = SimpleObservation(collection, + observationID, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment) + + self.assertIsNotNone(obs.collection, "Collection") + self.assertEqual(collection, obs.collection, "Collection") + + self.assertIsNotNone(obs.observation_id, "Observation ID") + self.assertEqual(observationID, obs.observation_id, "Observation ID") + + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + self.assertIsNotNone(obs.intent, "Observation intent") + self.assertEqual(intent, obs.intent, "Observation intent") + + self.assertIsNotNone(obs.obs_type, "obs type") + self.assertEqual(obs_type, obs.obs_type, "obs type") + + self.assertIsNotNone(obs.proposal, "Proposal") + self.assertEqual(proposal, obs.proposal, "Proposal") + + self.assertIsNotNone(obs.telescope, "Telescope") + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNotNone(obs.instrument, "Instrument") + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNotNone(obs.target, "Target") + self.assertEqual(target, obs.target, "Target") + + self.assertIsNotNone(obs.meta_release, "Metadata release") + self.assertEqual(meta_release, obs.meta_release, "Metadata release") + + self.assertIsNotNone(obs.planes, "Planes") + self.assertEqual(planes, obs.planes, "Planes") + + self.assertIsNotNone(obs.environment, "Environment") + self.assertEqual(environment, obs.environment, "Environment") + + +class TestCompositeObservation(unittest.TestCase): + + def test_all(self): + algorithm = Algorithm("mozaic") + obs = CompositeObservation("GSA", "A12345", algorithm) + self.assertEqual("GSA", obs.collection, "Collection") + self.assertEqual("A12345", obs.observation_id, "Observation ID") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + obs.algorithm = algorithm + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + # try to set algorithm to an invalid value + exception = False + try: + obs.algorithm = SimpleObservation._ALGORITHM + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + # try to set algorithm to None + exception = False + try: + obs.algorithm = None + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + self.assertEqual(0, len(obs.members), "Members") + observationURI1 = ObservationURI("caom:collection/obsID") + obs.members.add(observationURI1) + self.assertEqual(1, len(obs.members), "Members") + self.assertTrue(observationURI1 in obs.members) + + observationURI2 = ObservationURI("caom:collection/obsID2") + obs.members.add(observationURI2) + self.assertEqual(2, len(obs.members), "Members") + self.assertTrue(observationURI1 in obs.members) + self.assertTrue(observationURI2 in obs.members) + + #duplicates + observationURI3 = ObservationURI("caom:collection/obsID") + obs.members.add(observationURI3) + self.assertEqual(2, len(obs.members), "Members") + self.assertTrue(observationURI1 in obs.members) + self.assertTrue(observationURI2 in obs.members) + + # run the rest of the Observation tests + self.assertIsNone(obs.intent, "Default intent") + obs.intent = ObservationIntentType.CALIBRATION + self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent, "Observation intent") + + self.assertIsNone(obs.obs_type, "Default obs_type") + obs.obs_type = "obstype1" + self.assertEqual("obstype1", + obs.obs_type, "obs type") + + self.assertIsNone(obs.proposal, "Default proposal") + proposal = Proposal("ABC") + obs.proposal = proposal + self.assertEqual(proposal, + obs.proposal, "Proposal") + + self.assertIsNone(obs.telescope, "Default telescope") + telescope = Telescope("GSAGN") + obs.telescope = telescope + self.assertEqual(telescope, + obs.telescope, "Telescope") + + self.assertIsNone(obs.instrument, "Default instrument") + instrument = Instrument("NIRI") + obs.instrument = instrument + self.assertEqual(instrument, + obs.instrument, "Instrument") + + self.assertIsNone(obs.target, "Default target") + target = Target("TGT") + obs.target = target + self.assertEqual(target, + obs.target, "Target") + + self.assertIsNone(obs.environment, "Default environment") + environment = Environment() + obs.environment = environment + self.assertEqual(environment, + obs.environment, "Environment") + + self.assertIsNone(obs.target_position, "Default target position") + target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + obs.target_position = target_position + self.assertEqual(target_position, + obs.target_position, "TargetPosition") + + self.assertIsNone(obs.requirements, "Default requirements") + requirements = Requirements(Status.FAIL) + obs.requirements = requirements + self.assertEquals(requirements, obs.requirements, "requirements") + + self.assertIsNone(obs.meta_release, "Default metadata release") + date_now = datetime.now() + obs.meta_release = date_now + self.assertEqual(date_now, + obs.meta_release, "Metadata release") + + # Test the complete constructor + def test_complete_init(self): + collection = str("CFHT") + observationID = str("543210") + algorithm = str("algo") + sequence_number = int(3) + intent = ObservationIntentType.SCIENCE + obs_type = str("foo") + proposal = Proposal("123") + telescope = Telescope("TEL") + instrument = Instrument("INST") + target = Target("LMC") + meta_release = datetime.now() + planes = Util.TypedOrderedDict((Plane),) + environment = Environment() + target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + + obs = CompositeObservation(collection, + observationID, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position) + + self.assertIsNotNone(obs.collection, "Collection") + self.assertEqual(collection, obs.collection, "Collection") + + self.assertIsNotNone(obs.observation_id, "Observation ID") + self.assertEqual(observationID, obs.observation_id, "Observation ID") + + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertEqual(algorithm, obs.algorithm, "Algorithm") + + self.assertIsNotNone(obs.intent, "Observation intent") + self.assertEqual(intent, obs.intent, "Observation intent") + + self.assertIsNotNone(obs.obs_type, "obs type") + self.assertEqual(obs_type, obs.obs_type, "obs type") + + self.assertIsNotNone(obs.proposal, "Proposal") + self.assertEqual(proposal, obs.proposal, "Proposal") + + self.assertIsNotNone(obs.telescope, "Telescope") + self.assertEqual(telescope, obs.telescope, "Telescope") + + self.assertIsNotNone(obs.instrument, "Instrument") + self.assertEqual(instrument, obs.instrument, "Instrument") + + self.assertIsNotNone(obs.target, "Target") + self.assertEqual(target, obs.target, "Target") + + self.assertIsNotNone(obs.meta_release, "Metadata release") + self.assertEqual(meta_release, obs.meta_release, "Metadata release") + + self.assertIsNotNone(obs.planes, "Planes") + self.assertEqual(planes, obs.planes, "Planes") + + self.assertIsNotNone(obs.environment, "Environment") + self.assertEqual(environment, obs.environment, "Environment") + + self.assertIsNotNone(obs.target_position, "TargetPosition") + self.assertEqual(target_position, obs.target_position, + "TargetPosition") + + # Try changing the algorithm + algorithm2 = str("new algo") + obs.algorithm = algorithm2 + self.assertIsNotNone(obs.algorithm, "Algorithm") + self.assertNotEqual(algorithm, obs.algorithm, "Algorithm") + self.assertEqual(algorithm2, obs.algorithm, "Algorithm") + + +class TestAlgorithm(unittest.TestCase): + + def test_all(self): + algorithm = Algorithm("myAlgorithm") + self.assertEqual("myAlgorithm", algorithm.name, "Algorithm name") + + +class TestEnvironment(unittest.TestCase): + + def test_all(self): + environment = Environment() + + self.assertIsNone(environment.seeing, "Default seeing") + environment.seeing = 123.321 + self.assertEqual(123.321, environment.seeing, "Seeing") + self.assertIsNone(environment.humidity, "Default humidity") + environment.humidity = 0.333 + self.assertEqual(0.333, environment.humidity, "humidity") + self.assertIsNone(environment.elevation, "Default elevation") + environment.elevation = 12.12 + self.assertEqual(12.12, environment.elevation, "Elevation") + self.assertIsNone(environment.tau, "Default tau") + environment.tau = 0.456 + self.assertEqual(0.456, environment.tau, "Tau") + self.assertIsNone(environment.wavelength_tau, "Default wavelength tau") + environment.wavelength_tau = 200.02 + self.assertEqual(200.02, environment.wavelength_tau, "Wavelength tau") + self.assertIsNone(environment.ambient_temp, + "Default ambient temperature") + environment.ambient_temp = 12.44 + self.assertEqual(12.44, environment.ambient_temp, + "Ambient temperature") + self.assertIsNone(environment.photometric, "Default photometric") + environment.photometric = True + self.assertTrue(environment.photometric, "Photometric") + + +class TestIntrument(unittest.TestCase): + + def test_all(self): + instrument = Instrument("myInstrument") + self.assertEqual("myInstrument", instrument.name, "Instrument name") + self.assertEqual(0, len(instrument.keywords), "Default number of keywords") + + instrument.keywords.add("optical") + self.assertEqual(1, len(instrument.keywords), "Number of keywords") + self.assertTrue("optical" in instrument.keywords, "Keyword not found") + + instrument.keywords.add("radio") + self.assertEqual(2, len(instrument.keywords), "Number of keywords") + self.assertTrue("radio" in instrument.keywords, "Keyword not found") + + +class TestProposal(unittest.TestCase): + + def test_all(self): + proposal = Proposal("myProposal") + self.assertEqual("myProposal", proposal.proposal_id, "Proposal ID") + self.assertEqual(0, len(proposal.keywords), "Default number of keywords") + proposal.keywords.add("optical") + self.assertEqual(1, len(proposal.keywords), "Number of keywords") + self.assertTrue("optical" in proposal.keywords, "Keyword not found") + self.assertIsNone(proposal.pi_name, "Default PI") + proposal.pi_name = "John Doe" + self.assertEqual("John Doe", proposal.pi_name, "PI") + self.assertIsNone(proposal.project, "Default PI") + proposal.project = "Project A" + self.assertEqual("Project A", proposal.project, "Project") + self.assertIsNone(proposal.title, "Default title") + proposal.title = "Something Interesting" + self.assertEqual("Something Interesting", proposal.title, "Title") + + +class TestRequirements(unittest.TestCase): + + def test_all(self): + self.assertRaises(TypeError, Requirements, "string") + requirements = Requirements(Status.FAIL) + self.assertEqual(Status.FAIL, requirements.flag, + "Requirements flag") + + +class TestTarget(unittest.TestCase): + + def test_all(self): + target = Target("myTarget") + self.assertEqual("myTarget", target.name, "target name") + + target.target_type = TargetType.FIELD + self.assertEqual(TargetType.FIELD, target.target_type, "target type") + + self.assertEqual(0, len(target.keywords), "Default number of keywords") + target.keywords.add("optical") + self.assertEqual(1, len(target.keywords), "Number of keywords") + self.assertTrue("optical" in target.keywords, "Keyword not found") + + self.assertIsNone(target.redshift, "Default redshift") + target.redshift = 123.321 + self.assertEqual(123.321, target.redshift, "Redshift") + + self.assertIsNone(target.standard, "Default standard") + target.standard = True + self.assertTrue(target.standard, "Standard") + + self.assertIsNone(target.moving, "Default moving") + target.moving = True + self.assertTrue(target.moving, "Moving") + + target = Target("myOtherTarget", TargetType.OBJECT, False, 1.2, {"radio"}, False) + self.assertEquals("myOtherTarget", target.name, "target name") + self.assertEquals(TargetType.OBJECT, target.target_type, "target type") + self.assertFalse(target.standard, "Standard") + self.assertEquals(1.2, target.redshift, "Redshift") + self.assertEquals(1, len(target.keywords), "Keywords") + self.assertTrue("radio" in target.keywords, "Keywords") + self.assertFalse(target.moving, "Moving") + + +class TestTargetPosition(unittest.TestCase): + + def test_all(self): + self.assertRaises(TypeError, TargetPosition, "string") + point = Point(1.0, 2.0) + target_position = TargetPosition(point, "coordsys") + self.assertIsNotNone(target_position.coordinates, + "target position coordinates") + self.assertEqual(point.cval1, target_position.coordinates.cval1, + "coordinates cval1") + self.assertEqual(point.cval2, target_position.coordinates.cval2, + "coordinates cval2") + self.assertIsNotNone(target_position.coordsys, + "target position coordsys") + self.assertEqual("coordsys", target_position.coordsys, "coordsys") + self.assertIsNone(target_position.equinox, + "target position equinox") + + target_position = TargetPosition(point, "coordsys", 1.0) + self.assertIsNotNone(target_position.equinox, + "target position equinox") + self.assertEqual(1.0, target_position.equinox, + "equinox") + + +class TestTelescope(unittest.TestCase): + + def test_all(self): + telescope = Telescope("myTelescope") + self.assertEqual("myTelescope", telescope.name, "telescope name") + self.assertEqual(0, len(telescope.keywords), "Default number of keywords") + + telescope.keywords.add("optical") + self.assertEqual(1, len(telescope.keywords), "Number of keywords") + self.assertTrue("optical" in telescope.keywords, "Keyword not found") + + self.assertIsNone(telescope.geo_location_x, "Default geo location x") + telescope.geo_location_x = 123.321 + self.assertEqual(123.321, telescope.geo_location_x, "Geo location x") + + self.assertIsNone(telescope.geo_location_y, "Default geo location y") + telescope.geo_location_y = 333.33 + self.assertEqual(333.33, telescope.geo_location_y, "Geo location y") + + self.assertIsNone(telescope.geo_location_z, "Default geo location z") + telescope.geo_location_z = 12.12 + self.assertEqual(12.12, telescope.geo_location_z, "Geo location z") + + + +if __name__ == '__main__': + unittest.main() diff --git a/caom2tools/caom2/tests/test/test_part.py b/caom2tools/caom2/tests/test_part.py similarity index 97% rename from caom2tools/caom2/tests/test/test_part.py rename to caom2tools/caom2/tests/test_part.py index 33aa7bba..bd301a4c 100644 --- a/caom2tools/caom2/tests/test/test_part.py +++ b/caom2tools/caom2/tests/test_part.py @@ -72,9 +72,9 @@ import unittest -from caom2.caom2_chunk import Chunk -from caom2.caom2_enums import ProductType -from caom2.caom2_part import Part +from caom2.artifact import ProductType +from caom2.chunk import Chunk +from caom2.part import Part class TestPart(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_plane.py b/caom2tools/caom2/tests/test_plane.py new file mode 100644 index 00000000..e15b3d43 --- /dev/null +++ b/caom2tools/caom2/tests/test_plane.py @@ -0,0 +1,557 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines TestPlane class """ + +import unittest +from datetime import datetime + +from caom2.artifact import Artifact +from caom2.artifact import ProductType, ReleaseType +from caom2.observation import ObservationURI +from caom2.plane import CalibrationLevel +from caom2.plane import DataProductType +from caom2.plane import DataQuality +from caom2.plane import Energy +from caom2.plane import EnergyBand +from caom2.plane import EnergyTransition +from caom2.plane import Metrics +from caom2.plane import Plane +from caom2.plane import PlaneURI +from caom2.plane import Polarization +from caom2.plane import PolarizationState +from caom2.plane import Position +from caom2.plane import Provenance +from caom2.plane import Quality +from caom2.plane import Time + + +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + self.assertEqual(CalibrationLevel.get(999), None) + self.assertRaises(AttributeError, CalibrationLevel.get, None) + self.assertRaises(AttributeError, CalibrationLevel.get, "foo") + + self.assertEqual(DataProductType.get("no_such_string"), None) + self.assertRaises(AttributeError, DataProductType.get, None) + self.assertRaises(AttributeError, DataProductType.get, 1) + + self.assertEqual(EnergyBand.get("no_such_string"), None) + self.assertRaises(AttributeError, EnergyBand.get, None) + self.assertRaises(AttributeError, EnergyBand.get, 1) + + self.assertEqual(PolarizationState.get("no_such_string"), None) + self.assertRaises(AttributeError, PolarizationState.get, None) + self.assertRaises(AttributeError, PolarizationState.get, 1) + + self.assertEqual(Quality.get("no_such_string"), None) + self.assertRaises(AttributeError, Quality.get, None) + self.assertRaises(AttributeError, Quality.get, 1) + + # test that we can get the object for each enum by name + self.assertEqual(CalibrationLevel.RAW_INSTRUMENT.value, 0) + self.assertEqual(CalibrationLevel.RAW_STANDARD.value, 1) + self.assertEqual(CalibrationLevel.CALIBRATED.value, 2) + self.assertEqual(CalibrationLevel.PRODUCT.value, 3) + + self.assertEqual(DataProductType.IMAGE.value, "image") + self.assertEqual(DataProductType.CATALOG.value, "catalog") + self.assertEqual(DataProductType.CUBE.value, "cube") + self.assertEqual(DataProductType.EVENTLIST.value, "eventlist") + self.assertEqual(DataProductType.SPECTRUM.value, "spectrum") + self.assertEqual(DataProductType.TIMESERIES.value, "timeseries") + self.assertEqual(DataProductType.VISIBILITY.value, "visibility") + + self.assertEqual(EnergyBand.get('RADIO').value, "Radio") + self.assertEqual(EnergyBand.get('MILLIMETER').value, "Millimeter") + self.assertEqual(EnergyBand.get('INFRARED').value, "Infrared") + self.assertEqual(EnergyBand.get('OPTICAL').value, "Optical") + self.assertEqual(EnergyBand.get('UV').value, "UV") + self.assertEqual(EnergyBand.get('EUV').value, "EUV") + self.assertEqual(EnergyBand.get('XRAY').value, "X-ray") + self.assertEqual(EnergyBand.get('GAMMARAY').value, "Gamma-ray") + + self.assertEqual(PolarizationState.get('I').value, "I") + self.assertEqual(PolarizationState.get('Q').value, "Q") + self.assertEqual(PolarizationState.get('U').value, "U") + self.assertEqual(PolarizationState.get('V').value, "V") + self.assertEqual(PolarizationState.get('LL').value, "LL") + self.assertEqual(PolarizationState.get('LR').value, "LR") + self.assertEqual(PolarizationState.get('RL').value, "RL") + self.assertEqual(PolarizationState.get('RR').value, "RR") + self.assertEqual(PolarizationState.get('XX').value, "XX") + self.assertEqual(PolarizationState.get('XY').value, "XY") + self.assertEqual(PolarizationState.get('YX').value, "YX") + self.assertEqual(PolarizationState.get('YY').value, "YY") + + self.assertEqual(Quality.get('JUNK').value, "junk") + + +class TestPlane(unittest.TestCase): + + def test_all(self): + plane = Plane("ProdID") + self.assertEqual("ProdID", plane.product_id, "Product ID") + self.assertEqual(0, len(plane.artifacts), + "Default number of artifacts") + self.assertIsNone(plane.meta_release, "Default meta release date") + date_now = datetime.now() + plane.meta_release = date_now + self.assertEqual(date_now, plane.meta_release, "Metadata release date") + self.assertIsNone(plane.data_release, "Default data release date") + date_now = datetime.now() + plane.data_release = date_now + self.assertEqual(date_now, plane.data_release, "Data release date") + self.assertIsNone(plane.data_product_type, "Default data product type") + plane.data_product_type = DataProductType.IMAGE + self.assertEqual(DataProductType.IMAGE, plane.data_product_type, + "Data product type") + self.assertIsNone(plane.calibration_level, + "Default calibration level") + plane.calibration_level = CalibrationLevel.CALIBRATED + self.assertEqual(CalibrationLevel.CALIBRATED, + plane.calibration_level, "CalibrationLevel") + self.assertIsNone(plane.quality, + "Default quality") + quality = DataQuality(Quality.JUNK) + plane.quality = quality + self.assertEqual(quality, + plane.quality, "Quality") + self.assertIsNone(plane.provenance, "Default provenance") + provenance = Provenance("myProv") + plane.provenance = provenance + self.assertEqual("myProv", plane.provenance.name, "Provenance - name") + self.assertIsNone(plane.metrics, "Default metrics") + metrics = Metrics() + plane.metrics = metrics + self.assertEqual(metrics, plane.metrics, "Provenance - metrics") + #self.assertIsNone(plane.observable, "Default observable") + self.assertIsNone(plane.position, "Default position") + self.assertIsNone(plane.energy, "Default energy") + self.assertIsNone(plane.time, "Default time") + self.assertIsNone(plane.polarization, "Default polarization") + + artifact1 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) + plane.artifacts["caom:GEMINI/222/333"] = artifact1 + self.assertEquals(1, len(plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) + + artifact2 = Artifact("caom:CFHT/55/66", ProductType.SCIENCE, ReleaseType.DATA) + plane.artifacts["caom:CFHT/55/66"] = artifact2 + self.assertEquals(2, len(plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) + + #try to append a duplicate artifact + artifact3 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) + plane.artifacts["caom:GEMINI/222/333"] = artifact3 + self.assertEquals(2, len(plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) + + #Error cases + exception = False + try: + plane = Plane(None) + except TypeError: + exception = True + self.assertTrue(exception, "Null argument in initialize") + + #exception = False + #try: + # plane.compute_observable() + #except TypeError: + # exception = True + #self.assertTrue(exception, + # "compute_observable implemented - Testing needed") + + #exception = False + #try: + # plane.compute_position() + #except TypeError: + # exception = True + #self.assertTrue(exception, + # "compute_position implemented - Testing needed") + + exception = False + try: + plane.compute_energy() + except NotImplementedError: + exception = True + self.assertTrue(exception, + "compute_energy implemented - Testing needed") + + exception = False + try: + plane.compute_time() + except NotImplementedError: + exception = True + self.assertTrue(exception, "compute_time implemented - Testing needed") + + exception = False + try: + plane.compute_polarization() + except NotImplementedError: + exception = True + self.assertTrue(exception, "compute_polarization implemented" + " - Testing needed") + + +class TestPlaneURI(unittest.TestCase): + + def test_all(self): + planeURI = PlaneURI("caom:GEMINI/12345/3333") + self.assertEqual("caom:GEMINI/12345/3333", planeURI.uri, + "Plane URI") + self.assertEqual("GEMINI", planeURI.observation_uri.collection, + "Collection") + self.assertEqual("12345", planeURI.observation_uri.observation_id, + "Observation ID") + self.assertEqual("3333", planeURI.product_id, "Product ID") + + planeURI = PlaneURI.get_plane_uri(ObservationURI("caom:CFHT/654321"), + "555") + self.assertEqual("caom:CFHT/654321/555", planeURI.uri, + "Observation URI") + self.assertEqual("CFHT", planeURI.observation_uri.collection, + "Collection") + self.assertEqual("654321", planeURI.observation_uri.observation_id, + "Observation ID") + self.assertEqual("555", planeURI.product_id, "Product ID") + + exception = False + try: + planeURI = PlaneURI.get_plane_uri(None, "123") + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + planeURI = PlaneURI.get_plane_uri("GEMINI", None) + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + #wrong scheme + exception = False + try: + planeURI = PlaneURI("somescheme:GEMINI/12345/3333") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + planeURI = PlaneURI("caom:GEMINI/12345") + except ValueError: + exception = True + self.assertTrue(exception, "Missing exception") + + +class TestDataQuality(unittest.TestCase): + + def test_all(self): + + self.assertRaises(TypeError, DataQuality, "string") + quality = DataQuality(Quality.JUNK) + self.assertEqual(Quality.JUNK, quality.flag, + "DataQuality flag") + + +class TestMetrics(unittest.TestCase): + + def test_all(self): + metrics = Metrics() + + self.assertIsNone(metrics.source_number_density, + "Default source number density") + metrics.source_number_density = 22.22 + self.assertEquals(22.22, metrics.source_number_density, + "Source number density") + self.assertIsNone(metrics.background, "Default background") + metrics.background = 12.34 + self.assertEquals(12.34, metrics.background, "Background") + self.assertIsNone(metrics.background_std_dev, + "Default background standard deviation") + metrics.background_std_dev = 34.34 + self.assertEquals(34.34, metrics.background_std_dev, + "Background standard deviation") + self.assertIsNone(metrics.flux_density_limit, + "Default flux density limit") + metrics.flux_density_limit = 55.55 + self.assertEquals(55.55, metrics.flux_density_limit, + "Flux density limit") + self.assertIsNone(metrics.mag_limit, "Default mag limit") + metrics.mag_limit = 20.08 + self.assertEquals(20.08, metrics.mag_limit, "Mag limit") + + +class TestProvenance(unittest.TestCase): + + def test_all(self): + provenance = Provenance("MyProvenance") + self.assertEqual("MyProvenance", provenance.name, "Name") + + self.assertIsNone(provenance.version, "Default version") + provenance.version = "XII" + self.assertEquals("XII", provenance.version, "Version") + self.assertIsNone(provenance.project, "Default project") + provenance.project = "CFHTLS" + self.assertEquals("CFHTLS", provenance.project, "Project") + self.assertIsNone(provenance.producer, "Default producer") + provenance.producer = "prod" + self.assertEquals("prod", provenance.producer, "Producer") + self.assertIsNone(provenance.run_id, "Default run ID") + provenance.run_id = "A23" + self.assertEquals("A23", provenance.run_id, "Run ID") + self.assertIsNone(provenance.reference, "Default reference") + + self.assertEqual(0, len(provenance.inputs), "Default inputs") + planeURI1 = PlaneURI("caom:HST/11/00") + provenance.inputs.add(planeURI1) + self.assertEqual(1, len(provenance.inputs), "Default inputs") + self.assertTrue(planeURI1 in provenance.inputs) + + planeURI2 = PlaneURI("caom:HST/22/00") + provenance.inputs.add(planeURI2) + self.assertEqual(2, len(provenance.inputs), "Default inputs") + self.assertTrue(planeURI1 in provenance.inputs) + self.assertTrue(planeURI2 in provenance.inputs) + + # testing duplicates + planeURI3 = PlaneURI("caom:HST/22/00") + provenance.inputs.add(planeURI3) + self.assertEqual(2, len(provenance.inputs), "Default inputs") + self.assertTrue(planeURI1 in provenance.inputs) + self.assertTrue(planeURI2 in provenance.inputs) + + self.assertIsNone(provenance.last_executed, "Default last executed") + now_date = datetime.now() + provenance.last_executed = now_date + self.assertEquals(now_date, provenance.last_executed, "Last executed") + + self.assertEquals(0, len(provenance.keywords), "0 default keywords") + provenance.keywords.add("keyword1") + self.assertEquals(1, len(provenance.keywords), "1 keyword") + self.assertTrue("keyword1" in provenance.keywords, "Keyword not found") + + provenance.keywords.add("keyword2") + self.assertEquals(2, len(provenance.keywords), "2 keyword") + self.assertTrue("keyword2" in provenance.keywords, "Keyword not found") + + # test the full constructor + provenance = Provenance("MyOtherProvenance", + "Version2.0", + "JCMT", + "Mutt Lang", + "b32", + "caom:JCMT/33/00", + now_date) + + self.assertIsNotNone(provenance.name) + self.assertIsNotNone(provenance.version) + self.assertIsNotNone(provenance.project) + self.assertIsNotNone(provenance.producer) + self.assertIsNotNone(provenance.run_id) + self.assertIsNotNone(provenance.reference) + self.assertIsNotNone(provenance.last_executed) + + self.assertEquals("MyOtherProvenance", provenance.name, "name") + self.assertEquals("Version2.0", provenance.version, "version") + self.assertEquals("JCMT", provenance.project, "project") + self.assertEquals("Mutt Lang", provenance.producer, "producer") + self.assertEquals("b32", provenance.run_id, "run_id") + self.assertEquals("caom:JCMT/33/00", provenance.reference, "reference") + self.assertEquals(now_date, provenance.last_executed, "last_executed") + + +class TestPosition(unittest.TestCase): + + def test_all(self): + position = Position() + + self.assertIsNone(position.bounds, "Default bounds") + #position.bounds = 123 + #self.assertEqual(123, position.bounds, "Bounds") + self.assertIsNone(position.dimension, "Default dimension") + #position.dimension = 123 + #self.assertEqual(123, position.dimension, "Dimension") + self.assertIsNone(position.resolution, "Default resolution") + position.resolution = 123.321 + self.assertEqual(123.321, position.resolution, "Resolution") + self.assertIsNone(position.sample_size, "Default sample size") + position.sample_size = 321.123 + self.assertEqual(321.123, position.sample_size, "Sample size") + self.assertFalse(position.time_dependent, "Default time dependent") + position.time_dependent = True + self.assertTrue(position.time_dependent, "Time dependent") + + +class TestEnergy(unittest.TestCase): + + def test_all(self): + energy = Energy() + self.assertIsNone(energy.value, "Default energy value") + energy.value = 33.33 + self.assertEqual(33.33, energy.value, "Energy value") + self.assertIsNone(energy.bounds, "Default energy bounds") + #TODO switch to Interval + #energy.bounds = 22 + self.assertIsNone(energy.dimension, "Default energy dimension") + energy.dimension = 1000L + self.assertEqual(1000L, energy.dimension, "Energy dimension") + self.assertIsNone(energy.resolving_power, + "Default energy resolving power") + energy.resolving_power = 123.12 + self.assertEqual(123.12, energy.resolving_power, + "Energy resolving power") + self.assertIsNone(energy.sample_size, "Default energy sample size") + energy.sample_size = 123.321 + self.assertEqual(123.321, energy.sample_size, "Energy sample size") + self.assertIsNone(energy.bandpass_name, "Default energy band pass") + energy.bandpass_name = "EBN" + self.assertEqual("EBN", energy.bandpass_name, "Energy bandpass name") + self.assertIsNone(energy.em_band, "Default energy em band") + energy.em_band = EnergyBand.OPTICAL + self.assertEqual(EnergyBand.OPTICAL, energy.em_band, "Energy band") + self.assertIsNone(energy.transition, "Default energy transition") + #TODO replace with EnergyTransistion + #energy.transition = "BLAH" + + +class TestEnergyTransition(unittest.TestCase): + + def test__init__(self): + # test for invalid values + self.assertRaises(TypeError, EnergyTransition, None, None) + self.assertRaises(TypeError, EnergyTransition, 'aString', None) + self.assertRaises(TypeError, EnergyTransition, None, 'aString') + self.assertRaises(TypeError, EnergyTransition, 1, 'aString') + self.assertRaises(TypeError, EnergyTransition, 'aString', 2) + # test for happy path + transition = EnergyTransition("aSpecies", "aTransition") + self.assertEqual(transition._species, "aSpecies") + self.assertEqual(transition._transition, "aTransition") + + def test_setters(self): + # test that we cannot change the attribute values + transition = EnergyTransition("aSpecies", "aTransition") + try: + transition.species = "newSpecies" + transition.transition = "newTransition" + except AttributeError: + pass + else: + raise AttributeError("at least one attribute was changed") + + +class TestPolarizaton(unittest.TestCase): + + def test_all(self): + polarization = Polarization() + + self.assertIsNone(polarization.dimension, + "Default polarization dimension") + energy = Energy() + energy.bandpass_name = '123' + self.assertEqual('123', energy.bandpass_name, "Polarization dimension") + + #TODO add test for state + + +class TestTime(unittest.TestCase): + + def test_all(self): + time = Time() + self.assertIsNone(time.value, "Default value") + self.assertIsNone(time.bounds, "Default bounds") + self.assertIsNone(time.dimension, "Default dimension") + self.assertIsNone(time.resolution, "Default resolution") + self.assertIsNone(time.sample_size, "Default sample size") + self.assertIsNone(time.exposure, "Default exposure") + + time.value = 34.34 + self.assertEqual(34.34, time.value, "Value") + time.dimension = 777L + self.assertEqual(777L, time.dimension, "Dimension") + time.resolution = 77.777 + self.assertEqual(77.777, time.resolution, "Resolution") + time.sample_size = 12.34 + self.assertEqual(12.34, time.sample_size, "Sample size") + time.exposure = 55.55 + self.assertEqual(55.55, time.exposure, "Exposure") + + +if __name__ == '__main__': + unittest.main() + diff --git a/caom2tools/caom2/tests/test/test_caom2_util.py b/caom2tools/caom2/tests/test_util.py similarity index 92% rename from caom2tools/caom2/tests/test/test_caom2_util.py rename to caom2tools/caom2/tests/test_util.py index febdd2e0..16826501 100644 --- a/caom2tools/caom2/tests/test/test_caom2_util.py +++ b/caom2tools/caom2/tests/test_util.py @@ -73,23 +73,22 @@ import unittest import uuid -from caom2.caom2_artifact import Artifact -from caom2.caom2_energy import Energy -from caom2.caom2_enums import ProductType, ReleaseType -from caom2.caom2_part import Part -from caom2.caom2_plane import Plane -from caom2.caom2_plane_uri import PlaneURI -from caom2.util.caom2_util import TypedList -from caom2.util.caom2_util import TypedOrderedDict -from caom2.util.caom2_util import TypedSet -from caom2.util.caom2_util import long2uuid -from caom2.util.caom2_util import uuid2long -from caom2.util.caom2_util import validate_path_component +from caom2.artifact import Artifact +from caom2.artifact import ProductType +from caom2.artifact import ReleaseType +from caom2.part import Part +from caom2.plane import Energy +from caom2.plane import Plane +from caom2.plane import PlaneURI +from caom2.util import TypedList +from caom2.util import TypedOrderedDict +from caom2.util import TypedSet +from caom2.util import Util class TestCaomUtil(unittest.TestCase): - def testTypedList(self): + def test_typed_list(self): mylist1 = TypedList((str), "Test1") self.assertEquals(1, len(mylist1), "list1 length") self.assertEqual("Test1", mylist1[0], "Non matching elements") @@ -161,37 +160,37 @@ def testTypedList(self): def test_validate_path_component(self): energy = Energy() - validate_path_component(energy, "something", "some:test\\path") + Util.validate_path_component(energy, "something", "some:test\\path") exception = False try: - validate_path_component(energy, "energyfield", "some:test path") + Util.validate_path_component(energy, "energyfield", "some:test path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test/path") + Util.validate_path_component(energy, "energyfield", "some:test/path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test||path") + Util.validate_path_component(energy, "energyfield", "some:test||path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - validate_path_component(energy, "energyfield", "some:test %path") + Util.validate_path_component(energy, "energyfield", "some:test %path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") - def testTypedSet(self): + def test_typed_set(self): myset = TypedSet((str),) with self.assertRaises(AssertionError): @@ -219,7 +218,7 @@ def testTypedSet(self): myset.add("Test1") self.assertTrue(len(myset) == 1) - def testTypedOrderedDict(self): + def test_typed_ordered_dict(self): # test validation and constructor with an empty dictionary testPlane10 = Plane('key10') @@ -310,32 +309,33 @@ def testuuid2long(self): # > 64 bit uuid u = uuid.UUID('3d26e30b-10cc-4301-8193-f2e0c6b63302') try: - uuid2long(u) + Util.uuid2long(u) self.fail("> 64 uuid should raise ValueError") except ValueError: pass u = uuid.UUID('00000000-0000-0000-0000-000000000001') - l = uuid2long(u) + l = Util.uuid2long(u) self.assertEqual(1L, l) u = uuid.UUID('00000000-0000-0000-0000-000000bc614e') - l = uuid2long(u) + l = Util.uuid2long(u) self.assertEqual(12345678L, l) def testlong2uuid(self): # > 64 bit long l = 123456781234567812345678L try: - long2uuid(l) + Util.long2uuid(l) self.fail("> 64 bit long should raise ValueError") except ValueError: pass l = 3296038095975885829 - uid = long2uuid(l) + uid = Util.long2uuid(l) self.assertEqual('00000000-0000-0000-2dbd-e12f64cc2c05', str(uid)) + if __name__ == '__main__': unittest.main() diff --git a/caom2tools/caom2/tests/test_wcs.py b/caom2tools/caom2/tests/test_wcs.py new file mode 100644 index 00000000..4544499b --- /dev/null +++ b/caom2tools/caom2/tests/test_wcs.py @@ -0,0 +1,461 @@ +#!/usr/bin/env python +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +import unittest + +from caom2 import wcs + + +class TestAxis(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.Axis, None, None) + self.assertRaises(TypeError, wcs.Axis, None, "cunit") + self.assertRaises(TypeError, wcs.Axis, "ctype", int(1)) + self.assertRaises(TypeError, wcs.Axis, int(1), "cunit") + + axis = wcs.Axis("ctype", "cunit") + self.assertEqual(axis.ctype, "ctype") + self.assertEqual(axis.cunit, "cunit") + + +class TestCoord2D(unittest.TestCase): + + def test_init(self): + + coord1 = wcs.RefCoord(float(1.0), float(2.0)) + coord2 = wcs.RefCoord(float(3.0), float(4.0)) + + self.assertRaises(TypeError, wcs.Coord2D, None, None) + self.assertRaises(TypeError, wcs.Coord2D, None, coord2) + self.assertRaises(TypeError, wcs.Coord2D, coord1, None) + self.assertRaises(TypeError, wcs.Coord2D, str("s"), coord2) + self.assertRaises(TypeError, wcs.Coord2D, coord1, str("s")) + + coord_2d = wcs.Coord2D(coord1, coord2) + self.assertEqual(coord_2d.coord1, coord1) + self.assertEqual(coord_2d.coord2, coord2) + + +class TestCoordAxis1D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordAxis1D, None) + self.assertRaises(TypeError, wcs.CoordAxis1D, int(1)) + + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) + self.assertEqual(axis_1d.axis, axis) + with self.assertRaises(TypeError): + axis_1d.error = str("s") + axis_1d.bounds = str("s") + axis_1d.function = str("s") + axis_1d.range = str("s") + + error = wcs.CoordError(float(1.0), float(2.0)) + axis_1d.error = error + self.assertEqual(axis_1d.error, error) + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + coordRange = wcs.CoordRange1D(start, end) + axis_1d.range = coordRange + self.assertEqual(axis_1d.range, coordRange) + + bounds = wcs.CoordBounds1D() + axis_1d.bounds = bounds + self.assertEqual(axis_1d.bounds, bounds) + + naxis = long(1) + delta = float(2.5) + ref_coord = wcs.RefCoord(float(1.0), float(2.0)) + function = wcs.CoordFunction1D(naxis, delta, ref_coord) + axis_1d.function = function + self.assertEqual(axis_1d.function, function) + + +class TestCoordAxis2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordAxis2D, None, None) + self.assertRaises(TypeError, wcs.CoordAxis2D, None, int(1)) + self.assertRaises(TypeError, wcs.CoordAxis2D, int(1), None) + + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + self.assertEqual(axis_2d.axis1, axis1) + self.assertEqual(axis_2d.axis2, axis2) + with self.assertRaises(TypeError): + axis_2d.error1 = str("s") + axis_2d.error2 = str("s") + axis_2d.bounds = str("s") + axis_2d.function = str("s") + axis_2d.range = str("s") + + error1 = wcs.CoordError(float(1.0), float(2.0)) + axis_2d.error1 = error1 + self.assertEqual(axis_2d.error1, error1) + + error2 = wcs.CoordError(float(3.0), float(4.0)) + axis_2d.error2 = error2 + self.assertEqual(axis_2d.error2, error2) + + start = wcs.Coord2D(wcs.RefCoord(float(1.0), float(2.0)), + wcs.RefCoord(float(3.0), float(4.0))) + end = wcs.Coord2D(wcs.RefCoord(float(5.0), float(6.0)), + wcs.RefCoord(float(7.0), float(8.0))) + coordRange = wcs.CoordRange2D(start, end) + axis_2d.range = coordRange + self.assertEqual(axis_2d.range, coordRange) + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + circle = wcs.CoordCircle2D(center, radius) + axis_2d.bounds = circle + self.assertEqual(axis_2d.bounds, circle) + + polygon = wcs.CoordPolygon2D() + axis_2d.bounds = polygon + self.assertEqual(axis_2d.bounds, polygon) + + dimension = wcs.Dimension2D(long(1), long(2)) + ref_coord = wcs.Coord2D(wcs.RefCoord(float(9.0), float(10.0)), + wcs.RefCoord(float(11.0), float(12.0))) + cd11 = float(1.1) + cd12 = float(1.2) + cd21 = float(2.1) + cd22 = float(2.2) + function = wcs.CoordFunction2D(dimension, ref_coord, + cd11, cd12, cd21, cd22) + axis_2d.function = function + self.assertEqual(axis_2d.function, function) + + +class TestCoordBounds1D(unittest.TestCase): + + def test_init(self): + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + coordRange = wcs.CoordRange1D(start, end) + + bounds = wcs.CoordBounds1D() + bounds.samples.append(coordRange) + self.assertTrue(bounds.samples.count(coordRange) == 1) + self.assertEqual(bounds.samples.pop(), coordRange) + + with self.assertRaises(TypeError): + bounds.samples = [str("s")] + + +class TestCoordBounds2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.CoordBounds2D, None) + self.assertRaises(TypeError, wcs.CoordBounds2D, float(1.0)) + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + circle = wcs.CoordCircle2D(center, radius) + + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(wcs.ValueCoord2D(float(1.0), float(2.0))) + + bounds = wcs.CoordBounds2D(circle) + self.assertEqual(bounds.bounds, circle) + + bounds = wcs.CoordBounds2D(polygon) + self.assertEqual(bounds.bounds, polygon) + + +class TestCoordCircle2D(unittest.TestCase): + + def test_init(self): + + center = wcs.ValueCoord2D(float(1.0), float(2.0)) + radius = float(1.5) + + self.assertRaises(TypeError, wcs.CoordCircle2D, None, None) + self.assertRaises(TypeError, wcs.CoordCircle2D, None, radius) + self.assertRaises(TypeError, wcs.CoordCircle2D, center, None) + self.assertRaises(TypeError, wcs.CoordCircle2D, int(1), radius) + self.assertRaises(TypeError, wcs.CoordCircle2D, center, int(1)) + + circle = wcs.CoordCircle2D(center, radius) + self.assertEqual(circle.center, center) + self.assertEqual(circle.radius, radius) + + +class TestCoordError(unittest.TestCase): + + def test_init(self): + self.assertRaises(TypeError, wcs.CoordError, None, None) + self.assertRaises(TypeError, wcs.CoordError, None, float(1.0)) + self.assertRaises(TypeError, wcs.CoordError, float(1.0), None) + self.assertRaises(TypeError, wcs.CoordError, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.CoordError, float(1.0), int(1)) + + error = wcs.CoordError(float(1), float(2)) + print error.rnder + self.assertIsNotNone(error) + self.assertEqual(error.syser, float(1)) + self.assertEqual(error.rnder, float(2)) + + +class TestCoordFunction1D(unittest.TestCase): + + def test_init(self): + + naxis = long(1) + delta = float(2.5) + ref_coord = wcs.RefCoord(float(1.0), float(2.0)) + + self.assertRaises(TypeError, wcs.CoordFunction1D, None, None, + None) + self.assertRaises(TypeError, wcs.CoordFunction1D, None, delta, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, None, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, delta, + None) + self.assertRaises(TypeError, wcs.CoordFunction1D, int(1), delta, + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, int(1), + ref_coord) + self.assertRaises(TypeError, wcs.CoordFunction1D, naxis, delta, + int(1)) + + function = wcs.CoordFunction1D(naxis, delta, ref_coord) + self.assertEqual(function.naxis, naxis) + self.assertEqual(function.delta, delta) + self.assertEqual(function.ref_coord, ref_coord) + + +class TestCoordFunction2D(unittest.TestCase): + + def test_init(self): + + dimension = wcs.Dimension2D(long(1), long(2)) + ref_coord = wcs.Coord2D(wcs.RefCoord(float(9.0), float(10.0)), + wcs.RefCoord(float(11.0), float(12.0))) + cd11 = float(1.1) + cd12 = float(1.2) + cd21 = float(2.1) + cd22 = float(2.2) + + self.assertRaises(TypeError, wcs.CoordFunction2D, None, + ref_coord, cd11, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + None, cd11, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, None, cd12, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, None, cd21, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, cd12, None, cd22) + self.assertRaises(TypeError, wcs.CoordFunction2D, dimension, + ref_coord, cd11, cd12, cd21, None) + + function = wcs.CoordFunction2D(dimension, ref_coord, + cd11, cd12, cd21, cd22) + self.assertEqual(function.dimension, dimension) + self.assertEqual(function.ref_coord, ref_coord) + self.assertEqual(function.cd11, cd11) + self.assertEqual(function.cd12, cd12) + self.assertEqual(function.cd21, cd21) + self.assertEqual(function.cd22, cd22) + + +class TestCoordPolygon2D(unittest.TestCase): + + def test_init(self): + + value_coord2d = wcs.ValueCoord2D(float(1.0), float(2.0)) + + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(value_coord2d) + self.assertTrue(polygon.vertices.count(value_coord2d) == 1) + self.assertEqual(polygon.vertices.pop(), value_coord2d) + + with self.assertRaises(TypeError): + polygon.vertices = [str("s")] + + +class TestCoordRange1D(unittest.TestCase): + + def test_init(self): + + start = wcs.RefCoord(float(1.0), float(2.0)) + end = wcs.RefCoord(float(3.0), float(4.0)) + + self.assertRaises(TypeError, wcs.CoordRange1D, None, None) + self.assertRaises(TypeError, wcs.CoordRange1D, None, end) + self.assertRaises(TypeError, wcs.CoordRange1D, start, None) + self.assertRaises(TypeError, wcs.CoordRange1D, int(1), end) + self.assertRaises(TypeError, wcs.CoordRange1D, start, int(1)) + + coordRange = wcs.CoordRange1D(start, end) + self.assertEqual(coordRange.start, start) + self.assertEqual(coordRange.end, end) + + +class TestCoordRange2D(unittest.TestCase): + + def test_init(self): + + start = wcs.Coord2D(wcs.RefCoord(float(1.0), float(2.0)), + wcs.RefCoord(float(3.0), float(4.0))) + end = wcs.Coord2D(wcs.RefCoord(float(5.0), float(6.0)), + wcs.RefCoord(float(7.0), float(8.0))) + + self.assertRaises(TypeError, wcs.CoordRange2D, None, None) + self.assertRaises(TypeError, wcs.CoordRange2D, None, end) + self.assertRaises(TypeError, wcs.CoordRange2D, start, None) + self.assertRaises(TypeError, wcs.CoordRange2D, int(1), end) + self.assertRaises(TypeError, wcs.CoordRange2D, start, int(1)) + + coordRange = wcs.CoordRange2D(start, end) + self.assertEqual(coordRange.start, start) + self.assertEqual(coordRange.end, end) + + +class TestDimension2D(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.Dimension2D, None, None) + self.assertRaises(TypeError, wcs.Dimension2D, long(1), None) + self.assertRaises(TypeError, wcs.Dimension2D, None, long(1)) + self.assertRaises(TypeError, wcs.Dimension2D, int(1), long(1)) + self.assertRaises(TypeError, wcs.Dimension2D, long(1), int(1)) + + dimension = wcs.Dimension2D(long(1), long(2)) + self.assertEqual(dimension.naxis1, long(1)) + self.assertEqual(dimension.naxis2, long(2)) + + +class TestRefCoord(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.RefCoord, None, None) + self.assertRaises(TypeError, wcs.RefCoord, None, float(1.0)) + self.assertRaises(TypeError, wcs.RefCoord, float(1.0), None) + self.assertRaises(TypeError, wcs.RefCoord, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.RefCoord, float(1.0), int(1)) + + ref_coord = wcs.RefCoord(float(1), float(2)) + self.assertIsNotNone(ref_coord) + self.assertEqual(ref_coord.pix, float(1)) + self.assertEqual(ref_coord.val, float(2)) + + +class TestSlice(unittest.TestCase): + + def test_init(self): + + axis = wcs.Axis("ctype", "cunit") + myBin = long(1) + + self.assertRaises(TypeError, wcs.Slice, None, None) + self.assertRaises(TypeError, wcs.Slice, None, myBin) + self.assertRaises(TypeError, wcs.Slice, axis, None) + self.assertRaises(TypeError, wcs.Slice, str("s"), myBin) + self.assertRaises(TypeError, wcs.Slice, axis, int(1)) + + mySlice = wcs.Slice(axis, myBin) + self.assertEqual(mySlice.axis, axis) + self.assertEqual(mySlice.bin, long(1)) + + +class TestValueCoord2d(unittest.TestCase): + + def test_init(self): + + self.assertRaises(TypeError, wcs.ValueCoord2D, None, None) + self.assertRaises(TypeError, wcs.ValueCoord2D, None, float(1.0)) + self.assertRaises(TypeError, wcs.ValueCoord2D, float(1.0), None) + self.assertRaises(TypeError, wcs.ValueCoord2D, int(1), float(1.0)) + self.assertRaises(TypeError, wcs.ValueCoord2D, float(1.0), int(1)) + + value_coord2d = wcs.ValueCoord2D(float(1), float(2)) + self.assertIsNotNone(value_coord2d) + self.assertEqual(value_coord2d.coord1, float(1)) + self.assertEqual(value_coord2d.coord2, float(2)) + + +if __name__ == '__main__': + unittest.main() + diff --git a/caom2tools/caom2/tests/test/test_observation_reader_writer.py b/caom2tools/caom2/tests/test_xml_reader_writer.py similarity index 75% rename from caom2tools/caom2/tests/test/test_observation_reader_writer.py rename to caom2tools/caom2/tests/test_xml_reader_writer.py index db4c14a0..e7617504 100644 --- a/caom2tools/caom2/tests/test/test_observation_reader_writer.py +++ b/caom2tools/caom2/tests/test_xml_reader_writer.py @@ -71,16 +71,22 @@ """ Defines TestObservationReaderWriter class """ import StringIO +import errno +import filecmp +import glob +import os +import shutil import unittest -from caom2.xml.caom2_xml_constants import CAOM20_NAMESPACE, CAOM21_NAMESPACE, CAOM22_NAMESPACE -from caom2.caom2_composite_observation import CompositeObservation -from caom2.caom2_simple_observation import SimpleObservation -from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -from caom2.xml.caom2_observation_reader import ObservationReader -from caom2.xml.caom2_observation_writer import ObservationWriter -from test_caom2instances import Caom2TestInstances +from caom2.observation import CompositeObservation +from caom2.observation import SimpleObservation +from caom2.wcs import CoordCircle2D +from caom2.wcs import CoordPolygon2D +from caom2.xml_reader_writer import CAOM20_NAMESPACE +from caom2.xml_reader_writer import CAOM21_NAMESPACE +from caom2.xml_reader_writer import ObservationReader +from caom2.xml_reader_writer import ObservationWriter +from caom_test_instances import Caom2TestInstances class TestObservationReaderWriter(unittest.TestCase): @@ -213,6 +219,90 @@ def test_versions(self): test_observation(self, observation, True, True, 22) +class TestRoundTrip(unittest.TestCase): + + TEST_FILE_SOURCE_DIR = '../caom2/test/data' + XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' + XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' + + def make_test_dir(self): + try: + os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) + except OSError as exception: + if exception.errno != errno.EEXIST: + raise + + def copy_files(self): + for filename in glob.glob(os.path.join(TestRoundTrip. + TEST_FILE_SOURCE_DIR, '*.xml')): + shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) + + def init(self): + self.make_test_dir() + self.copy_files() + + def cleanup(self): + shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) + + def get_file_list(self): + return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR) \ + if f.endswith('.xml')] + + def do_test(self, reader, writer, filename): + sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + + '/' + filename) + print "test file: " + sourceFilePath + sourceXMLfp = open(sourceFilePath, 'r') + observation = reader.read(sourceFilePath) + sourceXMLfp.close() + destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename + destXMLfp = open(destFilePath, 'w') + writer.write(observation, destXMLfp) + destXMLfp.close() + self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), + 'files are different, ' + + 'file from Java was: ' + sourceFilePath + ' ' + 'file from Python was: ' + destFilePath) + + # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 + # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 + # objects. The two XML files are then compared to ensure that they + # are the same. The test fails if the files are not the same. The + # test/data/*.xml files can be used in this test. + + def test_round_trip(self): + print "Test Round Trip" + + try: + self.init() + files = self.get_file_list() + self.assertTrue(len(files) > 0, 'No XML files in ' + + TestRoundTrip.XML_FILE_SOURCE_DIR) + try: + os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) + except OSError as e: + if e.errno != errno.EEXIST: + raise + + reader = ObservationReader(True) + writer20 = ObservationWriter(True, False, "caom2", CAOM20_NAMESPACE) + writer21 = ObservationWriter(True, False, "caom2", CAOM21_NAMESPACE) + writer22 = ObservationWriter(True, False, "caom2") + for filename in files: + if filename.endswith("CAOM-2.2.xml"): + self.do_test(reader, writer22, filename) + elif filename.endswith("CAOM-2.1.xml"): + self.do_test(reader, writer21, filename) + else: + self.do_test(reader, writer20, filename) + + #finally: + # self.cleanup() + except Exception as e: + #if e.errno != errno.EEXIST: + raise + + def minimal_simple(depth, bounds_is_circle, version): instances = Caom2TestInstances() instances.complete = False @@ -263,10 +353,10 @@ def test_observation(self, observation, validate, write_empty_collections, versi xmlfile.close() reader = ObservationReader(True) returned = reader.read('/tmp/test.xml') - compareObservations(self, observation, returned, version) + compare_observations(self, observation, returned, version) -def compareObservations(self, expected, actual, version): +def compare_observations(self, expected, actual, version): assert ((isinstance(expected, SimpleObservation) and isinstance(actual, SimpleObservation)) or @@ -298,23 +388,23 @@ def compareObservations(self, expected, actual, version): self.assertEqual(expected.sequence_number, actual.sequence_number) self.assertEqual(expected.intent, actual.intent) self.assertEqual(expected.meta_release, actual.meta_release) - compareProposal(self, expected.proposal, actual.proposal) - compareTarget(self, expected.target, actual.target) - compareTargetPosition(self, expected.target_position, actual.target_position) - compareTelescope(self, expected.telescope, actual.telescope) - compareInstrument(self, expected.instrument, actual.instrument) - compareEnvironment(self, expected.environment, actual.environment) + compare_proposal(self, expected.proposal, actual.proposal) + compare_target(self, expected.target, actual.target) + compare_target_position(self, expected.target_position, actual.target_position) + compare_telescope(self, expected.telescope, actual.telescope) + compare_instrument(self, expected.instrument, actual.instrument) + compare_environment(self, expected.environment, actual.environment) if version == 21: - compareRequirements(self, expected.requirements, actual.requirements) + compare_requirements(self, expected.requirements, actual.requirements) - comparePlanes(self, expected.planes, actual.planes, version) + compare_planes(self, expected.planes, actual.planes, version) if (isinstance(expected, CompositeObservation) and isinstance(actual, CompositeObservation)): - compareMembers(self, expected.members, actual.members) + compare_members(self, expected.members, actual.members) -def compareProposal(self, expected, actual): +def compare_proposal(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -328,7 +418,7 @@ def compareProposal(self, expected, actual): self.assertTrue(keyword in actual.keywords) -def compareTarget(self, expected, actual): +def compare_target(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -341,19 +431,19 @@ def compareTarget(self, expected, actual): -def compareTargetPosition(self, expected, actual): +def compare_target_position(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) self.assertIsNotNone(actual.coordinates) self.assertIsNotNone(actual.coordsys) - comparePoint(self, expected.coordinates, actual.coordinates) + compare_point(self, expected.coordinates, actual.coordinates) self.assertEqual(expected.coordsys, actual.coordsys) self.assertEqual(expected.equinox, actual.equinox) -def compareTelescope(self, expected, actual): +def compare_telescope(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -367,7 +457,7 @@ def compareTelescope(self, expected, actual): -def compareInstrument(self, expected, actual): +def compare_instrument(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -377,7 +467,7 @@ def compareInstrument(self, expected, actual): self.assertTrue(keyword in actual.keywords) -def compareEnvironment(self, expected, actual): +def compare_environment(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -391,17 +481,17 @@ def compareEnvironment(self, expected, actual): self.assertEqual(expected.photometric, actual.photometric) -def compareMembers(self, expected, actual): +def compare_members(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) self.assertEqual(len(expected), len(actual)) for expected_member, actual_member in zip(expected, actual): - compareObservationURI(self, expected_member, actual_member) + compare_observation_uri(self, expected_member, actual_member) -def compareObservationURI(self, expected, actual): +def compare_observation_uri(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -411,7 +501,7 @@ def compareObservationURI(self, expected, actual): self.assertEquals(expected.observation_id, actual.observation_id) -def compareRequirements(self, expected, actual): +def compare_requirements(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -419,7 +509,7 @@ def compareRequirements(self, expected, actual): self.assertEquals(expected.flag, actual.flag) -def comparePlanes(self, expected, actual, version): +def compare_planes(self, expected, actual, version): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -447,16 +537,16 @@ def comparePlanes(self, expected, actual, version): actual_plane.data_product_type) self.assertEqual(expected_plane.calibration_level, actual_plane.calibration_level) - compareProvenance(self, expected_plane.provenance, - actual_plane.provenance) - compareMetrics(self, expected_plane.metrics, actual_plane.metrics) + compare_provenance(self, expected_plane.provenance, + actual_plane.provenance) + compare_metrics(self, expected_plane.metrics, actual_plane.metrics) if version == 21: - compareQuality(self, expected_plane.quality, actual_plane.quality) + compare_quality(self, expected_plane.quality, actual_plane.quality) - compareArtifacts(self, expected_plane.artifacts, actual_plane.artifacts, version) + compare_artifacts(self, expected_plane.artifacts, actual_plane.artifacts, version) -def compareProvenance(self, expected, actual): +def compare_provenance(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -467,10 +557,10 @@ def compareProvenance(self, expected, actual): self.assertEqual(expected.run_id, actual.run_id) self.assertEqual(expected.reference, actual.reference) self.assertEqual(expected.last_executed, actual.last_executed) - compareInputs(self, expected.inputs, actual.inputs) + compare_inputs(self, expected.inputs, actual.inputs) -def compareMetrics(self, expected, actual): +def compare_metrics(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -482,7 +572,7 @@ def compareMetrics(self, expected, actual): self.assertEqual(expected.mag_limit, actual.mag_limit) -def compareQuality(self, expected, actual): +def compare_quality(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -490,7 +580,7 @@ def compareQuality(self, expected, actual): self.assertEqual(expected.flag, actual.flag) -def compareInputs(self, expected, actual): +def compare_inputs(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -500,7 +590,7 @@ def compareInputs(self, expected, actual): self.assertEqual(expected_plane_uri, actual_plane_uri) -def compareArtifacts(self, expected, actual, version): +def compare_artifacts(self, expected, actual, version): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -524,10 +614,10 @@ def compareArtifacts(self, expected, actual, version): self.assertEqual(expected_artifact.product_type, actual_artifact.product_type) if version > 21: self.assertEqual(expected_artifact.release_type, actual_artifact.release_type) - compareParts(self, expected_artifact.parts, actual_artifact.parts, version) + compare_parts(self, expected_artifact.parts, actual_artifact.parts, version) -def compareParts(self, expected, actual, version): +def compare_parts(self, expected, actual, version): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -548,10 +638,10 @@ def compareParts(self, expected, actual, version): actual_part._last_modified) self.assertEqual(expected_part.name, actual_part.name) self.assertEqual(expected_part.product_type, actual_part.product_type) - compareChunks(self, expected_part.chunks, actual_part.chunks) + compare_chunks(self, expected_part.chunks, actual_part.chunks) -def compareChunks(self, expected, actual): +def compare_chunks(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) @@ -580,41 +670,41 @@ def compareChunks(self, expected, actual): self.assertEqual(expected_chunk.time_axis, actual_chunk.time_axis) self.assertEqual(expected_chunk.polarization_axis, actual_chunk.polarization_axis) - compareObservableAxis(self, expected_chunk.observable, - actual_chunk.observable) - compareSpatialWCS(self, expected_chunk.position, actual_chunk.position) - compareSpectralWCS(self, expected_chunk.energy, actual_chunk.energy) - compareTemporalWCS(self, expected_chunk.time, actual_chunk.time) - comparePolarizationWCS(self, expected_chunk.polarization, - actual_chunk.polarization) + compare_observable_axis(self, expected_chunk.observable, + actual_chunk.observable) + compare_spatial_wcs(self, expected_chunk.position, actual_chunk.position) + compare_spectral_wcs(self, expected_chunk.energy, actual_chunk.energy) + compare_temporal_wcs(self, expected_chunk.time, actual_chunk.time) + compare_polarization_wcs(self, expected_chunk.polarization, + actual_chunk.polarization) -def compareObservableAxis(self, expected, actual): +def compare_observable_axis(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - compareSlice(self, expected.dependent, actual.dependent) - compareSlice(self, expected.independent, actual.independent) + compare_slice(self, expected.dependent, actual.dependent) + compare_slice(self, expected.independent, actual.independent) -def compareSpatialWCS(self, expected, actual): +def compare_spatial_wcs(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - compareCoordAxis2D(self, expected.axis, actual.axis) + compare_coord_axis2d(self, expected.axis, actual.axis) self.assertEqual(expected.coordsys, actual.coordsys) self.assertEqual(expected.equinox, actual.equinox) self.assertEqual(expected.resolution, actual.resolution) -def compareSpectralWCS(self, expected, actual): +def compare_spectral_wcs(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) + compare_coord_axis1d(self, expected.axis, actual.axis) self.assertEqual(expected.bandpass_name, actual.bandpass_name) self.assertEqual(expected.resolving_power, actual.resolving_power) self.assertEqual(expected.restfrq, actual.restfrq) @@ -627,12 +717,12 @@ def compareSpectralWCS(self, expected, actual): self.assertEqual(expected.zsource, actual.zsource) -def compareTemporalWCS(self, expected, actual): +def compare_temporal_wcs(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) + compare_coord_axis1d(self, expected.axis, actual.axis) self.assertEqual(expected.exposure, actual.exposure) self.assertEqual(expected.resolution, actual.resolution) self.assertEqual(expected.timesys, actual.timesys) @@ -640,15 +730,15 @@ def compareTemporalWCS(self, expected, actual): self.assertEqual(expected.mjdref, actual.mjdref) -def comparePolarizationWCS(self, expected, actual): +def compare_polarization_wcs(self, expected, actual): if expected is None and actual is None: return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - compareCoordAxis1D(self, expected.axis, actual.axis) + compare_coord_axis1d(self, expected.axis, actual.axis) -def compareAxis(self, expected, actual): +def compare_axis(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -659,16 +749,16 @@ def compareAxis(self, expected, actual): self.assertEqual(expected.cunit, actual.cunit) -def compareCoord2D(self, expected, actual): +def compare_coord2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) - compareRefCoord(self, expected.coord1, actual.coord1) - compareRefCoord(self, expected.coord2, actual.coord2) + compare_ref_coord(self, expected.coord1, actual.coord1) + compare_ref_coord(self, expected.coord2, actual.coord2) -def compareValueCoord2D(self, expected, actual): +def compare_value_coord2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -677,34 +767,34 @@ def compareValueCoord2D(self, expected, actual): self.assertEqual(expected.coord2, actual.coord2) -def compareCoordAxis1D(self, expected, actual): +def compare_coord_axis1d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) - compareCoordError(self, expected.error, actual.error) - compareCoordRange1D(self, expected.range, actual.range) - compareCoordBounds1D(self, expected.bounds, actual.bounds) - compareCoordFunction1D(self, expected.function, actual.function) + compare_coord_error(self, expected.error, actual.error) + compare_coord_range1d(self, expected.range, actual.range) + compare_coord_bounds1d(self, expected.bounds, actual.bounds) + compare_coord_function1d(self, expected.function, actual.function) -def compareCoordAxis2D(self, expected, actual): +def compare_coord_axis2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) self.assertIsNotNone(actual.axis1) self.assertIsNotNone(actual.axis2) - compareAxis(self, expected.axis1, actual.axis1) - compareAxis(self, expected.axis2, actual.axis2) - compareCoordError(self, expected.error1, actual.error1) - compareCoordError(self, expected.error2, actual.error2) - compareCoordRange2D(self, expected.range, actual.range) - compareCoordBounds2D(self, expected.bounds, actual.bounds) - compareCoordFunction2D(self, expected.function, actual.function) + compare_axis(self, expected.axis1, actual.axis1) + compare_axis(self, expected.axis2, actual.axis2) + compare_coord_error(self, expected.error1, actual.error1) + compare_coord_error(self, expected.error2, actual.error2) + compare_coord_range2d(self, expected.range, actual.range) + compare_coord_bounds2d(self, expected.bounds, actual.bounds) + compare_coord_function2d(self, expected.function, actual.function) -def compareCoordBounds1D(self, expected, actual): +def compare_coord_bounds1d(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -713,36 +803,36 @@ def compareCoordBounds1D(self, expected, actual): self.assertIsNotNone(actual.samples) self.assertEqual(len(expected.samples), len(actual.samples)) for expected_range, actual_range in zip(expected.samples, actual.samples): - compareCoordRange1D(self, expected_range, actual_range) + compare_coord_range1d(self, expected_range, actual_range) -def compareCoordBounds2D(self, expected, actual): +def compare_coord_bounds2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) if (isinstance(expected, CoordCircle2D) and isinstance(actual, CoordCircle2D)): - compareCoordCircle2D(self, expected, actual) + compare_coord_circle2d(self, expected, actual) elif (isinstance(expected, CoordPolygon2D) and isinstance(actual, CoordPolygon2D)): - compareCoordPolygon2D(self, expected, actual) + compare_coord_polygon2d(self, expected, actual) else: self.fail("CoordBounds2D expected and actual are different types.") -def compareCoordCircle2D(self, expected, actual): +def compare_coord_circle2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) self.assertIsNotNone(actual.center) self.assertIsNotNone(actual.radius) - compareValueCoord2D(self, expected.center, actual.center) + compare_value_coord2d(self, expected.center, actual.center) self.assertEqual(expected.radius, actual.radius) -def compareCoordError(self, expected, actual): +def compare_coord_error(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -756,17 +846,17 @@ def compareCoordError(self, expected, actual): self.assertEqual(expected.rnder, actual.rnder) -def compareCoordFunction1D(self, expected, actual): +def compare_coord_function1d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) self.assertEqual(expected.naxis, actual.naxis) self.assertEqual(expected.delta, actual.delta) - compareRefCoord(self, expected.ref_coord, actual.ref_coord) + compare_ref_coord(self, expected.ref_coord, actual.ref_coord) -def compareCoordFunction2D(self, expected, actual): +def compare_coord_function2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -777,15 +867,15 @@ def compareCoordFunction2D(self, expected, actual): self.assertIsNotNone(actual.cd12) self.assertIsNotNone(actual.cd21) self.assertIsNotNone(actual.cd22) - compareDimension2D(self, expected.dimension, actual.dimension) - compareCoord2D(self, expected.ref_coord, actual.ref_coord) + compare_dimension2d(self, expected.dimension, actual.dimension) + compare_coord2d(self, expected.ref_coord, actual.ref_coord) self.assertEqual(expected.cd11, actual.cd11, 0.0) self.assertEqual(expected.cd12, actual.cd12, 0.0) self.assertEqual(expected.cd21, actual.cd21, 0.0) self.assertEqual(expected.cd22, actual.cd22, 0.0) -def compareCoordPolygon2D(self, expected, actual): +def compare_coord_polygon2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -795,30 +885,30 @@ def compareCoordPolygon2D(self, expected, actual): self.assertEqual(len(expected.vertices), len(actual.vertices)) for expected_coord_2d, actual_coord_2d in zip(expected.vertices, actual.vertices): - compareValueCoord2D(self, expected_coord_2d, actual_coord_2d) + compare_value_coord2d(self, expected_coord_2d, actual_coord_2d) -def compareCoordRange1D(self, expected, actual): +def compare_coord_range1d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) - compareRefCoord(self, expected.start, actual.start) - compareRefCoord(self, expected.end, actual.end) + compare_ref_coord(self, expected.start, actual.start) + compare_ref_coord(self, expected.end, actual.end) -def compareCoordRange2D(self, expected, actual): +def compare_coord_range2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return self.assertIsNotNone(actual) self.assertIsNotNone(actual.start) self.assertIsNotNone(actual.end) - compareCoord2D(self, expected.start, actual.start) - compareCoord2D(self, expected.end, actual.end) + compare_coord2d(self, expected.start, actual.start) + compare_coord2d(self, expected.end, actual.end) -def compareDimension2D(self, expected, actual): +def compare_dimension2d(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -827,7 +917,7 @@ def compareDimension2D(self, expected, actual): self.assertEqual(expected.naxis2, actual.naxis2) -def compareRefCoord(self, expected, actual): +def compare_ref_coord(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -836,7 +926,7 @@ def compareRefCoord(self, expected, actual): self.assertEqual(expected.val, actual.val) -def compareSlice(self, expected, actual): +def compare_slice(self, expected, actual): if expected is None: self.assertIsNone(actual) return @@ -844,10 +934,10 @@ def compareSlice(self, expected, actual): self.assertIsNotNone(actual.bin) self.assertIsNotNone(actual.axis) self.assertEqual(expected.bin, actual.bin) - compareAxis(self, expected.axis, actual.axis) + compare_axis(self, expected.axis, actual.axis) -def comparePoint(self, expected, actual): +def compare_point(self, expected, actual): if expected is None: self.assertIsNone(actual) return diff --git a/caom2tools/caom2/types/__init__.py b/caom2tools/caom2/types/__init__.py deleted file mode 100755 index 4afe65c3..00000000 --- a/caom2tools/caom2/types/__init__.py +++ /dev/null @@ -1,73 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines __init__ """ - -from caom2_point import Point diff --git a/caom2tools/caom2/types/caom2_box.py b/caom2tools/caom2/types/caom2_box.py deleted file mode 100644 index aa2d45d6..00000000 --- a/caom2tools/caom2/types/caom2_box.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines Box class""" - - -class Box(object): - - def __init__(self): - pass diff --git a/caom2tools/caom2/types/caom2_circle.py b/caom2tools/caom2/types/caom2_circle.py deleted file mode 100644 index bbb9f9dc..00000000 --- a/caom2tools/caom2/types/caom2_circle.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Circle class """ - - -class Circle(object): - - def __init__(self): - pass diff --git a/caom2tools/caom2/types/caom2_interval.py b/caom2tools/caom2/types/caom2_interval.py deleted file mode 100644 index 443a54f2..00000000 --- a/caom2tools/caom2/types/caom2_interval.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Interval class """ - - -class Interval(object): - - def __init__(self): - pass diff --git a/caom2tools/caom2/types/caom2_polygon.py b/caom2tools/caom2/types/caom2_polygon.py deleted file mode 100644 index 70c367b6..00000000 --- a/caom2tools/caom2/types/caom2_polygon.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Polygon class """ - - -class Polygon(object): - - def __init__(self): - pass diff --git a/caom2tools/caom2/types/caom2_vertex.py b/caom2tools/caom2/types/caom2_vertex.py deleted file mode 100644 index f8ec1471..00000000 --- a/caom2tools/caom2/types/caom2_vertex.py +++ /dev/null @@ -1,77 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Vertex class """ - - -class Vertex(object): - - def __init__(self): - pass diff --git a/caom2tools/caom2/util/caom2_util.py b/caom2tools/caom2/util.py similarity index 62% rename from caom2tools/caom2/util/caom2_util.py rename to caom2tools/caom2/util.py index 2640c0f7..9b8e9487 100644 --- a/caom2tools/caom2/util/caom2_util.py +++ b/caom2tools/caom2/util.py @@ -78,10 +78,122 @@ """ import collections -from datetime import datetime -import sys import struct +import sys import uuid +from datetime import datetime + +import artifact +import chunk +import observation +import part +import plane + + +class Util(object): + + # TODO both these are very bad, implement more sensibly + IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" + + def validate_path_component(self, caller, name, test): + """ + Function to validate a URI path component. Component is invalid + if it contains space ( ), slash (/), escape (\\) or percent (%) characters. + + Arguments: + caller : caller object + name : name of the component + test : component to be tested + + An assertionError is thrown when the the provided test argument + is invalid + """ + + assert (' ' not in test and + '/' not in test and + '||' not in test and + '%' not in test), ( + caller.__class__.__name__ + ": invalid " + name + + ": may not contain space ( ), slash (/), escape (\\), or percent (%)") + + def date2ivoa(self, d): + """ + Takes a datetime and returns a string formatted + to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS + """ + + if d is None: + return None + return d.strftime(self.IVOA_DATE_FORMAT)[:23] + + def str2ivoa(self, s): + """Takes a IVOA date formatted string and returns a datetime""" + + if s is None: + return None + return datetime.strptime(s, self.IVOA_DATE_FORMAT) + + def attr2str(self, s): + pass + + def repr2str(self, s): + pass + + def uuid2long(self, uid): + """ + UUID is 128 bits (32 bytes). Unpack the 32 bytes into two + 16 byte longs. For CAOM-2.0 compatibility only the least significant + 16 bytes in the UUID should have a value. + + return the UUID least significant bytes as a long. + """ + longs = struct.unpack('>qq', str(uid.bytes)) + if longs[0] != 0: + raise ValueError("lossy conversion from UUID to long: {}".format(uid)) + return longs[1] + + def long2uuid(self, l): + """ + Takes a long and creates a UUID using the 16 byte long + as the least significant bytes in the 32 byte UUID. + """ + if l.bit_length() > 63: + raise ValueError("expected 64 bit long {}".format(l)) + return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) + + def type_check(self, value, value_type, variable, override=None): + """Check value is of type value_type, or is override""" + + sys.tracebacklimit = None + if not isinstance(value, value_type) and value is not override: + if override is not False: + raise TypeError( + "Excepted {} or {} for {}, received {}".format(value_type, + override, + variable, + type(value))) + else: + raise TypeError( + "Expected {} for {}, received {}".format(value_type, + variable, + type(value))) + return True + + def value_check(self, value, min_value, max_value, variable, override=None): + """Check if value is inside allowed range, or override""" + + sys.tracebacklimit = None + if value != override and not (min_value <= value <= max_value): + if override is not False: + raise ValueError( + "Expected {} <= {} <= {} or {}, received {}".format( + min_value, variable, max_value, override, value)) + else: + raise ValueError( + "Expected {} <= {} <= {}, received {}".format( + min_value, variable, max_value, value)) + + return True class TypedList(collections.MutableSequence): @@ -117,11 +229,11 @@ def __str__(self): def __repr__(self): return "TypedList((%r))," % (self._oktypes) + ( - "(".join(["(%r)" % (v) for v in self]) + ")") + "(".join(["(%r)" % (v) for v in self]) + ")") def check(self, v): assert isinstance(v, self._oktypes), ( - "Wrong type in list. OK Types: {0}".format(self._oktypes)) + "Wrong type in list. OK Types: {0}".format(self._oktypes)) def __len__(self): return len(self.list) @@ -141,28 +253,6 @@ def insert(self, i, v): self.list.insert(i, v) -def validate_path_component(caller, name, test): - """ - Function to validate a URI path component. Component is invalid - if it contains space ( ), slash (/), escape (\\) or percent (%) characters. - - Arguments: - caller : caller object - name : name of the component - test : component to be tested - - An assertionError is thrown when the the provided test argument - is invalid - """ - - assert (' ' not in test and - '/' not in test and - '||' not in test and - '%' not in test), ( - caller.__class__.__name__ + ": invalid " + name + - ": may not contain space ( ), slash (/), escape (\\), or percent (%)") - - class TypedSet(collections.MutableSet): """ Class that implements a typed set in Python. Supported types @@ -194,7 +284,7 @@ def __init__(self, oktypes, *args): def check(self, v): assert isinstance(v, self._oktypes), ( - "Wrong type in list. OK Types: {0}".format(self._oktypes)) + "Wrong type in list. OK Types: {0}".format(self._oktypes)) def add(self, v): """Add an element.""" @@ -288,101 +378,54 @@ def __setitem__(self, key, value): super(TypedOrderedDict, self).__setitem__(key, value) -############################### -# To be moved to cadcUtil -############################### class ClassProperty(property): """ """ def __get__(self, cls, owner): return self.fget.__get__(None, owner)() -# TODO both these are very bad, implement more sensibly -IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - - -def date2ivoa(d): - """ - Takes a datetime and returns a string formatted - to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS - """ - - if d is None: - return None - return d.strftime(IVOA_DATE_FORMAT)[:23] - +class Validator(object): -def str2ivoa(s): - """Takes a IVOA date formatted string and returns a datetime""" + def __init__(self): + self.errors = {} - if s is None: - return None - return datetime.strptime(s, IVOA_DATE_FORMAT) - - -def attr2str(s): - pass - - -def repr2str(s): - pass - - -def uuid2long(uid): - """ - UUID is 128 bits (32 bytes). Unpack the 32 bytes into two - 16 byte longs. For CAOM-2.0 compatibility only the least significant - 16 bytes in the UUID should have a value. - - return the UUID least significant bytes as a long. - """ - longs = struct.unpack('>qq', str(uid.bytes)) - if longs[0] != 0: - raise ValueError("lossy conversion from UUID to long: {}".format(uid)) - return longs[1] - - -def long2uuid(l): - """ - Takes a long and creates a UUID using the 16 byte long - as the least significant bytes in the 32 byte UUID. - """ - if l.bit_length() > 63: - raise ValueError("expected 64 bit long {}".format(l)) - return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) - - -def typeCheck(value, value_type, variable, override=None): - """Check value is of type value_type, or is override""" - - sys.tracebacklimit = None - if not isinstance(value, value_type) and value is not override: - if override is not False: - raise TypeError( - "Excepted {} or {} for {}, received {}".format(value_type, - override, - variable, - type(value))) - else: - raise TypeError( - "Expected {} for {}, received {}".format(value_type, - variable, - type(value))) - return True - - -def valueCheck(value, min_value, max_value, variable, override=None): - """Check if value is inside allowed range, or override""" - - sys.tracebacklimit = None - if value != override and not (min_value <= value <= max_value): - if override is not False: - raise ValueError( - "Expected {} <= {} <= {} or {}, received {}".format( - min_value, variable, max_value, override, value)) - else: - raise ValueError( - "Expected {} <= {} <= {}, received {}".format( - min_value, variable, max_value, value)) - - return True + def validate(self, obs): + if not isinstance(obs, observation.Observation): + self.errors['observation'] = 'not an Observation instance' + return + self._validate_planes(obs.planes) + if len(self.errors) > 0: + return False + return True + + def _validate_planes(self, planes): + for product_id, _plane in planes.iteritems(): + if not isinstance(_plane, plane.Plane): + self.errors['plane'].append("not a Plane instance") + continue + if product_id != _plane.product_id: + self.errors['plane'].append("plane productIDs do not match") + self._validate_artifacts(_plane.artifacts) + + def _validate_artifacts(self, artifacts): + for uri, _artifact in artifacts.iteritems(): + if not isinstance(_artifact, artifact.Artifact): + self.errors['artifact'].append("not an Artifact instance") + continue + if uri != _artifact.uri: + self.errors['artifact'].append("artifact uris do not match") + self._validate_parts(_artifact.parts) + + def _validate_parts(self, parts): + for name, _part in parts.iteritems(): + if not isinstance(_part, part.Part): + self.errors['part'].append("not a Part instance") + continue + if name != _part.name: + self.errors['part'].append("part names do not match") + self._validate_chunks(_part.chunks) + + def _validate_chunks(self, chunks): + for _chunk in chunks: + if not isinstance(_chunk, chunk.Chunk): + self.errors['chunk'].append("not a chunk instance") diff --git a/caom2tools/caom2/util/__init__.py b/caom2tools/caom2/util/__init__.py deleted file mode 100755 index cd6c6be3..00000000 --- a/caom2tools/caom2/util/__init__.py +++ /dev/null @@ -1,71 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines __init__ """ diff --git a/caom2tools/caom2/util/caom2_validator.py b/caom2tools/caom2/util/caom2_validator.py deleted file mode 100644 index f315a4a1..00000000 --- a/caom2tools/caom2/util/caom2_validator.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines Validator class """ - - -from ..caom2_observation import Observation -from ..caom2_plane import Plane -from ..caom2_artifact import Artifact -from ..caom2_part import Part -from ..caom2_chunk import Chunk - - -class Validator(object): - - def __init__(self): - self.errors = {} - - def validate(self, obs): - if not isinstance(obs, Observation): - self.errors.append("") - return - self._validatePlanes(obs.planes) - if (len(self.errors) > 0): - return False - return True - - def _validatePlanes(self, planes): - for product_id, plane in planes.iteritems(): - if not isinstance(plane, Plane): - self.errors.append("") - continue - if (product_id != plane.product_id): - self.errors.append("") - self._validateArtifacts(plane.artifacts) - - def _validateArtifacts(self, artifacts): - for uri, artifact in artifacts.iteritems(): - if not isinstance(artifact, Artifact): - self.errors.append("") - continue - if (uri != artifact.uri): - self.errors.append("") - self._validateParts(artifact.parts) - - def _validateParts(self, parts): - for name, part in parts.iteritems(): - if not isinstance(part, Part): - self.errors.append("") - continue - if (name != part.name): - self.errors.append("") - self._validateChunks(parts.chunks) - - def _validateChunks(self, chunks): - for chunk in chunks: - if not isinstance(chunk, Chunk): - self.errors.append("") diff --git a/caom2tools/caom2/wcs.py b/caom2tools/caom2/wcs.py new file mode 100644 index 00000000..976465a5 --- /dev/null +++ b/caom2tools/caom2/wcs.py @@ -0,0 +1,1000 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + + +from caom_object import CaomObject +from util import TypedList +from util import Util + + +class Axis(CaomObject): + """the Axis class holds the definition of the axis type and units""" + + def __init__(self, ctype, cunit=None): + + self.ctype = ctype + self.cunit = cunit + + @property + def ctype(self): + """The Coordinate Type value for this axis. + + eg. DEC + type: str + + """ + return self._ctype + + @ctype.setter + def ctype(self, value): + Util.type_check(value, str, 'ctype', override=False) + self._ctype = value + + @property + def cunit(self): + """The unit of the coordinate that results after transform. + + eg. deg + type: str + + """ + return self._cunit + + @cunit.setter + def cunit(self, value): + Util.type_check(value, str, 'cunit') + self._cunit = value + + +class Coord2D(CaomObject): + """Represents the reference point. + + eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) + """ + + def __init__(self, coord1, coord2): + self.coord1 = coord1 + self.coord2 = coord2 + + @property + def coord1(self): + """A coordinate axis1 coordinate/pix pair, crpix1, crval1. + + eg. RefCoord(crpix1, crval1) + """ + return self._coord1 + + @coord1.setter + def coord1(self, value): + Util.type_check(value, RefCoord, 'coord1', override=False) + self._coord1 = value + + @property + def coord2(self): + """The axis2 coordinate reference pair (ei. crpix2/crval2. + + eg. RefCorrd(crpix2, crval2) + """ + return self._coord2 + + @coord2.setter + def coord2(self, value): + Util.type_check(value, RefCoord, 'coord2', override=False) + self._coord2 = value + + +class CoordAxis1D(CaomObject): + """Holds the metadata needed to transform a 1D pixel value into a + World Coordinate value. + + """ + + def __init__(self, axis, error=None, range=None, + bounds=None, function=None): + + self.axis = axis + self.error = error + self.range = range + self.bounds = bounds + self.function = function + + @property + def axis(self): + """An axis object which describes the type and units of this + coordinate axis. + + eg. Axis(ctype1,cunit1) + + """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, Axis, "Axis", override=False) + self._axis = value + + @property + def error(self): + """A CoordError object that describes the uncertainty in the. + + eg. CoordError(syser=0.1, rnder=0.1) + unit: cunit1 [of axis] + + """ + return self._error + + @error.setter + def error(self, value): + Util.type_check(value, CoordError, 'error') + self._error = value + + @property + def range(self): + """A range that defines a coordinate transformation. + + the transform is a linear interpolation over the range + given which is a specified as a set of two pix/val reference pair. + eg. CoordRange1D(start=RefCoord(pix1,val1),end=RefCoord(pix2,val2)) + unit: same as the axis you are defining. + + """ + return self._range + + @range.setter + def range(self, value): + Util.type_check(value, CoordRange1D, 'range') + self._range = value + + @property + def bounds(self): + """A polygon that defines the boundary of this axis, in 1D. + + eg. CoordBounds1D(ListOfRanges()) + The ranges are like those given for the range attribute. + + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + Util.type_check(value, CoordBounds1D, "bounds") + self._bounds = value + + @property + def function(self): + """A linear function that describes the tranformation between pixel + and world coordinate value. + + Since this is a 1D object and linear, the function is + y = m*x + b. + eg. CoordFunction1D(naxis, delta, RefCoord) + + """ + return self._function + + @function.setter + def function(self, value): + Util.type_check(value, CoordFunction1D, 'function') + self._function = value + + +class CoordAxis2D(CaomObject): + """This object hold the metadata need to transform a 2D pixel + array (say an image) into a World position, say RA/DEC + + """ + + def __init__(self, axis1, axis2, + error1=None, error2=None, + range=None, bounds=None, + function=None): + + self.axis1 = axis1 + self.axis2 = axis2 + self.error1 = error1 + self.error2 = error2 + self.range = range + self.bounds = bounds + self.function = function + + @property + def axis1(self): + """An axis object that desciribes the first dimension + of this 2d system. + + eg. axis1=Axis("RA","deg") + + """ + return self._axis1 + + @axis1.setter + def axis1(self, value): + Util.type_check(value, Axis, "axis1", override=False) + self._axis1 = value + + @property + def axis2(self): + """An axis objet that describes the 2nd dimensiotn of this 2d coord + system. + + eg. axis2=Axis("DEG","deg") + + """ + return self._axis2 + + @axis2.setter + def axis2(self, value): + Util.type_check(value, Axis, "axis2", override=False) + self._axis2 = value + + @property + def error1(self): + """An object that descibes the uncertainty in the pix/world transform. + + eg. CoordError() + type: CoordError + + """ + return self._error1 + + @error1.setter + def error1(self, value): + Util.type_check(value, CoordError, 'error1') + self._error1 = value + + @property + def error2(self): + """An object that describes the uncertainty in the pix/world transform + for the 2nd axis + + type: CoordError + + """ + return self._error2 + + @error2.setter + def error2(self, value): + Util.type_check(value, CoordError, "error2") + self._error2 = value + + @property + def range(self): + """Coordinate range defined by this CoordAxis2d object. + + type: CoordRange2D + """ + return self._range + + @range.setter + def range(self, value): + Util.type_check(value, CoordRange2D, 'range') + self._range = value + + @property + def bounds(self): + """The Coordinate boundary mapped by this CoordAxis2D object. + + ag. CoordPolygon2d((234,10),(234,11),(233,11),(234,11),(234,10)) + type: CoordPolygon2D or CoordCircle2D + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + Util.type_check(value, (CoordCircle2D, CoordPolygon2D), 'bounds') + self._bounds = value + + @property + def function(self): + """A function object that describes the relation + between pixels and wcs. + + ag. CoordFunction2D (see the help for that puppy) + type: CoordFunction2D + """ + return self._function + + @function.setter + def function(self, value): + Util.type_check(value, CoordFunction2D, 'function') + self._function = value + + +class CoordBounds1D(CaomObject): + """Contains the bounds for a 1D axis, a list of ranges + + """ + + def __init__(self, samples=None): + + if samples is None: + samples = TypedList((CoordRange1D),) + self.samples = samples + + @property + def samples(self): + """A list of CoordRange1D objects that define the + boundary of a 1D axis. + + see also caom2.util.TypedList and caom2.wcs.CoordRange1D + + eg. + samples.add(CoordRange1D(RefCoord(pix,val),RefCoord(pix,val))) + + """ + return self._samples + + @samples.setter + def samples(self, value): + Util.type_check(value, + TypedList, + 'samples', + override=False) + self._samples = value + + +class CoordBounds2D(CaomObject): + """Contains the bounds for a 2D axis + + """ + + def __init__(self, bounds): + if (isinstance(bounds, CoordCircle2D) or + isinstance(bounds, CoordPolygon2D)): + self.bounds = bounds + else: + raise TypeError( + "Expected CoordCircle2D or CoordPolygon2D, received {}" + .format(type(bounds))) + + @property + def bounds(self): + """The bounds expressed as a circle or polygon. + + eg CoordBounds2D(CoordCircle2D()) + type: CoordCircle2D or CoordPolygon2D + """ + return self._bounds + + @bounds.setter + def bounds(self, value): + self._bounds = value + + +class CoordCircle2D(CaomObject): + """A circle expressed in both pixel and WCS value coordinates. + + These objects are used to map out the bounds of spatial WCS. + + Currently radius is only given in WCS units.. should be both. + + """ + + def __init__(self, center, radius): + self.center = center + self.radius = radius + + @property + def center(self): + """The pixel/world coordinate location of the centre. + + eg ValueCoord2D(coord1, coord2) + type: ValueCoord2D + """ + return self._center + + @center.setter + def center(self, value): + Util.type_check(value, ValueCoord2D, 'center', override=False) + self._center = value + + @property + def radius(self): + """The radius of the circle. + + NOTE::: This should likely be a RefCoord too... + + unit: same as centre which is pix/cunit + type: float + """ + return self._radius + + @radius.setter + def radius(self, value): + Util.type_check(value, float, 'radius', override=False) + Util.value_check(value, 0, 1E10, 'radius') + self._radius = value + + +class CoordError(CaomObject): + """Holds the systematic (syser) and random (rnder) error on a + coordinate. + + The concept is that these values are functions of the coordinate + transformation but likely be expressed with sufficient precision + (for a query model) using a systematic and random component. Both + are taken to be symetric. + + Likely either of these could be 'None', but best set to '0' if + that's what you really want to express. + + """ + + def __init__(self, syser, rnder): + + self.syser = syser + self.rnder = rnder + + # Properties + @property + def syser(self): + """the systematic uncertainty in a coordinate transform. + + units: should be the same as the CoordAxis (s, arcsec, deg?) + + """ + return self._syser + + @syser.setter + def syser(self, value): + Util.type_check(value, float, "syser", override=False) + self._syser = value + + @property + def rnder(self): + """the random uncertainty in a coordinate transform. + + units: should be the same as the CoordAxis transform. + + """ + return self._rnder + + @rnder.setter + def rnder(self, value): + Util.type_check(value, float, "rnder", override=False) + self._rnder = value + + +class CoordFunction1D(CaomObject): + """Defines a linear function that transforms from pixel to WCS + values. + + """ + + def __init__(self, naxis, delta, ref_coord): + """ + Need to define the length of the axis, the slope of the + conversion and a reference coordinate. All are needed for a + valid 1D function. + + """ + + self.naxis = naxis + self.delta = delta + self.ref_coord = ref_coord + + @property + def naxis(self): + """The length of the axis. + + unit: pix + type: long + + """ + return self._naxis + + @naxis.setter + def naxis(self, value): + Util.type_check(value, long, 'naxis', override=False) + self._naxis = value + + @property + def delta(self): + """The step in WCS between pixels. + + unit: WCS/pix (days if this is a timeWCS) + type: float + + """ + return self._delta + + @delta.setter + def delta(self, value): + Util.type_check(value, float, 'delta', override=False) + self._delta = value + + @property + def ref_coord(self): + """the (pix,val) reference for this transformtion. + + eg. ref_coord=RefCoord(pix,val) + type: RefCoord + + """ + return self._ref_coord + + @ref_coord.setter + def ref_coord(self, value): + Util.type_check(value, RefCoord, 'ref_coord', override=False) + self._ref_coord = value + + +class CoordFunction2D(CaomObject): + """Describes the parameters needed for the standard CD matrix. + + defines a linear translation between pixel and WCS. + + """ + + def __init__(self, dimension, ref_coord, cd11, cd12, cd21, cd22): + self.dimension = dimension + self.ref_coord = ref_coord + self.cd11 = cd11 + self.cd12 = cd12 + self.cd21 = cd21 + self.cd22 = cd22 + + @property + def dimension(self): + """A Dimension2D object that holds the lengths of the axis + + eg. Diemnsion2D(naxis1=1024,naxis2=2048) + type: Dimension2D + + """ + return self._dimension + + @dimension.setter + def dimension(self, value): + Util.type_check(value, Dimension2D, 'dimension', override=False) + self._dimension = value + + @property + def ref_coord(self): + """A Coord2D object that holds the reference pixel location + + eg. Coord2D((crpix1,crval1),(crpix2,crval2)) + type: Coord2D + + """ + return self._ref_coord + + @ref_coord.setter + def ref_coord(self, value): + Util.type_check(value, Coord2D, 'ref_coord', override=False) + self._ref_coord = value + + @property + def cd11(self): + """The CD1_1 value (depenence of RA scale on x-pixel value) + + eg. cd11 = 5E-5 + unit: deg/pix + type: float + + """ + return self._cd11 + + @cd11.setter + def cd11(self, value): + Util.type_check(value, float, 'cd11', override=False) + self._cd11 = value + + @property + def cd12(self): + """The CD1_2 value (depenence of RA scale on y-pixel value) + + eg. cd12 = 5E-10 + unit: deg/pix + type: float + + """ + return self._cd12 + + @cd12.setter + def cd12(self, value): + Util.type_check(value, float, 'cd12', override=False) + self._cd12 = value + + @property + def cd21(self): + """The CD1_1 value (depenence of DEC scale on x-pixel value) + + eg. cd11 = 5E-10 + unit: deg/pix + type: float + + """ + return self._cd21 + + @cd21.setter + def cd21(self, value): + Util.type_check(value, float, 'cd21', override=False) + self._cd21 = value + + @property + def cd22(self): + """The CD2_2 value (depenence of DEC scale on y-pixel value) + + eg. cd12 = 5E-5 + unit: deg/pix + type: float + + """ + return self._cd22 + + @cd22.setter + def cd22(self, value): + Util.type_check(value, float, 'cd22', override=False) + self._cd22 = value + + +class CoordPolygon2D(CaomObject): + """A object to contain a TypeList ValueCoord2D vertices that are a + polygon. The vertices are given as ValueCoord2D objects, which are + coordinate pairs. + + eg. vertices.add(ValueCoord2D(coord1,coord2)) + + """ + + def __init__(self, vertices=None): + if vertices is None: + vertices = TypedList((ValueCoord2D),) + self.vertices = vertices + + @property + def vertices(self): + """A TypedList of ValueCoord2D objects that layout the vertices of a + polygon. + + A vertices can be added using the 'add' method.. + eg: vertices.add(ValueCoord2D()) + + see the caom2.wcs.ValueCoord2D help for details on making a + coordinate pair. + + type: TypedList((ValueCoord2D),) + + """ + return self._vertices + + @vertices.setter + def vertices(self, value): + Util.type_check(value, TypedList, 'vertices', override=False) + self._vertices = value + + +class CoordRange1D(CaomObject): + """a CoordRange1D object contains the start and end of + a range of values, expressed in both pixel and WCS units. + + """ + + def __init__(self, start, end): + self.start = start + self.end = end + + @property + def start(self): + """The pixel and world coordinate of the start of a range. + + eg. RefCoord(pix,val) + type: RefCoord + + """ + return self._start + + @start.setter + def start(self, value): + Util.type_check(value, RefCoord, "start", override=False) + self._start = value + + @property + def end(self): + """The pixel and world coordinate of the end of a range. + + eg. RefCoord(pix,val) + type: RefCoord + + """ + return self._end + + @end.setter + def end(self, value): + Util.type_check(value, RefCoord, "end", override=False) + self._end = value + + +class CoordRange2D(CaomObject): + """A range (x1,y1) to (x2,y2) in two dimenstions. + + The range object should know the coordinate in both + pixels and WCS units. + + """ + + def __init__(self, start, end): + self.start = start + self.end = end + + @property + def start(self): + """The starting coordinate pair of a range, in wcs units. + + eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) + """ + return self._start + + @start.setter + def start(self, value): + Util.type_check(value, Coord2D, 'start', override=False) + self._start = value + + @property + def end(self): + """The reference for the ending coordinate of a range. + + eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) + """ + return self._end + + @end.setter + def end(self, value): + Util.type_check(value, Coord2D, 'end', override=False) + self._end = value + + +class Dimension2D(CaomObject): + """Hey, how big is this thing? What are its dimensions. That's what + Dimension2D will tell you. + + """ + + def __init__(self, naxis1, naxis2): + self.naxis1 = naxis1 + self.naxis2 = naxis2 + + @property + def naxis1(self): + """The length of the first (x) dimension. + + eg. naxis1=1024 + unit: pix + type: long + + """ + return self._naxis1 + + @naxis1.setter + def naxis1(self, value): + Util.type_check(value, long, 'naxis1', override=False) + Util.value_check(value, 0, 1E10, 'naxis1', override=False) + self._naxis1 = value + + @property + def naxis2(self): + """The length of the second (y) dimension. + + eg. naxis2=2048 + unit: pix + type: long + + """ + return self._naxis2 + + @naxis2.setter + def naxis2(self, value): + Util.type_check(value, long, 'naxis2', override=False) + Util.value_check(value, 0, 1E10, 'naxis2', override=False) + self._naxis2 = value + + +class RefCoord(CaomObject): + """A refernce coordinate object, maps pixel value to wcs value + + """ + + def __init__(self, pix, val): + """maps a pixel location to a wcs value, as a reference spot. + + eg. RefCoord(crpix1, crval1) + + """ + self.pix = pix + self.val = val + + @property + def pix(self): + """The pixel location of a reference position. + + units: pix + type: float + + """ + return self._pix + + @pix.setter + def pix(self, value): + Util.type_check(value, float, 'pix', override=False) + self._pix = value + + @property + def val(self): + """The WCS value at the reference position. + + units: CUNIT + type: float + + """ + return self._val + + @val.setter + def val(self, value): + Util.type_check(value, float, 'val', override=False) + self._val = value + + +class Slice(CaomObject): + """defines a slice in a set of data contains values. + + The slice keeps track of the type/unit and values. + + ctype and cunit are stored in the axis variable. + values are stored in the bins + + """ + def __init__(self, axis, bin_): + self.axis = axis + self.bin = bin_ + + @property + def axis(self): + """A ctype/cunit pair for this slice of data. + + type: Axis(ctype,cunit) + + """ + return self._axis + + @axis.setter + def axis(self, value): + Util.type_check(value, Axis, 'axis', override=False) + self._axis = value + + @property + def bin(self): + """The pixel value on the axis. + + This value is use to transform to the WCS for this axis. + unit: pixel + type: long + """ + return self._bin + + @bin.setter + def bin(self, value): + Util.type_check(value, long, 'long', override=False) + self._bin = value + + +class ValueCoord2D(CaomObject): + """Represents the reference point.""" + + def __init__(self, coord1, coord2): + self.coord1 = coord1 + self.coord2 = coord2 + + @property + def coord1(self): + """Coordinate 1""" + return self._coord1 + + @coord1.setter + def coord1(self, value): + Util.type_check(value, float, 'coord1', override=False) + self._coord1 = value + + @property + def coord2(self): + """Coordinate 2""" + return self._coord2 + + @coord2.setter + def coord2(self, value): + Util.type_check(value, float, 'coord2', override=False) + self._coord2 = value + + +class EnergyTransition(CaomObject): + """ EnergyTransition """ + + def __init__(self, species, transition): + """ + Construct an EnergyTransition instance + + Arguments: + species + transition + """ + Util.type_check(species, str, "species", override=False) + Util.type_check(transition, str, "transition", override=False) + self._species = species + self._transition = transition + + @property + def species(self): + """ Species """ + return self._species + + @property + def transition(self): + """ Transition """ + return self._transition diff --git a/caom2tools/caom2/wcs/__init__.py b/caom2tools/caom2/wcs/__init__.py deleted file mode 100755 index 6851d8cf..00000000 --- a/caom2tools/caom2/wcs/__init__.py +++ /dev/null @@ -1,96 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines __init__ """ - - -from caom2_axis import Axis -from caom2_coord2d import Coord2D -from caom2_value_coord2d import ValueCoord2D -from caom2_coord_axis1d import CoordAxis1D -from caom2_coord_axis2d import CoordAxis2D -from caom2_coord_bounds1d import CoordBounds1D -from caom2_coord_bounds2d import CoordBounds2D -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_error import CoordError -from caom2_coord_function1d import CoordFunction1D -from caom2_coord_function2d import CoordFunction2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2_coord_range1d import CoordRange1D -from caom2_coord_range2d import CoordRange2D -from caom2_dimension2d import Dimension2D - -from caom2_observable_axis import ObservableAxis -from caom2_polarization_wcs import PolarizationWCS -from caom2_ref_coord import RefCoord -from caom2_slice import Slice -from caom2_spatial_wcs import SpatialWCS -from caom2_spectral_wcs import SpectralWCS -from caom2_temporal_wcs import TemporalWCS diff --git a/caom2tools/caom2/wcs/caom2_axis.py b/caom2tools/caom2/wcs/caom2_axis.py deleted file mode 100644 index 559aac1a..00000000 --- a/caom2tools/caom2/wcs/caom2_axis.py +++ /dev/null @@ -1,115 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" -Defines the Axis class -""" - -import caom2.util.caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Axis(Caom2Object): - """the Axis class holds the definition of the axis type and units""" - - def __init__(self, ctype, cunit=None): - - self.ctype = ctype - self.cunit = cunit - - @property - def ctype(self): - """The Coordinate Type value for this axis. - - eg. DEC - type: str - - """ - return self._ctype - - @ctype.setter - def ctype(self, value): - util.typeCheck(value, str, 'ctype', override=False) - self._ctype = value - - @property - def cunit(self): - """The unit of the coordinate that results after transform. - - eg. deg - type: str - - """ - return self._cunit - - @cunit.setter - def cunit(self, value): - util.typeCheck(value, str, 'cunit') - self._cunit = value diff --git a/caom2tools/caom2/wcs/caom2_coord2d.py b/caom2tools/caom2/wcs/caom2_coord2d.py deleted file mode 100644 index 1ca28c65..00000000 --- a/caom2tools/caom2/wcs/caom2_coord2d.py +++ /dev/null @@ -1,112 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of 2D coord object""" - -from caom2_ref_coord import RefCoord -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Coord2D(Caom2Object): - """Represents the reference point. - - eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) - """ - - def __init__(self, coord1, coord2): - self.coord1 = coord1 - self.coord2 = coord2 - - @property - def coord1(self): - """A coordinate axis1 coordinate/pix pair, crpix1, crval1. - - eg. RefCoord(crpix1, crval1) - """ - return self._coord1 - - @coord1.setter - def coord1(self, value): - util.typeCheck(value, RefCoord, 'coord1', override=False) - self._coord1 = value - - @property - def coord2(self): - """The axis2 coordinate reference pair (ei. crpix2/crval2. - - eg. RefCorrd(crpix2, crval2) - """ - return self._coord2 - - @coord2.setter - def coord2(self, value): - util.typeCheck(value, RefCoord, 'coord2', override=False) - self._coord2 = value diff --git a/caom2tools/caom2/wcs/caom2_coord_axis1d.py b/caom2tools/caom2/wcs/caom2_coord_axis1d.py deleted file mode 100644 index a9c1bbe5..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_axis1d.py +++ /dev/null @@ -1,174 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""Definition of the CoordAxis1D class""" - -from caom2_axis import Axis -from caom2_coord_error import CoordError -from caom2_coord_range1d import CoordRange1D -from caom2_coord_bounds1d import CoordBounds1D -from caom2_coord_function1d import CoordFunction1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class CoordAxis1D(Caom2Object): - """Holds the metadata needed to transform a 1D pixel value into a - World Coordinate value. - - """ - - def __init__(self, axis, error=None, range=None, - bounds=None, function=None): - - self.axis = axis - self.error = error - self.range = range - self.bounds = bounds - self.function = function - - @property - def axis(self): - """An axis object which describes the type and units of this - coordinate axis. - - eg. Axis(ctype1,cunit1) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, Axis, "Axis", override=False) - self._axis = value - - @property - def error(self): - """A CoordError object that describes the uncertainty in the. - - eg. CoordError(syser=0.1, rnder=0.1) - unit: cunit1 [of axis] - - """ - return self._error - - @error.setter - def error(self, value): - util.typeCheck(value, CoordError, 'error') - self._error = value - - @property - def range(self): - """A range that defines a coordinate transformation. - - the transform is a linear interpolation over the range - given which is a specified as a set of two pix/val reference pair. - eg. CoordRange1D(start=RefCoord(pix1,val1),end=RefCoord(pix2,val2)) - unit: same as the axis you are defining. - - """ - return self._range - - @range.setter - def range(self, value): - util.typeCheck(value, CoordRange1D, 'range') - self._range = value - - @property - def bounds(self): - """A polygon that defines the boundary of this axis, in 1D. - - eg. CoordBounds1D(ListOfRanges()) - The ranges are like those given for the range attribute. - - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, CoordBounds1D, "bounds") - self._bounds = value - - @property - def function(self): - """A linear function that describes the tranformation between pixel - and world coordinate value. - - Since this is a 1D object and linear, the function is - y = m*x + b. - eg. CoordFunction1D(naxis, delta, RefCoord) - - """ - return self._function - - @function.setter - def function(self, value): - util.typeCheck(value, CoordFunction1D, 'function') - self._function = value diff --git a/caom2tools/caom2/wcs/caom2_coord_axis2d.py b/caom2tools/caom2/wcs/caom2_coord_axis2d.py deleted file mode 100644 index 197dac94..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_axis2d.py +++ /dev/null @@ -1,202 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordAxis2D class""" - -from caom2_axis import Axis -from caom2_coord_error import CoordError -from caom2_coord_range2d import CoordRange2D -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2_coord_function2d import CoordFunction2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordAxis2D(Caom2Object): - """This object hold the metadata need to transform a 2D pixel - array (say an image) into a World position, say RA/DEC - - """ - - def __init__(self, axis1, axis2, - error1=None, error2=None, - range=None, bounds=None, - function=None): - - self.axis1 = axis1 - self.axis2 = axis2 - self.error1 = error1 - self.error2 = error2 - self.range = range - self.bounds = bounds - self.function = function - - @property - def axis1(self): - """An axis object that desciribes the first dimension - of this 2d system. - - eg. axis1=Axis("RA","deg") - - """ - return self._axis1 - - @axis1.setter - def axis1(self, value): - util.typeCheck(value, Axis, "axis1", override=False) - self._axis1 = value - - @property - def axis2(self): - """An axis objet that describes the 2nd dimensiotn of this 2d coord - system. - - eg. axis2=Axis("DEG","deg") - - """ - return self._axis2 - - @axis2.setter - def axis2(self, value): - util.typeCheck(value, Axis, "axis2", override=False) - self._axis2 = value - - @property - def error1(self): - """An object that descibes the uncertainty in the pix/world transform. - - eg. CoordError() - type: CoordError - - """ - return self._error1 - - @error1.setter - def error1(self, value): - util.typeCheck(value, CoordError, 'error1') - self._error1 = value - - @property - def error2(self): - """An object that describes the uncertainty in the pix/world transform - for the 2nd axis - - type: CoordError - - """ - return self._error2 - - @error2.setter - def error2(self, value): - util.typeCheck(value, CoordError, "error2") - self._error2 = value - - @property - def range(self): - """Coordinate range defined by this CoordAxis2d object. - - type: CoordRange2D - """ - return self._range - - @range.setter - def range(self, value): - util.typeCheck(value, CoordRange2D, 'range') - self._range = value - - @property - def bounds(self): - """The Coordinate boundary mapped by this CoordAxis2D object. - - ag. CoordPolygon2d((234,10),(234,11),(233,11),(234,11),(234,10)) - type: CoordPolygon2D or CoordCircle2D - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - util.typeCheck(value, (CoordCircle2D, CoordPolygon2D), 'bounds') - self._bounds = value - - @property - def function(self): - """A function object that describes the relation - between pixels and wcs. - - ag. CoordFunction2D (see the help for that puppy) - type: CoordFunction2D - """ - return self._function - - @function.setter - def function(self, value): - util.typeCheck(value, CoordFunction2D, 'function') - self._function = value diff --git a/caom2tools/caom2/wcs/caom2_coord_bounds1d.py b/caom2tools/caom2/wcs/caom2_coord_bounds1d.py deleted file mode 100644 index d034f9d1..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_bounds1d.py +++ /dev/null @@ -1,108 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordBounds1D class""" - -from caom2_coord_range1d import CoordRange1D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordBounds1D(Caom2Object): - """Contains the bounds for a 1D axis, a list of ranges - - """ - - def __init__(self, samples=None): - - if samples is None: - samples = util.TypedList((CoordRange1D),) - self.samples = samples - - @property - def samples(self): - """A list of CoordRange1D objects that define the - boundary of a 1D axis. - - see also caom2.util.TypedList and caom2.wcs.CoordRange1D - - eg. - samples.add(CoordRange1D(RefCoord(pix,val),RefCoord(pix,val))) - - """ - return self._samples - - @samples.setter - def samples(self, value): - util.typeCheck(value, - util.TypedList, - 'samples', - override=False) - self._samples = value diff --git a/caom2tools/caom2/wcs/caom2_coord_bounds2d.py b/caom2tools/caom2/wcs/caom2_coord_bounds2d.py deleted file mode 100644 index cb72b1b3..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_bounds2d.py +++ /dev/null @@ -1,103 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordBounds2D class""" - -from caom2_coord_circle2d import CoordCircle2D -from caom2_coord_polygon2d import CoordPolygon2D -from caom2.caom2_object import Caom2Object - - -class CoordBounds2D(Caom2Object): - """Contains the bounds for a 2D axis - - """ - - def __init__(self, bounds): - if (isinstance(bounds, CoordCircle2D) or - isinstance(bounds, CoordPolygon2D)): - self.bounds = bounds - else: - raise TypeError( - "Expected CoordCircle2D or CoordPolygon2D, received {}" - .format(type(bounds))) - - @property - def bounds(self): - """The bounds expressed as a circle or polygon. - - eg CoordBounds2D(CoordCircle2D()) - type: CoordCircle2D or CoordPolygon2D - """ - return self._bounds - - @bounds.setter - def bounds(self, value): - self._bounds = value diff --git a/caom2tools/caom2/wcs/caom2_coord_circle2d.py b/caom2tools/caom2/wcs/caom2_coord_circle2d.py deleted file mode 100644 index ffd7dac2..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_circle2d.py +++ /dev/null @@ -1,120 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" defines the CoordCircle2D class""" - -from caom2_value_coord2d import ValueCoord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordCircle2D(Caom2Object): - """A circle expressed in both pixel and WCS value coordinates. - - These objects are used to map out the bounds of spatial WCS. - - Currently radius is only given in WCS units.. should be both. - - """ - - def __init__(self, center, radius): - self.center = center - self.radius = radius - - @property - def center(self): - """The pixel/world coordinate location of the centre. - - eg ValueCoord2D(coord1, coord2) - type: ValueCoord2D - """ - return self._center - - @center.setter - def center(self, value): - util.typeCheck(value, ValueCoord2D, 'center', override=False) - self._center = value - - @property - def radius(self): - """The radius of the circle. - - NOTE::: This should likely be a RefCoord too... - - unit: same as centre which is pix/cunit - type: float - """ - return self._radius - - @radius.setter - def radius(self, value): - util.typeCheck(value, float, 'radius', override=False) - util.valueCheck(value, 0, 1E10, 'radius') - self._radius = value diff --git a/caom2tools/caom2/wcs/caom2_coord_error.py b/caom2tools/caom2/wcs/caom2_coord_error.py deleted file mode 100644 index 4d711051..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_error.py +++ /dev/null @@ -1,126 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordError class - -""" - - -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordError(Caom2Object): - """Holds the systematic (syser) and random (rnder) error on a - coordinate. - - The concept is that these values are functions of the coordinate - transformation but likely be expressed with sufficient precision - (for a query model) using a systematic and random component. Both - are taken to be symetric. - - Likely either of these could be 'None', but best set to '0' if - that's what you really want to express. - - """ - - def __init__(self, syser, rnder): - - self.syser = syser - self.rnder = rnder - - # Properties - @property - def syser(self): - """the systematic uncertainty in a coordinate transform. - - units: should be the same as the CoordAxis (s, arcsec, deg?) - - """ - return self._syser - - @syser.setter - def syser(self, value): - util.typeCheck(value, float, "syser", override=False) - self._syser = value - - @property - def rnder(self): - """the random uncertainty in a coordinate transform. - - units: should be the same as the CoordAxis transform. - - """ - return self._rnder - - @rnder.setter - def rnder(self, value): - util.typeCheck(value, float, "rnder", override=False) - self._rnder = value diff --git a/caom2tools/caom2/wcs/caom2_coord_function1d.py b/caom2tools/caom2/wcs/caom2_coord_function1d.py deleted file mode 100644 index 5565ce7c..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_function1d.py +++ /dev/null @@ -1,141 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordFunction1D class - -""" - -from caom2_ref_coord import RefCoord -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class CoordFunction1D(Caom2Object): - """Defines a linear function that transforms from pixel to WCS - values. - - """ - - def __init__(self, naxis, delta, ref_coord): - """ - Need to define the length of the axis, the slope of the - conversion and a reference coordinate. All are needed for a - valid 1D function. - - """ - - self.naxis = naxis - self.delta = delta - self.ref_coord = ref_coord - - @property - def naxis(self): - """The length of the axis. - - unit: pix - type: long - - """ - return self._naxis - - @naxis.setter - def naxis(self, value): - util.typeCheck(value, long, 'naxis', override=False) - self._naxis = value - - @property - def delta(self): - """The step in WCS between pixels. - - unit: WCS/pix (days if this is a timeWCS) - type: float - - """ - return self._delta - - @delta.setter - def delta(self, value): - util.typeCheck(value, float, 'delta', override=False) - self._delta = value - - @property - def ref_coord(self): - """the (pix,val) reference for this transformtion. - - eg. ref_coord=RefCoord(pix,val) - type: RefCoord - - """ - return self._ref_coord - - @ref_coord.setter - def ref_coord(self, value): - util.typeCheck(value, RefCoord, 'ref_coord', override=False) - self._ref_coord = value diff --git a/caom2tools/caom2/wcs/caom2_coord_function2d.py b/caom2tools/caom2/wcs/caom2_coord_function2d.py deleted file mode 100644 index ca64e16d..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_function2d.py +++ /dev/null @@ -1,188 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines a 'CoordFunction2D' class - -""" - -from caom2_dimension2d import Dimension2D -from caom2_coord2d import Coord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordFunction2D(Caom2Object): - """Describes the parameters needed for the standard CD matrix. - - defines a linear translation between pixel and WCS. - - """ - - def __init__(self, dimension, ref_coord, cd11, cd12, cd21, cd22): - self.dimension = dimension - self.ref_coord = ref_coord - self.cd11 = cd11 - self.cd12 = cd12 - self.cd21 = cd21 - self.cd22 = cd22 - - @property - def dimension(self): - """A Dimension2D object that holds the lengths of the axis - - eg. Diemnsion2D(naxis1=1024,naxis2=2048) - type: Dimension2D - - """ - return self._dimension - - @dimension.setter - def dimension(self, value): - util.typeCheck(value, Dimension2D, 'dimension', override=False) - self._dimension = value - - @property - def ref_coord(self): - """A Coord2D object that holds the reference pixel location - - eg. Coord2D((crpix1,crval1),(crpix2,crval2)) - type: Coord2D - - """ - return self._ref_coord - - @ref_coord.setter - def ref_coord(self, value): - util.typeCheck(value, Coord2D, 'ref_coord', override=False) - self._ref_coord = value - - @property - def cd11(self): - """The CD1_1 value (depenence of RA scale on x-pixel value) - - eg. cd11 = 5E-5 - unit: deg/pix - type: float - - """ - return self._cd11 - - @cd11.setter - def cd11(self, value): - util.typeCheck(value, float, 'cd11', override=False) - self._cd11 = value - - @property - def cd12(self): - """The CD1_2 value (depenence of RA scale on y-pixel value) - - eg. cd12 = 5E-10 - unit: deg/pix - type: float - - """ - return self._cd12 - - @cd12.setter - def cd12(self, value): - util.typeCheck(value, float, 'cd12', override=False) - self._cd12 = value - - @property - def cd21(self): - """The CD1_1 value (depenence of DEC scale on x-pixel value) - - eg. cd11 = 5E-10 - unit: deg/pix - type: float - - """ - return self._cd21 - - @cd21.setter - def cd21(self, value): - util.typeCheck(value, float, 'cd21', override=False) - self._cd21 = value - - @property - def cd22(self): - """The CD2_2 value (depenence of DEC scale on y-pixel value) - - eg. cd12 = 5E-5 - unit: deg/pix - type: float - - """ - return self._cd22 - - @cd22.setter - def cd22(self, value): - util.typeCheck(value, float, 'cd22', override=False) - self._cd22 = value diff --git a/caom2tools/caom2/wcs/caom2_coord_polygon2d.py b/caom2tools/caom2/wcs/caom2_coord_polygon2d.py deleted file mode 100644 index 56d8572a..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_polygon2d.py +++ /dev/null @@ -1,113 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordPolygon2D class - -""" - -from caom2_value_coord2d import ValueCoord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordPolygon2D(Caom2Object): - """A object to contain a TypeList ValueCoord2D vertices that are a - polygon. The vertices are given as ValueCoord2D objects, which are - coordinate pairs. - - eg. vertices.add(ValueCoord2D(coord1,coord2)) - - """ - - def __init__(self, vertices=None): - if vertices is None: - vertices = util.TypedList((ValueCoord2D),) - self.vertices = vertices - - @property - def vertices(self): - """A TypedList of ValueCoord2D objects that layout the vertices of a - polygon. - - A vertices can be added using the 'add' method.. - eg: vertices.add(ValueCoord2D()) - - see the caom2.wcs.ValueCoord2D help for details on making a - coordinate pair. - - type: TypedList((ValueCoord2D),) - - """ - return self._vertices - - @vertices.setter - def vertices(self, value): - util.typeCheck(value, util.TypedList, 'vertices', override=False) - self._vertices = value diff --git a/caom2tools/caom2/wcs/caom2_coord_range1d.py b/caom2tools/caom2/wcs/caom2_coord_range1d.py deleted file mode 100644 index 75afc2f9..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_range1d.py +++ /dev/null @@ -1,118 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines CoordRange1D class - -""" - -from caom2_ref_coord import RefCoord -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordRange1D(Caom2Object): - """a CoordRange1D object contains the start and end of - a range of values, expressed in both pixel and WCS units. - - """ - - def __init__(self, start, end): - self.start = start - self.end = end - - @property - def start(self): - """The pixel and world coordinate of the start of a range. - - eg. RefCoord(pix,val) - type: RefCoord - - """ - return self._start - - @start.setter - def start(self, value): - util.typeCheck(value, RefCoord, "start", override=False) - self._start = value - - @property - def end(self): - """The pixel and world coordinate of the end of a range. - - eg. RefCoord(pix,val) - type: RefCoord - - """ - return self._end - - @end.setter - def end(self, value): - util.typeCheck(value, RefCoord, "end", override=False) - self._end = value diff --git a/caom2tools/caom2/wcs/caom2_coord_range2d.py b/caom2tools/caom2/wcs/caom2_coord_range2d.py deleted file mode 100644 index 5f54f3c8..00000000 --- a/caom2tools/caom2/wcs/caom2_coord_range2d.py +++ /dev/null @@ -1,116 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the CoordRange2D class - -""" - -from caom2_coord2d import Coord2D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class CoordRange2D(Caom2Object): - """A range (x1,y1) to (x2,y2) in two dimenstions. - - The range object should know the coordinate in both - pixels and WCS units. - - """ - - def __init__(self, start, end): - self.start = start - self.end = end - - @property - def start(self): - """The starting coordinate pair of a range, in wcs units. - - eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) - """ - return self._start - - @start.setter - def start(self, value): - util.typeCheck(value, Coord2D, 'start', override=False) - self._start = value - - @property - def end(self): - """The reference for the ending coordinate of a range. - - eg: Coord2D(RefCoord(crpix1,crval1), RefCoord(crpix2,crval2)) - """ - return self._end - - @end.setter - def end(self, value): - util.typeCheck(value, Coord2D, 'end', override=False) - self._end = value diff --git a/caom2tools/caom2/wcs/caom2_dimension2d.py b/caom2tools/caom2/wcs/caom2_dimension2d.py deleted file mode 100644 index eed92ee8..00000000 --- a/caom2tools/caom2/wcs/caom2_dimension2d.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Dimension2d class - -""" - - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Dimension2D(Caom2Object): - """Hey, how big is this thing? What are its dimensions. That's what - Dimension2D will tell you. - - """ - - def __init__(self, naxis1, naxis2): - self.naxis1 = naxis1 - self.naxis2 = naxis2 - - @property - def naxis1(self): - """The length of the first (x) dimension. - - eg. naxis1=1024 - unit: pix - type: long - - """ - return self._naxis1 - - @naxis1.setter - def naxis1(self, value): - util.typeCheck(value, long, 'naxis1', override=False) - util.valueCheck(value, 0, 1E10, 'naxis1', override=False) - self._naxis1 = value - - @property - def naxis2(self): - """The length of the second (y) dimension. - - eg. naxis2=2048 - unit: pix - type: long - - """ - return self._naxis2 - - @naxis2.setter - def naxis2(self, value): - util.typeCheck(value, long, 'naxis2', override=False) - util.valueCheck(value, 0, 1E10, 'naxis2', override=False) - self._naxis2 = value diff --git a/caom2tools/caom2/wcs/caom2_observable_axis.py b/caom2tools/caom2/wcs/caom2_observable_axis.py deleted file mode 100644 index be61ed98..00000000 --- a/caom2tools/caom2/wcs/caom2_observable_axis.py +++ /dev/null @@ -1,151 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the ObservableAxis class - -""" - -from caom2_slice import Slice -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class ObservableAxis(Caom2Object): - """The slice through the data structure that provides the thing being - described by this Axis. - - this data structure is used when a file contains data that has set - of measured values (the dependent variable) and might also have - the coordinate at which those values are measured in another Slice - of the file. - - The Slice refers to a column in a FITS image. The bin is the - column index and ctype/cunit for the axis describe what the column - contiains. - - eg. - - NAXIS=2 - NAXIS1=3 - NAXIS2=N - l1 f1 s1 - l2 f2 s2 - l3 f3 s3 - . - . - lN fN sN - - where l? is the wavelength at which a measure of flux f? has been - made and l is the first column of a FITS data structure that is - 3,N in size. s? is a third slice that would be used to define - another observable. When defining the s? obserable the independent - variable must be defined for that ObservableAxis too. - - The l/f obserable would be recorded as - - dependent=Slice(Axis('wave','nm'),bin=1) - independent=Slice(Axis('flux','Jy'),bin=2) - Chunk.observable_axis=ObservableAxis(dependent, independent) - - - """ - def __init__(self, dependent, independent=None): - - self.dependent = dependent - self.independent = independent - - @property - def dependent(self): - """The dependent (y) variable slice. - - A slice provides the bin and the type/unit of the observable axis - """ - - return self._dependent - - @dependent.setter - def dependent(self, value): - util.typeCheck(value, Slice, 'dependent', override=False) - self._dependent = value - - @property - def independent(self): - """The dependent (y) variable slice. - - A slice that provides the pixel value and the type/unit for - conversion - - """ - return self._independent - - @independent.setter - def independent(self, value): - util.typeCheck(value, Slice, "independent") - self._independent = value diff --git a/caom2tools/caom2/wcs/caom2_polarization_wcs.py b/caom2tools/caom2/wcs/caom2_polarization_wcs.py deleted file mode 100644 index 30be5b86..00000000 --- a/caom2tools/caom2/wcs/caom2_polarization_wcs.py +++ /dev/null @@ -1,106 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the PolarizationWCS class""" - -from caom2_coord_axis1d import CoordAxis1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class PolarizationWCS(Caom2Object): - """A WCS structure that describes the relation ship between a pixel - location and the polarization value. - - """ - - def __init__(self, axis): - """Set up a CoordAxis1D object to represent the Polariation. - - """ - - self.axis = axis - - @property - def axis(self): - """A CoordAxis1D object that describes the pixel/value relation ship - for polarization of the data. - - type: CoordAxis1D - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - if value.axis.ctype != 'STOKES': - raise ValueError('CTYPE must be STOKES') - self._axis = value diff --git a/caom2tools/caom2/wcs/caom2_ref_coord.py b/caom2tools/caom2/wcs/caom2_ref_coord.py deleted file mode 100644 index cbdc9e3e..00000000 --- a/caom2tools/caom2/wcs/caom2_ref_coord.py +++ /dev/null @@ -1,122 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the RefCoord class - -""" - - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class RefCoord(Caom2Object): - """A refernce coordinate object, maps pixel value to wcs value - - """ - - def __init__(self, pix, val): - """maps a pixel location to a wcs value, as a reference spot. - - eg. RefCoord(crpix1, crval1) - - """ - self.pix = pix - self.val = val - - @property - def pix(self): - """The pixel location of a reference position. - - units: pix - type: float - - """ - return self._pix - - @pix.setter - def pix(self, value): - util.typeCheck(value, float, 'pix', override=False) - self._pix = value - - @property - def val(self): - """The WCS value at the reference position. - - units: CUNIT - type: float - - """ - return self._val - - @val.setter - def val(self, value): - util.typeCheck(value, float, 'val', override=False) - self._val = value diff --git a/caom2tools/caom2/wcs/caom2_slice.py b/caom2tools/caom2/wcs/caom2_slice.py deleted file mode 100644 index 7f33eebe..00000000 --- a/caom2tools/caom2/wcs/caom2_slice.py +++ /dev/null @@ -1,121 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the Slice class - -""" - - -from caom2_axis import Axis -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class Slice(Caom2Object): - """defines a slice in a set of data contains values. - - The slice keeps track of the type/unit and values. - - ctype and cunit are stored in the axis variable. - values are stored in the bins - - """ - def __init__(self, axis, bin_): - self.axis = axis - self.bin = bin_ - - @property - def axis(self): - """A ctype/cunit pair for this slice of data. - - type: Axis(ctype,cunit) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, Axis, 'axis', override=False) - self._axis = value - - @property - def bin(self): - """The pixel value on the axis. - - This value is use to transform to the WCS for this axis. - unit: pixel - type: long - """ - return self._bin - - @bin.setter - def bin(self, value): - util.typeCheck(value, long, 'long', override=False) - self._bin = value diff --git a/caom2tools/caom2/wcs/caom2_spatial_wcs.py b/caom2tools/caom2/wcs/caom2_spatial_wcs.py deleted file mode 100644 index 95e37bb0..00000000 --- a/caom2tools/caom2/wcs/caom2_spatial_wcs.py +++ /dev/null @@ -1,164 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SpatialWCS class - -""" - - -from caom2_coord_axis2d import CoordAxis2D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class SpatialWCS(Caom2Object): - """this object contains the WCS information needed to convert an - astronomical spatial location (ie. RA/DEC) into a pixel location - in the image. - - During ingestion a variety of extra information is created. - - """ - - def __init__(self, - axis, - coordsys=None, - equinox=None, - resolution=None): - - self.axis = axis - self.coordsys = coordsys - self.equinox = equinox - self.resolution = resolution - - @property - def axis(self): - """A CoordAxis2D object that contains - the actual WCS values (crpix etc.) - - type: CoordAxis2D - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis2D, 'axis', override=False) - self._axis = value - - @property - def coordsys(self): - """The Coordinate system of the transformation, likely ICRS or FK5. - - eg. SpatialWCS.coordsys="ICRS" - - type: str - - """ - return self._coordsys - - @coordsys.setter - def coordsys(self, value): - util.typeCheck(value, str, 'coordsys') - self._coordsys = value - - @property - def equinox(self): - """The Equinox of the coordinate system. - - You might think J2000, but must be expressed as a float, so in years - - unit: years - type: float - - """ - return self._equinox - - @equinox.setter - def equinox(self, value): - util.typeCheck(value, float, 'equinox') - util.valueCheck(value, 1800, 2500, 'equinox') - self._equinox = value - - @property - def resolution(self): - """The spatial resolution of the image data (account for seeing/beem). - - unit: arcsec - type: float - - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - util.valueCheck(value, 0, 360 * 3600.0, 'resolution') - self._resolution = value diff --git a/caom2tools/caom2/wcs/caom2_spectral_wcs.py b/caom2tools/caom2/wcs/caom2_spectral_wcs.py deleted file mode 100644 index 1e90ada3..00000000 --- a/caom2tools/caom2/wcs/caom2_spectral_wcs.py +++ /dev/null @@ -1,309 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""defines the SpectralWCS class""" - -from caom2.caom2_energy_transition import EnergyTransition -from caom2_coord_axis1d import CoordAxis1D -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class SpectralWCS(Caom2Object): - """A transformation that maps pixel coordinates to spectral ones. - - Note that a 2D image has implicit 'spectral' (and temporal) - dimension that is one pixel in size. Basically pixels are really - multidimensional voxels. - - Due to FITS standards this pixel starts at 0.5 and runs to 1.5 - with the centre being at 1.0 - - """ - - def __init__(self, - axis, - specsys, - ssysobs=None, - ssyssrc=None, - restfrq=None, - restwav=None, - velosys=None, - zsource=None, - velang=None, - bandpass_name=None, - transition=None, - resolving_power=None - ): - """The SpectralWCS can be defined in a number of different ways, to - define one you must provide a CoordAxis1D object that maps the - pixels to WCS values and a reference specsys. After that the - user can add what ever parts seam useful. More info is more - helpful for searching. - - """ - - self.axis = axis - self.specsys = specsys - self.ssysobs = ssysobs - self.ssyssrc = ssyssrc - self.restfrq = restfrq - self.restwav = restwav - self.velosys = velosys - self.zsource = zsource - self.velang = velang - self.bandpass_name = bandpass_name - self.transition = transition - self.resolving_power = resolving_power - - @property - def axis(self): - """A 1D coordinate axis object that contains the pix/wcs - transformation values. - - eg. CoordAxis1D(Axis('wave','flux'),...) - - """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - self._axis = value - - @property - def specsys(self): - """describes the reference frame in use for the spectral-axis - coordinate(s). - - eg. BARYCENT - - type: str - """ - return self._specsys - - @specsys.setter - def specsys(self, value): - util.typeCheck(value, str, 'specsys', override=False) - self._specsys = value - - @property - def ssysobs(self): - """describes the spectral reference frame that is constant over the - range of the non-spectral world coordinates - - For example, for a large image the the wavelength at the edges - is different from the centres. This refernce frame is one where they - are not different. - - Nominally 'TOPOCENT' - - type: str - """ - return self._ssysobs - - @ssysobs.setter - def ssysobs(self, value): - util.typeCheck(value, str, 'ssysobs') - self._ssysobs = value - - @property - def ssyssrc(self): - """The reference frame in which zsource is expressed. - - eg. BARYCENT - type: string - """ - return self._ssyssrc - - @ssyssrc.setter - def ssyssrc(self, value): - util.typeCheck(value, str, 'ssyssrc') - self._ssyssrc = value - - @property - def restfrq(self): - """The frequency of the spectal feature being observed. - - unit: Hz - type: float - """ - return self._restfrq - - @restfrq.setter - def restfrq(self, value): - util.typeCheck(value, float, 'restfrq') - self._restfrq = value - - @property - def restwav(self): - """The wavelength of spectral feature being observed, - not the wavelength observed but the wavelength of the - feature when at rest.. - - unit: m - type: float - """ - return self._restwav - - @restwav.setter - def restwav(self, value): - util.typeCheck(value, float, 'restwav') - self._restwav = value - - @property - def velosys(self): - """Relative radial velocity between the observer and the selected - standard of rest in the direction of the celestial reference - coordinate. - - eg. 26000 m/s - - - unit: m/s - type: float - """ - return self._velosys - - @velosys.setter - def velosys(self, value): - util.typeCheck(value, float, 'velosys') - self._velosys = value - - @property - def zsource(self): - """The redshift of the source emitting the photons. - - almost always None - - unit: z - type: float - """ - return self._zsource - - @zsource.setter - def zsource(self, value): - util.typeCheck(value, float, 'zsource') - util.valueCheck(value, -0.5, 1200, 'zsource') - self._zsource = value - - @property - def velang(self): - """I don't know what this is... angle of the velocity ??? """ - return self._velang - - @velang.setter - def velang(self, value): - util.typeCheck(value, float, 'velang') - self._velang = value - - @property - def bandpass_name(self): - """string the represent the bandpass of the observation. - - eg. r' - type: str - """ - return self._bandpass_name - - @bandpass_name.setter - def bandpass_name(self, value): - util.typeCheck(value, str, 'bandpass_name') - self._bandpass_name = value - - @property - def transition(self): - """which molecular transition has been observed. - - type: EnergyTransition object (see caom2.EnergyTransition for help) - """ - return self._transition - - @transition.setter - def transition(self, value): - util.typeCheck(value, EnergyTransition, "transition") - self._transition = value - - @property - def resolving_power(self): - """The R value of the spectal coverage. - - Normally this is something like dlamda/lamda - - unit: RATIO - type: float - """ - return self._resolving_power - - @resolving_power.setter - def resolving_power(self, value): - util.typeCheck(value, float, 'resolving_power') - util.valueCheck(value, 0, 1E8, 'resolving_power') - self._resolving_power = value diff --git a/caom2tools/caom2/wcs/caom2_temporal_wcs.py b/caom2tools/caom2/wcs/caom2_temporal_wcs.py deleted file mode 100644 index 02338aeb..00000000 --- a/caom2tools/caom2/wcs/caom2_temporal_wcs.py +++ /dev/null @@ -1,205 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""The definition of the TemporalWCS class""" - - -from caom2_coord_axis1d import CoordAxis1D -from caom2.caom2_object import Caom2Object -from caom2.util import caom2_util as util - - -class TemporalWCS(Caom2Object): - """Describes the Time variation within the data. - - In the case of a single exposure, define the center of the first - pixel (0.5) as the MJD of the exposure and size of the pixel - as the exposure time.""" - - def __init__(self, - axis, - timesys=None, - trefpos=None, - mjdref=None, - exposure=None, - resolution=None - ): - - self.axis = axis - self.timesys = timesys - self.trefpos = trefpos - self.mjdref = mjdref - self.exposure = exposure - self.resolution = resolution - - @property - def axis(self): - """A CoordAxis1D object that describes the TemporalWCS transform. - - eg. CoordAxis1D(Axis) """ - return self._axis - - @axis.setter - def axis(self, value): - util.typeCheck(value, CoordAxis1D, 'axis', override=False) - self._axis = value - - @property - def timesys(self): - """The time scale that you are using, almost alwasy UTC. - - eg. timesys = "UTC" - type: str - """ - return self._timesys - - @timesys.setter - def timesys(self, value): - util.typeCheck(value, str, 'timesys') - self._timesys = value - - @property - def trefpos(self): - """ specifies the spatial location at which the time is valid, either - where the observation was made or the point in space for which - light-time corrections have been applied. - - eg. trefpos = "TOPOCENTER" - type: str - """ - return self._trefpos - - @trefpos.setter - def trefpos(self, value): - util.typeCheck(value, str, 'trefpos') - self._trefpos = value - - @property - def mjdref(self): - """The Modified Julian Date of the at the reference location of the - location of the TimeWCS (aka. pixel 0.5). Nominally this the start - of the exposure. - - Why 0.5? FITS: the middle of the first pixel - is defined as pixel value 1.0 so, the start of that pixel - is location 0.5 - - eg. mjdref = 567643.1234 - unit: d - type: float - """ - return self._mjdref - - @mjdref.setter - def mjdref(self, value): - util.typeCheck(value, float, 'mjdref') - ### set the limits to be after 1800 but before year 2050 - util.valueCheck(value, -22000, 70000, 'mjdref') - self._mjdref = value - - @property - def exposure(self): - """The median exposure time per pixel. - - The exposure time if this not a time cube you are describing. - - eg. exposure = 100.0 - unit: s - type: float - """ - return self._exposure - - @exposure.setter - def exposure(self, value): - util.typeCheck(value, float, "exposure") - util.valueCheck(value, 0, 30 * 24 * 3600.0, "exposure") - self._exposure = value - - @property - def resolution(self): - """the resolution of the time sampling available. - - Normally this is going to be the same as the exposure above, - but a stack of exposures taken over many months has a very - large value for resolution while the exposure value is just - the sum of the individual exposure times. - - - eg. resolution = 100.0s - unit: s - type: float - """ - return self._resolution - - @resolution.setter - def resolution(self, value): - util.typeCheck(value, float, 'resolution') - util.valueCheck(value, 0, 100 * 365 * 24 * 3600.0, "resolution") - self._resolution = value diff --git a/caom2tools/caom2/wcs/caom2_value_coord2d.py b/caom2tools/caom2/wcs/caom2_value_coord2d.py deleted file mode 100644 index 0467cd1f..00000000 --- a/caom2tools/caom2/wcs/caom2_value_coord2d.py +++ /dev/null @@ -1,102 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -"""definition of value 2D coord object""" - -from caom2.util import caom2_util as util -from caom2.caom2_object import Caom2Object - - -class ValueCoord2D(Caom2Object): - """Represents the reference point.""" - - def __init__(self, coord1, coord2): - self.coord1 = coord1 - self.coord2 = coord2 - - @property - def coord1(self): - """Coordinate 1""" - return self._coord1 - - @coord1.setter - def coord1(self, value): - util.typeCheck(value, float, 'coord1', override=False) - self._coord1 = value - - @property - def coord2(self): - """Coordinate 2""" - return self._coord2 - - @coord2.setter - def coord2(self, value): - util.typeCheck(value, float, 'coord2', override=False) - self._coord2 = value diff --git a/caom2tools/caom2/xml/__init__.py b/caom2tools/caom2/xml/__init__.py deleted file mode 100644 index d3720208..00000000 --- a/caom2tools/caom2/xml/__init__.py +++ /dev/null @@ -1,77 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines __init__ """ - -# from caom2_observation_reader import ObservationReader -# from caom2_observation_writer import ObservationWriter -# from caom2_xml_constants import CAOM20_NAMESPACE -# from caom2_xml_constants import CAOM21_NAMESPACE -# from caom2_xml_constants import CAOM22_NAMESPACE diff --git a/caom2tools/caom2/xml/caom2_observation_reader.py b/caom2tools/caom2/xml/caom2_observation_reader.py deleted file mode 100644 index 35140e5b..00000000 --- a/caom2tools/caom2/xml/caom2_observation_reader.py +++ /dev/null @@ -1,1394 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines ObservationReader class """ - -import uuid - -import pkg_resources -from lxml import etree - -import caom2_xml_constants -from .. caom2_algorithm import Algorithm -from .. caom2_artifact import Artifact -from .. caom2_chunk import Chunk -from .. caom2_composite_observation import CompositeObservation -from .. caom2_data_quality import DataQuality -from .. caom2_energy_transition import EnergyTransition -from .. caom2_enums import CalibrationLevel -from .. caom2_enums import DataProductType -from .. caom2_enums import ObservationIntentType -from .. caom2_enums import ProductType -from .. caom2_enums import Quality -from .. caom2_enums import Status -from .. caom2_enums import TargetType -from .. caom2_enums import ReleaseType -from .. caom2_composite_observation import CompositeObservation -from .. caom2_data_quality import DataQuality -from .. caom2_energy_transition import EnergyTransition -from .. caom2_environment import Environment -from .. caom2_exceptions import ObservationParsingException -from .. caom2_instrument import Instrument -from .. caom2_metrics import Metrics -from .. caom2_observation_uri import ObservationURI -from .. caom2_part import Part -from .. caom2_plane import Plane -from .. caom2_plane_uri import PlaneURI -from .. caom2_proposal import Proposal -from .. caom2_provenance import Provenance -from .. caom2_requirements import Requirements -from .. caom2_simple_observation import SimpleObservation -from .. caom2_target import Target -from .. caom2_target_position import TargetPosition -from .. caom2_telescope import Telescope -from .. types.caom2_point import Point -from .. util.caom2_util import long2uuid -from .. util.caom2_util import str2ivoa -from .. wcs.caom2_axis import Axis -from .. wcs.caom2_coord2d import Coord2D -from .. wcs.caom2_coord_axis1d import CoordAxis1D -from .. wcs.caom2_coord_axis2d import CoordAxis2D -from .. wcs.caom2_coord_bounds1d import CoordBounds1D -from .. wcs.caom2_coord_circle2d import CoordCircle2D -from .. wcs.caom2_coord_error import CoordError -from .. wcs.caom2_coord_function1d import CoordFunction1D -from .. wcs.caom2_coord_function2d import CoordFunction2D -from .. wcs.caom2_coord_polygon2d import CoordPolygon2D -from .. wcs.caom2_coord_range1d import CoordRange1D -from .. wcs.caom2_coord_range2d import CoordRange2D -from .. wcs.caom2_dimension2d import Dimension2D -from .. wcs.caom2_observable_axis import ObservableAxis -from .. wcs.caom2_polarization_wcs import PolarizationWCS -from .. wcs.caom2_ref_coord import RefCoord -from .. wcs.caom2_slice import Slice -from .. wcs.caom2_spatial_wcs import SpatialWCS -from .. wcs.caom2_spectral_wcs import SpectralWCS -from .. wcs.caom2_temporal_wcs import TemporalWCS -from .. wcs.caom2_value_coord2d import ValueCoord2D - - -class ObservationReader(object): - """ObservationReader """ - - def __init__(self, valididate=False): - """Constructor. XML Schema validation may be disabled, in which case - the client is likely to fail in horrible ways if it received invalid - documents. However, performance may be improved. - - Arguments: - validate : If True enable schema validation, False otherwise - """ - self._validate = valididate - - if self._validate: - caom20_schema_path = pkg_resources.resource_filename( - caom2_xml_constants.CAOM2_PKG, caom2_xml_constants.CAOM20_SCHEMA_FILE) - - parser = etree.XMLParser(remove_blank_text=True) - xsd = etree.parse(caom20_schema_path, parser) - - caom21_schema = etree.Element( - '{http://www.w3.org/2001/XMLSchema}import', - namespace=caom2_xml_constants.CAOM21_NAMESPACE, - schemaLocation=caom2_xml_constants.CAOM21_SCHEMA_FILE) - xsd.getroot().insert(1, caom21_schema) - - caom22_schema = etree.Element( - '{http://www.w3.org/2001/XMLSchema}import', - namespace=caom2_xml_constants.CAOM22_NAMESPACE, - schemaLocation=caom2_xml_constants.CAOM22_SCHEMA_FILE) - xsd.getroot().insert(2, caom22_schema) - - self._xmlschema = etree.XMLSchema(xsd) - - def _set_entity_attributes(self, element, ns, caom2_entity): - expect_uuid = True - if caom2_xml_constants.CAOM20_NAMESPACE == ns: - expect_uuid = False - - element_id = element.get("{" + ns + "}id") - element_last_modified = element.get("{" + ns + "}lastModified") - - if expect_uuid: - uid = uuid.UUID(element_id) - else: - uid = long2uuid(long(element_id)) - caom2_entity._id = uid - - if element_last_modified: - caom2_entity._last_modified = str2ivoa(element_last_modified) - - def _getChildElement(self, elTag, parent, ns, required): - for element in list(parent): - if element.tag == "{" + ns + "}" + elTag: - if not element.keys() and not element.text: - # element is empty, return None - return None - else: - # element has content, return it - return element - - if required: - error = elTag + " element not found in " + parent.tag - raise ObservationParsingException(error) - else: - return None - - def _getChildText(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return childElement.text - - def _getChildTextAsInt(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return int(childElement.text) - - def _getChildTextAsLong(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return long(childElement.text) - - def _getChildTextAsFloat(self, elTag, parent, ns, required): - childElement = self._getChildElement(elTag, parent, ns, required) - if childElement is None: - return None - else: - return float(childElement.text) - - def _getAlgorithm(self, elTag, parent, ns, required): - """Build an Algorithm object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the algorithm element - ns : namespace of the document - required : indicates whether the element is required - return : an Algorithm object or - None if the document does not contain an algorithm element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Algorithm(self._getChildText("name", el, ns, True)) - - def _getMetaRelease(self, elTag, parent, ns, required): - """Build a MetaRelease object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the MetaRelease element - ns : namespace of the document - required : indicates whether the element is required - return : a MetaRelease object or - None if the document does not contain a MetaRelease element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - # TODO: need to catch exceptions, - # what kind of exceptions are thrown? - return str2ivoa(el.text) - - def _getProposal(self, elTag, parent, ns, required): - """Build a Proposal object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Proposal element - ns : namespace of the document - required : indicates whether the element is required - return : a Proposal object or - None if the document does not contain a Proposal element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - proposal = Proposal(self._getChildText("id", el, ns, True)) - proposal.pi_name = self._getChildText("pi", el, ns, False) - proposal.project = self._getChildText("project", el, ns, False) - proposal.title = self._getChildText("title", el, ns, False) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - proposal.keywords.add(keyword) - return proposal - - def _getTarget(self, elTag, parent, ns, required): - """Build a Target object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Target element - ns : namespace of the document - required : indicates whether the element is required - return : a Target object or - None if the document does not contain a Target element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - target = Target(self._getChildText("name", el, ns, True)) - targetType = self._getChildText("type", el, ns, False) - if targetType: - target.target_type = TargetType.getByValue(targetType) - target.standard = ("true" == - self._getChildText("standard", el, ns, False)) - target.redshift = ( - self._getChildTextAsFloat("redshift", el, ns, False)) - target.moving = ("true" == - self._getChildText("moving", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - target.keywords.add(keyword) - return target - - def _getTargetPosition(self, elTag, parent, ns, required): - """Build a TargetPosition object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Target element - ns : namespace of the document - required : indicates whether the element is required - return : a TargetPosition object or - None if the document does not contain a TargetPosition element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - target_position = TargetPosition( - self._getPoint("coordinates", el, ns, True), - self._getChildText("coordsys", el, ns, True)) - target_position.equinox = ( - self._getChildTextAsFloat("equinox", el, ns, False)) - return target_position - - def _getRequirements(self, elTag, parent, ns, required): - """Build an Requirements object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Requirements element - ns : namespace of the document - required : indicates whether the element is required - return : a Requirements object or - None if the document does not contain an Requirements element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - flag = self._getChildText("flag", el, ns, True) - requirements = Requirements(Status.getByValue(flag)) - return requirements - - def _getTelescope(self, elTag, parent, ns, required): - """Build a Telescope object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Telescope element - ns : namespace of the document - required : indicates whether the element is required - return : a Telescope object or - None if the document does not contain a Telescope element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - telescope = Telescope(self._getChildText("name", el, ns, True)) - telescope.geo_location_x = ( - self._getChildTextAsFloat("geoLocationX", el, ns, False)) - telescope.geo_location_y = ( - self._getChildTextAsFloat("geoLocationY", el, ns, False)) - telescope.geo_location_z = ( - self._getChildTextAsFloat("geoLocationZ", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - telescope.keywords.add(keyword) - return telescope - - def _getInstrument(self, elTag, parent, ns, required): - """Build an Instrument object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Instrument element - ns : namespace of the document - required : indicates whether the element is required - return : a Instrument object or - None if the document does not contain an Instrument element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - instrument = Instrument(self._getChildText("name", el, ns, True)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - instrument.keywords.add(keyword) - return instrument - - def _getEnvironment(self, elTag, parent, ns, required): - """Build an Environment object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Environment element - ns : namespace of the document - required : indicates whether the element is required - return : a Environment object or - None if the document does not contain an Environment element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - environment = Environment() - environment.seeing = ( - self._getChildTextAsFloat("seeing", el, ns, False)) - environment.humidity = ( - self._getChildTextAsFloat("humidity", el, ns, False)) - environment.elevation = ( - self._getChildTextAsFloat("elevation", el, ns, False)) - environment.tau = ( - self._getChildTextAsFloat("tau", el, ns, False)) - environment.wavelength_tau = ( - self._getChildTextAsFloat("wavelengthTau", el, ns, False)) - environment.ambient_temp = ( - self._getChildTextAsFloat("ambientTemp", el, ns, False)) - environment.photometric = ("true" == - self._getChildText("photometric", el, ns, False)) - return environment - - def _addMembers(self, members, parent, ns): - """Create ObservationURI objects from an XML representation of - ObservationURI elements found in members element, and add them to the - set of ObservationURI's - - Arguments: - members : Set of member's from the parent Observation object - parent : element containing the Environment element - ns : namespace of the document - return : an Environment object or - None if the document does not contain an Environment element - raise : ObservationParsingException - """ - el = self._getChildElement("members", parent, ns, False) - if el is not None: - for memberEl in el.iterchildren("{" + ns + "}observationURI"): - members.add(ObservationURI(memberEl.text)) - - if not members: - error = "No observationURI element found in members" - raise ObservationParsingException(error) - - def _addInputs(self, inputs, parent, ns): - """Create PlaneURI objects from an XML representation of the planeURI - elements and add them to the set of PlaneURIs. - - Arguments: - inputs : set of PlaneURI from the Provenance - parent : element containing the PlaneURI elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("inputs", parent, ns, False) - if el is not None: - for uriEl in el.iterchildren("{" + ns + "}planeURI"): - inputs.add(PlaneURI(uriEl.text)) - - if not inputs: - error = "No planeURI element found in members" - raise ObservationParsingException(error) - - def _getProvenance(self, elTag, parent, ns, required): - """Build a Provenance object from an XML representation of a - Provenance element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Provenance element - ns : namespace of the document - required : indicates whether the element is required - return : a Provenance object or - None if the document does not contain a Provenance element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - prov = Provenance(self._getChildText("name", el, ns, True)) - prov.version = self._getChildText("version", el, ns, False) - prov.project = self._getChildText("project", el, ns, False) - prov.producer = self._getChildText("producer", el, ns, False) - prov.run_id = self._getChildText("runID", el, ns, False) - reference = self._getChildText("reference", el, ns, False) - if reference: - prov.reference = reference - prov.last_executed = str2ivoa( - self._getChildText("lastExecuted", el, ns, False)) - keywords = self._getChildText("keywords", el, ns, False) - if keywords is not None: - for keyword in keywords.split(): - prov.keywords.add(keyword) - self._addInputs(prov.inputs, el, ns) - return prov - - def _getMetrics(self, elTag, parent, ns, required): - """Build a Metrics object from an XML representation of a - Metrics element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Metrics element - ns : namespace of the document - required : indicates whether the element is required - return : a Metrics object or - None if the document does not contain a Metrics element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - metrics = Metrics() - metrics.source_number_density = \ - self._getChildTextAsFloat("sourceNumberDensity", el, ns, False) - metrics.background = \ - self._getChildTextAsFloat("background", el, ns, False) - metrics.background_std_dev = \ - self._getChildTextAsFloat("backgroundStddev", el, ns, False) - metrics.flux_density_limit = \ - self._getChildTextAsFloat("fluxDensityLimit", el, ns, False) - metrics.mag_limit = \ - self._getChildTextAsFloat("magLimit", el, ns, False) - return metrics - - def _getQuality(self, elTag, parent, ns, required): - """Build an Quality object from an XML representation - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Quality element - ns : namespace of the document - required : indicates whether the element is required - return : a Quality object or - None if the document does not contain an Quality element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - flag = self._getChildText("flag", el, ns, True) - dataQuality = DataQuality(Quality.getByValue(flag)) - return dataQuality - - def _getPoint(self, elTag, parent, ns, required): - """Build an Point object from an XML representation - of an Point element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Point element - ns : namespace of the document - required : indicate whether the element is required - return : an Point object or - None if the document does not contain an Point element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Point(self._getChildTextAsFloat("cval1", el, ns, True), - self._getChildTextAsFloat("cval2", el, ns, True)) - - def _getAxis(self, elTag, parent, ns, required): - """Build an Axis object from an XML representation of an Axis element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Axis element - ns : namespace of the document - required : indicate whether the element is required - return : an Axis object or - None if the document does not contain an Axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Axis(self._getChildText("ctype", el, ns, True), - self._getChildText("cunit", el, ns, False)) - - def _getSlice(self, elTag, parent, ns, required): - """Build a Slice object from an XML representation of a Slice element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Slice element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Slice object or - None if the document does not contain a Slice element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Slice(self._getAxis("axis", el, ns, True), - self._getChildTextAsLong("bin", el, ns, True)) - - def _getObservableAxis(self, elTag, parent, ns, required): - """Build an ObservableAxis object from an XML representation of an - observable element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the Observable element - ns : namespace of the document - required : boolean indicating whether the element is required - return : an ObservableAxis object or - None if the document does not contain an Observable element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - observable = ObservableAxis( - self._getSlice("dependent", el, ns, True)) - observable.independent = \ - self._getSlice("independent", el, ns, False) - return observable - - def _getCoordError(self, elTag, parent, ns, required): - """Build a CoordError object from an XML representation of an error - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the error element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordError object or - None if the document does not contain an error element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordError( - self._getChildTextAsFloat("syser", el, ns, True), - self._getChildTextAsFloat("rnder", el, ns, True)) - - def _getRefCoord(self, elTag, parent, ns, required): - """Build a RefCoord object from an XML representation of a coord - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a RefCoord object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return RefCoord( - self._getChildTextAsFloat("pix", el, ns, True), - self._getChildTextAsFloat("val", el, ns, True)) - - def _getCoord2D(self, elTag, parent, ns, required): - """Build a Coord2D object from an XML representation of a coord - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Coord2D object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Coord2D( - self._getRefCoord("coord1", el, ns, True), - self._getRefCoord("coord2", el, ns, True)) - - def _getValueCoord2D(self, elTag, parent, ns, required): - """Build a ValueCoord2D object from an XML representation of a - value coord element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the coord element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a ValueCoord2D object or - None if the document does not contain a coord element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return ValueCoord2D( - self._getChildTextAsFloat("coord1", el, ns, True), - self._getChildTextAsFloat("coord2", el, ns, True)) - - def _getCoordRange2D(self, elTag, parent, ns, required): - """Build a CoordRange2D object from an XML representation of a range - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the range element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordRange2D object or - None if the document does not contain a range element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordRange2D( - self._getCoord2D("start", el, ns, True), - self._getCoord2D("end", el, ns, True)) - - def _getCoordCircle2D(self, elTag, parent, ns, required): - """Build a CoordCircle2D object from an XML representation of a circle - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the circle element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordCircle2D object or - None if the document does not contain a circle element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordCircle2D( - self._getValueCoord2D("center", el, ns, True), - self._getChildTextAsFloat("radius", el, ns, True)) - - def _getCoordPolygon2D(self, elTag, parent, ns, required): - """Build a CoordPolygon2D object from an XML representation - of a polygon element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the polygon element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordPolygon2D object or - None if the document does not contain a polygon element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - verticeEl = self._getChildElement("vertices", el, ns, True) - childrenVertices = list( - verticeEl.iterchildren(tag=("{" + ns + "}vertex"))) - if len(childrenVertices) < 3: - error = ("CoordPolygon2D must have a minimum of 3 vertices, " - "found " + len(childrenVertices)) - raise ObservationParsingException(error) - else: - polygon = CoordPolygon2D() - for childVertexEl in childrenVertices: - polygon.vertices.append(ValueCoord2D( - self._getChildTextAsFloat( - "coord1", childVertexEl, ns, True), - self._getChildTextAsFloat( - "coord2", childVertexEl, ns, True))) - return polygon - - def _getCoordBounds2D(self, elTag, parent, ns, required): - """Build a CoordBounds2D object from an XML representation of a bounds - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the bounds element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordBounds2D object or - None if the document does not contain a bounds element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - circle = self._getCoordCircle2D("circle", el, ns, False) - if circle is not None: - return circle - else: - polygon = self._getCoordPolygon2D("polygon", el, ns, False) - if polygon is not None: - return polygon - else: - error = "Unsupported element not found in " + elTag + \ - ": " + el.getText() - raise ObservationParsingException(error) - - def _getDimension2D(self, elTag, parent, ns, required): - """Build a Dimension2D object from an XML representation of a dimension - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the dimension element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a Dimention2D object or - None if the document does not contain a dimension element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return Dimension2D( - self._getChildTextAsLong("naxis1", el, ns, True), - self._getChildTextAsLong("naxis2", el, ns, True)) - - def _getCoordFunction2D(self, elTag, parent, ns, required): - """Build a CoordFunction2D object from an XML representation of a - function element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the function element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordFunction2D object or - None if the document does not contain a function element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordFunction2D( - self._getDimension2D("dimension", el, ns, True), - self._getCoord2D("refCoord", el, ns, True), - self._getChildTextAsFloat("cd11", el, ns, True), - self._getChildTextAsFloat("cd12", el, ns, True), - self._getChildTextAsFloat("cd21", el, ns, True), - self._getChildTextAsFloat("cd22", el, ns, True)) - - def _getCoordAxis2D(self, elTag, parent, ns, required): - """Build a CoordAxis2D object from an XML representation of an axis - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the axis element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordAxis2D object or - None if the document does not contain an axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - axis = CoordAxis2D(self._getAxis("axis1", el, ns, True), - self._getAxis("axis2", el, ns, True)) - axis.error1 = self._getCoordError("error1", el, ns, False) - axis.error2 = self._getCoordError("error2", el, ns, False) - axis.range = self._getCoordRange2D("range", el, ns, False) - axis.bounds = self._getCoordBounds2D("bounds", el, ns, False) - axis.function = self._getCoordFunction2D("function", el, ns, False) - return axis - - def _getSpatialWCS(self, elTag, parent, ns, required): - """Build a SpatialWCS object from an XML representation of a position - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a SpatialWCS object or - None if the document does not contain a position element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - position = SpatialWCS(self._getCoordAxis2D("axis", el, ns, False)) - position.coordsys = self._getChildText("coordsys", el, ns, False) - position.equinox = \ - self._getChildTextAsFloat("equinox", el, ns, False) - position.resolution = \ - self._getChildTextAsFloat("resolution", el, ns, False) - return position - - def _addChildrenToCoordRange1DList(self, elTag, ranges, parent, ns, - required): - """Create CoordRange1D objects from an XML representation of the - range elements and add them to the set of ranges. - - Arguments: - elTag : element tag which identifies the element - ranges : reference to set of ranges - parent : element containing the ranges elements - ns : namespace of the document - required : boolean indicating whether the element is required - """ - for rangeEl in parent.iterchildren("{" + ns + "}" + elTag): - ranges.append(CoordRange1D( - self._getRefCoord("start", rangeEl, ns, True), - self._getRefCoord("end", rangeEl, ns, True))) - - def _getCoordBounds1D(self, elTag, parent, ns, required): - """Build a CoordBounds1D object from an XML representation of a bounds - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the bounds element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordBounds1D object or - None if the document does not contain a bounds element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - coordBounds1D = CoordBounds1D() - samplesEl = self._getChildElement("samples", el, ns, False) - if samplesEl is not None: - self._addChildrenToCoordRange1DList( - "range", coordBounds1D.samples, samplesEl, ns, False) - return coordBounds1D - - def _getCoordRange1D(self, elTag, parent, ns, required): - """Build a CoordRange1D object from an XML representation of a range - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the range element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordRange1D object or - None if the document does not contain a range element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordRange1D( - self._getRefCoord("start", el, ns, True), - self._getRefCoord("end", el, ns, True)) - - def _getCoordFunction1D(self, elTag, parent, ns, required): - """Build a CoordFunction1D object from an XML representation of a - function element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the function element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordFunction1D object or - None if the document does not contain a function element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return CoordFunction1D( - self._getChildTextAsLong("naxis", el, ns, True), - self._getChildTextAsFloat("delta", el, ns, True), - self._getRefCoord("refCoord", el, ns, True)) - - def _getCoordAxis1D(self, elTag, parent, ns, required): - """Build a CoordAxis1D object from an XML representation of an axis - element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the axis element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a CoordAxis1D object or - None if the document does not contain an axis element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - axis = CoordAxis1D(self._getAxis("axis", el, ns, True)) - axis.error = self._getCoordError("error", el, ns, False) - axis.range = self._getCoordRange1D("range", el, ns, False) - axis.bounds = self._getCoordBounds1D("bounds", el, ns, False) - axis.function = self._getCoordFunction1D("function", el, ns, False) - return axis - - def _getTransition(self, elTag, parent, ns, required): - """Build an EnergyTransition object from an XML representation of - a transition element. - - Arguments: - elTag : element tag which identifies the element - parent : element containing the transition element - ns : namespace of the document - required : boolean indicating whether the element is reuiqred - return : an EnergyTransition object or - None if the document does not contain a transition element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return EnergyTransition( - self._getChildText("species", el, ns, True), - self._getChildText("transition", el, ns, True)) - - def _getSpectralWCS(self, elTag, parent, ns, required): - """Build a SpectralWCS object from an XML representation of an energy - element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a SpectralWCS object or - None if the document does not contain an energy element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - energy = SpectralWCS( - self._getCoordAxis1D("axis", el, ns, True), - self._getChildText("specsys", el, ns, True)) - energy.ssysobs = \ - self._getChildText("ssysobs", el, ns, False) - energy.ssyssrc = \ - self._getChildText("ssyssrc", el, ns, False) - energy.restfrq = \ - self._getChildTextAsFloat("restfrq", el, ns, False) - energy.restwav = \ - self._getChildTextAsFloat("restwav", el, ns, False) - energy.velosys = \ - self._getChildTextAsFloat("velosys", el, ns, False) - energy.zsource = \ - self._getChildTextAsFloat("zsource", el, ns, False) - energy.velang = \ - self._getChildTextAsFloat("velang", el, ns, False) - energy.bandpass_name = \ - self._getChildText("bandpassName", el, ns, False) - energy.resolving_power = \ - self._getChildTextAsFloat("resolvingPower", el, ns, False) - energy.transition = \ - self._getTransition("transition", el, ns, False) - return energy - - def _getTemporalWCS(self, elTag, parent, ns, required): - """Build a TemporalWCS object from an XML representation of an time - element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a TemporalWCS object or - None if the document does not contain an time element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - time = TemporalWCS( - self._getCoordAxis1D("axis", el, ns, True)) - time.timesys = \ - self._getChildText("timesys", el, ns, False) - time.trefpos = \ - self._getChildText("trefpos", el, ns, False) - time.mjdref = \ - self._getChildTextAsFloat("mjdref", el, ns, False) - time.exposure = \ - self._getChildTextAsFloat("exposure", el, ns, False) - time.resolution = \ - self._getChildTextAsFloat("resolution", el, ns, False) - return time - - def _getPolarizationWCS(self, elTag, parent, ns, required): - """Build a PolarizationWCS object from an XML representation of a - polarization element. - - Arguments: - elTag : element tag which indentifies the element - parent : element containing the position element - ns : namespace of the document - required : boolean indicating whether the element is required - return : a PolarizationWCS object or - None if the document does not contain an polarization element - raise : ObservationParsingException - """ - el = self._getChildElement(elTag, parent, ns, required) - if el is None: - return None - else: - return PolarizationWCS( - self._getCoordAxis1D("axis", el, ns, False)) - - def _addChunks(self, chunks, parent, ns): - """Build Chunk objects from an XML representation of Chunk elements - and add them to the set of Chunks. - - Argument: - chunks : set of Chunk objects from the Part - parent : element containing the Chunk elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("chunks", parent, ns, False) - if el is None: - return None - else: - for chunkEl in el.iterchildren("{" + ns + "}chunk"): - tempChunk = Chunk() - productType = \ - self._getChildText("productType", chunkEl, ns, False) - if productType: - tempChunk.product_type = \ - ProductType.getByValue(productType) - tempChunk.naxis = \ - self._getChildTextAsInt("naxis", chunkEl, ns, False) - tempChunk.observable_axis = \ - self._getChildTextAsInt("observableAxis", chunkEl, ns, - False) - tempChunk.position_axis_1 = \ - self._getChildTextAsInt("positionAxis1", chunkEl, ns, - False) - tempChunk.position_axis_2 = \ - self._getChildTextAsInt("positionAxis2", chunkEl, ns, - False) - tempChunk.energy_axis = \ - self._getChildTextAsInt("energyAxis", chunkEl, ns, False) - tempChunk.time_axis = \ - self._getChildTextAsInt("timeAxis", chunkEl, ns, False) - tempChunk.polarization_axis = \ - self._getChildTextAsInt("polarizationAxis", chunkEl, ns, - False) - tempChunk.observable = \ - self._getObservableAxis("observable", chunkEl, ns, False) - tempChunk.position = \ - self._getSpatialWCS("position", chunkEl, ns, False) - tempChunk.energy = \ - self._getSpectralWCS("energy", chunkEl, ns, False) - tempChunk.time = \ - self._getTemporalWCS("time", chunkEl, ns, False) - tempChunk.polarization = \ - self._getPolarizationWCS("polarization", chunkEl, ns, - False) - self._set_entity_attributes(chunkEl, ns, tempChunk) - chunks.append(tempChunk) - - def _addParts(self, parts, parent, ns): - """Build Part objects from an XML representation of Part elements and - add them to the set of Parts. - - Argument: - parts : set of Part objects from the Artifact - parent : element containing the Part elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("parts", parent, ns, False) - if el is None: - return None - else: - for partEl in el.iterchildren("{" + ns + "}part"): - tempPart = \ - Part(self._getChildText("name", partEl, ns, True)) - productType = \ - self._getChildText("productType", partEl, ns, False) - if productType: - tempPart.product_type = \ - ProductType.getByValue(productType) - self._addChunks(tempPart.chunks, partEl, ns) - self._set_entity_attributes(partEl, ns, tempPart) - parts[tempPart.name] = tempPart - - def _addArtifacts(self, artifacts, parent, ns): - """Build artifacts from an XML representation of the artifact elements - and add them to the set of Artifacts. - - Arguments: - artifacts : set of Artifacts from the Plane - parent : element containing the Artifact elements - ns : namespace fo the document - raise : ObservationParsingException - """ - el = self._getChildElement("artifacts", parent, ns, False) - if el is None: - return None - else: - for artifactEl in el.iterchildren("{" + ns + "}artifact"): - uri = self._getChildText("uri", artifactEl, ns, True) - - product_type = self._getChildText("productType", artifactEl, ns, False) - if product_type is None: - product_type = ProductType.SCIENCE - print "Using default Artifact.productType value {0}".format(str(ProductType.SCIENCE)) - else: - product_type = ProductType.getByValue(product_type) - - release_type = self._getChildText("releaseType", artifactEl, ns, False) - if release_type is None: - release_type = ReleaseType.DATA - print "Using default Artifact.releaseType value {0}".format(str(ReleaseType.DATA)) - else: - release_type = ReleaseType.getByValue(release_type) - - tempArtifact = Artifact(uri, product_type, release_type) - tempArtifact.content_type = self._getChildText("contentType", artifactEl, ns, False) - tempArtifact.content_length = ( - self._getChildTextAsLong("contentLength", artifactEl, ns, False)) - self._addParts(tempArtifact.parts, artifactEl, ns) - self._set_entity_attributes(artifactEl, ns, tempArtifact) - artifacts[tempArtifact.uri] = tempArtifact - - def _addPlanes(self, planes, parent, ns): - """Create Planes object from XML representation of Plane elements - and add them to the set of Planes. - - Arguments: - planes : Set of planes from the parent Observation object - parent : element containing the Plane elements - ns : namespace of the document - raise : ObservationParsingException - """ - el = self._getChildElement("planes", parent, ns, False) - if el is None: - return None - else: - for planeEl in el.iterchildren("{" + ns + "}plane"): - tempPlane = Plane( - self._getChildText("productID", planeEl, ns, True)) - tempPlane.meta_release = str2ivoa( - self._getChildText("metaRelease", planeEl, ns, False)) - tempPlane.data_release = str2ivoa( - self._getChildText("dataRelease", planeEl, ns, False)) - dataProductType = \ - self._getChildText("dataProductType", planeEl, ns, False) - if dataProductType: - tempPlane.data_product_type = \ - DataProductType.getByValue(dataProductType) - calibrationLevel = \ - self._getChildText("calibrationLevel", planeEl, ns, False) - if calibrationLevel: - tempPlane.calibration_level = \ - CalibrationLevel.getByValue(int(calibrationLevel)) - tempPlane.provenance = \ - self._getProvenance("provenance", planeEl, ns, False) - tempPlane.metrics = \ - self._getMetrics("metrics", planeEl, ns, False) - tempPlane.quality = \ - self._getQuality("quality", planeEl, ns, False) - self._addArtifacts(tempPlane.artifacts, planeEl, ns) - self._set_entity_attributes(planeEl, ns, tempPlane) - planes[tempPlane.product_id] = tempPlane - - if not planes: - error = "No plane element found in planes" - raise ObservationParsingException(error) - - def read(self, source): - """Build an Observation object from an XML document located in source. - Source an be a file name/path, a file object, a file-like object or a - URL using the HTTP or FTP protocol. - - Arguments: - source : source of XML document containing an Observation element - return : an Observation object - raise : ObservationParsingException - """ - doc = etree.parse(source) - if self._validate and self._xmlschema: - self._xmlschema.assertValid(doc) - root = doc.getroot() - ns = root.nsmap["caom2"] - collection = self._getChildElement("collection", root, ns, True).text - observationID = \ - self._getChildElement("observationID", root, ns, True).text - # Instantiate Algorithm - algorithm = self._getAlgorithm("algorithm", root, ns, True) - # Instantiate Observation - if root.get("{http://www.w3.org/2001/XMLSchema-instance}type") \ - == "caom2:SimpleObservation": - observation = SimpleObservation(collection, observationID) - observation.algorithm = algorithm - else: - observation = \ - CompositeObservation(collection, observationID, algorithm) - # Instantiate children of Observation - observation.sequence_number = \ - self._getChildTextAsInt("sequenceNumber", root, ns, False) - observation.obs_type = \ - self._getChildText("type", root, ns, False) - intent = self._getChildText("intent", root, ns, False) - if intent: - observation.intent = ObservationIntentType.getByValue(intent) - observation.meta_release = \ - self._getMetaRelease("metaRelease", root, ns, False) - observation.proposal = \ - self._getProposal("proposal", root, ns, False) - observation.target = \ - self._getTarget("target", root, ns, False) - observation.target_position = \ - self._getTargetPosition("targetPosition", root, ns, False) - observation.telescope = \ - self._getTelescope("telescope", root, ns, False) - observation.instrument = \ - self._getInstrument("instrument", root, ns, False) - observation.environment = \ - self._getEnvironment("environment", root, ns, False) - observation.requirements = \ - self._getRequirements("requirements", root, ns, False) - self._addPlanes(observation.planes, root, ns) - if isinstance(observation, CompositeObservation): - self._addMembers(observation.members, root, ns) - - self._set_entity_attributes(root, ns, observation) - return observation - -if __name__ == '__main__': - reader = ObservationReader(True) - reader.read('../../../../test/data/CompleteCompositePolygon.xml') diff --git a/caom2tools/caom2/xml/caom2_observation_writer.py b/caom2tools/caom2/xml/caom2_observation_writer.py deleted file mode 100644 index 4a53e2c0..00000000 --- a/caom2tools/caom2/xml/caom2_observation_writer.py +++ /dev/null @@ -1,737 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines ObservationWriter class """ - -from lxml import etree -import pkg_resources -import caom2_xml_constants -from .. caom2_observation import Observation -from .. caom2_composite_observation import CompositeObservation -from .. caom2_simple_observation import SimpleObservation -from .. wcs.caom2_coord_circle2d import CoordCircle2D -from .. wcs.caom2_coord_polygon2d import CoordPolygon2D -from .. caom2_enums import CalibrationLevel -from .. caom2_enums import DataProductType -from .. caom2_enums import ObservationIntentType -from .. caom2_enums import ProductType -from .. caom2_enums import Quality -from .. caom2_enums import Status -from .. caom2_enums import TargetType -from .. caom2_enums import ReleaseType -from .. util.caom2_util import date2ivoa -from .. util.caom2_util import uuid2long - - -class ObservationWriter(object): - """ ObservationWriter """ - - def __init__(self, validate=False, write_empty_collections=False, - namespace_prefix="caom2", namespace=None): - """ - Arguments: - validate : If True enable schema validation, False otherwise - write_empty_collections : if True write empty elements for empty collections - namespace_prefix : a CAOM-2.x namespace prefix - namespace : a valid CAOM-2.x target namespace - """ - self._validate = validate - self._write_empty_collections = write_empty_collections - - if namespace_prefix is None or not namespace_prefix: - raise RuntimeError('null or empty namespace_prefix not allowed') - - if namespace is None or namespace == caom2_xml_constants.CAOM22_NAMESPACE: - self._output_version = 22 - self._caom2_namespace = caom2_xml_constants.CAOM22 - self._namespace = caom2_xml_constants.CAOM22_NAMESPACE - elif namespace == caom2_xml_constants.CAOM21_NAMESPACE: - self._output_version = 21 - self._caom2_namespace = caom2_xml_constants.CAOM21 - self._namespace = caom2_xml_constants.CAOM21_NAMESPACE - elif namespace == caom2_xml_constants.CAOM20_NAMESPACE: - self._output_version = 20 - self._caom2_namespace = caom2_xml_constants.CAOM20 - self._namespace = caom2_xml_constants.CAOM20_NAMESPACE - else: - raise RuntimeError('invalid namespace {}'.format(namespace)) - - if self._validate: - if self._output_version == 20: - schema_file = caom2_xml_constants.CAOM20_SCHEMA_FILE - elif self._output_version == 21: - schema_file = caom2_xml_constants.CAOM21_SCHEMA_FILE - else: - schema_file = caom2_xml_constants.CAOM22_SCHEMA_FILE - schema_path = pkg_resources.resource_filename( - caom2_xml_constants.CAOM2_PKG, schema_file) - xmlschema_doc = etree.parse(schema_path) - self._xmlschema = etree.XMLSchema(xmlschema_doc) - - self._nsmap = {namespace_prefix: self._namespace, "xsi": caom2_xml_constants.XSI_NAMESPACE} - - def write(self, observation, out): - assert isinstance(observation, Observation), ( - "observation is not an Observation") - - obs = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) - if isinstance(observation, SimpleObservation): - obs.set(caom2_xml_constants.XSI + "type", "caom2:SimpleObservation") - else: - obs.set(caom2_xml_constants.XSI + "type", "caom2:CompositeObservation") - - self._addEnityAttributes(observation, obs) - - self._addElement("collection", observation.collection, obs) - self._addElement("observationID", observation.observation_id, obs) - self._addDatetimeElement("metaRelease", observation.meta_release, obs) - self._addElement("sequenceNumber", observation.sequence_number, obs) - self._addAlgorithmElement(observation.algorithm, obs) - self._addElement("type", observation.obs_type, obs) - if observation.intent is not None: - self._addElement( - "intent", ObservationIntentType.get(str(observation.intent)).value, obs) - - self._addProposalElement(observation.proposal, obs) - self._addTargetElement(observation.target, obs) - self._addTargetPositionElement(observation.target_position, obs) - self._addRequirementsElement(observation.requirements, obs) - self._addTelescopeElement(observation.telescope, obs) - self._addInstrumentElement(observation.instrument, obs) - self._addEnvironmentElement(observation.environment, obs) - self._addPlanesElement(observation.planes, obs) - - if isinstance(observation, CompositeObservation): - self._addMembersElement(observation.members, obs) - - if self._validate and self._xmlschema: - self._xmlschema.assertValid(obs) - - out.write(etree.tostring(obs, xml_declaration=True, encoding='UTF-8', - pretty_print=True)) - - def _addEnityAttributes(self, entity, element): - if self._output_version == 20: - uid = uuid2long(entity._id) - self._addAttribute("id", str(uid), element) - else: - self._addAttribute("id", str(entity._id), element) - - if entity._last_modified is not None: - self._addAttribute( - "lastModified", date2ivoa(entity._last_modified), element) - - def _addAlgorithmElement(self, algorithm, parent): - if algorithm is None: - return - - element = self._getCaom2Element("algorithm", parent) - self._addElement("name", algorithm.name, element) - - def _addProposalElement(self, proposal, parent): - if proposal is None: - return - - element = self._getCaom2Element("proposal", parent) - self._addElement("id", proposal.proposal_id, element) - self._addElement("pi", proposal.pi_name, element) - self._addElement("project", proposal.project, element) - self._addElement("title", proposal.title, element) - self._addListElement("keywords", proposal.keywords, element) - - def _addTargetElement(self, target, parent): - if target is None: - return - - element = self._getCaom2Element("target", parent) - self._addElement("name", target.name, element) - if target.target_type is not None: - self._addElement( - "type", TargetType.get(str(target.target_type)).value, element) - if target.standard is not None: - self._addElement("standard", str(target.standard).lower(), element) - self._addElement("redshift", target.redshift, element) - if target.moving is not None: - self._addElement("moving", str(target.moving).lower(), element) - self._addListElement("keywords", target.keywords, element) - - def _addTargetPositionElement(self, target_position, parent): - if target_position is None: - return - - element = self._getCaom2Element("targetPosition", parent) - self._addElement("coordsys", target_position.coordsys, element) - if target_position.equinox is not None: - self._addElement("equinox", target_position.equinox, element) - self._addPointElement("coordinates", target_position.coordinates, - element) - - def _addRequirementsElement(self, requirements, parent): - if self._output_version < 21: - return # Requirements added in CAOM-2.1 - if requirements is None: - return - - element = self._getCaom2Element("requirements", parent) - self._addElement( - "flag", Status.get(str(requirements.flag)).value, element) - - def _addTelescopeElement(self, telescope, parent): - if telescope is None: - return - - element = self._getCaom2Element("telescope", parent) - self._addElement("name", telescope.name, element) - self._addElement("geoLocationX", telescope.geo_location_x, element) - self._addElement("geoLocationY", telescope.geo_location_y, element) - self._addElement("geoLocationZ", telescope.geo_location_z, element) - self._addListElement("keywords", telescope.keywords, element) - - def _addInstrumentElement(self, instrument, parent): - if instrument is None: - return - - element = self._getCaom2Element("instrument", parent) - self._addElement("name", instrument.name, element) - self._addListElement("keywords", instrument.keywords, element) - - def _addEnvironmentElement(self, environment, parent): - if environment is None: - return - - element = self._getCaom2Element("environment", parent) - self._addElement("seeing", environment.seeing, element) - self._addElement("humidity", environment.humidity, element) - self._addElement("elevation", environment.elevation, element) - self._addElement("tau", environment.tau, element) - self._addElement("wavelengthTau", environment.wavelength_tau, element) - self._addElement("ambientTemp", environment.ambient_temp, element) - if environment.photometric is not None: - self._addElement("photometric", - str(environment.photometric).lower(), element) - - def _addMembersElement(self, members, parent): - if members is None or \ - (len(members) == 0 and not self._write_empty_collections): - return - - element = self._getCaom2Element("members", parent) - for member in members: - memberElement = self._getCaom2Element("observationURI", element) - memberElement.text = member.uri - - def _addPlanesElement(self, planes, parent): - if planes is None or \ - (len(planes) == 0 and not self._write_empty_collections): - return - - element = self._getCaom2Element("planes", parent) - for plane in planes.itervalues(): - planeElement = self._getCaom2Element("plane", element) - self._addEnityAttributes(plane, planeElement) - self._addElement("productID", plane.product_id, planeElement) - self._addDatetimeElement("metaRelease", plane.meta_release, - planeElement) - self._addDatetimeElement("dataRelease", plane.data_release, - planeElement) - if plane.data_product_type is not None: - self._addElement("dataProductType", - DataProductType.get(str(plane.data_product_type)).value, - planeElement) - if plane.calibration_level is not None: - self._addElement("calibrationLevel", - CalibrationLevel(str(plane.calibration_level)).value, - planeElement) - self._addProvenanceElement(plane.provenance, planeElement) - self._addMetricsElement(plane.metrics, planeElement) - self._addQualityElement(plane.quality, planeElement) - self._addArtifactsElement(plane.artifacts, planeElement) - - def _addProvenanceElement(self, provenance, parent): - if provenance is None: - return - - element = self._getCaom2Element("provenance", parent) - self._addElement("name", provenance.name, element) - self._addElement("version", provenance.version, element) - self._addElement("project", provenance.project, element) - self._addElement("producer", provenance.producer, element) - self._addElement("runID", provenance.run_id, element) - self._addElement("reference", provenance.reference, element) - self._addDatetimeElement("lastExecuted", provenance.last_executed, - element) - self._addListElement("keywords", provenance.keywords, element) - self._addInputsElement("inputs", provenance.inputs, element) - - def _addMetricsElement(self, metrics, parent): - if metrics is None: - return - - element = self._getCaom2Element("metrics", parent) - self._addElement("sourceNumberDensity", metrics.source_number_density, - element) - self._addElement("background", metrics.background, element) - self._addElement("backgroundStddev", metrics.background_std_dev, - element) - self._addElement("fluxDensityLimit", metrics.flux_density_limit, - element) - self._addElement("magLimit", metrics.mag_limit, element) - - def _addQualityElement(self, quality, parent): - if self._output_version < 21: - return # Requirements added in CAOM-2.1 - if quality is None: - return - - element = self._getCaom2Element("quality", parent) - self._addElement( - "flag", Quality.get(str(quality.flag)).value, element) - - def _addTransitionElement(self, transition, parent): - if transition is None: - return - - element = self._getCaom2Element("transition", parent) - self._addElement("species", transition.species, element) - self._addElement("transition", transition.transition, element) - - def _addArtifactsElement(self, artifacts, parent): - if artifacts is None: - return - - element = self._getCaom2Element("artifacts", parent) - for artifact in artifacts.itervalues(): - artifactElement = self._getCaom2Element("artifact", element) - self._addEnityAttributes(artifact, artifactElement) - self._addElement("uri", artifact.uri, artifactElement) - if self._output_version > 21: - self._addElement("productType", ProductType.get(str(artifact.product_type)).value, artifactElement) - self._addElement("releaseType", ReleaseType.get(str(artifact.release_type)).value, artifactElement) - self._addElement("contentType", artifact.content_type, artifactElement) - self._addElement("contentLength", artifact.content_length, artifactElement) - if self._output_version < 22: - self._addElement("productType", ProductType.get(str(artifact.product_type)).value, artifactElement) - self._addPartsElement(artifact.parts, artifactElement) - - def _addPartsElement(self, parts, parent): - if parts is None: - return - - element = self._getCaom2Element("parts", parent) - for part in parts.itervalues(): - partElement = self._getCaom2Element("part", element) - self._addEnityAttributes(part, partElement) - self._addElement("name", part.name, partElement) - if part.product_type is not None: - self._addElement("productType", - ProductType.get(str(part.product_type)).value, partElement) - self._addChunksElement(part.chunks, partElement) - - def _addChunksElement(self, chunks, parent): - if chunks is None: - return - - element = self._getCaom2Element("chunks", parent) - for chunk in chunks: - chunkElement = self._getCaom2Element("chunk", element) - self._addEnityAttributes(chunk, chunkElement) - if chunk.product_type is not None: - self._addElement("productType", - ProductType.get(str(chunk.product_type)).value, - chunkElement) - self._addElement("naxis", chunk.naxis, chunkElement) - self._addElement("observableAxis", chunk.observable_axis, - chunkElement) - self._addElement("positionAxis1", chunk.position_axis_1, - chunkElement) - self._addElement("positionAxis2", chunk.position_axis_2, - chunkElement) - self._addElement("energyAxis", chunk.energy_axis, chunkElement) - self._addElement("timeAxis", chunk.time_axis, chunkElement) - self._addElement("polarizationAxis", chunk.polarization_axis, - chunkElement) - - self._addObservableAxisElement(chunk.observable, chunkElement) - self._addSpatialWCSElement(chunk.position, chunkElement) - self._addSpectralWCSElement(chunk.energy, chunkElement) - self._addTemporalWCSElement(chunk.time, chunkElement) - self._addPolarizationWCSElement(chunk.polarization, chunkElement) - - def _addObservableAxisElement(self, observable, parent): - if observable is None: - return - - element = self._getCaom2Element("observable", parent) - self._addSliceElement("dependent", observable.dependent, element) - self._addSliceElement("independent", observable.independent, element) - - def _addSpatialWCSElement(self, position, parent): - """ Builds a representation of a SpatialWCS and adds it to the - parent element. """ - if position is None: - return - - element = self._getCaom2Element("position", parent) - self._addCoordAxis2DElement("axis", position.axis, element) - self._addElement("coordsys", position.coordsys, element) - self._addElement("equinox", position.equinox, element) - self._addElement("resolution", position.resolution, element) - - def _addSpectralWCSElement(self, energy, parent): - """ Builds a representation of a SpectralWCS and adds it to the - parent element.""" - if energy is None: - return - - element = self._getCaom2Element("energy", parent) - self._addCoordAxis1DElement("axis", energy.axis, element) - self._addElement("specsys", energy.specsys, element) - self._addElement("ssysobs", energy.ssysobs, element) - self._addElement("ssyssrc", energy.ssyssrc, element) - self._addElement("restfrq", energy.restfrq, element) - self._addElement("restwav", energy.restwav, element) - self._addElement("velosys", energy.velosys, element) - self._addElement("zsource", energy.zsource, element) - self._addElement("velang", energy.velang, element) - self._addElement("bandpassName", energy.bandpass_name, element) - self._addElement("resolvingPower", energy.resolving_power, element) - self._addTransitionElement(energy.transition, element) - - def _addTemporalWCSElement(self, time, parent): - """ Builds a representation of a TemporalWCS and adds it to the - parent element. """ - if time is None: - return - - element = self._getCaom2Element("time", parent) - self._addCoordAxis1DElement("axis", time.axis, element) - self._addElement("timesys", time.timesys, element) - self._addElement("trefpos", time.trefpos, element) - self._addElement("mjdref", time.mjdref, element) - self._addElement("exposure", time.exposure, element) - self._addElement("resolution", time.resolution, element) - - def _addPolarizationWCSElement(self, polarization, parent): - """ Builds a representation of a PolarizationWCS and adds it to the - parent element. """ - if polarization is None: - return - - element = self._getCaom2Element("polarization", parent) - self._addCoordAxis1DElement("axis", polarization.axis, element) - -#/*+ CAOM2 Types #-*/ - - def _addPointElement(self, name, point, parent): - """ Builds a representation of a Point and adds it to the - parent element. """ - if point is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("cval1", point.cval1, element) - self._addElement("cval2", point.cval2, element) - -#/*+ WCS Types #-*/ - - def _addAxisElement(self, name, axis, parent): - """ Builds a representation of a Axis and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("ctype", axis.ctype, element) - if axis.cunit: - self._addElement("cunit", axis.cunit, element) - - def _addCoord2DElement(self, name, coord, parent): - """ Builds a representation of a Coord2D and adds it to the - parent element. """ - if coord is None: - return - - element = self._getCaom2Element(name, parent) - self._addRefCoordElement("coord1", coord.coord1, element) - self._addRefCoordElement("coord2", coord.coord2, element) - - def _addValueCoord2DElement(self, name, coord, parent): - """ Builds a representation of a ValueCoord2D and adds it to the - parent element. """ - if coord is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("coord1", coord.coord1, element) - self._addElement("coord2", coord.coord2, element) - - def _addCoordAxis1DElement(self, name, axis, parent): - """ Builds a representation of a CoordAxis1D and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis", axis.axis, element) - self._addCoordErrorElement("error", axis.error, element) - self._addCoordRange1DElement("range", axis.range, element) - self._addCoordBounds1DElement("bounds", axis.bounds, element) - self._addCoordFunction1DElement("function", axis.function, element) - - def _addCoordAxis2DElement(self, name, axis, parent): - """ Builds a representation of a CoordAxis2D and adds it to the - parent element. """ - if axis is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis1", axis.axis1, element) - self._addAxisElement("axis2", axis.axis2, element) - self._addCoordErrorElement("error1", axis.error1, element) - self._addCoordErrorElement("error2", axis.error2, element) - self._addCoordRange2DElement("range", axis.range, element) - self._addCoordBounds2DElement("bounds", axis.bounds, element) - self._addCoordFunction2DElement("function", axis.function, element) - - def _addCoordBounds1DElement(self, name, bounds, parent): - """ Builds a representation of a CoordBounds1D and adds it to the - parent element. """ - if bounds is None: - return - - element = self._getCaom2Element(name, parent) - self._addCoordRange1DListElement("samples", bounds.samples, element) - - def _addCoordBounds2DElement(self, name, bounds, parent): - """Builds a representation of a CoordBounds2D and adds it to the - parent element. """ - if bounds is None: - return - - element = self._getCaom2Element(name, parent) - if isinstance(bounds, CoordCircle2D): - self._addCoordCircle2DElement("circle", - CoordCircle2D(bounds.center, - bounds.radius), element) - elif isinstance(bounds, CoordPolygon2D): - self._addCoordPolygon2DElement("polygon", bounds, element) - else: - raise TypeError("BUG: unsupported CoordBounds2D type " - + bounds.__class__.__name__) - - def _addCoordCircle2DElement(self, name, circle, parent): - """ Builds a representation of a CoordCircle2D and adds it to the - parent element. """ - if circle is None: - return - - element = self._getCaom2Element(name, parent) - self._addValueCoord2DElement("center", circle.center, element) - self._addElement("radius", circle.radius, element) - - def _addCoordErrorElement(self, name, error, parent): - """ Builds a representation of a CoordError and adds it to the - parent element. """ - if error is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("syser", error.syser, element) - self._addElement("rnder", error.rnder, element) - - def _addCoordFunction1DElement(self, name, function, parent): - """ Builds a representation of a CoordFunction1D and adds it to the - parent element. """ - if function is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("naxis", function.naxis, element) - self._addElement("delta", function.delta, element) - self._addRefCoordElement("refCoord", function.ref_coord, element) - - def _addCoordFunction2DElement(self, name, function, parent): - """ Builds a representation of a CoordFunction2D and adds it to the - parent element. """ - if function is None: - return - - element = self._getCaom2Element(name, parent) - self._addDimension2DElement("dimension", function.dimension, element) - self._addCoord2DElement("refCoord", function.ref_coord, element) - self._addElement("cd11", function.cd11, element) - self._addElement("cd12", function.cd12, element) - self._addElement("cd21", function.cd21, element) - self._addElement("cd22", function.cd22, element) - - def _addCoordPolygon2DElement(self, name, polygon, parent): - """ Builds a representation of a CoordPolygon2D and adds it to the - parent element. """ - if polygon is None: - return - - element = self._getCaom2Element(name, parent) - if (len(polygon.vertices) > 0): - verticesElement = self._getCaom2Element("vertices", element) - for vertex in polygon.vertices: - self._addValueCoord2DElement("vertex", vertex, verticesElement) - - def _addCoordRange1DElement(self, name, _range, parent): - """ Builds a representation of a CoordRange1D and adds it to the - parent element. """ - if _range is None: - return - - element = self._getCaom2Element(name, parent) - self._addRefCoordElement("start", _range.start, element) - self._addRefCoordElement("end", _range.end, element) - - def _addCoordRange2DElement(self, name, _range, parent): - """ Builds a representation of a CoordRange2D and adds it to the - parent element. """ - if _range is None: - return - - element = self._getCaom2Element(name, parent) - self._addCoord2DElement("start", _range.start, element) - self._addCoord2DElement("end", _range.end, element) - - def _addDimension2DElement(self, name, dimension, parent): - """ Builds a representation of a Dimension2D and adds it to the - parent element. """ - if dimension is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("naxis1", dimension.naxis1, element) - self._addElement("naxis2", dimension.naxis2, element) - - def _addRefCoordElement(self, name, refCoord, parent): - """ Builds a representation of a RefCoord and adds it to the - parent element. """ - if refCoord is None: - return - - element = self._getCaom2Element(name, parent) - self._addElement("pix", refCoord.pix, element) - self._addElement("val", refCoord.val, element) - - def _addSliceElement(self, name, _slice, parent): - """ Builds a representation of a Slice and adds it to the - parent element. """ - if _slice is None: - return - - element = self._getCaom2Element(name, parent) - self._addAxisElement("axis", _slice.axis, element) - self._addElement("bin", _slice.bin, element) - - def _addAttribute(self, name, value, element): - element.set(self._caom2_namespace + name, value) - - def _addElement(self, name, text, parent): - if text is None: - return - element = self._getCaom2Element(name, parent) - if isinstance(text, str): - element.text = text - else: - element.text = str(text) - - def _addDatetimeElement(self, name, value, parent): - if value is None: - return - element = self._getCaom2Element(name, parent) - element.text = date2ivoa(value) - - def _addListElement(self, name, collection, parent): - if collection is None or \ - (len(collection) == 0 and not self._write_empty_collections): - return - element = self._getCaom2Element(name, parent) - element.text = ' '.join(collection) - - def _addCoordRange1DListElement(self, name, values, parent): - if values is None: - return - element = self._getCaom2Element(name, parent) - for v in values: - self._addCoordRange1DElement("range", v, element) - - def _addInputsElement(self, name, collection, parent): - if collection is None or \ - (len(collection) == 0 and not self._write_empty_collections): - return - element = self._getCaom2Element(name, parent) - for plane_uri in collection: - self._addElement("planeURI", plane_uri.uri, element) - - def _getCaom2Element(self, tag, parent): - return etree.SubElement(parent, self._caom2_namespace + tag) diff --git a/caom2tools/caom2/xml/caom2_xml_constants.py b/caom2tools/caom2/xml/caom2_xml_constants.py deleted file mode 100644 index abb4b282..00000000 --- a/caom2tools/caom2/xml/caom2_xml_constants.py +++ /dev/null @@ -1,86 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -CAOM2_PKG = 'caom2' - -CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' -CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' -CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' - -CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' -CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' -CAOM22_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.2' - -CAOM20 = "{%s}" % CAOM20_NAMESPACE -CAOM21 = "{%s}" % CAOM21_NAMESPACE -CAOM22 = "{%s}" % CAOM22_NAMESPACE - -XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" -XSI = "{%s}" % XSI_NAMESPACE \ No newline at end of file diff --git a/caom2tools/caom2/xml_reader_writer.py b/caom2tools/caom2/xml_reader_writer.py new file mode 100644 index 00000000..2ca526be --- /dev/null +++ b/caom2tools/caom2/xml_reader_writer.py @@ -0,0 +1,2013 @@ +#!/usr/bin/env python2.7 +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines ObservationReader class """ + +import uuid + +import pkg_resources +from lxml import etree + +import artifact +import chunk +import data_type +import observation +import part +import plane +import wcs +from util import Util + +CAOM2_PKG = 'caom2' + +CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' +CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' +CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' + +CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' +CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' +CAOM22_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.2' + +CAOM20 = "{%s}" % CAOM20_NAMESPACE +CAOM21 = "{%s}" % CAOM21_NAMESPACE +CAOM22 = "{%s}" % CAOM22_NAMESPACE + +XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" +XSI = "{%s}" % XSI_NAMESPACE + + +class ObservationReader(object): + """ObservationReader """ + + def __init__(self, valididate=False): + """Constructor. XML Schema validation may be disabled, in which case + the client is likely to fail in horrible ways if it received invalid + documents. However, performance may be improved. + + Arguments: + validate : If True enable schema validation, False otherwise + """ + self._validate = valididate + + if self._validate: + caom20_schema_path = pkg_resources.resource_filename( + CAOM2_PKG, CAOM20_SCHEMA_FILE) + + parser = etree.XMLParser(remove_blank_text=True) + xsd = etree.parse(caom20_schema_path, parser) + + caom21_schema = etree.Element( + '{http://www.w3.org/2001/XMLSchema}import', + namespace=CAOM21_NAMESPACE, + schemaLocation=CAOM21_SCHEMA_FILE) + xsd.getroot().insert(1, caom21_schema) + + caom22_schema = etree.Element( + '{http://www.w3.org/2001/XMLSchema}import', + namespace=CAOM22_NAMESPACE, + schemaLocation=CAOM22_SCHEMA_FILE) + xsd.getroot().insert(2, caom22_schema) + + self._xmlschema = etree.XMLSchema(xsd) + + def _set_entity_attributes(self, element, ns, caom2_entity): + expect_uuid = True + if CAOM20_NAMESPACE == ns: + expect_uuid = False + + element_id = element.get("{" + ns + "}id") + element_last_modified = element.get("{" + ns + "}lastModified") + + if expect_uuid: + uid = uuid.UUID(element_id) + else: + uid = Util.long2uuid(long(element_id)) + caom2_entity._id = uid + + if element_last_modified: + caom2_entity._last_modified = Util.str2ivoa(element_last_modified) + + def _get_child_element(self, elTag, parent, ns, required): + for element in list(parent): + if element.tag == "{" + ns + "}" + elTag: + if not element.keys() and not element.text: + # element is empty, return None + return None + else: + # element has content, return it + return element + + if required: + error = elTag + " element not found in " + parent.tag + raise ObservationParsingException(error) + else: + return None + + def _get_child_text(self, elTag, parent, ns, required): + childElement = self._get_child_element(elTag, parent, ns, required) + if childElement is None: + return None + else: + return childElement.text + + def _get_child_text_as_int(self, elTag, parent, ns, required): + childElement = self._get_child_element(elTag, parent, ns, required) + if childElement is None: + return None + else: + return int(childElement.text) + + def _get_child_text_as_long(self, elTag, parent, ns, required): + childElement = self._get_child_element(elTag, parent, ns, required) + if childElement is None: + return None + else: + return long(childElement.text) + + def _get_child_text_as_float(self, elTag, parent, ns, required): + childElement = self._get_child_element(elTag, parent, ns, required) + if childElement is None: + return None + else: + return float(childElement.text) + + def _get_algorithm(self, elTag, parent, ns, required): + """Build an Algorithm object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the algorithm element + ns : namespace of the document + required : indicates whether the element is required + return : an Algorithm object or + None if the document does not contain an algorithm element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return observation.Algorithm(self._get_child_text("name", el, ns, True)) + + def _get_meta_release(self, elTag, parent, ns, required): + """Build a MetaRelease object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the MetaRelease element + ns : namespace of the document + required : indicates whether the element is required + return : a MetaRelease object or + None if the document does not contain a MetaRelease element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + # TODO: need to catch exceptions, + # what kind of exceptions are thrown? + return Util.str2ivoa(el.text) + + def _get_proposal(self, elTag, parent, ns, required): + """Build a Proposal object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Proposal element + ns : namespace of the document + required : indicates whether the element is required + return : a Proposal object or + None if the document does not contain a Proposal element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + proposal = observation.Proposal(self._get_child_text("id", el, ns, True)) + proposal.pi_name = self._get_child_text("pi", el, ns, False) + proposal.project = self._get_child_text("project", el, ns, False) + proposal.title = self._get_child_text("title", el, ns, False) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + proposal.keywords.add(keyword) + return proposal + + def _get_target(self, elTag, parent, ns, required): + """Build a Target object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Target element + ns : namespace of the document + required : indicates whether the element is required + return : a Target object or + None if the document does not contain a Target element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + target = observation.Target(self._get_child_text("name", el, ns, True)) + targetType = self._get_child_text("type", el, ns, False) + if targetType: + target.target_type = observation.TargetType.getByValue(targetType) + target.standard = ("true" == + self._get_child_text("standard", el, ns, False)) + target.redshift = ( + self._get_child_text_as_float("redshift", el, ns, False)) + target.moving = ("true" == + self._get_child_text("moving", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + target.keywords.add(keyword) + return target + + def _get_target_position(self, elTag, parent, ns, required): + """Build a TargetPosition object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Target element + ns : namespace of the document + required : indicates whether the element is required + return : a TargetPosition object or + None if the document does not contain a TargetPosition element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + target_position = observation.TargetPosition( + self._get_point("coordinates", el, ns, True), + self._get_child_text("coordsys", el, ns, True)) + target_position.equinox = ( + self._get_child_text_as_float("equinox", el, ns, False)) + return target_position + + def _get_requirements(self, elTag, parent, ns, required): + """Build an Requirements object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Requirements element + ns : namespace of the document + required : indicates whether the element is required + return : a Requirements object or + None if the document does not contain an Requirements element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + flag = self._get_child_text("flag", el, ns, True) + requirements = observation.Requirements(observation.Status.getByValue(flag)) + return requirements + + def _get_telescope(self, elTag, parent, ns, required): + """Build a Telescope object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Telescope element + ns : namespace of the document + required : indicates whether the element is required + return : a Telescope object or + None if the document does not contain a Telescope element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + telescope = observation.Telescope(self._get_child_text("name", el, ns, True)) + telescope.geo_location_x = ( + self._get_child_text_as_float("geoLocationX", el, ns, False)) + telescope.geo_location_y = ( + self._get_child_text_as_float("geoLocationY", el, ns, False)) + telescope.geo_location_z = ( + self._get_child_text_as_float("geoLocationZ", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + telescope.keywords.add(keyword) + return telescope + + def _get_instrument(self, elTag, parent, ns, required): + """Build an Instrument object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Instrument element + ns : namespace of the document + required : indicates whether the element is required + return : a Instrument object or + None if the document does not contain an Instrument element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + instrument = observation.Instrument(self._get_child_text("name", el, ns, True)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + instrument.keywords.add(keyword) + return instrument + + def _get_environment(self, elTag, parent, ns, required): + """Build an Environment object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Environment element + ns : namespace of the document + required : indicates whether the element is required + return : a Environment object or + None if the document does not contain an Environment element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + environment = observation.Environment() + environment.seeing = ( + self._get_child_text_as_float("seeing", el, ns, False)) + environment.humidity = ( + self._get_child_text_as_float("humidity", el, ns, False)) + environment.elevation = ( + self._get_child_text_as_float("elevation", el, ns, False)) + environment.tau = ( + self._get_child_text_as_float("tau", el, ns, False)) + environment.wavelength_tau = ( + self._get_child_text_as_float("wavelengthTau", el, ns, False)) + environment.ambient_temp = ( + self._get_child_text_as_float("ambientTemp", el, ns, False)) + environment.photometric = ("true" == + self._get_child_text("photometric", el, ns, False)) + return environment + + def _add_members(self, members, parent, ns): + """Create ObservationURI objects from an XML representation of + ObservationURI elements found in members element, and add them to the + set of ObservationURI's + + Arguments: + members : Set of member's from the parent Observation object + parent : element containing the Environment element + ns : namespace of the document + return : an Environment object or + None if the document does not contain an Environment element + raise : ObservationParsingException + """ + el = self._get_child_element("members", parent, ns, False) + if el is not None: + for memberEl in el.iterchildren("{" + ns + "}observationURI"): + members.add(observation.ObservationURI(memberEl.text)) + + if not members: + error = "No observationURI element found in members" + raise ObservationParsingException(error) + + def _add_inputs(self, inputs, parent, ns): + """Create PlaneURI objects from an XML representation of the planeURI + elements and add them to the set of PlaneURIs. + + Arguments: + inputs : set of PlaneURI from the Provenance + parent : element containing the PlaneURI elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("inputs", parent, ns, False) + if el is not None: + for uriEl in el.iterchildren("{" + ns + "}planeURI"): + inputs.add(plane.PlaneURI(uriEl.text)) + + if not inputs: + error = "No planeURI element found in members" + raise ObservationParsingException(error) + + def _get_provenance(self, elTag, parent, ns, required): + """Build a Provenance object from an XML representation of a + Provenance element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Provenance element + ns : namespace of the document + required : indicates whether the element is required + return : a Provenance object or + None if the document does not contain a Provenance element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + prov = plane.Provenance(self._get_child_text("name", el, ns, True)) + prov.version = self._get_child_text("version", el, ns, False) + prov.project = self._get_child_text("project", el, ns, False) + prov.producer = self._get_child_text("producer", el, ns, False) + prov.run_id = self._get_child_text("runID", el, ns, False) + reference = self._get_child_text("reference", el, ns, False) + if reference: + prov.reference = reference + prov.last_executed = Util.str2ivoa( + self._get_child_text("lastExecuted", el, ns, False)) + keywords = self._get_child_text("keywords", el, ns, False) + if keywords is not None: + for keyword in keywords.split(): + prov.keywords.add(keyword) + self._add_inputs(prov.inputs, el, ns) + return prov + + def _get_metrics(self, elTag, parent, ns, required): + """Build a Metrics object from an XML representation of a + Metrics element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Metrics element + ns : namespace of the document + required : indicates whether the element is required + return : a Metrics object or + None if the document does not contain a Metrics element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + metrics = plane.Metrics() + metrics.source_number_density = \ + self._get_child_text_as_float("sourceNumberDensity", el, ns, False) + metrics.background = \ + self._get_child_text_as_float("background", el, ns, False) + metrics.background_std_dev = \ + self._get_child_text_as_float("backgroundStddev", el, ns, False) + metrics.flux_density_limit = \ + self._get_child_text_as_float("fluxDensityLimit", el, ns, False) + metrics.mag_limit = \ + self._get_child_text_as_float("magLimit", el, ns, False) + return metrics + + def _get_quality(self, elTag, parent, ns, required): + """Build an Quality object from an XML representation + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Quality element + ns : namespace of the document + required : indicates whether the element is required + return : a Quality object or + None if the document does not contain an Quality element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + flag = self._get_child_text("flag", el, ns, True) + dataQuality = plane.DataQuality(plane.Quality.getByValue(flag)) + return dataQuality + + def _get_point(self, elTag, parent, ns, required): + """Build an Point object from an XML representation + of an Point element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Point element + ns : namespace of the document + required : indicate whether the element is required + return : an Point object or + None if the document does not contain an Point element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return data_type.Point(self._get_child_text_as_float("cval1", el, ns, True), + self._get_child_text_as_float("cval2", el, ns, True)) + + def _get_axis(self, elTag, parent, ns, required): + """Build an Axis object from an XML representation of an Axis element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Axis element + ns : namespace of the document + required : indicate whether the element is required + return : an Axis object or + None if the document does not contain an Axis element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return data_type.Axis(self._get_child_text("ctype", el, ns, True), + self._get_child_text("cunit", el, ns, False)) + + def _get_slice(self, elTag, parent, ns, required): + """Build a Slice object from an XML representation of a Slice element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Slice element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Slice object or + None if the document does not contain a Slice element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return data_type.Slice(self._get_axis("axis", el, ns, True), + self._get_child_text_as_long("bin", el, ns, True)) + + def _get_observable_axis(self, elTag, parent, ns, required): + """Build an ObservableAxis object from an XML representation of an + observable element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the Observable element + ns : namespace of the document + required : boolean indicating whether the element is required + return : an ObservableAxis object or + None if the document does not contain an Observable element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + observable = chunk.ObservableAxis( + self._get_slice("dependent", el, ns, True)) + observable.independent = \ + self._get_slice("independent", el, ns, False) + return observable + + def _get_coord_error(self, elTag, parent, ns, required): + """Build a CoordError object from an XML representation of an error + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the error element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordError object or + None if the document does not contain an error element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordError( + self._get_child_text_as_float("syser", el, ns, True), + self._get_child_text_as_float("rnder", el, ns, True)) + + def _get_ref_coord(self, elTag, parent, ns, required): + """Build a RefCoord object from an XML representation of a coord + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a RefCoord object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.RefCoord( + self._get_child_text_as_float("pix", el, ns, True), + self._get_child_text_as_float("val", el, ns, True)) + + def _get_coord2d(self, elTag, parent, ns, required): + """Build a Coord2D object from an XML representation of a coord + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Coord2D object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.Coord2D( + self._get_ref_coord("coord1", el, ns, True), + self._get_ref_coord("coord2", el, ns, True)) + + def _get_value_coord2d(self, elTag, parent, ns, required): + """Build a ValueCoord2D object from an XML representation of a + value coord element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the coord element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a ValueCoord2D object or + None if the document does not contain a coord element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.ValueCoord2D( + self._get_child_text_as_float("coord1", el, ns, True), + self._get_child_text_as_float("coord2", el, ns, True)) + + def _get_coord_range2d(self, elTag, parent, ns, required): + """Build a CoordRange2D object from an XML representation of a range + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the range element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordRange2D object or + None if the document does not contain a range element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordRange2D( + self._get_coord2d("start", el, ns, True), + self._get_coord2d("end", el, ns, True)) + + def _get_coord_circle2d(self, elTag, parent, ns, required): + """Build a CoordCircle2D object from an XML representation of a circle + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the circle element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordCircle2D object or + None if the document does not contain a circle element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordCircle2D( + self._get_value_coord2d("center", el, ns, True), + self._get_child_text_as_float("radius", el, ns, True)) + + def _get_coord_polygon2d(self, elTag, parent, ns, required): + """Build a CoordPolygon2D object from an XML representation + of a polygon element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the polygon element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordPolygon2D object or + None if the document does not contain a polygon element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + verticeEl = self._get_child_element("vertices", el, ns, True) + childrenVertices = list( + verticeEl.iterchildren(tag=("{" + ns + "}vertex"))) + if len(childrenVertices) < 3: + error = ("CoordPolygon2D must have a minimum of 3 vertices, " + "found " + len(childrenVertices)) + raise ObservationParsingException(error) + else: + polygon = wcs.CoordPolygon2D() + for childVertexEl in childrenVertices: + polygon.vertices.append(wcs.ValueCoord2D( + self._get_child_text_as_float( + "coord1", childVertexEl, ns, True), + self._get_child_text_as_float( + "coord2", childVertexEl, ns, True))) + return polygon + + def _get_coord_bounds2d(self, elTag, parent, ns, required): + """Build a CoordBounds2D object from an XML representation of a bounds + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the bounds element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordBounds2D object or + None if the document does not contain a bounds element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + circle = self._get_coord_circle2d("circle", el, ns, False) + if circle is not None: + return circle + else: + polygon = self._get_coord_polygon2d("polygon", el, ns, False) + if polygon is not None: + return polygon + else: + error = "Unsupported element not found in " + elTag + \ + ": " + el.getText() + raise ObservationParsingException(error) + + def _get_dimension2d(self, elTag, parent, ns, required): + """Build a Dimension2D object from an XML representation of a dimension + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the dimension element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a Dimention2D object or + None if the document does not contain a dimension element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.Dimension2D( + self._get_child_text_as_long("naxis1", el, ns, True), + self._get_child_text_as_long("naxis2", el, ns, True)) + + def _get_coord_function2d(self, elTag, parent, ns, required): + """Build a CoordFunction2D object from an XML representation of a + function element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the function element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordFunction2D object or + None if the document does not contain a function element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordFunction2D( + self._get_dimension2d("dimension", el, ns, True), + self._get_coord2d("refCoord", el, ns, True), + self._get_child_text_as_float("cd11", el, ns, True), + self._get_child_text_as_float("cd12", el, ns, True), + self._get_child_text_as_float("cd21", el, ns, True), + self._get_child_text_as_float("cd22", el, ns, True)) + + def _get_coord_axis2d(self, elTag, parent, ns, required): + """Build a CoordAxis2D object from an XML representation of an axis + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the axis element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordAxis2D object or + None if the document does not contain an axis element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + axis = wcs.CoordAxis2D(self._get_axis("axis1", el, ns, True), + self._get_axis("axis2", el, ns, True)) + axis.error1 = self._get_coord_error("error1", el, ns, False) + axis.error2 = self._get_coord_error("error2", el, ns, False) + axis.range = self._get_coord_range2d("range", el, ns, False) + axis.bounds = self._get_coord_bounds2d("bounds", el, ns, False) + axis.function = self._get_coord_function2d("function", el, ns, False) + return axis + + def _get_spatial_wcs(self, elTag, parent, ns, required): + """Build a SpatialWCS object from an XML representation of a position + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a SpatialWCS object or + None if the document does not contain a position element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + position = wcs.SpatialWCS(self._get_coord_axis2d("axis", el, ns, False)) + position.coordsys = self._get_child_text("coordsys", el, ns, False) + position.equinox = \ + self._get_child_text_as_float("equinox", el, ns, False) + position.resolution = \ + self._get_child_text_as_float("resolution", el, ns, False) + return position + + def _add_children_to_coord_range1d_list(self, elTag, ranges, parent, ns, + required): + """Create CoordRange1D objects from an XML representation of the + range elements and add them to the set of ranges. + + Arguments: + elTag : element tag which identifies the element + ranges : reference to set of ranges + parent : element containing the ranges elements + ns : namespace of the document + required : boolean indicating whether the element is required + """ + for rangeEl in parent.iterchildren("{" + ns + "}" + elTag): + ranges.append(wcs.CoordRange1D( + self._get_ref_coord("start", rangeEl, ns, True), + self._get_ref_coord("end", rangeEl, ns, True))) + + def _get_coord_bounds1d(self, elTag, parent, ns, required): + """Build a CoordBounds1D object from an XML representation of a bounds + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the bounds element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordBounds1D object or + None if the document does not contain a bounds element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + coordBounds1D = wcs.CoordBounds1D() + samplesEl = self._get_child_element("samples", el, ns, False) + if samplesEl is not None: + self._add_children_to_coord_range1d_list( + "range", coordBounds1D.samples, samplesEl, ns, False) + return coordBounds1D + + def _get_coord_range1d(self, elTag, parent, ns, required): + """Build a CoordRange1D object from an XML representation of a range + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the range element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordRange1D object or + None if the document does not contain a range element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordRange1D( + self._get_ref_coord("start", el, ns, True), + self._get_ref_coord("end", el, ns, True)) + + def _get_coord_function1d(self, elTag, parent, ns, required): + """Build a CoordFunction1D object from an XML representation of a + function element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the function element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordFunction1D object or + None if the document does not contain a function element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return wcs.CoordFunction1D( + self._get_child_text_as_long("naxis", el, ns, True), + self._get_child_text_as_float("delta", el, ns, True), + self._get_ref_coord("refCoord", el, ns, True)) + + def _get_coord_axis1d(self, elTag, parent, ns, required): + """Build a CoordAxis1D object from an XML representation of an axis + element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the axis element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a CoordAxis1D object or + None if the document does not contain an axis element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + axis = wcs.CoordAxis1D(self._get_axis("axis", el, ns, True)) + axis.error = self._get_coord_error("error", el, ns, False) + axis.range = self._get_coord_range1d("range", el, ns, False) + axis.bounds = self._get_coord_bounds1d("bounds", el, ns, False) + axis.function = self._get_coord_function1d("function", el, ns, False) + return axis + + def _get_transition(self, elTag, parent, ns, required): + """Build an EnergyTransition object from an XML representation of + a transition element. + + Arguments: + elTag : element tag which identifies the element + parent : element containing the transition element + ns : namespace of the document + required : boolean indicating whether the element is reuiqred + return : an EnergyTransition object or + None if the document does not contain a transition element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return plane.EnergyTransition( + self._get_child_text("species", el, ns, True), + self._get_child_text("transition", el, ns, True)) + + def _get_spectral_wcs(self, elTag, parent, ns, required): + """Build a SpectralWCS object from an XML representation of an energy + element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a SpectralWCS object or + None if the document does not contain an energy element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + energy = chunk.SpectralWCS( + self._get_coord_axis1d("axis", el, ns, True), + self._get_child_text("specsys", el, ns, True)) + energy.ssysobs = \ + self._get_child_text("ssysobs", el, ns, False) + energy.ssyssrc = \ + self._get_child_text("ssyssrc", el, ns, False) + energy.restfrq = \ + self._get_child_text_as_float("restfrq", el, ns, False) + energy.restwav = \ + self._get_child_text_as_float("restwav", el, ns, False) + energy.velosys = \ + self._get_child_text_as_float("velosys", el, ns, False) + energy.zsource = \ + self._get_child_text_as_float("zsource", el, ns, False) + energy.velang = \ + self._get_child_text_as_float("velang", el, ns, False) + energy.bandpass_name = \ + self._get_child_text("bandpassName", el, ns, False) + energy.resolving_power = \ + self._get_child_text_as_float("resolvingPower", el, ns, False) + energy.transition = \ + self._get_transition("transition", el, ns, False) + return energy + + def _get_temporal_wcs(self, elTag, parent, ns, required): + """Build a TemporalWCS object from an XML representation of an time + element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a TemporalWCS object or + None if the document does not contain an time element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + time = chunk.TemporalWCS( + self._get_coord_axis1d("axis", el, ns, True)) + time.timesys = \ + self._get_child_text("timesys", el, ns, False) + time.trefpos = \ + self._get_child_text("trefpos", el, ns, False) + time.mjdref = \ + self._get_child_text_as_float("mjdref", el, ns, False) + time.exposure = \ + self._get_child_text_as_float("exposure", el, ns, False) + time.resolution = \ + self._get_child_text_as_float("resolution", el, ns, False) + return time + + def _get_polarization_wcs(self, elTag, parent, ns, required): + """Build a PolarizationWCS object from an XML representation of a + polarization element. + + Arguments: + elTag : element tag which indentifies the element + parent : element containing the position element + ns : namespace of the document + required : boolean indicating whether the element is required + return : a PolarizationWCS object or + None if the document does not contain an polarization element + raise : ObservationParsingException + """ + el = self._get_child_element(elTag, parent, ns, required) + if el is None: + return None + else: + return chunk.PolarizationWCS( + self._get_coord_axis1d("axis", el, ns, False)) + + def _add_chunks(self, chunks, parent, ns): + """Build Chunk objects from an XML representation of Chunk elements + and add them to the set of Chunks. + + Argument: + chunks : set of Chunk objects from the Part + parent : element containing the Chunk elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("chunks", parent, ns, False) + if el is None: + return None + else: + for chunkEl in el.iterchildren("{" + ns + "}chunk"): + tempChunk = chunk.Chunk() + productType = \ + self._get_child_text("productType", chunkEl, ns, False) + if productType: + tempChunk.product_type = \ + artifact.ProductType.getByValue(productType) + tempChunk.naxis = \ + self._get_child_text_as_int("naxis", chunkEl, ns, False) + tempChunk.observable_axis = \ + self._get_child_text_as_int("observableAxis", chunkEl, ns, + False) + tempChunk.position_axis_1 = \ + self._get_child_text_as_int("positionAxis1", chunkEl, ns, + False) + tempChunk.position_axis_2 = \ + self._get_child_text_as_int("positionAxis2", chunkEl, ns, + False) + tempChunk.energy_axis = \ + self._get_child_text_as_int("energyAxis", chunkEl, ns, False) + tempChunk.time_axis = \ + self._get_child_text_as_int("timeAxis", chunkEl, ns, False) + tempChunk.polarization_axis = \ + self._get_child_text_as_int("polarizationAxis", chunkEl, ns, + False) + tempChunk.observable = \ + self._get_observable_axis("observable", chunkEl, ns, False) + tempChunk.position = \ + self._get_spatial_wcs("position", chunkEl, ns, False) + tempChunk.energy = \ + self._get_spectral_wcs("energy", chunkEl, ns, False) + tempChunk.time = \ + self._get_temporal_wcs("time", chunkEl, ns, False) + tempChunk.polarization = \ + self._get_polarization_wcs("polarization", chunkEl, ns, + False) + self._set_entity_attributes(chunkEl, ns, tempChunk) + chunks.append(tempChunk) + + def _add_parts(self, parts, parent, ns): + """Build Part objects from an XML representation of Part elements and + add them to the set of Parts. + + Argument: + parts : set of Part objects from the Artifact + parent : element containing the Part elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("parts", parent, ns, False) + if el is None: + return None + else: + for partEl in el.iterchildren("{" + ns + "}part"): + tempPart = \ + part.Part(self._get_child_text("name", partEl, ns, True)) + productType = \ + self._get_child_text("productType", partEl, ns, False) + if productType: + tempPart.product_type = \ + artifact.ProductType.getByValue(productType) + self._add_chunks(tempPart.chunks, partEl, ns) + self._set_entity_attributes(partEl, ns, tempPart) + parts[tempPart.name] = tempPart + + def _add_artifacts(self, artifacts, parent, ns): + """Build artifacts from an XML representation of the artifact elements + and add them to the set of Artifacts. + + Arguments: + artifacts : set of Artifacts from the Plane + parent : element containing the Artifact elements + ns : namespace fo the document + raise : ObservationParsingException + """ + el = self._get_child_element("artifacts", parent, ns, False) + if el is None: + return None + else: + for artifactEl in el.iterchildren("{" + ns + "}artifact"): + uri = self._get_child_text("uri", artifactEl, ns, True) + + product_type = self._get_child_text("productType", artifactEl, ns, False) + if product_type is None: + product_type = artifact.ProductType.SCIENCE + print "Using default Artifact.productType value {0}".format(str(artifact.ProductType.SCIENCE)) + else: + product_type = artifact.ProductType.getByValue(product_type) + + release_type = self._get_child_text("releaseType", artifactEl, ns, False) + if release_type is None: + release_type = artifact.ReleaseType.DATA + print "Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA)) + else: + release_type = artifact.ReleaseType.getByValue(release_type) + + tempArtifact = artifact.Artifact(uri, product_type, release_type) + tempArtifact.content_type = self._get_child_text("contentType", artifactEl, ns, False) + tempArtifact.content_length = ( + self._get_child_text_as_long("contentLength", artifactEl, ns, False)) + self._add_parts(tempArtifact.parts, artifactEl, ns) + self._set_entity_attributes(artifactEl, ns, tempArtifact) + artifacts[tempArtifact.uri] = tempArtifact + + def _add_planes(self, planes, parent, ns): + """Create Planes object from XML representation of Plane elements + and add them to the set of Planes. + + Arguments: + planes : Set of planes from the parent Observation object + parent : element containing the Plane elements + ns : namespace of the document + raise : ObservationParsingException + """ + el = self._get_child_element("planes", parent, ns, False) + if el is None: + return None + else: + for planeEl in el.iterchildren("{" + ns + "}plane"): + tempPlane = plane.Plane( + self._get_child_text("productID", planeEl, ns, True)) + tempPlane.meta_release = Util.str2ivoa( + self._get_child_text("metaRelease", planeEl, ns, False)) + tempPlane.data_release = Util.str2ivoa( + self._get_child_text("dataRelease", planeEl, ns, False)) + dataProductType = \ + self._get_child_text("dataProductType", planeEl, ns, False) + if dataProductType: + tempPlane.data_product_type = \ + plane.DataProductType.getByValue(dataProductType) + calibrationLevel = \ + self._get_child_text("calibrationLevel", planeEl, ns, False) + if calibrationLevel: + tempPlane.calibration_level = \ + plane.CalibrationLevel.getByValue(int(calibrationLevel)) + tempPlane.provenance = \ + self._get_provenance("provenance", planeEl, ns, False) + tempPlane.metrics = \ + self._get_metrics("metrics", planeEl, ns, False) + tempPlane.quality = \ + self._get_quality("quality", planeEl, ns, False) + self._add_artifacts(tempPlane.artifacts, planeEl, ns) + self._set_entity_attributes(planeEl, ns, tempPlane) + planes[tempPlane.product_id] = tempPlane + + if not planes: + error = "No plane element found in planes" + raise ObservationParsingException(error) + + def read(self, source): + """Build an Observation object from an XML document located in source. + Source an be a file name/path, a file object, a file-like object or a + URL using the HTTP or FTP protocol. + + Arguments: + source : source of XML document containing an Observation element + return : an Observation object + raise : ObservationParsingException + """ + doc = etree.parse(source) + if self._validate and self._xmlschema: + self._xmlschema.assertValid(doc) + root = doc.getroot() + ns = root.nsmap["caom2"] + collection = self._get_child_element("collection", root, ns, True).text + observationID = \ + self._get_child_element("observationID", root, ns, True).text + # Instantiate Algorithm + algorithm = self._get_algorithm("algorithm", root, ns, True) + # Instantiate Observation + if root.get("{http://www.w3.org/2001/XMLSchema-instance}type") \ + == "caom2:SimpleObservation": + obs = observation.SimpleObservation(collection, observationID) + obs.algorithm = algorithm + else: + obs = \ + observation.CompositeObservation(collection, observationID, algorithm) + # Instantiate children of Observation + obs.sequence_number = \ + self._get_child_text_as_int("sequenceNumber", root, ns, False) + obs.obs_type = \ + self._get_child_text("type", root, ns, False) + intent = self._get_child_text("intent", root, ns, False) + if intent: + obs.intent = obs.ObservationIntentType.getByValue(intent) + obs.meta_release = \ + self._get_meta_release("metaRelease", root, ns, False) + obs.proposal = \ + self._get_proposal("proposal", root, ns, False) + obs.target = \ + self._get_target("target", root, ns, False) + obs.target_position = \ + self._get_target_position("targetPosition", root, ns, False) + obs.telescope = \ + self._get_telescope("telescope", root, ns, False) + obs.instrument = \ + self._get_instrument("instrument", root, ns, False) + obs.environment = \ + self._get_environment("environment", root, ns, False) + obs.requirements = \ + self._get_requirements("requirements", root, ns, False) + self._add_planes(obs.planes, root, ns) + if isinstance(obs, obs.CompositeObservation): + self._add_members(obs.members, root, ns) + + self._set_entity_attributes(root, ns, obs) + return obs + + +class ObservationWriter(object): + """ ObservationWriter """ + + def __init__(self, validate=False, write_empty_collections=False, + namespace_prefix="caom2", namespace=None): + """ + Arguments: + validate : If True enable schema validation, False otherwise + write_empty_collections : if True write empty elements for empty collections + namespace_prefix : a CAOM-2.x namespace prefix + namespace : a valid CAOM-2.x target namespace + """ + self._validate = validate + self._write_empty_collections = write_empty_collections + + if namespace_prefix is None or not namespace_prefix: + raise RuntimeError('null or empty namespace_prefix not allowed') + + if namespace is None or namespace == CAOM22_NAMESPACE: + self._output_version = 22 + self._caom2_namespace = CAOM22 + self._namespace = CAOM22_NAMESPACE + elif namespace == CAOM21_NAMESPACE: + self._output_version = 21 + self._caom2_namespace = CAOM21 + self._namespace = CAOM21_NAMESPACE + elif namespace == CAOM20_NAMESPACE: + self._output_version = 20 + self._caom2_namespace = CAOM20 + self._namespace = CAOM20_NAMESPACE + else: + raise RuntimeError('invalid namespace {}'.format(namespace)) + + if self._validate: + if self._output_version == 20: + schema_file = CAOM20_SCHEMA_FILE + elif self._output_version == 21: + schema_file = CAOM21_SCHEMA_FILE + else: + schema_file = CAOM22_SCHEMA_FILE + schema_path = pkg_resources.resource_filename( + CAOM2_PKG, schema_file) + xmlschema_doc = etree.parse(schema_path) + self._xmlschema = etree.XMLSchema(xmlschema_doc) + + self._nsmap = {namespace_prefix: self._namespace, "xsi": XSI_NAMESPACE} + + def write(self, observation, out): + assert isinstance(observation, observation.Observation), ( + "observation is not an Observation") + + obs = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) + if isinstance(observation, observation.SimpleObservation): + obs.set(XSI + "type", "caom2:SimpleObservation") + else: + obs.set(XSI + "type", "caom2:CompositeObservation") + + self._add_enity_attributes(observation, obs) + + self._add_element("collection", observation.collection, obs) + self._add_element("observationID", observation.observation_id, obs) + self._add_datetime_element("metaRelease", observation.meta_release, obs) + self._add_element("sequenceNumber", observation.sequence_number, obs) + self._add_algorithm_element(observation.algorithm, obs) + self._add_element("type", observation.obs_type, obs) + if observation.intent is not None: + self._add_element( + "intent", observation.ObservationIntentType.get(str(observation.intent)).value, obs) + + self._add_proposal_element(observation.proposal, obs) + self._add_target_element(observation.target, obs) + self._add_target_position_element(observation.target_position, obs) + self._add_requirements_element(observation.requirements, obs) + self._add_telescope_element(observation.telescope, obs) + self._add_instrument_element(observation.instrument, obs) + self._add_environment_element(observation.environment, obs) + self._add_planes_element(observation.planes, obs) + + if isinstance(observation, observation.CompositeObservation): + self._add_members_element(observation.members, obs) + + if self._validate and self._xmlschema: + self._xmlschema.assertValid(obs) + + out.write(etree.tostring(obs, xml_declaration=True, encoding='UTF-8', + pretty_print=True)) + + def _add_enity_attributes(self, entity, element): + if self._output_version == 20: + uid = Util.uuid2long(entity._id) + self._add_attribute("id", str(uid), element) + else: + self._add_attribute("id", str(entity._id), element) + + if entity._last_modified is not None: + self._add_attribute( + "lastModified", Util.date2ivoa(entity._last_modified), element) + + def _add_algorithm_element(self, algorithm, parent): + if algorithm is None: + return + + element = self._get_caom_element("algorithm", parent) + self._add_element("name", algorithm.name, element) + + def _add_proposal_element(self, proposal, parent): + if proposal is None: + return + + element = self._get_caom_element("proposal", parent) + self._add_element("id", proposal.proposal_id, element) + self._add_element("pi", proposal.pi_name, element) + self._add_element("project", proposal.project, element) + self._add_element("title", proposal.title, element) + self._add_list_element("keywords", proposal.keywords, element) + + def _add_target_element(self, target, parent): + if target is None: + return + + element = self._get_caom_element("target", parent) + self._add_element("name", target.name, element) + if target.target_type is not None: + self._add_element( + "type", observation.TargetType.get(str(target.target_type)).value, element) + if target.standard is not None: + self._add_element("standard", str(target.standard).lower(), element) + self._add_element("redshift", target.redshift, element) + if target.moving is not None: + self._add_element("moving", str(target.moving).lower(), element) + self._add_list_element("keywords", target.keywords, element) + + def _add_target_position_element(self, target_position, parent): + if target_position is None: + return + + element = self._get_caom_element("targetPosition", parent) + self._add_element("coordsys", target_position.coordsys, element) + if target_position.equinox is not None: + self._add_element("equinox", target_position.equinox, element) + self._add_point_element("coordinates", target_position.coordinates, + element) + + def _add_requirements_element(self, requirements, parent): + if self._output_version < 21: + return # Requirements added in CAOM-2.1 + if requirements is None: + return + + element = self._get_caom_element("requirements", parent) + self._add_element( + "flag", observation.Status.get(str(requirements.flag)).value, element) + + def _add_telescope_element(self, telescope, parent): + if telescope is None: + return + + element = self._get_caom_element("telescope", parent) + self._add_element("name", telescope.name, element) + self._add_element("geoLocationX", telescope.geo_location_x, element) + self._add_element("geoLocationY", telescope.geo_location_y, element) + self._add_element("geoLocationZ", telescope.geo_location_z, element) + self._add_list_element("keywords", telescope.keywords, element) + + def _add_instrument_element(self, instrument, parent): + if instrument is None: + return + + element = self._get_caom_element("instrument", parent) + self._add_element("name", instrument.name, element) + self._add_list_element("keywords", instrument.keywords, element) + + def _add_environment_element(self, environment, parent): + if environment is None: + return + + element = self._get_caom_element("environment", parent) + self._add_element("seeing", environment.seeing, element) + self._add_element("humidity", environment.humidity, element) + self._add_element("elevation", environment.elevation, element) + self._add_element("tau", environment.tau, element) + self._add_element("wavelengthTau", environment.wavelength_tau, element) + self._add_element("ambientTemp", environment.ambient_temp, element) + if environment.photometric is not None: + self._add_element("photometric", + str(environment.photometric).lower(), element) + + def _add_members_element(self, members, parent): + if members is None or \ + (len(members) == 0 and not self._write_empty_collections): + return + + element = self._get_caom_element("members", parent) + for member in members: + member_element = self._get_caom_element("observationURI", element) + member_element.text = member.uri + + def _add_planes_element(self, planes, parent): + if planes is None or \ + (len(planes) == 0 and not self._write_empty_collections): + return + + element = self._get_caom_element("planes", parent) + for plane in planes.itervalues(): + plane_element = self._get_caom_element("plane", element) + self._add_enity_attributes(plane, plane_element) + self._add_element("productID", plane.product_id, plane_element) + self._add_datetime_element("metaRelease", plane.meta_release, + plane_element) + self._add_datetime_element("dataRelease", plane.data_release, + plane_element) + if plane.data_product_type is not None: + self._add_element("dataProductType", + plane.DataProductType.get(str(plane.data_product_type)).value, + plane_element) + if plane.calibration_level is not None: + self._add_element("calibrationLevel", + plane.CalibrationLevel(str(plane.calibration_level)).value, + plane_element) + self._add_provenance_element(plane.provenance, plane_element) + self._add_metrics_element(plane.metrics, plane_element) + self._add_quality_element(plane.quality, plane_element) + self._add_artifacts_element(plane.artifacts, plane_element) + + def _add_provenance_element(self, provenance, parent): + if provenance is None: + return + + element = self._get_caom_element("provenance", parent) + self._add_element("name", provenance.name, element) + self._add_element("version", provenance.version, element) + self._add_element("project", provenance.project, element) + self._add_element("producer", provenance.producer, element) + self._add_element("runID", provenance.run_id, element) + self._add_element("reference", provenance.reference, element) + self._add_datetime_element("lastExecuted", provenance.last_executed, + element) + self._add_list_element("keywords", provenance.keywords, element) + self._add_inputs_element("inputs", provenance.inputs, element) + + def _add_metrics_element(self, metrics, parent): + if metrics is None: + return + + element = self._get_caom_element("metrics", parent) + self._add_element("sourceNumberDensity", metrics.source_number_density, + element) + self._add_element("background", metrics.background, element) + self._add_element("backgroundStddev", metrics.background_std_dev, + element) + self._add_element("fluxDensityLimit", metrics.flux_density_limit, + element) + self._add_element("magLimit", metrics.mag_limit, element) + + def _add_quality_element(self, quality, parent): + if self._output_version < 21: + return # Requirements added in CAOM-2.1 + if quality is None: + return + + element = self._get_caom_element("quality", parent) + self._add_element( + "flag", plane.Quality.get(str(quality.flag)).value, element) + + def _add_transition_element(self, transition, parent): + if transition is None: + return + + element = self._get_caom_element("transition", parent) + self._add_element("species", transition.species, element) + self._add_element("transition", transition.transition, element) + + def _add_artifacts_element(self, artifacts, parent): + if artifacts is None: + return + + element = self._get_caom_element("artifacts", parent) + for _artifact in artifacts.itervalues(): + artifact_element = self._get_caom_element("artifact", element) + self._add_enity_attributes(_artifact, artifact_element) + self._add_element("uri", _artifact.uri, artifact_element) + if self._output_version > 21: + self._add_element("productType", artifact.ProductType.get( + str(_artifact.product_type)).value, artifact_element) + self._add_element("releaseType", artifact.ReleaseType.get( + str(_artifact.release_type)).value, artifact_element) + self._add_element("contentType", _artifact.content_type, artifact_element) + self._add_element("contentLength", _artifact.content_length, artifact_element) + if self._output_version < 22: + self._add_element("productType", artifact.ProductType.get( + str(_artifact.product_type)).value, artifact_element) + self._add_parts_element(_artifact.parts, artifact_element) + + def _add_parts_element(self, parts, parent): + if parts is None: + return + + element = self._get_caom_element("parts", parent) + for _part in parts.itervalues(): + part_element = self._get_caom_element("part", element) + self._add_enity_attributes(_part, part_element) + self._add_element("name", _part.name, part_element) + if _part.product_type is not None: + self._add_element("productType", artifact.ProductType.get( + str(_part.product_type)).value, part_element) + self._add_chunks_element(_part.chunks, part_element) + + def _add_chunks_element(self, chunks, parent): + if chunks is None: + return + + element = self._get_caom_element("chunks", parent) + for _chunk in chunks: + chunk_element = self._get_caom_element("chunk", element) + self._add_enity_attributes(_chunk, chunk_element) + if _chunk.product_type is not None: + self._add_element("productType", + artifact.ProductType.get(str(_chunk.product_type)).value, + chunk_element) + self._add_element("naxis", _chunk.naxis, chunk_element) + self._add_element("observableAxis", _chunk.observable_axis, + chunk_element) + self._add_element("positionAxis1", _chunk.position_axis_1, + chunk_element) + self._add_element("positionAxis2", _chunk.position_axis_2, + chunk_element) + self._add_element("energyAxis", _chunk.energy_axis, chunk_element) + self._add_element("timeAxis", _chunk.time_axis, chunk_element) + self._add_element("polarizationAxis", _chunk.polarization_axis, + chunk_element) + + self._add_observable_axis_element(_chunk.observable, chunk_element) + self._add_spatial_wcs_element(_chunk.position, chunk_element) + self._add_spectral_wcs_element(_chunk.energy, chunk_element) + self._add_temporal_wcs_element(_chunk.time, chunk_element) + self._add_polarization_wcs_element(_chunk.polarization, chunk_element) + + def _add_observable_axis_element(self, observable, parent): + if observable is None: + return + + element = self._get_caom_element("observable", parent) + self._add_slice_element("dependent", observable.dependent, element) + self._add_slice_element("independent", observable.independent, element) + + def _add_spatial_wcs_element(self, position, parent): + """ Builds a representation of a SpatialWCS and adds it to the + parent element. """ + if position is None: + return + + element = self._get_caom_element("position", parent) + self._add_coord_axis_2d_element("axis", position.axis, element) + self._add_element("coordsys", position.coordsys, element) + self._add_element("equinox", position.equinox, element) + self._add_element("resolution", position.resolution, element) + + def _add_spectral_wcs_element(self, energy, parent): + """ Builds a representation of a SpectralWCS and adds it to the + parent element.""" + if energy is None: + return + + element = self._get_caom_element("energy", parent) + self._add_coord_axis_1d_element("axis", energy.axis, element) + self._add_element("specsys", energy.specsys, element) + self._add_element("ssysobs", energy.ssysobs, element) + self._add_element("ssyssrc", energy.ssyssrc, element) + self._add_element("restfrq", energy.restfrq, element) + self._add_element("restwav", energy.restwav, element) + self._add_element("velosys", energy.velosys, element) + self._add_element("zsource", energy.zsource, element) + self._add_element("velang", energy.velang, element) + self._add_element("bandpassName", energy.bandpass_name, element) + self._add_element("resolvingPower", energy.resolving_power, element) + self._add_transition_element(energy.transition, element) + + def _add_temporal_wcs_element(self, time, parent): + """ Builds a representation of a TemporalWCS and adds it to the + parent element. """ + if time is None: + return + + element = self._get_caom_element("time", parent) + self._add_coord_axis_1d_element("axis", time.axis, element) + self._add_element("timesys", time.timesys, element) + self._add_element("trefpos", time.trefpos, element) + self._add_element("mjdref", time.mjdref, element) + self._add_element("exposure", time.exposure, element) + self._add_element("resolution", time.resolution, element) + + def _add_polarization_wcs_element(self, polarization, parent): + """ Builds a representation of a PolarizationWCS and adds it to the + parent element. """ + if polarization is None: + return + + element = self._get_caom_element("polarization", parent) + self._add_coord_axis_1d_element("axis", polarization.axis, element) + + #/*+ CAOM2 Types #-*/ + + def _add_point_element(self, name, point, parent): + """ Builds a representation of a Point and adds it to the + parent element. """ + if point is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("cval1", point.cval1, element) + self._add_element("cval2", point.cval2, element) + + #/*+ WCS Types #-*/ + + def _add_axis_element(self, name, axis, parent): + """ Builds a representation of a Axis and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("ctype", axis.ctype, element) + if axis.cunit: + self._add_element("cunit", axis.cunit, element) + + def _add_coord_2d_element(self, name, coord, parent): + """ Builds a representation of a Coord2D and adds it to the + parent element. """ + if coord is None: + return + + element = self._get_caom_element(name, parent) + self._add_ref_coord_element("coord1", coord.coord1, element) + self._add_ref_coord_element("coord2", coord.coord2, element) + + def _add_value_coord_2d_element(self, name, coord, parent): + """ Builds a representation of a ValueCoord2D and adds it to the + parent element. """ + if coord is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("coord1", coord.coord1, element) + self._add_element("coord2", coord.coord2, element) + + def _add_coord_axis_1d_element(self, name, axis, parent): + """ Builds a representation of a CoordAxis1D and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis", axis.axis, element) + self._add_coord_error_element("error", axis.error, element) + self._add_coord_range_1d_element("range", axis.range, element) + self._add_coord_bounds_1d_element("bounds", axis.bounds, element) + self._add_coord_function_1d_element("function", axis.function, element) + + def _add_coord_axis_2d_element(self, name, axis, parent): + """ Builds a representation of a CoordAxis2D and adds it to the + parent element. """ + if axis is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis1", axis.axis1, element) + self._add_axis_element("axis2", axis.axis2, element) + self._add_coord_error_element("error1", axis.error1, element) + self._add_coord_error_element("error2", axis.error2, element) + self._add_coord_range_2d_element("range", axis.range, element) + self._add_coord_bounds_2d_element("bounds", axis.bounds, element) + self._add_coord_function_2d_element("function", axis.function, element) + + def _add_coord_bounds_1d_element(self, name, bounds, parent): + """ Builds a representation of a CoordBounds1D and adds it to the + parent element. """ + if bounds is None: + return + + element = self._get_caom_element(name, parent) + self._add_coord_range_1d_list_element("samples", bounds.samples, element) + + def _add_coord_bounds_2d_element(self, name, bounds, parent): + """Builds a representation of a CoordBounds2D and adds it to the + parent element. """ + if bounds is None: + return + + element = self._get_caom_element(name, parent) + if isinstance(bounds, wcs.CoordCircle2D): + self._add_coord_circle_2d_element("circle", + wcs.CoordCircle2D(bounds.center, + bounds.radius), element) + elif isinstance(bounds, wcs.CoordPolygon2D): + self._add_coord_polygon_2d_element("polygon", bounds, element) + else: + raise TypeError("BUG: unsupported CoordBounds2D type " + + bounds.__class__.__name__) + + def _add_coord_circle_2d_element(self, name, circle, parent): + """ Builds a representation of a CoordCircle2D and adds it to the + parent element. """ + if circle is None: + return + + element = self._get_caom_element(name, parent) + self._add_value_coord_2d_element("center", circle.center, element) + self._add_element("radius", circle.radius, element) + + def _add_coord_error_element(self, name, error, parent): + """ Builds a representation of a CoordError and adds it to the + parent element. """ + if error is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("syser", error.syser, element) + self._add_element("rnder", error.rnder, element) + + def _add_coord_function_1d_element(self, name, function, parent): + """ Builds a representation of a CoordFunction1D and adds it to the + parent element. """ + if function is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("naxis", function.naxis, element) + self._add_element("delta", function.delta, element) + self._add_ref_coord_element("refCoord", function.ref_coord, element) + + def _add_coord_function_2d_element(self, name, function, parent): + """ Builds a representation of a CoordFunction2D and adds it to the + parent element. """ + if function is None: + return + + element = self._get_caom_element(name, parent) + self._add_dimension_2d_element("dimension", function.dimension, element) + self._add_coord_2d_element("refCoord", function.ref_coord, element) + self._add_element("cd11", function.cd11, element) + self._add_element("cd12", function.cd12, element) + self._add_element("cd21", function.cd21, element) + self._add_element("cd22", function.cd22, element) + + def _add_coord_polygon_2d_element(self, name, polygon, parent): + """ Builds a representation of a CoordPolygon2D and adds it to the + parent element. """ + if polygon is None: + return + + element = self._get_caom_element(name, parent) + if len(polygon.vertices) > 0: + vertices_element = self._get_caom_element("vertices", element) + for vertex in polygon.vertices: + self._add_value_coord_2d_element("vertex", vertex, vertices_element) + + def _add_coord_range_1d_element(self, name, _range, parent): + """ Builds a representation of a CoordRange1D and adds it to the + parent element. """ + if _range is None: + return + + element = self._get_caom_element(name, parent) + self._add_ref_coord_element("start", _range.start, element) + self._add_ref_coord_element("end", _range.end, element) + + def _add_coord_range_2d_element(self, name, _range, parent): + """ Builds a representation of a CoordRange2D and adds it to the + parent element. """ + if _range is None: + return + + element = self._get_caom_element(name, parent) + self._add_coord_2d_element("start", _range.start, element) + self._add_coord_2d_element("end", _range.end, element) + + def _add_dimension_2d_element(self, name, dimension, parent): + """ Builds a representation of a Dimension2D and adds it to the + parent element. """ + if dimension is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("naxis1", dimension.naxis1, element) + self._add_element("naxis2", dimension.naxis2, element) + + def _add_ref_coord_element(self, name, refCoord, parent): + """ Builds a representation of a RefCoord and adds it to the + parent element. """ + if refCoord is None: + return + + element = self._get_caom_element(name, parent) + self._add_element("pix", refCoord.pix, element) + self._add_element("val", refCoord.val, element) + + def _add_slice_element(self, name, _slice, parent): + """ Builds a representation of a Slice and adds it to the + parent element. """ + if _slice is None: + return + + element = self._get_caom_element(name, parent) + self._add_axis_element("axis", _slice.axis, element) + self._add_element("bin", _slice.bin, element) + + def _add_attribute(self, name, value, element): + element.set(self._caom2_namespace + name, value) + + def _add_element(self, name, text, parent): + if text is None: + return + element = self._get_caom_element(name, parent) + if isinstance(text, str): + element.text = text + else: + element.text = str(text) + + def _add_datetime_element(self, name, value, parent): + if value is None: + return + element = self._get_caom_element(name, parent) + element.text = Util.date2ivoa(value) + + def _add_list_element(self, name, collection, parent): + if collection is None or \ + (len(collection) == 0 and not self._write_empty_collections): + return + element = self._get_caom_element(name, parent) + element.text = ' '.join(collection) + + def _add_coord_range_1d_list_element(self, name, values, parent): + if values is None: + return + element = self._get_caom_element(name, parent) + for v in values: + self._add_coord_range_1d_element("range", v, element) + + def _add_inputs_element(self, name, collection, parent): + if collection is None or \ + (len(collection) == 0 and not self._write_empty_collections): + return + element = self._get_caom_element(name, parent) + for plane_uri in collection: + self._add_element("planeURI", plane_uri.uri, element) + + def _get_caom_element(self, tag, parent): + return etree.SubElement(parent, self._caom2_namespace + tag) + + +class ObservationParsingException(Exception): + pass + diff --git a/caom2tools/caom2/requirements.txt b/caom2tools/requirements.txt similarity index 100% rename from caom2tools/caom2/requirements.txt rename to caom2tools/requirements.txt diff --git a/caom2tools/caom2/setup.cfg b/caom2tools/setup.cfg similarity index 100% rename from caom2tools/caom2/setup.cfg rename to caom2tools/setup.cfg diff --git a/caom2tools/caom2/setup.py b/caom2tools/setup.py similarity index 100% rename from caom2tools/caom2/setup.py rename to caom2tools/setup.py From 5336a7e1cc51d3d4c59d55c631b70af1ffecfaa6 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 15 Nov 2016 08:08:28 -0800 Subject: [PATCH 06/54] s1950: update imports in caom_test_instances.py --- caom2tools/caom2/tests/caom_test_instances.py | 286 ++++++++---------- 1 file changed, 125 insertions(+), 161 deletions(-) diff --git a/caom2tools/caom2/tests/caom_test_instances.py b/caom2tools/caom2/tests/caom_test_instances.py index ad0e1b21..5eb23272 100644 --- a/caom2tools/caom2/tests/caom_test_instances.py +++ b/caom2tools/caom2/tests/caom_test_instances.py @@ -73,57 +73,13 @@ import collections from datetime import datetime -# from caom2.caom2_algorithm import Algorithm -# from caom2.artifact import Artifact -# from caom2.chunk import Chunk -# from caom2.caom2_composite_observation import CompositeObservation -# from caom2.caom2_data_quality import DataQuality -# from caom2.caom2_energy_transition import EnergyTransition -# from caom2.caom_enums import CalibrationLevel -# from caom2.caom_enums import DataProductType -# from caom2.caom_enums import ObservationIntentType -# from caom2.caom_enums import ProductType -# from caom2.caom_enums import Quality -# from caom2.caom_enums import Status -# from caom2.caom_enums import TargetType -# from caom2.caom_enums import ReleaseType -# from caom2.caom2_environment import Environment -# from caom2.caom2_instrument import Instrument -# from caom2.caom2_metrics import Metrics -# from caom2.caom2_observation_uri import ObservationURI -# from caom2.part import Part -# from caom2.plane import Plane -# from caom2.caom2_plane_uri import PlaneURI -# from caom2.caom2_proposal import Proposal -# from caom2.caom2_provenance import Provenance -# from caom2.caom2_requirements import Requirements -# from caom2.caom2_simple_observation import SimpleObservation -# from caom2.caom2_target import Target -# from caom2.caom2_target_position import TargetPosition -# from caom2.caom2_telescope import Telescope -# from caom2.data_type.caom2_point import Point -# from caom2.util.caom2_util import TypedList, TypedSet -# from caom2.wcs.caom2_axis import Axis -# from caom2.wcs.caom2_coord2d import Coord2D -# from caom2.wcs.caom2_coord_axis1d import CoordAxis1D -# from caom2.wcs.caom2_coord_axis2d import CoordAxis2D -# from caom2.wcs.caom2_coord_bounds1d import CoordBounds1D -# from caom2.wcs.caom2_coord_circle2d import CoordCircle2D -# from caom2.wcs.caom2_coord_error import CoordError -# from caom2.wcs.caom2_coord_function1d import CoordFunction1D -# from caom2.wcs.caom2_coord_function2d import CoordFunction2D -# from caom2.wcs.caom2_coord_polygon2d import CoordPolygon2D -# from caom2.wcs.caom2_coord_range1d import CoordRange1D -# from caom2.wcs.caom2_coord_range2d import CoordRange2D -# from caom2.wcs.caom2_dimension2d import Dimension2D -# from caom2.wcs.caom2_observable_axis import ObservableAxis -# from caom2.wcs.caom2_polarization_wcs import PolarizationWCS -# from caom2.wcs.caom2_ref_coord import RefCoord -# from caom2.wcs.caom2_slice import Slice -# from caom2.wcs.caom2_spatial_wcs import SpatialWCS -# from caom2.wcs.caom2_spectral_wcs import SpectralWCS -# from caom2.wcs.caom2_temporal_wcs import TemporalWCS -# from caom2.wcs.caom2_value_coord2d import ValueCoord2D +from caom2 import artifact +from caom2 import chunk +from caom2 import observation as obs +from caom2 import part +from caom2 import plane +from caom2 import util +from caom2 import wcs class Caom2TestInstances(object): @@ -173,13 +129,13 @@ def caom_version(self, v): self._caom_version = v def get_simple_observation(self): - observation = SimpleObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id) + observation = \ + obs.SimpleObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id) if self.complete: observation.sequence_number = int(5) observation.obs_type = "flat" - observation.intent = ( - ObservationIntentType.CALIBRATION) + observation.intent = obs.ObservationIntentType.CALIBRATION observation.meta_release = Caom2TestInstances._ivoa_date observation.proposal = self.get_proposal() observation.target = self.get_target() @@ -194,14 +150,14 @@ def get_simple_observation(self): return observation def get_composite_observation(self): - observation = CompositeObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id, - self.get_algorithm()) + observation = \ + obs.CompositeObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id, + self.get_algorithm()) if self.complete: observation.sequence_number = int(10) observation.obs_type = "filed" - observation.intent = ( - ObservationIntentType.SCIENCE) + observation.intent = obs.ObservationIntentType.SCIENCE observation.meta_release = Caom2TestInstances._ivoa_date observation.proposal = self.get_proposal() observation.target = self.get_target() @@ -217,10 +173,10 @@ def get_composite_observation(self): return observation def get_algorithm(self): - return Algorithm("algorithmName") + return obs.Algorithm("algorithmName") def get_proposal(self): - proposal = Proposal("proposalId") + proposal = obs.Proposal("proposalId") proposal.pi_name = "proposalPi" proposal.project = "proposalProject" proposal.title = "proposalTitle" @@ -228,24 +184,24 @@ def get_proposal(self): return proposal def get_target(self): - target = Target("targetName") - target.target_type = TargetType.OBJECT + target = obs.Target("targetName") + target.target_type = obs.TargetType.OBJECT target.standard = False target.redshift = 1.5 target.keywords.update(Caom2TestInstances._keywords) return target def get_target_position(self): - point = Point(1.0, 2.0) - target_position = TargetPosition(point, "coordsys") + point = wcs.Point(1.0, 2.0) + target_position = obs.TargetPosition(point, "coordsys") target_position.equinox = 3.0 return target_position def get_requirements(self): - return Requirements(Status.FAIL) + return obs.Requirements(obs.Status.FAIL) def get_telescope(self): - telescope = Telescope("telescopeName") + telescope = obs.Telescope("telescopeName") telescope.geo_location_x = 1.0 telescope.geo_location_y = 2.0 telescope.geo_location_z = 3.0 @@ -253,12 +209,12 @@ def get_telescope(self): return telescope def get_instrument(self): - instrument = Instrument("instrumentName") + instrument = obs.Instrument("instrumentName") instrument.keywords.update(Caom2TestInstances._keywords) return instrument def get_environment(self): - env = Environment() + env = obs.Environment() env.seeing = 0.08 env.humidity = 0.35 env.elevation = 2.7 @@ -269,31 +225,31 @@ def get_environment(self): return env def get_members(self): - members = TypedSet( - ObservationURI, ObservationURI("caom:foo/bar")) + members = util.TypedSet( + obs.ObservationURI, obs.ObservationURI("caom:foo/bar")) return members def get_planes(self): planes = collections.OrderedDict() - plane = Plane("productID") + _plane = plane.Plane("productID") if self.complete: - plane.meta_release = Caom2TestInstances._ivoa_date - plane.data_release = Caom2TestInstances._ivoa_date - plane.data_product_type = DataProductType.IMAGE - plane.calibration_level = CalibrationLevel.PRODUCT - plane.provenance = self.get_provenance() - plane.metrics = self.get_metrics() + _plane.meta_release = Caom2TestInstances._ivoa_date + _plane.data_release = Caom2TestInstances._ivoa_date + _plane.data_product_type = plane.DataProductType.IMAGE + _plane.calibration_level = plane.CalibrationLevel.PRODUCT + _plane.provenance = self.get_provenance() + _plane.metrics = self.get_metrics() if self.caom_version == 21: - plane.quality = self.get_quality() + _plane.quality = self.get_quality() if self.depth > 2: for k, v in self.get_artifacts().iteritems(): - plane.artifacts[k] = v - planes["productID"] = plane + _plane.artifacts[k] = v + planes["productID"] = _plane return planes def get_provenance(self): - provenance = Provenance("name") + provenance = plane.Provenance("name") provenance.version = "version" provenance.product = "product" provenance.producer = "producer" @@ -305,11 +261,12 @@ def get_provenance(self): return provenance def get_inputs(self): - return TypedSet(PlaneURI, PlaneURI("caom:foo/bar/plane1"), - PlaneURI("caom:foo/bar/plane2")) + return util.TypedSet(plane.PlaneURI, + plane.PlaneURI("caom:foo/bar/plane1"), + plane.PlaneURI("caom:foo/bar/plane2")) def get_metrics(self): - metrics = Metrics() + metrics = plane.Metrics() metrics.source_number_density = float(1.0) metrics.background = float(2.0) metrics.background_std_dev = float(3.0) @@ -318,60 +275,62 @@ def get_metrics(self): return metrics def get_quality(self): - return DataQuality(Quality.JUNK) + return plane.DataQuality(plane.Quality.JUNK) def get_artifacts(self): artifacts = collections.OrderedDict() - artifact = Artifact("ad:foo/bar1", ProductType.SCIENCE, ReleaseType.META) + _artifact = artifact.Artifact("ad:foo/bar1", + artifact.ProductType.SCIENCE, + artifact.ReleaseType.META) if self.complete: - artifact.content_type = "application/fits" - artifact.content_length = 12345L + _artifact.content_type = "application/fits" + _artifact.content_length = 12345L if self.depth > 3: for k, v in self.get_parts().iteritems(): - artifact.parts[k] = v - artifacts["ad:foo/bar1"] = artifact + _artifact.parts[k] = v + artifacts["ad:foo/bar1"] = _artifact return artifacts def get_parts(self): parts = collections.OrderedDict() - part = Part("x") + _part = part.Part("x") if self.complete: - part.product_type = ProductType.SCIENCE + _part.product_type = artifact.ProductType.SCIENCE if self.depth > 4: for chunk in self.get_chunks(): - part.chunks.append(chunk) - parts["x"] = part + _part.chunks.append(chunk) + parts["x"] = _part return parts def get_chunks(self): - chunks = TypedList(Chunk,) - chunk = Chunk() + chunks = util.TypedList(chunk.Chunk,) + _chunk = chunk.Chunk() if self.complete: - chunk.product_type = ProductType.SCIENCE - chunk.naxis = 5 - chunk.observable_axis = 1 - chunk.position_axis_1 = 1 - chunk.position_axis_2 = 2 - chunk.energy_axis = 3 - chunk.time_axis = 4 - chunk.polarization_axis = 5 - chunk.observable = self.get_observable_axis() - chunk.position = self.get_spatial_wcs() - chunk.energy = self.get_spectral_wcs() - chunk.time = self.get_temporal_wcs() - chunk.polarization = self.get_polarization_wcs() - chunks.append(chunk) + _chunk.product_type = artifact.ProductType.SCIENCE + _chunk.naxis = 5 + _chunk.observable_axis = 1 + _chunk.position_axis_1 = 1 + _chunk.position_axis_2 = 2 + _chunk.energy_axis = 3 + _chunk.time_axis = 4 + _chunk.polarization_axis = 5 + _chunk.observable = self.get_observable_axis() + _chunk.position = self.get_spatial_wcs() + _chunk.energy = self.get_spectral_wcs() + _chunk.time = self.get_temporal_wcs() + _chunk.polarization = self.get_polarization_wcs() + chunks.append(_chunk) return chunks def get_observable_axis(self): - observable = ObservableAxis(self.get_slice()) + observable = chunk.ObservableAxis(self.get_slice()) if self.complete: observable.independent = self.get_slice() return observable def get_spatial_wcs(self): - coord_axis_2d = self.get_coord_axis_2d() - position = SpatialWCS(coord_axis_2d) + coord_axis2d = self.get_coord_axis2d() + position = chunk.SpatialWCS(coord_axis2d) if self.complete: position.coordsys = "position coordsys" position.equinox = 2000.0 @@ -379,8 +338,8 @@ def get_spatial_wcs(self): return position def get_spectral_wcs(self): - axis = self.get_coord_axis_1d() - energy = SpectralWCS(axis, "energy specsys") + axis = self.get_coord_axis1d() + energy = chunk.SpectralWCS(axis, "energy specsys") if self.complete: energy.ssysobs = "energy ssysobs" energy.ssyssrc = "energy ssyssrc" @@ -391,12 +350,12 @@ def get_spectral_wcs(self): energy.velang = 5.0 energy.bandpassName = "energy bandpassName" energy.resolvingPower = 6.0 - energy.transition = EnergyTransition("H", "21cm") + energy.transition = plane.EnergyTransition("H", "21cm") return energy def get_temporal_wcs(self): - axis = self.get_coord_axis_1d() - time = TemporalWCS(axis) + axis = self.get_coord_axis1d() + time = chunk.TemporalWCS(axis) if self.complete: time.exposure = 1.0 time.resolution = 2.0 @@ -406,53 +365,58 @@ def get_temporal_wcs(self): return time def get_polarization_wcs(self): - axis = Axis('STOKES') - axis_1d = CoordAxis1D(axis) + axis = wcs.Axis('STOKES') + axis1d = wcs.CoordAxis1D(axis) #IQUV - axis_1d.function = CoordFunction1D(4L, 1.0, RefCoord(1.0, 1.0)) - pol = PolarizationWCS(axis_1d) + axis1d.function = wcs.CoordFunction1D(4L, 1.0, + wcs.RefCoord(1.0, 1.0)) + pol = chunk.PolarizationWCS(axis1d) return pol def get_slice(self): - return Slice(Axis("sliceCtype", "sliceCunit"), 1L) + return wcs.Slice(wcs.Axis("sliceCtype", "sliceCunit"), 1L) - def get_coord_axis_1d(self): - coord_axis_1d = CoordAxis1D(Axis("axisCtype", "axisCunit")) + def get_coord_axis1d(self): + coord_axis1d = wcs.CoordAxis1D(wcs.Axis("axisCtype", "axisCunit")) if self.complete: - coord_axis_1d.error = CoordError(1.0, 1.5) - coord_axis_1d.range = CoordRange1D(RefCoord(2.0, 2.5), - RefCoord(3.0, 3.5)) - coord_axis_1d.function = ( - CoordFunction1D(4L, 4.5, RefCoord(5.0, 5.5))) - bounds = CoordBounds1D() - bounds.samples.append(CoordRange1D(RefCoord(6.0, 6.5), - RefCoord(7.0, 7.5))) - bounds.samples.append(CoordRange1D(RefCoord(8.0, 8.5), - RefCoord(9.0, 9.5))) - coord_axis_1d.bounds = bounds - return coord_axis_1d - - def get_coord_axis_2d(self): - axis1 = Axis("axis1Ctype", "axis1Cunit") - axis2 = Axis("axis2Ctype", "axis2Cunit") - coord_axis_2d = CoordAxis2D(axis1, axis2) + coord_axis1d.error = wcs.CoordError(1.0, 1.5) + coord_axis1d.range = wcs.CoordRange1D(wcs.RefCoord(2.0, 2.5), + wcs.RefCoord(3.0, 3.5)) + coord_axis1d.function = ( + wcs.CoordFunction1D(4L, 4.5, wcs.RefCoord(5.0, 5.5))) + bounds = wcs.CoordBounds1D() + bounds.samples.append(wcs.CoordRange1D(wcs.RefCoord(6.0, 6.5), + wcs.RefCoord(7.0, 7.5))) + bounds.samples.append(wcs.CoordRange1D(wcs.RefCoord(8.0, 8.5), + wcs.RefCoord(9.0, 9.5))) + coord_axis1d.bounds = bounds + return coord_axis1d + + def get_coord_axis2d(self): + axis1 = wcs.Axis("axis1Ctype", "axis1Cunit") + axis2 = wcs.Axis("axis2Ctype", "axis2Cunit") + coord_axis2d = wcs.CoordAxis2D(axis1, axis2) if self.complete: - coord_axis_2d.error1 = CoordError(1.0, 1.5) - coord_axis_2d.error2 = CoordError(2.0, 2.5) - start = Coord2D(RefCoord(3.0, 3.5), RefCoord(4.0, 4.5)) - end = Coord2D(RefCoord(5.0, 5.5), RefCoord(6.0, 6.5)) - coord_axis_2d.range = CoordRange2D(start, end) - dimension = Dimension2D(7L, 8L) - ref_coord = Coord2D(RefCoord(9.0, 9.5), RefCoord(10.0, 10.5)) - coord_axis_2d.function = (CoordFunction2D(dimension, ref_coord, - 11.0, 12.0, 13.0, 14.0)) + coord_axis2d.error1 = wcs.CoordError(1.0, 1.5) + coord_axis2d.error2 = wcs.CoordError(2.0, 2.5) + start = wcs.Coord2D(wcs.RefCoord(3.0, 3.5), + wcs.RefCoord(4.0, 4.5)) + end = wcs.Coord2D(wcs.RefCoord(5.0, 5.5), + wcs.RefCoord(6.0, 6.5)) + coord_axis2d.range = wcs.CoordRange2D(start, end) + dimension = wcs.Dimension2D(7L, 8L) + ref_coord = wcs.Coord2D(wcs.RefCoord(9.0, 9.5), + wcs.RefCoord(10.0, 10.5)) + coord_axis2d.function = ( + wcs.CoordFunction2D(dimension, ref_coord, + 11.0, 12.0, 13.0, 14.0)) if self.bounds_is_circle: - center = ValueCoord2D(15.0, 16.0) - coord_axis_2d.bounds = CoordCircle2D(center, 17.0) + center = wcs.ValueCoord2D(15.0, 16.0) + coord_axis2d.bounds = wcs.CoordCircle2D(center, 17.0) else: - polygon = CoordPolygon2D() - polygon.vertices.append(ValueCoord2D(15.0, 16.0)) - polygon.vertices.append(ValueCoord2D(17.0, 18.0)) - polygon.vertices.append(ValueCoord2D(19.0, 20.0)) - coord_axis_2d.bounds = polygon - return coord_axis_2d + polygon = wcs.CoordPolygon2D() + polygon.vertices.append(wcs.ValueCoord2D(15.0, 16.0)) + polygon.vertices.append(wcs.ValueCoord2D(17.0, 18.0)) + polygon.vertices.append(wcs.ValueCoord2D(19.0, 20.0)) + coord_axis2d.bounds = polygon + return coord_axis2d From 83a4ef49c7de26215774947210c4fb46ef83fcb6 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 15 Nov 2016 08:14:07 -0800 Subject: [PATCH 07/54] s1950: renamed data_type.py to shape.py --- caom2tools/caom2/__init__.py | 12 ++++++------ caom2tools/caom2/observation.py | 2 +- caom2tools/caom2/plane.py | 8 ++++---- caom2tools/caom2/{data_type.py => shape.py} | 0 caom2tools/caom2/tests/test_observation.py | 2 +- .../tests/{test_data_type.py => test_shape.py} | 4 ++-- caom2tools/caom2/xml_reader_writer.py | 14 +++++++------- 7 files changed, 21 insertions(+), 21 deletions(-) rename caom2tools/caom2/{data_type.py => shape.py} (100%) rename caom2tools/caom2/tests/{test_data_type.py => test_shape.py} (98%) diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index 5cb9d73b..77f4911e 100755 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -103,12 +103,12 @@ from wcs import EnergyTransition # Discovery data types -from data_type import Box -from data_type import Circle -from data_type import Interval -from data_type import Point -from data_type import Polygon -from data_type import Vertex +from shape import Box +from shape import Circle +from shape import Interval +from shape import Point +from shape import Polygon +from shape import Vertex # Chunk level classes from chunk import Chunk diff --git a/caom2tools/caom2/observation.py b/caom2tools/caom2/observation.py index 6e82dcde..110e078a 100644 --- a/caom2tools/caom2/observation.py +++ b/caom2tools/caom2/observation.py @@ -75,7 +75,7 @@ from caom_object import AbstractCaomEntity from caom_object import CaomObject -from data_type import Point +from shape import Point from enum import Enum from plane import Plane from util import TypedOrderedDict diff --git a/caom2tools/caom2/plane.py b/caom2tools/caom2/plane.py index 6f4b2163..21fd7ed0 100644 --- a/caom2tools/caom2/plane.py +++ b/caom2tools/caom2/plane.py @@ -77,10 +77,10 @@ from artifact import Artifact from caom_object import AbstractCaomEntity from caom_object import CaomObject -from data_type import Box -from data_type import Circle -from data_type import Interval -from data_type import Polygon +from shape import Box +from shape import Circle +from shape import Interval +from shape import Polygon from enum import Enum from observation import ObservationURI from util import TypedOrderedDict diff --git a/caom2tools/caom2/data_type.py b/caom2tools/caom2/shape.py similarity index 100% rename from caom2tools/caom2/data_type.py rename to caom2tools/caom2/shape.py diff --git a/caom2tools/caom2/tests/test_observation.py b/caom2tools/caom2/tests/test_observation.py index f9bf55c3..467856a6 100644 --- a/caom2tools/caom2/tests/test_observation.py +++ b/caom2tools/caom2/tests/test_observation.py @@ -73,7 +73,7 @@ import unittest from datetime import datetime -from caom2.data_type import Point +from caom2.shape import Point from caom2.observation import Algorithm from caom2.observation import CompositeObservation from caom2.observation import Environment diff --git a/caom2tools/caom2/tests/test_data_type.py b/caom2tools/caom2/tests/test_shape.py similarity index 98% rename from caom2tools/caom2/tests/test_data_type.py rename to caom2tools/caom2/tests/test_shape.py index 43e85c52..21d0f709 100644 --- a/caom2tools/caom2/tests/test_data_type.py +++ b/caom2tools/caom2/tests/test_shape.py @@ -70,8 +70,8 @@ import unittest -from caom2.data_type import Point -from caom2.data_type import SegmentType +from caom2.shape import Point +from caom2.shape import SegmentType class TestEnums(unittest.TestCase): diff --git a/caom2tools/caom2/xml_reader_writer.py b/caom2tools/caom2/xml_reader_writer.py index 2ca526be..2615c554 100644 --- a/caom2tools/caom2/xml_reader_writer.py +++ b/caom2tools/caom2/xml_reader_writer.py @@ -77,7 +77,7 @@ import artifact import chunk -import data_type +import shape import observation import part import plane @@ -563,8 +563,8 @@ def _get_point(self, elTag, parent, ns, required): if el is None: return None else: - return data_type.Point(self._get_child_text_as_float("cval1", el, ns, True), - self._get_child_text_as_float("cval2", el, ns, True)) + return shape.Point(self._get_child_text_as_float("cval1", el, ns, True), + self._get_child_text_as_float("cval2", el, ns, True)) def _get_axis(self, elTag, parent, ns, required): """Build an Axis object from an XML representation of an Axis element. @@ -582,8 +582,8 @@ def _get_axis(self, elTag, parent, ns, required): if el is None: return None else: - return data_type.Axis(self._get_child_text("ctype", el, ns, True), - self._get_child_text("cunit", el, ns, False)) + return shape.Axis(self._get_child_text("ctype", el, ns, True), + self._get_child_text("cunit", el, ns, False)) def _get_slice(self, elTag, parent, ns, required): """Build a Slice object from an XML representation of a Slice element. @@ -601,8 +601,8 @@ def _get_slice(self, elTag, parent, ns, required): if el is None: return None else: - return data_type.Slice(self._get_axis("axis", el, ns, True), - self._get_child_text_as_long("bin", el, ns, True)) + return shape.Slice(self._get_axis("axis", el, ns, True), + self._get_child_text_as_long("bin", el, ns, True)) def _get_observable_axis(self, elTag, parent, ns, required): """Build an ObservableAxis object from an XML representation of an From 23d857e0ac7beacd298df934dcbc8b2ffa7f5985 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 15 Nov 2016 09:13:18 -0800 Subject: [PATCH 08/54] s1950: renamed xml_reader_writer to obs_reader_writer, more camel case fixes --- caom2tools/caom2/__init__.py | 10 +- ..._reader_writer.py => obs_reader_writer.py} | 558 +++++++++--------- ...er_writer.py => test_obs_reader_writer.py} | 8 +- 3 files changed, 288 insertions(+), 288 deletions(-) rename caom2tools/caom2/{xml_reader_writer.py => obs_reader_writer.py} (81%) rename caom2tools/caom2/tests/{test_xml_reader_writer.py => test_obs_reader_writer.py} (99%) diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index 77f4911e..b7f9797a 100755 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -162,8 +162,8 @@ from observation import TargetType # observation reader and writer -from xml_reader_writer import ObservationReader -from xml_reader_writer import ObservationWriter -from xml_reader_writer import CAOM20_NAMESPACE -from xml_reader_writer import CAOM21_NAMESPACE -from xml_reader_writer import CAOM22_NAMESPACE +from obs_reader_writer import ObservationReader +from obs_reader_writer import ObservationWriter +from obs_reader_writer import CAOM20_NAMESPACE +from obs_reader_writer import CAOM21_NAMESPACE +from obs_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/caom2/xml_reader_writer.py b/caom2tools/caom2/obs_reader_writer.py similarity index 81% rename from caom2tools/caom2/xml_reader_writer.py rename to caom2tools/caom2/obs_reader_writer.py index 2615c554..21c94bd3 100644 --- a/caom2tools/caom2/xml_reader_writer.py +++ b/caom2tools/caom2/obs_reader_writer.py @@ -153,9 +153,9 @@ def _set_entity_attributes(self, element, ns, caom2_entity): if element_last_modified: caom2_entity._last_modified = Util.str2ivoa(element_last_modified) - def _get_child_element(self, elTag, parent, ns, required): + def _get_child_element(self, element_tag, parent, ns, required): for element in list(parent): - if element.tag == "{" + ns + "}" + elTag: + if element.tag == "{" + ns + "}" + element_tag: if not element.keys() and not element.text: # element is empty, return None return None @@ -164,40 +164,40 @@ def _get_child_element(self, elTag, parent, ns, required): return element if required: - error = elTag + " element not found in " + parent.tag + error = element_tag + " element not found in " + parent.tag raise ObservationParsingException(error) else: return None - def _get_child_text(self, elTag, parent, ns, required): - childElement = self._get_child_element(elTag, parent, ns, required) - if childElement is None: + def _get_child_text(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: return None else: - return childElement.text + return child_element.text - def _get_child_text_as_int(self, elTag, parent, ns, required): - childElement = self._get_child_element(elTag, parent, ns, required) - if childElement is None: + def _get_child_text_as_int(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: return None else: - return int(childElement.text) + return int(child_element.text) - def _get_child_text_as_long(self, elTag, parent, ns, required): - childElement = self._get_child_element(elTag, parent, ns, required) - if childElement is None: + def _get_child_text_as_long(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: return None else: - return long(childElement.text) + return long(child_element.text) - def _get_child_text_as_float(self, elTag, parent, ns, required): - childElement = self._get_child_element(elTag, parent, ns, required) - if childElement is None: + def _get_child_text_as_float(self, element_tag, parent, ns, required): + child_element = self._get_child_element(element_tag, parent, ns, required) + if child_element is None: return None else: - return float(childElement.text) + return float(child_element.text) - def _get_algorithm(self, elTag, parent, ns, required): + def _get_algorithm(self, element_tag, parent, ns, required): """Build an Algorithm object from an XML representation Arguments: @@ -209,13 +209,13 @@ def _get_algorithm(self, elTag, parent, ns, required): None if the document does not contain an algorithm element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: return observation.Algorithm(self._get_child_text("name", el, ns, True)) - def _get_meta_release(self, elTag, parent, ns, required): + def _get_meta_release(self, element_tag, parent, ns, required): """Build a MetaRelease object from an XML representation Arguments: @@ -227,7 +227,7 @@ def _get_meta_release(self, elTag, parent, ns, required): None if the document does not contain a MetaRelease element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -235,7 +235,7 @@ def _get_meta_release(self, elTag, parent, ns, required): # what kind of exceptions are thrown? return Util.str2ivoa(el.text) - def _get_proposal(self, elTag, parent, ns, required): + def _get_proposal(self, element_tag, parent, ns, required): """Build a Proposal object from an XML representation Arguments: @@ -247,7 +247,7 @@ def _get_proposal(self, elTag, parent, ns, required): None if the document does not contain a Proposal element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -261,7 +261,7 @@ def _get_proposal(self, elTag, parent, ns, required): proposal.keywords.add(keyword) return proposal - def _get_target(self, elTag, parent, ns, required): + def _get_target(self, element_tag, parent, ns, required): """Build a Target object from an XML representation Arguments: @@ -273,14 +273,14 @@ def _get_target(self, elTag, parent, ns, required): None if the document does not contain a Target element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: target = observation.Target(self._get_child_text("name", el, ns, True)) - targetType = self._get_child_text("type", el, ns, False) - if targetType: - target.target_type = observation.TargetType.getByValue(targetType) + target_type = self._get_child_text("type", el, ns, False) + if target_type: + target.target_type = observation.TargetType.getByValue(target_type) target.standard = ("true" == self._get_child_text("standard", el, ns, False)) target.redshift = ( @@ -293,7 +293,7 @@ def _get_target(self, elTag, parent, ns, required): target.keywords.add(keyword) return target - def _get_target_position(self, elTag, parent, ns, required): + def _get_target_position(self, element_tag, parent, ns, required): """Build a TargetPosition object from an XML representation Arguments: @@ -305,7 +305,7 @@ def _get_target_position(self, elTag, parent, ns, required): None if the document does not contain a TargetPosition element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -316,7 +316,7 @@ def _get_target_position(self, elTag, parent, ns, required): self._get_child_text_as_float("equinox", el, ns, False)) return target_position - def _get_requirements(self, elTag, parent, ns, required): + def _get_requirements(self, element_tag, parent, ns, required): """Build an Requirements object from an XML representation Arguments: @@ -328,7 +328,7 @@ def _get_requirements(self, elTag, parent, ns, required): None if the document does not contain an Requirements element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -336,7 +336,7 @@ def _get_requirements(self, elTag, parent, ns, required): requirements = observation.Requirements(observation.Status.getByValue(flag)) return requirements - def _get_telescope(self, elTag, parent, ns, required): + def _get_telescope(self, element_tag, parent, ns, required): """Build a Telescope object from an XML representation Arguments: @@ -348,7 +348,7 @@ def _get_telescope(self, elTag, parent, ns, required): None if the document does not contain a Telescope element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -365,7 +365,7 @@ def _get_telescope(self, elTag, parent, ns, required): telescope.keywords.add(keyword) return telescope - def _get_instrument(self, elTag, parent, ns, required): + def _get_instrument(self, element_tag, parent, ns, required): """Build an Instrument object from an XML representation Arguments: @@ -377,7 +377,7 @@ def _get_instrument(self, elTag, parent, ns, required): None if the document does not contain an Instrument element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -388,7 +388,7 @@ def _get_instrument(self, elTag, parent, ns, required): instrument.keywords.add(keyword) return instrument - def _get_environment(self, elTag, parent, ns, required): + def _get_environment(self, element_tag, parent, ns, required): """Build an Environment object from an XML representation Arguments: @@ -400,7 +400,7 @@ def _get_environment(self, elTag, parent, ns, required): None if the document does not contain an Environment element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -436,8 +436,8 @@ def _add_members(self, members, parent, ns): """ el = self._get_child_element("members", parent, ns, False) if el is not None: - for memberEl in el.iterchildren("{" + ns + "}observationURI"): - members.add(observation.ObservationURI(memberEl.text)) + for member_element in el.iterchildren("{" + ns + "}observationURI"): + members.add(observation.ObservationURI(member_element.text)) if not members: error = "No observationURI element found in members" @@ -455,14 +455,14 @@ def _add_inputs(self, inputs, parent, ns): """ el = self._get_child_element("inputs", parent, ns, False) if el is not None: - for uriEl in el.iterchildren("{" + ns + "}planeURI"): - inputs.add(plane.PlaneURI(uriEl.text)) + for uri_element in el.iterchildren("{" + ns + "}planeURI"): + inputs.add(plane.PlaneURI(uri_element.text)) if not inputs: error = "No planeURI element found in members" raise ObservationParsingException(error) - def _get_provenance(self, elTag, parent, ns, required): + def _get_provenance(self, element_tag, parent, ns, required): """Build a Provenance object from an XML representation of a Provenance element. @@ -475,7 +475,7 @@ def _get_provenance(self, elTag, parent, ns, required): None if the document does not contain a Provenance element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -496,7 +496,7 @@ def _get_provenance(self, elTag, parent, ns, required): self._add_inputs(prov.inputs, el, ns) return prov - def _get_metrics(self, elTag, parent, ns, required): + def _get_metrics(self, element_tag, parent, ns, required): """Build a Metrics object from an XML representation of a Metrics element. @@ -509,7 +509,7 @@ def _get_metrics(self, elTag, parent, ns, required): None if the document does not contain a Metrics element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -526,7 +526,7 @@ def _get_metrics(self, elTag, parent, ns, required): self._get_child_text_as_float("magLimit", el, ns, False) return metrics - def _get_quality(self, elTag, parent, ns, required): + def _get_quality(self, element_tag, parent, ns, required): """Build an Quality object from an XML representation Arguments: @@ -538,15 +538,15 @@ def _get_quality(self, elTag, parent, ns, required): None if the document does not contain an Quality element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: flag = self._get_child_text("flag", el, ns, True) - dataQuality = plane.DataQuality(plane.Quality.getByValue(flag)) - return dataQuality + data_quality = plane.DataQuality(plane.Quality.getByValue(flag)) + return data_quality - def _get_point(self, elTag, parent, ns, required): + def _get_point(self, element_tag, parent, ns, required): """Build an Point object from an XML representation of an Point element. @@ -559,14 +559,14 @@ def _get_point(self, elTag, parent, ns, required): None if the document does not contain an Point element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: return shape.Point(self._get_child_text_as_float("cval1", el, ns, True), self._get_child_text_as_float("cval2", el, ns, True)) - def _get_axis(self, elTag, parent, ns, required): + def _get_axis(self, element_tag, parent, ns, required): """Build an Axis object from an XML representation of an Axis element. Arguments: @@ -578,14 +578,14 @@ def _get_axis(self, elTag, parent, ns, required): None if the document does not contain an Axis element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: return shape.Axis(self._get_child_text("ctype", el, ns, True), self._get_child_text("cunit", el, ns, False)) - def _get_slice(self, elTag, parent, ns, required): + def _get_slice(self, element_tag, parent, ns, required): """Build a Slice object from an XML representation of a Slice element. Arguments: @@ -597,14 +597,14 @@ def _get_slice(self, elTag, parent, ns, required): None if the document does not contain a Slice element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: return shape.Slice(self._get_axis("axis", el, ns, True), self._get_child_text_as_long("bin", el, ns, True)) - def _get_observable_axis(self, elTag, parent, ns, required): + def _get_observable_axis(self, element_tag, parent, ns, required): """Build an ObservableAxis object from an XML representation of an observable element. @@ -617,7 +617,7 @@ def _get_observable_axis(self, elTag, parent, ns, required): None if the document does not contain an Observable element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -627,7 +627,7 @@ def _get_observable_axis(self, elTag, parent, ns, required): self._get_slice("independent", el, ns, False) return observable - def _get_coord_error(self, elTag, parent, ns, required): + def _get_coord_error(self, element_tag, parent, ns, required): """Build a CoordError object from an XML representation of an error element. @@ -640,7 +640,7 @@ def _get_coord_error(self, elTag, parent, ns, required): None if the document does not contain an error element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -648,7 +648,7 @@ def _get_coord_error(self, elTag, parent, ns, required): self._get_child_text_as_float("syser", el, ns, True), self._get_child_text_as_float("rnder", el, ns, True)) - def _get_ref_coord(self, elTag, parent, ns, required): + def _get_ref_coord(self, element_tag, parent, ns, required): """Build a RefCoord object from an XML representation of a coord element. @@ -661,7 +661,7 @@ def _get_ref_coord(self, elTag, parent, ns, required): None if the document does not contain a coord element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -669,7 +669,7 @@ def _get_ref_coord(self, elTag, parent, ns, required): self._get_child_text_as_float("pix", el, ns, True), self._get_child_text_as_float("val", el, ns, True)) - def _get_coord2d(self, elTag, parent, ns, required): + def _get_coord2d(self, element_tag, parent, ns, required): """Build a Coord2D object from an XML representation of a coord element. @@ -682,7 +682,7 @@ def _get_coord2d(self, elTag, parent, ns, required): None if the document does not contain a coord element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -690,7 +690,7 @@ def _get_coord2d(self, elTag, parent, ns, required): self._get_ref_coord("coord1", el, ns, True), self._get_ref_coord("coord2", el, ns, True)) - def _get_value_coord2d(self, elTag, parent, ns, required): + def _get_value_coord2d(self, element_tag, parent, ns, required): """Build a ValueCoord2D object from an XML representation of a value coord element. @@ -703,7 +703,7 @@ def _get_value_coord2d(self, elTag, parent, ns, required): None if the document does not contain a coord element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -711,7 +711,7 @@ def _get_value_coord2d(self, elTag, parent, ns, required): self._get_child_text_as_float("coord1", el, ns, True), self._get_child_text_as_float("coord2", el, ns, True)) - def _get_coord_range2d(self, elTag, parent, ns, required): + def _get_coord_range2d(self, element_tag, parent, ns, required): """Build a CoordRange2D object from an XML representation of a range element. @@ -724,7 +724,7 @@ def _get_coord_range2d(self, elTag, parent, ns, required): None if the document does not contain a range element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -732,7 +732,7 @@ def _get_coord_range2d(self, elTag, parent, ns, required): self._get_coord2d("start", el, ns, True), self._get_coord2d("end", el, ns, True)) - def _get_coord_circle2d(self, elTag, parent, ns, required): + def _get_coord_circle2d(self, element_tag, parent, ns, required): """Build a CoordCircle2D object from an XML representation of a circle element. @@ -745,7 +745,7 @@ def _get_coord_circle2d(self, elTag, parent, ns, required): None if the document does not contain a circle element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -753,7 +753,7 @@ def _get_coord_circle2d(self, elTag, parent, ns, required): self._get_value_coord2d("center", el, ns, True), self._get_child_text_as_float("radius", el, ns, True)) - def _get_coord_polygon2d(self, elTag, parent, ns, required): + def _get_coord_polygon2d(self, element_tag, parent, ns, required): """Build a CoordPolygon2D object from an XML representation of a polygon element. @@ -766,28 +766,28 @@ def _get_coord_polygon2d(self, elTag, parent, ns, required): None if the document does not contain a polygon element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: - verticeEl = self._get_child_element("vertices", el, ns, True) - childrenVertices = list( - verticeEl.iterchildren(tag=("{" + ns + "}vertex"))) - if len(childrenVertices) < 3: + vertice_element = self._get_child_element("vertices", el, ns, True) + children_vertices = list( + vertice_element.iterchildren(tag=("{" + ns + "}vertex"))) + if len(children_vertices) < 3: error = ("CoordPolygon2D must have a minimum of 3 vertices, " - "found " + len(childrenVertices)) + "found " + len(children_vertices)) raise ObservationParsingException(error) else: polygon = wcs.CoordPolygon2D() - for childVertexEl in childrenVertices: + for child_vertex_el in children_vertices: polygon.vertices.append(wcs.ValueCoord2D( self._get_child_text_as_float( - "coord1", childVertexEl, ns, True), + "coord1", child_vertex_el, ns, True), self._get_child_text_as_float( - "coord2", childVertexEl, ns, True))) + "coord2", child_vertex_el, ns, True))) return polygon - def _get_coord_bounds2d(self, elTag, parent, ns, required): + def _get_coord_bounds2d(self, element_tag, parent, ns, required): """Build a CoordBounds2D object from an XML representation of a bounds element. @@ -800,7 +800,7 @@ def _get_coord_bounds2d(self, elTag, parent, ns, required): None if the document does not contain a bounds element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -812,11 +812,11 @@ def _get_coord_bounds2d(self, elTag, parent, ns, required): if polygon is not None: return polygon else: - error = "Unsupported element not found in " + elTag + \ + error = "Unsupported element not found in " + element_tag + \ ": " + el.getText() raise ObservationParsingException(error) - def _get_dimension2d(self, elTag, parent, ns, required): + def _get_dimension2d(self, element_tag, parent, ns, required): """Build a Dimension2D object from an XML representation of a dimension element. @@ -829,7 +829,7 @@ def _get_dimension2d(self, elTag, parent, ns, required): None if the document does not contain a dimension element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -837,7 +837,7 @@ def _get_dimension2d(self, elTag, parent, ns, required): self._get_child_text_as_long("naxis1", el, ns, True), self._get_child_text_as_long("naxis2", el, ns, True)) - def _get_coord_function2d(self, elTag, parent, ns, required): + def _get_coord_function2d(self, element_tag, parent, ns, required): """Build a CoordFunction2D object from an XML representation of a function element. @@ -850,7 +850,7 @@ def _get_coord_function2d(self, elTag, parent, ns, required): None if the document does not contain a function element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -862,7 +862,7 @@ def _get_coord_function2d(self, elTag, parent, ns, required): self._get_child_text_as_float("cd21", el, ns, True), self._get_child_text_as_float("cd22", el, ns, True)) - def _get_coord_axis2d(self, elTag, parent, ns, required): + def _get_coord_axis2d(self, element_tag, parent, ns, required): """Build a CoordAxis2D object from an XML representation of an axis element. @@ -875,7 +875,7 @@ def _get_coord_axis2d(self, elTag, parent, ns, required): None if the document does not contain an axis element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -888,7 +888,7 @@ def _get_coord_axis2d(self, elTag, parent, ns, required): axis.function = self._get_coord_function2d("function", el, ns, False) return axis - def _get_spatial_wcs(self, elTag, parent, ns, required): + def _get_spatial_wcs(self, element_tag, parent, ns, required): """Build a SpatialWCS object from an XML representation of a position element. @@ -901,7 +901,7 @@ def _get_spatial_wcs(self, elTag, parent, ns, required): None if the document does not contain a position element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -913,7 +913,7 @@ def _get_spatial_wcs(self, elTag, parent, ns, required): self._get_child_text_as_float("resolution", el, ns, False) return position - def _add_children_to_coord_range1d_list(self, elTag, ranges, parent, ns, + def _add_children_to_coord_range1d_list(self, element_tag, ranges, parent, ns, required): """Create CoordRange1D objects from an XML representation of the range elements and add them to the set of ranges. @@ -925,12 +925,12 @@ def _add_children_to_coord_range1d_list(self, elTag, ranges, parent, ns, ns : namespace of the document required : boolean indicating whether the element is required """ - for rangeEl in parent.iterchildren("{" + ns + "}" + elTag): + for range_element in parent.iterchildren("{" + ns + "}" + element_tag): ranges.append(wcs.CoordRange1D( - self._get_ref_coord("start", rangeEl, ns, True), - self._get_ref_coord("end", rangeEl, ns, True))) + self._get_ref_coord("start", range_element, ns, True), + self._get_ref_coord("end", range_element, ns, True))) - def _get_coord_bounds1d(self, elTag, parent, ns, required): + def _get_coord_bounds1d(self, element_tag, parent, ns, required): """Build a CoordBounds1D object from an XML representation of a bounds element. @@ -943,18 +943,18 @@ def _get_coord_bounds1d(self, elTag, parent, ns, required): None if the document does not contain a bounds element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: - coordBounds1D = wcs.CoordBounds1D() - samplesEl = self._get_child_element("samples", el, ns, False) - if samplesEl is not None: + coord_bounds1d = wcs.CoordBounds1D() + samples_element = self._get_child_element("samples", el, ns, False) + if samples_element is not None: self._add_children_to_coord_range1d_list( - "range", coordBounds1D.samples, samplesEl, ns, False) - return coordBounds1D + "range", coord_bounds1d.samples, samples_element, ns, False) + return coord_bounds1d - def _get_coord_range1d(self, elTag, parent, ns, required): + def _get_coord_range1d(self, element_tag, parent, ns, required): """Build a CoordRange1D object from an XML representation of a range element. @@ -967,7 +967,7 @@ def _get_coord_range1d(self, elTag, parent, ns, required): None if the document does not contain a range element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -975,7 +975,7 @@ def _get_coord_range1d(self, elTag, parent, ns, required): self._get_ref_coord("start", el, ns, True), self._get_ref_coord("end", el, ns, True)) - def _get_coord_function1d(self, elTag, parent, ns, required): + def _get_coord_function1d(self, element_tag, parent, ns, required): """Build a CoordFunction1D object from an XML representation of a function element. @@ -988,7 +988,7 @@ def _get_coord_function1d(self, elTag, parent, ns, required): None if the document does not contain a function element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -997,7 +997,7 @@ def _get_coord_function1d(self, elTag, parent, ns, required): self._get_child_text_as_float("delta", el, ns, True), self._get_ref_coord("refCoord", el, ns, True)) - def _get_coord_axis1d(self, elTag, parent, ns, required): + def _get_coord_axis1d(self, element_tag, parent, ns, required): """Build a CoordAxis1D object from an XML representation of an axis element. @@ -1010,7 +1010,7 @@ def _get_coord_axis1d(self, elTag, parent, ns, required): None if the document does not contain an axis element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -1021,7 +1021,7 @@ def _get_coord_axis1d(self, elTag, parent, ns, required): axis.function = self._get_coord_function1d("function", el, ns, False) return axis - def _get_transition(self, elTag, parent, ns, required): + def _get_transition(self, element_tag, parent, ns, required): """Build an EnergyTransition object from an XML representation of a transition element. @@ -1034,7 +1034,7 @@ def _get_transition(self, elTag, parent, ns, required): None if the document does not contain a transition element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -1042,7 +1042,7 @@ def _get_transition(self, elTag, parent, ns, required): self._get_child_text("species", el, ns, True), self._get_child_text("transition", el, ns, True)) - def _get_spectral_wcs(self, elTag, parent, ns, required): + def _get_spectral_wcs(self, element_tag, parent, ns, required): """Build a SpectralWCS object from an XML representation of an energy element. @@ -1055,7 +1055,7 @@ def _get_spectral_wcs(self, elTag, parent, ns, required): None if the document does not contain an energy element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -1084,7 +1084,7 @@ def _get_spectral_wcs(self, elTag, parent, ns, required): self._get_transition("transition", el, ns, False) return energy - def _get_temporal_wcs(self, elTag, parent, ns, required): + def _get_temporal_wcs(self, element_tag, parent, ns, required): """Build a TemporalWCS object from an XML representation of an time element. @@ -1097,7 +1097,7 @@ def _get_temporal_wcs(self, elTag, parent, ns, required): None if the document does not contain an time element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -1115,7 +1115,7 @@ def _get_temporal_wcs(self, elTag, parent, ns, required): self._get_child_text_as_float("resolution", el, ns, False) return time - def _get_polarization_wcs(self, elTag, parent, ns, required): + def _get_polarization_wcs(self, element_tag, parent, ns, required): """Build a PolarizationWCS object from an XML representation of a polarization element. @@ -1128,7 +1128,7 @@ def _get_polarization_wcs(self, elTag, parent, ns, required): None if the document does not contain an polarization element raise : ObservationParsingException """ - el = self._get_child_element(elTag, parent, ns, required) + el = self._get_child_element(element_tag, parent, ns, required) if el is None: return None else: @@ -1149,44 +1149,44 @@ def _add_chunks(self, chunks, parent, ns): if el is None: return None else: - for chunkEl in el.iterchildren("{" + ns + "}chunk"): - tempChunk = chunk.Chunk() - productType = \ - self._get_child_text("productType", chunkEl, ns, False) - if productType: - tempChunk.product_type = \ - artifact.ProductType.getByValue(productType) - tempChunk.naxis = \ - self._get_child_text_as_int("naxis", chunkEl, ns, False) - tempChunk.observable_axis = \ - self._get_child_text_as_int("observableAxis", chunkEl, ns, + for chunk_element in el.iterchildren("{" + ns + "}chunk"): + _chunk = chunk.Chunk() + product_type = \ + self._get_child_text("productType", chunk_element, ns, False) + if product_type: + _chunk.product_type = \ + artifact.ProductType.getByValue(product_type) + _chunk.naxis = \ + self._get_child_text_as_int("naxis", chunk_element, ns, False) + _chunk.observable_axis = \ + self._get_child_text_as_int("observableAxis", chunk_element, ns, False) - tempChunk.position_axis_1 = \ - self._get_child_text_as_int("positionAxis1", chunkEl, ns, + _chunk.position_axis_1 = \ + self._get_child_text_as_int("positionAxis1", chunk_element, ns, False) - tempChunk.position_axis_2 = \ - self._get_child_text_as_int("positionAxis2", chunkEl, ns, + _chunk.position_axis_2 = \ + self._get_child_text_as_int("positionAxis2", chunk_element, ns, False) - tempChunk.energy_axis = \ - self._get_child_text_as_int("energyAxis", chunkEl, ns, False) - tempChunk.time_axis = \ - self._get_child_text_as_int("timeAxis", chunkEl, ns, False) - tempChunk.polarization_axis = \ - self._get_child_text_as_int("polarizationAxis", chunkEl, ns, + _chunk.energy_axis = \ + self._get_child_text_as_int("energyAxis", chunk_element, ns, False) + _chunk.time_axis = \ + self._get_child_text_as_int("timeAxis", chunk_element, ns, False) + _chunk.polarization_axis = \ + self._get_child_text_as_int("polarizationAxis", chunk_element, ns, False) - tempChunk.observable = \ - self._get_observable_axis("observable", chunkEl, ns, False) - tempChunk.position = \ - self._get_spatial_wcs("position", chunkEl, ns, False) - tempChunk.energy = \ - self._get_spectral_wcs("energy", chunkEl, ns, False) - tempChunk.time = \ - self._get_temporal_wcs("time", chunkEl, ns, False) - tempChunk.polarization = \ - self._get_polarization_wcs("polarization", chunkEl, ns, + _chunk.observable = \ + self._get_observable_axis("observable", chunk_element, ns, False) + _chunk.position = \ + self._get_spatial_wcs("position", chunk_element, ns, False) + _chunk.energy = \ + self._get_spectral_wcs("energy", chunk_element, ns, False) + _chunk.time = \ + self._get_temporal_wcs("time", chunk_element, ns, False) + _chunk.polarization = \ + self._get_polarization_wcs("polarization", chunk_element, ns, False) - self._set_entity_attributes(chunkEl, ns, tempChunk) - chunks.append(tempChunk) + self._set_entity_attributes(chunk_element, ns, _chunk) + chunks.append(_chunk) def _add_parts(self, parts, parent, ns): """Build Part objects from an XML representation of Part elements and @@ -1202,17 +1202,17 @@ def _add_parts(self, parts, parent, ns): if el is None: return None else: - for partEl in el.iterchildren("{" + ns + "}part"): - tempPart = \ - part.Part(self._get_child_text("name", partEl, ns, True)) - productType = \ - self._get_child_text("productType", partEl, ns, False) - if productType: - tempPart.product_type = \ - artifact.ProductType.getByValue(productType) - self._add_chunks(tempPart.chunks, partEl, ns) - self._set_entity_attributes(partEl, ns, tempPart) - parts[tempPart.name] = tempPart + for part_element in el.iterchildren("{" + ns + "}part"): + _part = \ + part.Part(self._get_child_text("name", part_element, ns, True)) + product_type = \ + self._get_child_text("productType", part_element, ns, False) + if product_type: + _part.product_type = \ + artifact.ProductType.getByValue(product_type) + self._add_chunks(_part.chunks, part_element, ns) + self._set_entity_attributes(part_element, ns, _part) + parts[_part.name] = _part def _add_artifacts(self, artifacts, parent, ns): """Build artifacts from an XML representation of the artifact elements @@ -1228,30 +1228,30 @@ def _add_artifacts(self, artifacts, parent, ns): if el is None: return None else: - for artifactEl in el.iterchildren("{" + ns + "}artifact"): - uri = self._get_child_text("uri", artifactEl, ns, True) + for artifact_element in el.iterchildren("{" + ns + "}artifact"): + uri = self._get_child_text("uri", artifact_element, ns, True) - product_type = self._get_child_text("productType", artifactEl, ns, False) + product_type = self._get_child_text("productType", artifact_element, ns, False) if product_type is None: product_type = artifact.ProductType.SCIENCE print "Using default Artifact.productType value {0}".format(str(artifact.ProductType.SCIENCE)) else: product_type = artifact.ProductType.getByValue(product_type) - release_type = self._get_child_text("releaseType", artifactEl, ns, False) + release_type = self._get_child_text("releaseType", artifact_element, ns, False) if release_type is None: release_type = artifact.ReleaseType.DATA print "Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA)) else: release_type = artifact.ReleaseType.getByValue(release_type) - tempArtifact = artifact.Artifact(uri, product_type, release_type) - tempArtifact.content_type = self._get_child_text("contentType", artifactEl, ns, False) - tempArtifact.content_length = ( - self._get_child_text_as_long("contentLength", artifactEl, ns, False)) - self._add_parts(tempArtifact.parts, artifactEl, ns) - self._set_entity_attributes(artifactEl, ns, tempArtifact) - artifacts[tempArtifact.uri] = tempArtifact + _artifact = artifact.Artifact(uri, product_type, release_type) + _artifact.content_type = self._get_child_text("contentType", artifact_element, ns, False) + _artifact.content_length = ( + self._get_child_text_as_long("contentLength", artifact_element, ns, False)) + self._add_parts(_artifact.parts, artifact_element, ns) + self._set_entity_attributes(artifact_element, ns, _artifact) + artifacts[_artifact.uri] = _artifact def _add_planes(self, planes, parent, ns): """Create Planes object from XML representation of Plane elements @@ -1267,32 +1267,32 @@ def _add_planes(self, planes, parent, ns): if el is None: return None else: - for planeEl in el.iterchildren("{" + ns + "}plane"): - tempPlane = plane.Plane( - self._get_child_text("productID", planeEl, ns, True)) - tempPlane.meta_release = Util.str2ivoa( - self._get_child_text("metaRelease", planeEl, ns, False)) - tempPlane.data_release = Util.str2ivoa( - self._get_child_text("dataRelease", planeEl, ns, False)) - dataProductType = \ - self._get_child_text("dataProductType", planeEl, ns, False) - if dataProductType: - tempPlane.data_product_type = \ - plane.DataProductType.getByValue(dataProductType) - calibrationLevel = \ - self._get_child_text("calibrationLevel", planeEl, ns, False) - if calibrationLevel: - tempPlane.calibration_level = \ - plane.CalibrationLevel.getByValue(int(calibrationLevel)) - tempPlane.provenance = \ - self._get_provenance("provenance", planeEl, ns, False) - tempPlane.metrics = \ - self._get_metrics("metrics", planeEl, ns, False) - tempPlane.quality = \ - self._get_quality("quality", planeEl, ns, False) - self._add_artifacts(tempPlane.artifacts, planeEl, ns) - self._set_entity_attributes(planeEl, ns, tempPlane) - planes[tempPlane.product_id] = tempPlane + for plane_element in el.iterchildren("{" + ns + "}plane"): + _plane = plane.Plane( + self._get_child_text("productID", plane_element, ns, True)) + _plane.meta_release = Util.str2ivoa( + self._get_child_text("metaRelease", plane_element, ns, False)) + _plane.data_release = Util.str2ivoa( + self._get_child_text("dataRelease", plane_element, ns, False)) + data_product_type = \ + self._get_child_text("dataProductType", plane_element, ns, False) + if data_product_type: + _plane.data_product_type = \ + plane.DataProductType.getByValue(data_product_type) + calibration_level = \ + self._get_child_text("calibrationLevel", plane_element, ns, False) + if calibration_level: + _plane.calibration_level = \ + plane.CalibrationLevel.getByValue(int(calibration_level)) + _plane.provenance = \ + self._get_provenance("provenance", plane_element, ns, False) + _plane.metrics = \ + self._get_metrics("metrics", plane_element, ns, False) + _plane.quality = \ + self._get_quality("quality", plane_element, ns, False) + self._add_artifacts(_plane.artifacts, plane_element, ns) + self._set_entity_attributes(plane_element, ns, _plane) + planes[_plane.product_id] = _plane if not planes: error = "No plane element found in planes" @@ -1314,18 +1314,18 @@ def read(self, source): root = doc.getroot() ns = root.nsmap["caom2"] collection = self._get_child_element("collection", root, ns, True).text - observationID = \ + observation_id = \ self._get_child_element("observationID", root, ns, True).text # Instantiate Algorithm algorithm = self._get_algorithm("algorithm", root, ns, True) # Instantiate Observation if root.get("{http://www.w3.org/2001/XMLSchema-instance}type") \ == "caom2:SimpleObservation": - obs = observation.SimpleObservation(collection, observationID) + obs = observation.SimpleObservation(collection, observation_id) obs.algorithm = algorithm else: obs = \ - observation.CompositeObservation(collection, observationID, algorithm) + observation.CompositeObservation(collection, observation_id, algorithm) # Instantiate children of Observation obs.sequence_number = \ self._get_child_text_as_int("sequenceNumber", root, ns, False) @@ -1405,44 +1405,44 @@ def __init__(self, validate=False, write_empty_collections=False, self._nsmap = {namespace_prefix: self._namespace, "xsi": XSI_NAMESPACE} - def write(self, observation, out): - assert isinstance(observation, observation.Observation), ( + def write(self, obs, out): + assert isinstance(obs, observation.Observation), ( "observation is not an Observation") - obs = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) - if isinstance(observation, observation.SimpleObservation): - obs.set(XSI + "type", "caom2:SimpleObservation") + obs_element = etree.Element(self._caom2_namespace + "Observation", nsmap=self._nsmap) + if isinstance(obs, observation.SimpleObservation): + obs_element.set(XSI + "type", "caom2:SimpleObservation") else: - obs.set(XSI + "type", "caom2:CompositeObservation") + obs_element.set(XSI + "type", "caom2:CompositeObservation") - self._add_enity_attributes(observation, obs) + self._add_enity_attributes(obs, obs_element) - self._add_element("collection", observation.collection, obs) - self._add_element("observationID", observation.observation_id, obs) - self._add_datetime_element("metaRelease", observation.meta_release, obs) - self._add_element("sequenceNumber", observation.sequence_number, obs) - self._add_algorithm_element(observation.algorithm, obs) - self._add_element("type", observation.obs_type, obs) - if observation.intent is not None: + self._add_element("collection", obs.collection, obs_element) + self._add_element("observationID", obs.observation_id, obs_element) + self._add_datetime_element("metaRelease", obs.meta_release, obs_element) + self._add_element("sequenceNumber", obs.sequence_number, obs_element) + self._add_algorithm_element(obs.algorithm, obs_element) + self._add_element("type", obs.obs_type, obs_element) + if obs.intent is not None: self._add_element( - "intent", observation.ObservationIntentType.get(str(observation.intent)).value, obs) + "intent", observation.ObservationIntentType.get(str(obs.intent)).value, obs_element) - self._add_proposal_element(observation.proposal, obs) - self._add_target_element(observation.target, obs) - self._add_target_position_element(observation.target_position, obs) - self._add_requirements_element(observation.requirements, obs) - self._add_telescope_element(observation.telescope, obs) - self._add_instrument_element(observation.instrument, obs) - self._add_environment_element(observation.environment, obs) - self._add_planes_element(observation.planes, obs) + self._add_proposal_element(obs.proposal, obs_element) + self._add_target_element(obs.target, obs_element) + self._add_target_position_element(obs.target_position, obs_element) + self._add_requirements_element(obs.requirements, obs_element) + self._add_telescope_element(obs.telescope, obs_element) + self._add_instrument_element(obs.instrument, obs_element) + self._add_environment_element(obs.environment, obs_element) + self._add_planes_element(obs.planes, obs_element) - if isinstance(observation, observation.CompositeObservation): - self._add_members_element(observation.members, obs) + if isinstance(obs, observation.CompositeObservation): + self._add_members_element(obs.members, obs_element) if self._validate and self._xmlschema: - self._xmlschema.assertValid(obs) + self._xmlschema.assertValid(obs_element) - out.write(etree.tostring(obs, xml_declaration=True, encoding='UTF-8', + out.write(etree.tostring(obs_element, xml_declaration=True, encoding='UTF-8', pretty_print=True)) def _add_enity_attributes(self, entity, element): @@ -1561,26 +1561,26 @@ def _add_planes_element(self, planes, parent): return element = self._get_caom_element("planes", parent) - for plane in planes.itervalues(): + for _plane in planes.itervalues(): plane_element = self._get_caom_element("plane", element) - self._add_enity_attributes(plane, plane_element) - self._add_element("productID", plane.product_id, plane_element) - self._add_datetime_element("metaRelease", plane.meta_release, + self._add_enity_attributes(_plane, plane_element) + self._add_element("productID", _plane.product_id, plane_element) + self._add_datetime_element("metaRelease", _plane.meta_release, plane_element) - self._add_datetime_element("dataRelease", plane.data_release, + self._add_datetime_element("dataRelease", _plane.data_release, plane_element) - if plane.data_product_type is not None: + if _plane.data_product_type is not None: self._add_element("dataProductType", - plane.DataProductType.get(str(plane.data_product_type)).value, + plane.DataProductType.get(str(_plane.data_product_type)).value, plane_element) - if plane.calibration_level is not None: + if _plane.calibration_level is not None: self._add_element("calibrationLevel", - plane.CalibrationLevel(str(plane.calibration_level)).value, + plane.CalibrationLevel(str(_plane.calibration_level)).value, plane_element) - self._add_provenance_element(plane.provenance, plane_element) - self._add_metrics_element(plane.metrics, plane_element) - self._add_quality_element(plane.quality, plane_element) - self._add_artifacts_element(plane.artifacts, plane_element) + self._add_provenance_element(_plane.provenance, plane_element) + self._add_metrics_element(_plane.metrics, plane_element) + self._add_quality_element(_plane.quality, plane_element) + self._add_artifacts_element(_plane.artifacts, plane_element) def _add_provenance_element(self, provenance, parent): if provenance is None: @@ -1710,7 +1710,7 @@ def _add_spatial_wcs_element(self, position, parent): return element = self._get_caom_element("position", parent) - self._add_coord_axis_2d_element("axis", position.axis, element) + self._add_coord_axis2d_element("axis", position.axis, element) self._add_element("coordsys", position.coordsys, element) self._add_element("equinox", position.equinox, element) self._add_element("resolution", position.resolution, element) @@ -1722,7 +1722,7 @@ def _add_spectral_wcs_element(self, energy, parent): return element = self._get_caom_element("energy", parent) - self._add_coord_axis_1d_element("axis", energy.axis, element) + self._add_coord_axis1d_element("axis", energy.axis, element) self._add_element("specsys", energy.specsys, element) self._add_element("ssysobs", energy.ssysobs, element) self._add_element("ssyssrc", energy.ssyssrc, element) @@ -1742,7 +1742,7 @@ def _add_temporal_wcs_element(self, time, parent): return element = self._get_caom_element("time", parent) - self._add_coord_axis_1d_element("axis", time.axis, element) + self._add_coord_axis1d_element("axis", time.axis, element) self._add_element("timesys", time.timesys, element) self._add_element("trefpos", time.trefpos, element) self._add_element("mjdref", time.mjdref, element) @@ -1756,7 +1756,7 @@ def _add_polarization_wcs_element(self, polarization, parent): return element = self._get_caom_element("polarization", parent) - self._add_coord_axis_1d_element("axis", polarization.axis, element) + self._add_coord_axis1d_element("axis", polarization.axis, element) #/*+ CAOM2 Types #-*/ @@ -1783,7 +1783,7 @@ def _add_axis_element(self, name, axis, parent): if axis.cunit: self._add_element("cunit", axis.cunit, element) - def _add_coord_2d_element(self, name, coord, parent): + def _add_coord2d_element(self, name, coord, parent): """ Builds a representation of a Coord2D and adds it to the parent element. """ if coord is None: @@ -1793,7 +1793,7 @@ def _add_coord_2d_element(self, name, coord, parent): self._add_ref_coord_element("coord1", coord.coord1, element) self._add_ref_coord_element("coord2", coord.coord2, element) - def _add_value_coord_2d_element(self, name, coord, parent): + def _add_value_coord2d_element(self, name, coord, parent): """ Builds a representation of a ValueCoord2D and adds it to the parent element. """ if coord is None: @@ -1803,7 +1803,7 @@ def _add_value_coord_2d_element(self, name, coord, parent): self._add_element("coord1", coord.coord1, element) self._add_element("coord2", coord.coord2, element) - def _add_coord_axis_1d_element(self, name, axis, parent): + def _add_coord_axis1d_element(self, name, axis, parent): """ Builds a representation of a CoordAxis1D and adds it to the parent element. """ if axis is None: @@ -1812,11 +1812,11 @@ def _add_coord_axis_1d_element(self, name, axis, parent): element = self._get_caom_element(name, parent) self._add_axis_element("axis", axis.axis, element) self._add_coord_error_element("error", axis.error, element) - self._add_coord_range_1d_element("range", axis.range, element) - self._add_coord_bounds_1d_element("bounds", axis.bounds, element) - self._add_coord_function_1d_element("function", axis.function, element) + self._add_coord_range1d_element("range", axis.range, element) + self._add_coord_bounds1d_element("bounds", axis.bounds, element) + self._add_coord_function1d_element("function", axis.function, element) - def _add_coord_axis_2d_element(self, name, axis, parent): + def _add_coord_axis2d_element(self, name, axis, parent): """ Builds a representation of a CoordAxis2D and adds it to the parent element. """ if axis is None: @@ -1827,11 +1827,11 @@ def _add_coord_axis_2d_element(self, name, axis, parent): self._add_axis_element("axis2", axis.axis2, element) self._add_coord_error_element("error1", axis.error1, element) self._add_coord_error_element("error2", axis.error2, element) - self._add_coord_range_2d_element("range", axis.range, element) - self._add_coord_bounds_2d_element("bounds", axis.bounds, element) - self._add_coord_function_2d_element("function", axis.function, element) + self._add_coord_range2d_element("range", axis.range, element) + self._add_coord_bounds2d_element("bounds", axis.bounds, element) + self._add_coord_function2d_element("function", axis.function, element) - def _add_coord_bounds_1d_element(self, name, bounds, parent): + def _add_coord_bounds1d_element(self, name, bounds, parent): """ Builds a representation of a CoordBounds1D and adds it to the parent element. """ if bounds is None: @@ -1840,7 +1840,7 @@ def _add_coord_bounds_1d_element(self, name, bounds, parent): element = self._get_caom_element(name, parent) self._add_coord_range_1d_list_element("samples", bounds.samples, element) - def _add_coord_bounds_2d_element(self, name, bounds, parent): + def _add_coord_bounds2d_element(self, name, bounds, parent): """Builds a representation of a CoordBounds2D and adds it to the parent element. """ if bounds is None: @@ -1848,23 +1848,23 @@ def _add_coord_bounds_2d_element(self, name, bounds, parent): element = self._get_caom_element(name, parent) if isinstance(bounds, wcs.CoordCircle2D): - self._add_coord_circle_2d_element("circle", - wcs.CoordCircle2D(bounds.center, + self._add_coord_circle2d_element("circle", + wcs.CoordCircle2D(bounds.center, bounds.radius), element) elif isinstance(bounds, wcs.CoordPolygon2D): - self._add_coord_polygon_2d_element("polygon", bounds, element) + self._add_coord_polygon2d_element("polygon", bounds, element) else: raise TypeError("BUG: unsupported CoordBounds2D type " + bounds.__class__.__name__) - def _add_coord_circle_2d_element(self, name, circle, parent): + def _add_coord_circle2d_element(self, name, circle, parent): """ Builds a representation of a CoordCircle2D and adds it to the parent element. """ if circle is None: return element = self._get_caom_element(name, parent) - self._add_value_coord_2d_element("center", circle.center, element) + self._add_value_coord2d_element("center", circle.center, element) self._add_element("radius", circle.radius, element) def _add_coord_error_element(self, name, error, parent): @@ -1877,7 +1877,7 @@ def _add_coord_error_element(self, name, error, parent): self._add_element("syser", error.syser, element) self._add_element("rnder", error.rnder, element) - def _add_coord_function_1d_element(self, name, function, parent): + def _add_coord_function1d_element(self, name, function, parent): """ Builds a representation of a CoordFunction1D and adds it to the parent element. """ if function is None: @@ -1888,21 +1888,21 @@ def _add_coord_function_1d_element(self, name, function, parent): self._add_element("delta", function.delta, element) self._add_ref_coord_element("refCoord", function.ref_coord, element) - def _add_coord_function_2d_element(self, name, function, parent): + def _add_coord_function2d_element(self, name, function, parent): """ Builds a representation of a CoordFunction2D and adds it to the parent element. """ if function is None: return element = self._get_caom_element(name, parent) - self._add_dimension_2d_element("dimension", function.dimension, element) - self._add_coord_2d_element("refCoord", function.ref_coord, element) + self._add_dimension2d_element("dimension", function.dimension, element) + self._add_coord2d_element("refCoord", function.ref_coord, element) self._add_element("cd11", function.cd11, element) self._add_element("cd12", function.cd12, element) self._add_element("cd21", function.cd21, element) self._add_element("cd22", function.cd22, element) - def _add_coord_polygon_2d_element(self, name, polygon, parent): + def _add_coord_polygon2d_element(self, name, polygon, parent): """ Builds a representation of a CoordPolygon2D and adds it to the parent element. """ if polygon is None: @@ -1912,9 +1912,9 @@ def _add_coord_polygon_2d_element(self, name, polygon, parent): if len(polygon.vertices) > 0: vertices_element = self._get_caom_element("vertices", element) for vertex in polygon.vertices: - self._add_value_coord_2d_element("vertex", vertex, vertices_element) + self._add_value_coord2d_element("vertex", vertex, vertices_element) - def _add_coord_range_1d_element(self, name, _range, parent): + def _add_coord_range1d_element(self, name, _range, parent): """ Builds a representation of a CoordRange1D and adds it to the parent element. """ if _range is None: @@ -1924,17 +1924,17 @@ def _add_coord_range_1d_element(self, name, _range, parent): self._add_ref_coord_element("start", _range.start, element) self._add_ref_coord_element("end", _range.end, element) - def _add_coord_range_2d_element(self, name, _range, parent): + def _add_coord_range2d_element(self, name, _range, parent): """ Builds a representation of a CoordRange2D and adds it to the parent element. """ if _range is None: return element = self._get_caom_element(name, parent) - self._add_coord_2d_element("start", _range.start, element) - self._add_coord_2d_element("end", _range.end, element) + self._add_coord2d_element("start", _range.start, element) + self._add_coord2d_element("end", _range.end, element) - def _add_dimension_2d_element(self, name, dimension, parent): + def _add_dimension2d_element(self, name, dimension, parent): """ Builds a representation of a Dimension2D and adds it to the parent element. """ if dimension is None: @@ -1944,15 +1944,15 @@ def _add_dimension_2d_element(self, name, dimension, parent): self._add_element("naxis1", dimension.naxis1, element) self._add_element("naxis2", dimension.naxis2, element) - def _add_ref_coord_element(self, name, refCoord, parent): + def _add_ref_coord_element(self, name, ref_coord, parent): """ Builds a representation of a RefCoord and adds it to the parent element. """ - if refCoord is None: + if ref_coord is None: return element = self._get_caom_element(name, parent) - self._add_element("pix", refCoord.pix, element) - self._add_element("val", refCoord.val, element) + self._add_element("pix", ref_coord.pix, element) + self._add_element("val", ref_coord.val, element) def _add_slice_element(self, name, _slice, parent): """ Builds a representation of a Slice and adds it to the @@ -1994,7 +1994,7 @@ def _add_coord_range_1d_list_element(self, name, values, parent): return element = self._get_caom_element(name, parent) for v in values: - self._add_coord_range_1d_element("range", v, element) + self._add_coord_range1d_element("range", v, element) def _add_inputs_element(self, name, collection, parent): if collection is None or \ diff --git a/caom2tools/caom2/tests/test_xml_reader_writer.py b/caom2tools/caom2/tests/test_obs_reader_writer.py similarity index 99% rename from caom2tools/caom2/tests/test_xml_reader_writer.py rename to caom2tools/caom2/tests/test_obs_reader_writer.py index e7617504..5361ffb9 100644 --- a/caom2tools/caom2/tests/test_xml_reader_writer.py +++ b/caom2tools/caom2/tests/test_obs_reader_writer.py @@ -82,10 +82,10 @@ from caom2.observation import SimpleObservation from caom2.wcs import CoordCircle2D from caom2.wcs import CoordPolygon2D -from caom2.xml_reader_writer import CAOM20_NAMESPACE -from caom2.xml_reader_writer import CAOM21_NAMESPACE -from caom2.xml_reader_writer import ObservationReader -from caom2.xml_reader_writer import ObservationWriter +from caom2.obs_reader_writer import CAOM20_NAMESPACE +from caom2.obs_reader_writer import CAOM21_NAMESPACE +from caom2.obs_reader_writer import ObservationReader +from caom2.obs_reader_writer import ObservationWriter from caom_test_instances import Caom2TestInstances From c0d9124473605d80d4a5e038c856039d56bde4b8 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 15 Nov 2016 13:59:23 -0800 Subject: [PATCH 09/54] s1950: renamed unit test dir from tests to test --- caom2tools/MANIFEST.in | 2 +- caom2tools/__init__.py | 6 +- caom2tools/caom2/__init__.py | 164 ++++++++++-------- caom2tools/caom2/artifact.py | 14 +- caom2tools/caom2/caom_object.py | 26 ++- caom2tools/caom2/{util.py => caom_util.py} | 0 caom2tools/caom2/chunk.py | 47 +++-- caom2tools/caom2/obs_reader_writer.py | 2 +- caom2tools/caom2/observation.py | 44 +++-- caom2tools/caom2/part.py | 19 +- caom2tools/caom2/plane.py | 63 ++++--- caom2tools/caom2/shape.py | 16 +- caom2tools/caom2/test/__init__.py | 71 ++++++++ .../{tests => test}/caom_test_instances.py | 24 +-- .../data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../data/CompleteCompositeCircle.xml | 0 .../CompleteCompositePolygon-CAOM-2.1.xml | 0 .../CompleteCompositePolygon-CAOM-2.2.xml | 0 .../data/CompleteCompositePolygon.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../data/CompleteSimpleCircle.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../data/CompleteSimplePolygon.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../data/MinimalCompositeCircle.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../data/MinimalCompositePolygon.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../data/MinimalSimpleCircle.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../data/MinimalSimplePolygon.xml | 0 .../caom2/{tests => test}/test_artifact.py | 8 +- .../caom2/{tests => test}/test_caom_object.py | 14 +- .../test_util.py => test/test_caom_util.py} | 22 +-- .../caom2/{tests => test}/test_chunk.py | 24 +-- .../{tests => test}/test_obs_reader_writer.py | 16 +- .../caom2/{tests => test}/test_observation.py | 36 ++-- caom2tools/caom2/{tests => test}/test_part.py | 6 +- .../caom2/{tests => test}/test_plane.py | 36 ++-- .../caom2/{tests => test}/test_shape.py | 33 ++-- caom2tools/caom2/{tests => test}/test_wcs.py | 2 +- caom2tools/caom2/tests/setup_package.py | 3 - caom2tools/caom2/wcs.py | 50 +++--- caom2tools/setup.py | 8 +- caom2tools/{tests => test}/__init__.py | 0 caom2tools/{tests => test}/coveragerc | 0 caom2tools/{tests => test}/setup_package.py | 0 54 files changed, 407 insertions(+), 349 deletions(-) rename caom2tools/caom2/{util.py => caom_util.py} (100%) create mode 100644 caom2tools/caom2/test/__init__.py rename caom2tools/caom2/{tests => test}/caom_test_instances.py (97%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositeCircle.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteCompositePolygon.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimpleCircle.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/CompleteSimplePolygon.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositeCircle.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalCompositePolygon.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimpleCircle.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename caom2tools/caom2/{tests => test}/data/MinimalSimplePolygon.xml (100%) rename caom2tools/caom2/{tests => test}/test_artifact.py (97%) rename caom2tools/caom2/{tests => test}/test_caom_object.py (93%) rename caom2tools/caom2/{tests/test_util.py => test/test_caom_util.py} (96%) rename caom2tools/caom2/{tests => test}/test_chunk.py (96%) rename caom2tools/caom2/{tests => test}/test_obs_reader_writer.py (98%) rename caom2tools/caom2/{tests => test}/test_observation.py (97%) rename caom2tools/caom2/{tests => test}/test_part.py (97%) rename caom2tools/caom2/{tests => test}/test_plane.py (96%) rename caom2tools/caom2/{tests => test}/test_shape.py (84%) rename caom2tools/caom2/{tests => test}/test_wcs.py (99%) delete mode 100644 caom2tools/caom2/tests/setup_package.py rename caom2tools/{tests => test}/__init__.py (100%) rename caom2tools/{tests => test}/coveragerc (100%) rename caom2tools/{tests => test}/setup_package.py (100%) diff --git a/caom2tools/MANIFEST.in b/caom2tools/MANIFEST.in index 08f21c97..5d7be42c 100644 --- a/caom2tools/MANIFEST.in +++ b/caom2tools/MANIFEST.in @@ -1,2 +1,2 @@ include caom2/*.xsd -include caom2/test/data/*.xml +include caom2/tests/data/*.xml diff --git a/caom2tools/__init__.py b/caom2tools/__init__.py index e7359a5f..22a75cf8 100644 --- a/caom2tools/__init__.py +++ b/caom2tools/__init__.py @@ -7,10 +7,10 @@ # Affiliated packages may add whatever they like to this file, but # should keep this content at the top. # ---------------------------------------------------------------------------- -from ._astropy_init import * +# from ._astropy_init import * # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -if not _ASTROPY_SETUP_: +# if not _ASTROPY_SETUP_: # from .caom2tools import * - pass +# pass diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index b7f9797a..2851e29e 100755 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -68,102 +68,112 @@ #*********************************************************************** # -""" Deines __init__ """ +""" Defines __init__ """ + +# import artifact as artifact +# import caom_object as caom_object +# import chunk as chunk +# import observation as observation +# import part as part +# import plane as plane +# import caom_util as caom_util +# import wcs as wcs +from caom_util import Util as Util # -from caom_object import CaomObject -from caom_object import AbstractCaomEntity +# from .caom_object import CaomObject +# from .caom_object import AbstractCaomEntity # Util classes -from util import Util -from util import TypedList -from util import TypedSet -from util import TypedOrderedDict -from util import ClassProperty -from util import Validator +# from util import Util +# from .util import TypedList +# from .util import TypedSet +# from .util import TypedOrderedDict +# from .util import ClassProperty +# from .util import Validator # WCS data types -from wcs import Axis -from wcs import Coord2D -from wcs import CoordAxis1D -from wcs import CoordAxis2D -from wcs import CoordBounds1D -from wcs import CoordBounds2D -from wcs import CoordCircle2D -from wcs import CoordError -from wcs import CoordFunction1D -from wcs import CoordFunction2D -from wcs import CoordPolygon2D -from wcs import CoordRange1D -from wcs import CoordRange2D -from wcs import Dimension2D -from wcs import RefCoord -from wcs import Slice -from wcs import ValueCoord2D -from wcs import EnergyTransition +# from .wcs import Axis +# from .wcs import Coord2D +# from .wcs import CoordAxis1D +# from .wcs import CoordAxis2D +# from .wcs import CoordBounds1D +# from .wcs import CoordBounds2D +# from .wcs import CoordCircle2D +# from .wcs import CoordError +# from .wcs import CoordFunction1D +# from .wcs import CoordFunction2D +# from .wcs import CoordPolygon2D +# from .wcs import CoordRange1D +# from .wcs import CoordRange2D +# from .wcs import Dimension2D +# from .wcs import RefCoord +# from .wcs import Slice +# from .wcs import ValueCoord2D +# from .wcs import EnergyTransition # Discovery data types -from shape import Box -from shape import Circle -from shape import Interval -from shape import Point -from shape import Polygon -from shape import Vertex +# from .shape import Box +# from .shape import Circle +# from .shape import Interval +# from .shape import Point +# from .shape import Polygon +# from .shape import Vertex # Chunk level classes -from chunk import Chunk -from chunk import ObservableAxis -from chunk import SpatialWCS -from chunk import SpectralWCS -from chunk import TemporalWCS -from chunk import PolarizationWCS +# from .chunk import Chunk +# from .chunk import ObservableAxis +# from .chunk import SpatialWCS +# from .chunk import SpectralWCS +# from .chunk import TemporalWCS +# from .chunk import PolarizationWCS # Part level classes -from part import Part +# from .part import Part # Artifact level classes -from artifact import Artifact +# from .artifact import Artifact # Plane level classes -from plane import Plane -from plane import PlaneURI -from plane import DataQuality -from plane import Metrics -from plane import Provenance -from plane import Position -from plane import Energy -from plane import EnergyTransition -from plane import Polarization -from plane import Time +# from .plane import Plane +# from .plane import PlaneURI +# from .plane import DataQuality +# from .plane import Metrics +# from .plane import Provenance +# from .plane import Position +# from .plane import Energy +# from .plane import EnergyTransition +# from .plane import Polarization +# from .plane import Time # Observation level classes -from observation import Observation -from observation import ObservationURI -from observation import SimpleObservation -from observation import CompositeObservation -from observation import Algorithm -from observation import Environment -from observation import Proposal -from observation import Requirements -from observation import Target -from observation import TargetPosition -from observation import Telescope +# from .observation import Observation +# from .observation import ObservationURI +# from .observation import SimpleObservation +# from .observation import CompositeObservation +# from .observation import Algorithm +# from .observation import Environment +# from .observation import Proposal +# from .observation import Requirements +# from .observation import Target +# from .observation import TargetPosition +# from .observation import Telescope # enums -from artifact import ProductType -from artifact import ReleaseType -from plane import CalibrationLevel -from plane import DataProductType -from plane import EnergyBand -from plane import PolarizationState -from plane import Quality -from observation import ObservationIntentType -from observation import Status -from observation import TargetType +# from .artifact import ProductType +# from .artifact import ReleaseType +# from .plane import CalibrationLevel +# from .plane import DataProductType +# from .plane import EnergyBand +# from .plane import PolarizationState +# from .plane import Quality +# from .observation import ObservationIntentType +# from .observation import Status +# from .observation import TargetType # observation reader and writer -from obs_reader_writer import ObservationReader -from obs_reader_writer import ObservationWriter -from obs_reader_writer import CAOM20_NAMESPACE -from obs_reader_writer import CAOM21_NAMESPACE -from obs_reader_writer import CAOM22_NAMESPACE +# from .obs_reader_writer import ObservationReader +# from .obs_reader_writer import ObservationWriter +# from .obs_reader_writer import CAOM20_NAMESPACE +# from .obs_reader_writer import CAOM21_NAMESPACE +# from .obs_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/caom2/artifact.py b/caom2tools/caom2/artifact.py index 70aba8da..f46332c1 100644 --- a/caom2tools/caom2/artifact.py +++ b/caom2tools/caom2/artifact.py @@ -74,11 +74,11 @@ from urlparse import urlparse -from caom_object import AbstractCaomEntity +import caom_object +import caom_util +import part +from caom_util import Util from enum import Enum -from part import Part -from util import TypedOrderedDict -from util import Util ProductType = Enum('ProductType', SCIENCE="science", @@ -96,7 +96,7 @@ META="meta") -class Artifact(AbstractCaomEntity): +class Artifact(caom_object.AbstractCaomEntity): """Contains the meta data assocaited with a file. - location of the file (uri) @@ -132,7 +132,7 @@ def __init__(self, self.content_type = content_type self.content_length = content_length if parts is None: - parts = TypedOrderedDict((Part),) + parts = caom_util.TypedOrderedDict((part.Part),) self.parts = parts def _key(self): @@ -254,7 +254,7 @@ def parts(self): @parts.setter def parts(self, value): Util.type_check(value, - TypedOrderedDict, + caom_util.TypedOrderedDict, 'parts', override=False) self._parts = value diff --git a/caom2tools/caom2/caom_object.py b/caom2tools/caom2/caom_object.py index 2b57a673..cade8eb6 100644 --- a/caom2tools/caom2/caom_object.py +++ b/caom2tools/caom2/caom_object.py @@ -74,7 +74,7 @@ import uuid from datetime import datetime -from util import Util +from caom_util import Util class CaomObject(object): @@ -87,12 +87,10 @@ def __init__(self): def __str__(self): args = inspect.getargspec(self.__init__).args[1:] - clsName = self.__class__.__name__ - return "\n".join( - ["{}.{} : {}".format(clsName, - arg, - getattr(self, arg, None)) - for arg in args]) + class_name = self.__class__.__name__ + return "\n".join(["{}.{} : {}". + format(class_name, arg, getattr(self, arg, None)) + for arg in args]) def __eq__(self, other): if type(other) == type(self): @@ -102,17 +100,15 @@ def __eq__(self, other): def __repr__(self): args = inspect.getargspec(self.__init__).args[1:] - clsName = "" + class_name = "" if self.__class__.__module__ != '__main__': - clsName += self.__class__.__module__ + "." - clsName += self.__class__.__name__ - pading = " " * (len(clsName) + 1) - return clsName + "(" + ( + class_name += self.__class__.__module__ + "." + class_name += self.__class__.__name__ + pading = " " * (len(class_name) + 1) + return class_name + "(" + ( ",\n" + pading).join( ["%s=%r" % (arg, getattr(self, arg, None) - ) for arg in args - ] - ) + ")" + ) for arg in args]) + ")" class AbstractCaomEntity(CaomObject): diff --git a/caom2tools/caom2/util.py b/caom2tools/caom2/caom_util.py similarity index 100% rename from caom2tools/caom2/util.py rename to caom2tools/caom2/caom_util.py diff --git a/caom2tools/caom2/chunk.py b/caom2tools/caom2/chunk.py index 2eb9622a..ae40745f 100644 --- a/caom2tools/caom2/chunk.py +++ b/caom2tools/caom2/chunk.py @@ -72,17 +72,14 @@ """ -from artifact import ProductType -from caom_object import AbstractCaomEntity -from caom_object import CaomObject -from plane import EnergyTransition -from util import Util -from wcs import CoordAxis1D -from wcs import CoordAxis2D -from wcs import Slice +import artifact +import caom_object +import plane +from caom_util import Util +import wcs -class Chunk(AbstractCaomEntity): +class Chunk(caom_object.AbstractCaomEntity): """A caom2.Chunk object. A chunk is a peice of file part. eg. a column in a Table extension of a FITS file. @@ -140,7 +137,7 @@ def product_type(self): eg. Chunk.product_type = ProductType('SCIENCE') Allowed values: - """ + str(ProductType.names()) + """ + """ + str(artifact.ProductType.names()) + """ """ @@ -148,10 +145,10 @@ def product_type(self): @product_type.setter def product_type(self, value): - if isinstance(value, str) and value in ProductType.names(): + if isinstance(value, str) and value in artifact.ProductType.names(): ## be helpful - value = ProductType('value') - Util.type_check(value, ProductType, 'product_type') + value = artifact.ProductType('value') + Util.type_check(value, artifact.ProductType, 'product_type') self._product_type = value @property @@ -361,7 +358,7 @@ def polarization(self, value): self._polarization = value -class ObservableAxis(CaomObject): +class ObservableAxis(caom_object.CaomObject): """The slice through the data structure that provides the thing being described by this Axis. @@ -416,7 +413,7 @@ def dependent(self): @dependent.setter def dependent(self, value): - Util.type_check(value, Slice, 'dependent', override=False) + Util.type_check(value, wcs.Slice, 'dependent', override=False) self._dependent = value @property @@ -431,11 +428,11 @@ def independent(self): @independent.setter def independent(self, value): - Util.type_check(value, Slice, "independent") + Util.type_check(value, wcs.Slice, "independent") self._independent = value -class SpatialWCS(CaomObject): +class SpatialWCS(caom_object.CaomObject): """this object contains the WCS information needed to convert an astronomical spatial location (ie. RA/DEC) into a pixel location in the image. @@ -467,7 +464,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, CoordAxis2D, 'axis', override=False) + Util.type_check(value, wcs.CoordAxis2D, 'axis', override=False) self._axis = value @property @@ -521,7 +518,7 @@ def resolution(self, value): self._resolution = value -class SpectralWCS(CaomObject): +class SpectralWCS(caom_object.CaomObject): """A transformation that maps pixel coordinates to spectral ones. Note that a 2D image has implicit 'spectral' (and temporal) @@ -580,7 +577,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, CoordAxis1D, 'axis', override=False) + Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) self._axis = value @property @@ -733,7 +730,7 @@ def transition(self): @transition.setter def transition(self, value): - Util.type_check(value, EnergyTransition, "transition") + Util.type_check(value, plane.EnergyTransition, "transition") self._transition = value @property @@ -754,7 +751,7 @@ def resolving_power(self, value): self._resolving_power = value -class TemporalWCS(CaomObject): +class TemporalWCS(caom_object.CaomObject): """Describes the Time variation within the data. In the case of a single exposure, define the center of the first @@ -786,7 +783,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, CoordAxis1D, 'axis', override=False) + Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) self._axis = value @property @@ -883,7 +880,7 @@ def resolution(self, value): self._resolution = value -class PolarizationWCS(CaomObject): +class PolarizationWCS(caom_object.CaomObject): """A WCS structure that describes the relation ship between a pixel location and the polarization value. @@ -908,7 +905,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, CoordAxis1D, 'axis', override=False) + Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) if value.axis.ctype != 'STOKES': raise ValueError('CTYPE must be STOKES') self._axis = value diff --git a/caom2tools/caom2/obs_reader_writer.py b/caom2tools/caom2/obs_reader_writer.py index 21c94bd3..d55890ca 100644 --- a/caom2tools/caom2/obs_reader_writer.py +++ b/caom2tools/caom2/obs_reader_writer.py @@ -82,7 +82,7 @@ import part import plane import wcs -from util import Util +from caom_util import Util CAOM2_PKG = 'caom2' diff --git a/caom2tools/caom2/observation.py b/caom2tools/caom2/observation.py index 110e078a..5d41a2cd 100644 --- a/caom2tools/caom2/observation.py +++ b/caom2tools/caom2/observation.py @@ -73,14 +73,12 @@ from datetime import datetime from urlparse import SplitResult -from caom_object import AbstractCaomEntity -from caom_object import CaomObject -from shape import Point +import caom_object +import plane +import shape +import caom_util from enum import Enum -from plane import Plane -from util import TypedOrderedDict -from util import TypedSet -from util import Util +from caom_util import Util ObservationIntentType = Enum('ObservationIntentType', CALIBRATION="calibration", @@ -94,7 +92,7 @@ OBJECT="object") -class Observation(AbstractCaomEntity): +class Observation(caom_object.AbstractCaomEntity): """ Observation @@ -190,7 +188,7 @@ def __init__(self, self.requirements = requirements self.meta_release = meta_release if planes is None: - planes = Util.TypedOrderedDict((Plane),) + planes = Util.TypedOrderedDict((plane.Plane),) self.planes = planes # Properties @@ -251,7 +249,7 @@ def planes(self): @planes.setter def planes(self, value): - Util.type_check(value, TypedOrderedDict, 'planes') + Util.type_check(value, caom_util.TypedOrderedDict, 'planes') self._planes = value @property @@ -441,7 +439,7 @@ def meta_release(self, value): self._meta_release = value -class ObservationURI(CaomObject): +class ObservationURI(caom_object.CaomObject): """ Observation URI """ _SCHEME = str("caom") @@ -535,7 +533,7 @@ def observation_id(self): return self._observation_id -class SimpleObservation(Observation): +class SimpleObservation(observation.Observation): """A convenience class for building Observations where algorithm='exposure'. @@ -618,7 +616,7 @@ def algorithm(self, value=_ALGORITHM): self._algorithm = value -class CompositeObservation(Observation): +class CompositeObservation(observation.Observation): """ Composite Observation @@ -661,7 +659,7 @@ def __init__(self, environment, target_position ) - self._members = TypedSet((ObservationURI),) + self._members = caom_util.TypedSet(ObservationURI, ) @property def algorithm(self): @@ -681,7 +679,7 @@ def members(self): return self._members -class Algorithm(CaomObject): +class Algorithm(caom_object.CaomObject): """ The concept of Algorithm is to provide a way for users to find all composite observation sets that have been built using a particular @@ -718,7 +716,7 @@ def name(self): return self._name -class Environment(CaomObject): +class Environment(caom_object.CaomObject): """A CAOM2 Environment Object. This object contains the various values that can be set in the environment @@ -841,7 +839,7 @@ def photometric(self, value): self._photometric = value -class Instrument(CaomObject): +class Instrument(caom_object.CaomObject): """The telescopic instrument that recorded a given observation. Each observation should have an associated instrument. @@ -894,7 +892,7 @@ def keywords(self): return self._keywords -class Proposal(CaomObject): +class Proposal(caom_object.CaomObject): """ Proposal """ def __init__(self, @@ -990,7 +988,7 @@ def title(self, value): self._title = value -class Requirements(CaomObject): +class Requirements(caom_object.CaomObject): """ Requirements """ def __init__(self, flag): @@ -1013,7 +1011,7 @@ def flag(self, value): self._flag = value -class Target(CaomObject): +class Target(caom_object.CaomObject): """ Target """ def __init__(self, name, @@ -1136,7 +1134,7 @@ def moving(self, value): self._moving = value -class TargetPosition(CaomObject): +class TargetPosition(caom_object.CaomObject): """ TargetPosition """ def __init__(self, coordinates, coordsys, equinox=None): @@ -1161,7 +1159,7 @@ def coordinates(self): @coordinates.setter def coordinates(self, value): - Util.type_check(value, Point, "coordinates") + Util.type_check(value, shape.Point, "coordinates") self._coordinates = value @property @@ -1185,7 +1183,7 @@ def equinox(self, value): self._equinox = value -class Telescope(CaomObject): +class Telescope(caom_object.CaomObject): """ Telescope """ def __init__(self, name, diff --git a/caom2tools/caom2/part.py b/caom2tools/caom2/part.py index 6124f1d3..744904a1 100644 --- a/caom2tools/caom2/part.py +++ b/caom2tools/caom2/part.py @@ -71,15 +71,14 @@ """Defines the caom2.Part class which describes the caom2_Observation_Plane_Artifact_Part object.""" +import artifact +import caom_object +import chunk +import caom_util +from caom_util import Util -from caom_object import AbstractCaomEntity -from chunk import Chunk -from artifact import ProductType -from util import TypedList -from util import Util - -class Part(AbstractCaomEntity): +class Part(caom_object.AbstractCaomEntity): """A qualitative subsection of an artifact. eg: a extension of a FITS file. @@ -93,7 +92,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = TypedList((Chunk),) + chunks = caom_util.TypedList((chunk.Chunk), ) self.chunks = chunks def _key(self): @@ -117,7 +116,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - Util.type_check(value, ProductType, "product_type") + Util.type_check(value, artifact.ProductType, "product_type") self._product_type = value @property @@ -145,5 +144,5 @@ def chunks(self): @chunks.setter def chunks(self, value): - Util.type_check(value, TypedList, 'chunks', override=False) + Util.type_check(value, caom_util.TypedList, 'chunks', override=False) self._chunks = value diff --git a/caom2tools/caom2/plane.py b/caom2tools/caom2/plane.py index 21fd7ed0..b928ae12 100644 --- a/caom2tools/caom2/plane.py +++ b/caom2tools/caom2/plane.py @@ -74,19 +74,14 @@ from urlparse import SplitResult from urlparse import urlsplit -from artifact import Artifact -from caom_object import AbstractCaomEntity -from caom_object import CaomObject -from shape import Box -from shape import Circle -from shape import Interval -from shape import Polygon +import artifact +import caom_object +import observation +import shape +import caom_util +import wcs from enum import Enum -from observation import ObservationURI -from util import TypedOrderedDict -from util import TypedSet -from util import Util -from wcs import Dimension2D +from caom_util import Util CalibrationLevel = Enum('CalibrationLevel', RAW_INSTRUMENT=0, @@ -131,7 +126,7 @@ JUNK="junk") -class Plane(AbstractCaomEntity): +class Plane(caom_object.AbstractCaomEntity): """ Plane class """ def __init__(self, product_id, @@ -152,7 +147,7 @@ def __init__(self, product_id, super(Plane, self).__init__() self.product_id = product_id if artifacts is None: - artifacts = TypedOrderedDict((Artifact),) + artifacts = caom_util.TypedOrderedDict((artifact.Artifact), ) self.artifacts = artifacts self.meta_release = meta_release @@ -210,7 +205,7 @@ def artifacts(self): @artifacts.setter def artifacts(self, value): - Util.type_check(value, TypedOrderedDict, 'artifacts', override=False) + Util.type_check(value, caom_util.TypedOrderedDict, 'artifacts', override=False) self._artifacts = value @property @@ -408,7 +403,7 @@ def compute_polarization(self): "has not been implemented in this module") -class PlaneURI(CaomObject): +class PlaneURI(caom_object.CaomObject): """ Plane URI """ def __init__(self, uri): @@ -442,13 +437,13 @@ def get_plane_uri(cls, observation_uri, product_id): observation_uri : the uri of the observation product_id : ID of the product """ - Util.type_check(observation_uri, ObservationURI, "observation_uri", + Util.type_check(observation_uri, observation.ObservationURI, "observation_uri", override=False) Util.type_check(product_id, str, "observation_uri", override=False) Util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path - uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + + uri = SplitResult(observation.ObservationURI._SCHEME, "", path + "/" + product_id, "", "").geturl() return cls(uri) @@ -464,7 +459,7 @@ def uri(self, value): Util.type_check(value, str, "uri", override=False) tmp = urlsplit(value) - if tmp.scheme != ObservationURI._SCHEME: + if tmp.scheme != observation.ObservationURI._SCHEME: raise ValueError("{} doesn't have an allowed scheme".format(value)) if tmp.geturl() != value: raise ValueError("Failed to parse uri correctly: {}".format(value)) @@ -477,8 +472,8 @@ def uri(self, value): self._product_id = product_id self._observation_uri = \ - ObservationURI.get_observation_uri(collection, - observation_id) + observation.ObservationURI.get_observation_uri(collection, + observation_id) self._uri = value @property @@ -493,7 +488,7 @@ def observation_uri(self): return self._observation_uri -class DataQuality(CaomObject): +class DataQuality(caom_object.CaomObject): """ DataQuality """ def __init__(self, flag): @@ -516,7 +511,7 @@ def flag(self, value): self._flag = value -class Metrics(CaomObject): +class Metrics(caom_object.CaomObject): """ Metrics """ def __init__(self): @@ -614,7 +609,7 @@ def mag_limit(self, value): self._mag_limit = value -class Provenance(CaomObject): +class Provenance(caom_object.CaomObject): """ Provenance """ def __init__(self, name, @@ -643,7 +638,7 @@ def __init__(self, name, self.last_executed = last_executed self._keywords = set() - self._inputs = TypedSet((PlaneURI),) + self._inputs = caom_util.TypedSet((PlaneURI), ) # Properties @@ -726,7 +721,7 @@ def inputs(self): return self._inputs -class Position(CaomObject): +class Position(caom_object.CaomObject): """ Position """ def __init__(self, bounds=None, @@ -757,7 +752,7 @@ def bounds(self): @bounds.setter def bounds(self, value): if value is not None: - assert isinstance(value, (Box, Circle, Polygon)), ( + assert isinstance(value, (shape.Box, shape.Circle, shape.Polygon)), ( "bounds is not a Shape: {0}".format(value)) self._bounds = value @@ -769,7 +764,7 @@ def dimension(self): @dimension.setter def dimension(self, value): if value is not None: - assert isinstance(value, Dimension2D), ( + assert isinstance(value, wcs.Dimension2D), ( "dimension is not a Dimension2D: {0}".format(value)) self._dimension = value @@ -810,7 +805,7 @@ def time_dependent(self, value): self._time_dependent = value -class Energy(CaomObject): +class Energy(caom_object.CaomObject): """ Energy """ def __init__(self): @@ -850,7 +845,7 @@ def bounds(self): @bounds.setter def bounds(self, value): if value is not None: - assert isinstance(value, Interval), ( + assert isinstance(value, shape.Interval), ( "energy bounds is not an Interval: {0}".format(value)) self._bounds = value @@ -927,7 +922,7 @@ def transition(self, value): self._transition = value -class EnergyTransition(CaomObject): +class EnergyTransition(caom_object.CaomObject): """ EnergyTransition """ def __init__(self, species, transition): @@ -954,7 +949,7 @@ def transition(self): return self._transition -class Polarization(CaomObject): +class Polarization(caom_object.CaomObject): """ Polarization """ def __init__(self, @@ -986,7 +981,7 @@ def dimension(self, value): self._dimension = value -class Time(CaomObject): +class Time(caom_object.CaomObject): """ Time """ def __init__(self, @@ -1041,7 +1036,7 @@ def bounds(self): @bounds.setter def bounds(self, value): - Util.type_check(value, Interval, 'bounds') + Util.type_check(value, shape.Interval, 'bounds') self._bounds = value @property diff --git a/caom2tools/caom2/shape.py b/caom2tools/caom2/shape.py index 6f8687ff..6730666e 100644 --- a/caom2tools/caom2/shape.py +++ b/caom2tools/caom2/shape.py @@ -69,8 +69,8 @@ # from enum import Enum -from caom_object import CaomObject -from util import Util +import caom_object +from caom_util import Util SegmentType = Enum('SegmentType', @@ -79,25 +79,25 @@ MOVE=2) -class Box(CaomObject): +class Box(caom_object.CaomObject): def __init__(self): pass -class Circle(CaomObject): +class Circle(caom_object.CaomObject): def __init__(self): pass -class Interval(CaomObject): +class Interval(caom_object.CaomObject): def __init__(self): pass -class Point(CaomObject): +class Point(caom_object.CaomObject): def __init__(self, cval1, cval2): @@ -129,13 +129,13 @@ def cval2(self, value): self._cval2 = value -class Polygon(CaomObject): +class Polygon(caom_object.CaomObject): def __init__(self): pass -class Vertex(CaomObject): +class Vertex(caom_object.CaomObject): def __init__(self): pass diff --git a/caom2tools/caom2/test/__init__.py b/caom2tools/caom2/test/__init__.py new file mode 100644 index 00000000..425cb2f4 --- /dev/null +++ b/caom2tools/caom2/test/__init__.py @@ -0,0 +1,71 @@ +# +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Defines __init__ """ \ No newline at end of file diff --git a/caom2tools/caom2/tests/caom_test_instances.py b/caom2tools/caom2/test/caom_test_instances.py similarity index 97% rename from caom2tools/caom2/tests/caom_test_instances.py rename to caom2tools/caom2/test/caom_test_instances.py index 5eb23272..c2d62631 100644 --- a/caom2tools/caom2/tests/caom_test_instances.py +++ b/caom2tools/caom2/test/caom_test_instances.py @@ -73,13 +73,13 @@ import collections from datetime import datetime -from caom2 import artifact -from caom2 import chunk -from caom2 import observation as obs -from caom2 import part -from caom2 import plane -from caom2 import util -from caom2 import wcs +import artifact +import chunk +import observation as obs +import part +import plane +import caom_util +import wcs class Caom2TestInstances(object): @@ -225,7 +225,7 @@ def get_environment(self): return env def get_members(self): - members = util.TypedSet( + members = caom_util.TypedSet( obs.ObservationURI, obs.ObservationURI("caom:foo/bar")) return members @@ -261,9 +261,9 @@ def get_provenance(self): return provenance def get_inputs(self): - return util.TypedSet(plane.PlaneURI, - plane.PlaneURI("caom:foo/bar/plane1"), - plane.PlaneURI("caom:foo/bar/plane2")) + return caom_util.TypedSet(plane.PlaneURI, + plane.PlaneURI("caom:foo/bar/plane1"), + plane.PlaneURI("caom:foo/bar/plane2")) def get_metrics(self): metrics = plane.Metrics() @@ -303,7 +303,7 @@ def get_parts(self): return parts def get_chunks(self): - chunks = util.TypedList(chunk.Chunk,) + chunks = caom_util.TypedList(chunk.Chunk, ) _chunk = chunk.Chunk() if self.complete: _chunk.product_type = artifact.ProductType.SCIENCE diff --git a/caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/CompleteCompositeCircle.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositeCircle.xml rename to caom2tools/caom2/test/data/CompleteCompositeCircle.xml diff --git a/caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/CompleteCompositePolygon.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteCompositePolygon.xml rename to caom2tools/caom2/test/data/CompleteCompositePolygon.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimpleCircle.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimpleCircle.xml rename to caom2tools/caom2/test/data/CompleteSimpleCircle.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/CompleteSimplePolygon.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/data/CompleteSimplePolygon.xml rename to caom2tools/caom2/test/data/CompleteSimplePolygon.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositeCircle.xml b/caom2tools/caom2/test/data/MinimalCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositeCircle.xml rename to caom2tools/caom2/test/data/MinimalCompositeCircle.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/MinimalCompositePolygon.xml b/caom2tools/caom2/test/data/MinimalCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalCompositePolygon.xml rename to caom2tools/caom2/test/data/MinimalCompositePolygon.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimpleCircle.xml b/caom2tools/caom2/test/data/MinimalSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimpleCircle.xml rename to caom2tools/caom2/test/data/MinimalSimpleCircle.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/tests/data/MinimalSimplePolygon.xml b/caom2tools/caom2/test/data/MinimalSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/tests/data/MinimalSimplePolygon.xml rename to caom2tools/caom2/test/data/MinimalSimplePolygon.xml diff --git a/caom2tools/caom2/tests/test_artifact.py b/caom2tools/caom2/test/test_artifact.py similarity index 97% rename from caom2tools/caom2/tests/test_artifact.py rename to caom2tools/caom2/test/test_artifact.py index 0be92e4a..59225779 100644 --- a/caom2tools/caom2/tests/test_artifact.py +++ b/caom2tools/caom2/test/test_artifact.py @@ -73,10 +73,10 @@ import unittest from urlparse import urlparse -from caom2.artifact import Artifact -from caom2.artifact import ProductType -from caom2.artifact import ReleaseType -from caom2.part import Part +from caom2tools.caom2.artifact import Artifact +from caom2tools.caom2.artifact import ProductType +from caom2tools.caom2.artifact import ReleaseType +from caom2tools.caom2.part import Part class TestEnums(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_caom_object.py b/caom2tools/caom2/test/test_caom_object.py similarity index 93% rename from caom2tools/caom2/tests/test_caom_object.py rename to caom2tools/caom2/test/test_caom_object.py index 795ee9ce..bc4f8775 100644 --- a/caom2tools/caom2/tests/test_caom_object.py +++ b/caom2tools/caom2/test/test_caom_object.py @@ -72,13 +72,13 @@ import unittest -from caom2.artifact import Artifact, ProductType, ReleaseType -from caom2.caom_object import AbstractCaomEntity -from caom2.chunk import Chunk -from caom2.observation import Algorithm -from caom2.observation import Observation -from caom2.part import Part -from caom2.plane import Plane +from caom2tools.caom2.artifact import Artifact, ProductType, ReleaseType +from caom2tools.caom2.caom_object import AbstractCaomEntity +from caom2tools.caom2.chunk import Chunk +from caom2tools.caom2.observation import Algorithm +from caom2tools.caom2.observation import Observation +from caom2tools.caom2.part import Part +from caom2tools.caom2.plane import Plane class TestCaom2IdGenerator(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_util.py b/caom2tools/caom2/test/test_caom_util.py similarity index 96% rename from caom2tools/caom2/tests/test_util.py rename to caom2tools/caom2/test/test_caom_util.py index 16826501..249fb4c4 100644 --- a/caom2tools/caom2/tests/test_util.py +++ b/caom2tools/caom2/test/test_caom_util.py @@ -73,17 +73,17 @@ import unittest import uuid -from caom2.artifact import Artifact -from caom2.artifact import ProductType -from caom2.artifact import ReleaseType -from caom2.part import Part -from caom2.plane import Energy -from caom2.plane import Plane -from caom2.plane import PlaneURI -from caom2.util import TypedList -from caom2.util import TypedOrderedDict -from caom2.util import TypedSet -from caom2.util import Util +from caom2tools.caom2.artifact import Artifact +from caom2tools.caom2.artifact import ProductType +from caom2tools.caom2.artifact import ReleaseType +from caom2tools.caom2.part import Part +from caom2tools.caom2.plane import Energy +from caom2tools.caom2.plane import Plane +from caom2tools.caom2.plane import PlaneURI +from caom2tools.caom2.caom_util import TypedList +from caom2tools.caom2.caom_util import TypedOrderedDict +from caom2tools.caom2.caom_util import TypedSet +from caom2tools.caom2.caom_util import Util class TestCaomUtil(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_chunk.py b/caom2tools/caom2/test/test_chunk.py similarity index 96% rename from caom2tools/caom2/tests/test_chunk.py rename to caom2tools/caom2/test/test_chunk.py index d0e8bea7..fc281837 100644 --- a/caom2tools/caom2/tests/test_chunk.py +++ b/caom2tools/caom2/test/test_chunk.py @@ -72,18 +72,18 @@ import unittest -from caom2.artifact import ProductType -from caom2.chunk import Chunk -from caom2.chunk import ObservableAxis -from caom2.chunk import PolarizationWCS -from caom2.chunk import SpatialWCS -from caom2.chunk import SpectralWCS -from caom2.chunk import TemporalWCS -from caom2.plane import EnergyTransition -from caom2.wcs import Axis -from caom2.wcs import CoordAxis1D -from caom2.wcs import CoordAxis2D -from caom2.wcs import Slice +from caom2tools.caom2.artifact import ProductType +from caom2tools.caom2.chunk import Chunk +from caom2tools.caom2.chunk import ObservableAxis +from caom2tools.caom2.chunk import PolarizationWCS +from caom2tools.caom2.chunk import SpatialWCS +from caom2tools.caom2.chunk import SpectralWCS +from caom2tools.caom2.chunk import TemporalWCS +from caom2tools.caom2.plane import EnergyTransition +from caom2tools.caom2.wcs import Axis +from caom2tools.caom2.wcs import CoordAxis1D +from caom2tools.caom2.wcs import CoordAxis2D +from caom2tools.caom2.wcs import Slice class TestChunk(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py similarity index 98% rename from caom2tools/caom2/tests/test_obs_reader_writer.py rename to caom2tools/caom2/test/test_obs_reader_writer.py index 5361ffb9..edd14d69 100644 --- a/caom2tools/caom2/tests/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -78,14 +78,14 @@ import shutil import unittest -from caom2.observation import CompositeObservation -from caom2.observation import SimpleObservation -from caom2.wcs import CoordCircle2D -from caom2.wcs import CoordPolygon2D -from caom2.obs_reader_writer import CAOM20_NAMESPACE -from caom2.obs_reader_writer import CAOM21_NAMESPACE -from caom2.obs_reader_writer import ObservationReader -from caom2.obs_reader_writer import ObservationWriter +from caom2tools.caom2.observation import CompositeObservation +from caom2tools.caom2.observation import SimpleObservation +from caom2tools.caom2.wcs import CoordCircle2D +from caom2tools.caom2.wcs import CoordPolygon2D +from caom2tools.caom2.obs_reader_writer import CAOM20_NAMESPACE +from caom2tools.caom2.obs_reader_writer import CAOM21_NAMESPACE +from caom2tools.caom2.obs_reader_writer import ObservationReader +from caom2tools.caom2.obs_reader_writer import ObservationWriter from caom_test_instances import Caom2TestInstances diff --git a/caom2tools/caom2/tests/test_observation.py b/caom2tools/caom2/test/test_observation.py similarity index 97% rename from caom2tools/caom2/tests/test_observation.py rename to caom2tools/caom2/test/test_observation.py index 467856a6..a959e1ee 100644 --- a/caom2tools/caom2/tests/test_observation.py +++ b/caom2tools/caom2/test/test_observation.py @@ -73,24 +73,24 @@ import unittest from datetime import datetime -from caom2.shape import Point -from caom2.observation import Algorithm -from caom2.observation import CompositeObservation -from caom2.observation import Environment -from caom2.observation import Instrument -from caom2.observation import Observation -from caom2.observation import ObservationIntentType -from caom2.observation import ObservationURI -from caom2.observation import Proposal -from caom2.observation import Requirements -from caom2.observation import SimpleObservation -from caom2.observation import Status -from caom2.observation import Target -from caom2.observation import TargetPosition -from caom2.observation import TargetType -from caom2.observation import Telescope -from caom2.plane import Plane -from caom2.util import Util +from caom2tools.caom2.shape import Point +from caom2tools.caom2.observation import Algorithm +from caom2tools.caom2.observation import CompositeObservation +from caom2tools.caom2.observation import Environment +from caom2tools.caom2.observation import Instrument +from caom2tools.caom2.observation import Observation +from caom2tools.caom2.observation import ObservationIntentType +from caom2tools.caom2.observation import ObservationURI +from caom2tools.caom2.observation import Proposal +from caom2tools.caom2.observation import Requirements +from caom2tools.caom2.observation import SimpleObservation +from caom2tools.caom2.observation import Status +from caom2tools.caom2.observation import Target +from caom2tools.caom2.observation import TargetPosition +from caom2tools.caom2.observation import TargetType +from caom2tools.caom2.observation import Telescope +from caom2tools.caom2.plane import Plane +from caom2tools.caom2.caom_util import Util class TestEnums(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_part.py b/caom2tools/caom2/test/test_part.py similarity index 97% rename from caom2tools/caom2/tests/test_part.py rename to caom2tools/caom2/test/test_part.py index bd301a4c..c60268f7 100644 --- a/caom2tools/caom2/tests/test_part.py +++ b/caom2tools/caom2/test/test_part.py @@ -72,9 +72,9 @@ import unittest -from caom2.artifact import ProductType -from caom2.chunk import Chunk -from caom2.part import Part +from caom2tools.caom2.artifact import ProductType +from caom2tools.caom2.chunk import Chunk +from caom2tools.caom2.part import Part class TestPart(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_plane.py b/caom2tools/caom2/test/test_plane.py similarity index 96% rename from caom2tools/caom2/tests/test_plane.py rename to caom2tools/caom2/test/test_plane.py index e15b3d43..b16ac53d 100644 --- a/caom2tools/caom2/tests/test_plane.py +++ b/caom2tools/caom2/test/test_plane.py @@ -73,24 +73,24 @@ import unittest from datetime import datetime -from caom2.artifact import Artifact -from caom2.artifact import ProductType, ReleaseType -from caom2.observation import ObservationURI -from caom2.plane import CalibrationLevel -from caom2.plane import DataProductType -from caom2.plane import DataQuality -from caom2.plane import Energy -from caom2.plane import EnergyBand -from caom2.plane import EnergyTransition -from caom2.plane import Metrics -from caom2.plane import Plane -from caom2.plane import PlaneURI -from caom2.plane import Polarization -from caom2.plane import PolarizationState -from caom2.plane import Position -from caom2.plane import Provenance -from caom2.plane import Quality -from caom2.plane import Time +from caom2tools.caom2.artifact import Artifact +from caom2tools.caom2.artifact import ProductType, ReleaseType +from caom2tools.caom2.observation import ObservationURI +from caom2tools.caom2.plane import CalibrationLevel +from caom2tools.caom2.plane import DataProductType +from caom2tools.caom2.plane import DataQuality +from caom2tools.caom2.plane import Energy +from caom2tools.caom2.plane import EnergyBand +from caom2tools.caom2.plane import EnergyTransition +from caom2tools.caom2.plane import Metrics +from caom2tools.caom2.plane import Plane +from caom2tools.caom2.plane import PlaneURI +from caom2tools.caom2.plane import Polarization +from caom2tools.caom2.plane import PolarizationState +from caom2tools.caom2.plane import Position +from caom2tools.caom2.plane import Provenance +from caom2tools.caom2.plane import Quality +from caom2tools.caom2.plane import Time class TestEnums(unittest.TestCase): diff --git a/caom2tools/caom2/tests/test_shape.py b/caom2tools/caom2/test/test_shape.py similarity index 84% rename from caom2tools/caom2/tests/test_shape.py rename to caom2tools/caom2/test/test_shape.py index 21d0f709..3457f097 100644 --- a/caom2tools/caom2/tests/test_shape.py +++ b/caom2tools/caom2/test/test_shape.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -70,37 +70,32 @@ import unittest -from caom2.shape import Point -from caom2.shape import SegmentType +from caom2tools.caom2 import shape class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(SegmentType.get(999), None) - self.assertRaises(AttributeError, SegmentType.get, None) - self.assertRaises(AttributeError, SegmentType.get, "foo") + self.assertEqual(shape.SegmentType.get(999), None) + self.assertRaises(AttributeError, shape.SegmentType.get, None) + self.assertRaises(AttributeError, shape.SegmentType.get, "foo") - self.assertEqual(SegmentType.CLOSE.value, 0) - self.assertEqual(SegmentType.LINE.value, 1) - self.assertEqual(SegmentType.MOVE.value, 2) + self.assertEqual(shape.SegmentType.CLOSE.value, 0) + self.assertEqual(shape.SegmentType.LINE.value, 1) + self.assertEqual(shape.SegmentType.MOVE.value, 2) class TestPoint(unittest.TestCase): def test_all(self): - self.assertRaises(TypeError, Point, None, None) - self.assertRaises(TypeError, Point, None, 1.0) - self.assertRaises(TypeError, Point, 1.0, None) - self.assertRaises(TypeError, Point, "string", int(1)) - self.assertRaises(TypeError, Point, int(1), "string") + self.assertRaises(TypeError, shape.Point, None, None) + self.assertRaises(TypeError, shape.Point, None, 1.0) + self.assertRaises(TypeError, shape.Point, 1.0, None) + self.assertRaises(TypeError, shape.Point, "string", int(1)) + self.assertRaises(TypeError, shape.Point, int(1), "string") - point = Point(1.0, 2.0) + point = shape.Point(1.0, 2.0) self.assertEqual(point.cval1, 1.0) self.assertEqual(point.cval2, 2.0) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/tests/test_wcs.py b/caom2tools/caom2/test/test_wcs.py similarity index 99% rename from caom2tools/caom2/tests/test_wcs.py rename to caom2tools/caom2/test/test_wcs.py index 4544499b..585c7e5a 100644 --- a/caom2tools/caom2/tests/test_wcs.py +++ b/caom2tools/caom2/test/test_wcs.py @@ -70,7 +70,7 @@ import unittest -from caom2 import wcs +from caom2tools.caom2 import wcs class TestAxis(unittest.TestCase): diff --git a/caom2tools/caom2/tests/setup_package.py b/caom2tools/caom2/tests/setup_package.py deleted file mode 100644 index 3cef2cb5..00000000 --- a/caom2tools/caom2/tests/setup_package.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_package_data(): - return { - 'caom2tools.caom2.tests': ['coveragerc']} diff --git a/caom2tools/caom2/wcs.py b/caom2tools/caom2/wcs.py index 976465a5..6a320e03 100644 --- a/caom2tools/caom2/wcs.py +++ b/caom2tools/caom2/wcs.py @@ -69,12 +69,12 @@ # -from caom_object import CaomObject -from util import TypedList -from util import Util +import caom_object +import caom_util +from caom_util import Util -class Axis(CaomObject): +class Axis(caom_object.CaomObject): """the Axis class holds the definition of the axis type and units""" def __init__(self, ctype, cunit=None): @@ -113,7 +113,7 @@ def cunit(self, value): self._cunit = value -class Coord2D(CaomObject): +class Coord2D(caom_object.CaomObject): """Represents the reference point. eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) @@ -150,7 +150,7 @@ def coord2(self, value): self._coord2 = value -class CoordAxis1D(CaomObject): +class CoordAxis1D(caom_object.CaomObject): """Holds the metadata needed to transform a 1D pixel value into a World Coordinate value. @@ -245,7 +245,7 @@ def function(self, value): self._function = value -class CoordAxis2D(CaomObject): +class CoordAxis2D(caom_object.CaomObject): """This object hold the metadata need to transform a 2D pixel array (say an image) into a World position, say RA/DEC @@ -367,7 +367,7 @@ def function(self, value): self._function = value -class CoordBounds1D(CaomObject): +class CoordBounds1D(caom_object.CaomObject): """Contains the bounds for a 1D axis, a list of ranges """ @@ -375,7 +375,7 @@ class CoordBounds1D(CaomObject): def __init__(self, samples=None): if samples is None: - samples = TypedList((CoordRange1D),) + samples = caom_util.TypedList((CoordRange1D),) self.samples = samples @property @@ -394,13 +394,13 @@ def samples(self): @samples.setter def samples(self, value): Util.type_check(value, - TypedList, + caom_util.TypedList, 'samples', override=False) self._samples = value -class CoordBounds2D(CaomObject): +class CoordBounds2D(caom_object.CaomObject): """Contains the bounds for a 2D axis """ @@ -428,7 +428,7 @@ def bounds(self, value): self._bounds = value -class CoordCircle2D(CaomObject): +class CoordCircle2D(caom_object.CaomObject): """A circle expressed in both pixel and WCS value coordinates. These objects are used to map out the bounds of spatial WCS. @@ -473,7 +473,7 @@ def radius(self, value): self._radius = value -class CoordError(CaomObject): +class CoordError(caom_object.CaomObject): """Holds the systematic (syser) and random (rnder) error on a coordinate. @@ -522,7 +522,7 @@ def rnder(self, value): self._rnder = value -class CoordFunction1D(CaomObject): +class CoordFunction1D(caom_object.CaomObject): """Defines a linear function that transforms from pixel to WCS values. @@ -586,7 +586,7 @@ def ref_coord(self, value): self._ref_coord = value -class CoordFunction2D(CaomObject): +class CoordFunction2D(caom_object.CaomObject): """Describes the parameters needed for the standard CD matrix. defines a linear translation between pixel and WCS. @@ -696,7 +696,7 @@ def cd22(self, value): self._cd22 = value -class CoordPolygon2D(CaomObject): +class CoordPolygon2D(caom_object.CaomObject): """A object to contain a TypeList ValueCoord2D vertices that are a polygon. The vertices are given as ValueCoord2D objects, which are coordinate pairs. @@ -707,7 +707,7 @@ class CoordPolygon2D(CaomObject): def __init__(self, vertices=None): if vertices is None: - vertices = TypedList((ValueCoord2D),) + vertices = caom_util.TypedList((ValueCoord2D),) self.vertices = vertices @property @@ -728,11 +728,11 @@ def vertices(self): @vertices.setter def vertices(self, value): - Util.type_check(value, TypedList, 'vertices', override=False) + Util.type_check(value, caom_util.TypedList, 'vertices', override=False) self._vertices = value -class CoordRange1D(CaomObject): +class CoordRange1D(caom_object.CaomObject): """a CoordRange1D object contains the start and end of a range of values, expressed in both pixel and WCS units. @@ -773,7 +773,7 @@ def end(self, value): self._end = value -class CoordRange2D(CaomObject): +class CoordRange2D(caom_object.CaomObject): """A range (x1,y1) to (x2,y2) in two dimenstions. The range object should know the coordinate in both @@ -812,7 +812,7 @@ def end(self, value): self._end = value -class Dimension2D(CaomObject): +class Dimension2D(caom_object.CaomObject): """Hey, how big is this thing? What are its dimensions. That's what Dimension2D will tell you. @@ -857,7 +857,7 @@ def naxis2(self, value): self._naxis2 = value -class RefCoord(CaomObject): +class RefCoord(caom_object.CaomObject): """A refernce coordinate object, maps pixel value to wcs value """ @@ -902,7 +902,7 @@ def val(self, value): self._val = value -class Slice(CaomObject): +class Slice(caom_object.CaomObject): """defines a slice in a set of data contains values. The slice keeps track of the type/unit and values. @@ -945,7 +945,7 @@ def bin(self, value): self._bin = value -class ValueCoord2D(CaomObject): +class ValueCoord2D(caom_object.CaomObject): """Represents the reference point.""" def __init__(self, coord1, coord2): @@ -973,7 +973,7 @@ def coord2(self, value): self._coord2 = value -class EnergyTransition(CaomObject): +class EnergyTransition(caom_object.CaomObject): """ EnergyTransition """ def __init__(self, species, transition): diff --git a/caom2tools/setup.py b/caom2tools/setup.py index 1fe26e7c..2eb8cb4e 100755 --- a/caom2tools/setup.py +++ b/caom2tools/setup.py @@ -55,11 +55,11 @@ author_email='cadc@nrc.ca', license='GPLv3', long_description='Python library for the CAOM-2.2 data model', - packages=find_packages(exclude=['caom2.test']), - package_data={'caom2': ['CAOM-2.0.xsd', 'CAOM-2.1.xsd', 'CAOM-2.2.xsd'], 'caom2.test.data': ['*.xml']}, + # packages=find_packages(exclude=['caom2.test']), + package_data={'caom2': ['CAOM-2.0.xsd', 'CAOM-2.1.xsd', 'CAOM-2.2.xsd'], 'caom2.tests.data': ['*.xml']}, include_package_data=True, - requires=['distribute', 'lxml'], - provides=['caom2'], + requires=['lxml', 'requests'], + provides=['caom2tools'], zip_safe=False ) diff --git a/caom2tools/tests/__init__.py b/caom2tools/test/__init__.py similarity index 100% rename from caom2tools/tests/__init__.py rename to caom2tools/test/__init__.py diff --git a/caom2tools/tests/coveragerc b/caom2tools/test/coveragerc similarity index 100% rename from caom2tools/tests/coveragerc rename to caom2tools/test/coveragerc diff --git a/caom2tools/tests/setup_package.py b/caom2tools/test/setup_package.py similarity index 100% rename from caom2tools/tests/setup_package.py rename to caom2tools/test/setup_package.py From bb7ad7a5fbb971a898e6c6e305db1f345fe22abf Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Wed, 16 Nov 2016 14:14:48 -0800 Subject: [PATCH 10/54] s1950: fix most unit tests --- caom2tools/caom2/__init__.py | 2 +- caom2tools/caom2/artifact.py | 17 +- caom2tools/caom2/caom_object.py | 4 +- caom2tools/caom2/caom_util.py | 287 ++++++++------- caom2tools/caom2/chunk.py | 94 ++--- caom2tools/caom2/obs_reader_writer.py | 34 +- caom2tools/caom2/observation.py | 204 +++++------ caom2tools/caom2/part.py | 9 +- caom2tools/caom2/plane.py | 87 +++-- caom2tools/caom2/shape.py | 9 +- caom2tools/caom2/test/__init__.py | 4 +- caom2tools/caom2/test/caom_test_instances.py | 106 +++--- caom2tools/caom2/test/test_artifact.py | 159 ++++---- caom2tools/caom2/test/test_caom_object.py | 46 +-- caom2tools/caom2/test/test_caom_util.py | 258 ++++++------- caom2tools/caom2/test/test_chunk.py | 323 ++++++----------- .../caom2/test/test_obs_reader_writer.py | 245 +++++++------ caom2tools/caom2/test/test_observation.py | 339 +++++++++-------- caom2tools/caom2/test/test_part.py | 52 +-- caom2tools/caom2/test/test_plane.py | 341 +++++++++--------- caom2tools/caom2/test/test_shape.py | 7 +- caom2tools/caom2/test/test_wcs.py | 8 +- caom2tools/caom2/wcs.py | 97 +++-- caom2tools/setup.py | 4 +- 24 files changed, 1290 insertions(+), 1446 deletions(-) mode change 100755 => 100644 caom2tools/caom2/__init__.py diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py old mode 100755 new mode 100644 index 2851e29e..7cc3bcae --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -78,7 +78,7 @@ # import plane as plane # import caom_util as caom_util # import wcs as wcs -from caom_util import Util as Util +# from caom_util import Util as Util # # from .caom_object import CaomObject diff --git a/caom2tools/caom2/artifact.py b/caom2tools/caom2/artifact.py index f46332c1..3a9536e2 100644 --- a/caom2tools/caom2/artifact.py +++ b/caom2tools/caom2/artifact.py @@ -77,7 +77,6 @@ import caom_object import caom_util import part -from caom_util import Util from enum import Enum ProductType = Enum('ProductType', @@ -163,9 +162,9 @@ def uri(self): @uri.setter def uri(self, value): - Util.type_check(value, str, 'uri') + caom_util.type_check(value, str, 'uri') uri = urlparse(value).geturl() - Util.value_check(value, None, None, 'uri', override=uri) + caom_util.value_check(value, None, None, 'uri', override=uri) self._uri = uri @property @@ -181,7 +180,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - Util.type_check(value, ProductType, "product_type", False) + caom_util.type_check(value, ProductType, "product_type", False) self._product_type = value @property @@ -197,7 +196,7 @@ def release_type(self): @release_type.setter def release_type(self, value): - Util.type_check(value, ReleaseType, "release_type", False) + caom_util.type_check(value, ReleaseType, "release_type", False) self._release_type = value @property @@ -210,7 +209,7 @@ def content_type(self): @content_type.setter def content_type(self, value): - Util.type_check(value, str, "content_type") + caom_util.type_check(value, str, "content_type") self._content_type = value @property @@ -225,8 +224,8 @@ def content_length(self): @content_length.setter def content_length(self, value): - Util.type_check(value, long, "content_length") - Util.value_check(value, 0, 1E10, "content_length") + caom_util.type_check(value, long, "content_length") + caom_util.value_check(value, 0, 1E10, "content_length") self._content_length = value @property @@ -253,7 +252,7 @@ def parts(self): @parts.setter def parts(self, value): - Util.type_check(value, + caom_util.type_check(value, caom_util.TypedOrderedDict, 'parts', override=False) diff --git a/caom2tools/caom2/caom_object.py b/caom2tools/caom2/caom_object.py index cade8eb6..d89b5e74 100644 --- a/caom2tools/caom2/caom_object.py +++ b/caom2tools/caom2/caom_object.py @@ -74,7 +74,7 @@ import uuid from datetime import datetime -from caom_util import Util +import caom_util class CaomObject(object): @@ -138,7 +138,7 @@ def _gen_id(cls, fulluuid=False): rand = vmrandom | randtime if rand & 0x8000000000000000: rand = 0x1000000000000000 + rand - return Util.long2uuid(rand) + return caom_util.long2uuid(rand) @classmethod def _gen_last_modified(cls): diff --git a/caom2tools/caom2/caom_util.py b/caom2tools/caom2/caom_util.py index 9b8e9487..7df14a7a 100644 --- a/caom2tools/caom2/caom_util.py +++ b/caom2tools/caom2/caom_util.py @@ -83,117 +83,124 @@ import uuid from datetime import datetime -import artifact -import chunk -import observation -import part -import plane +# import artifact +# import chunk +# import observation +# import part +# import plane -class Util(object): +# TODO both these are very bad, implement more sensibly +IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - # TODO both these are very bad, implement more sensibly - IVOA_DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" - def validate_path_component(self, caller, name, test): - """ - Function to validate a URI path component. Component is invalid - if it contains space ( ), slash (/), escape (\\) or percent (%) characters. +def validate_path_component(caller, name, test): + """ + Function to validate a URI path component. Component is invalid + if it contains space ( ), slash (/), escape (\\) or percent (%) characters. - Arguments: - caller : caller object - name : name of the component - test : component to be tested + Arguments: + caller : caller object + name : name of the component + test : component to be tested - An assertionError is thrown when the the provided test argument - is invalid - """ + An assertionError is thrown when the the provided test argument + is invalid + """ - assert (' ' not in test and - '/' not in test and - '||' not in test and - '%' not in test), ( - caller.__class__.__name__ + ": invalid " + name + - ": may not contain space ( ), slash (/), escape (\\), or percent (%)") + assert (' ' not in test and + '/' not in test and + '||' not in test and + '%' not in test), ( + caller.__class__.__name__ + ": invalid " + name + + ": may not contain space ( ), slash (/), escape (\\), or percent (%)") - def date2ivoa(self, d): - """ - Takes a datetime and returns a string formatted - to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS - """ - if d is None: - return None - return d.strftime(self.IVOA_DATE_FORMAT)[:23] +def date2ivoa(d): + """ + Takes a datetime and returns a string formatted + to the IVOA date format yyyy-MM-dd'T'HH:mm:ss.SSS + """ + + if d is None: + return None + return d.strftime(IVOA_DATE_FORMAT)[:23] - def str2ivoa(self, s): - """Takes a IVOA date formatted string and returns a datetime""" - if s is None: - return None - return datetime.strptime(s, self.IVOA_DATE_FORMAT) +def str2ivoa(s): + """Takes a IVOA date formatted string and returns a datetime""" - def attr2str(self, s): - pass + if s is None: + return None + return datetime.strptime(s, IVOA_DATE_FORMAT) - def repr2str(self, s): - pass - def uuid2long(self, uid): - """ - UUID is 128 bits (32 bytes). Unpack the 32 bytes into two - 16 byte longs. For CAOM-2.0 compatibility only the least significant - 16 bytes in the UUID should have a value. +def attr2str(s): + pass - return the UUID least significant bytes as a long. - """ - longs = struct.unpack('>qq', str(uid.bytes)) - if longs[0] != 0: - raise ValueError("lossy conversion from UUID to long: {}".format(uid)) - return longs[1] - def long2uuid(self, l): - """ - Takes a long and creates a UUID using the 16 byte long - as the least significant bytes in the 32 byte UUID. - """ - if l.bit_length() > 63: - raise ValueError("expected 64 bit long {}".format(l)) - return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) - - def type_check(self, value, value_type, variable, override=None): - """Check value is of type value_type, or is override""" - - sys.tracebacklimit = None - if not isinstance(value, value_type) and value is not override: - if override is not False: - raise TypeError( - "Excepted {} or {} for {}, received {}".format(value_type, - override, - variable, - type(value))) - else: - raise TypeError( - "Expected {} for {}, received {}".format(value_type, - variable, - type(value))) - return True - - def value_check(self, value, min_value, max_value, variable, override=None): - """Check if value is inside allowed range, or override""" - - sys.tracebacklimit = None - if value != override and not (min_value <= value <= max_value): - if override is not False: - raise ValueError( - "Expected {} <= {} <= {} or {}, received {}".format( - min_value, variable, max_value, override, value)) - else: - raise ValueError( - "Expected {} <= {} <= {}, received {}".format( - min_value, variable, max_value, value)) - - return True +def repr2str(s): + pass + + +def uuid2long(uid): + """ + UUID is 128 bits (32 bytes). Unpack the 32 bytes into two + 16 byte longs. For CAOM-2.0 compatibility only the least significant + 16 bytes in the UUID should have a value. + + return the UUID least significant bytes as a long. + """ + longs = struct.unpack('>qq', str(uid.bytes)) + if longs[0] != 0: + raise ValueError("lossy conversion from UUID to long: {}".format(uid)) + return longs[1] + + +def long2uuid(l): + """ + Takes a long and creates a UUID using the 16 byte long + as the least significant bytes in the 32 byte UUID. + """ + if l.bit_length() > 63: + raise ValueError("expected 64 bit long {}".format(l)) + return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) + + +def type_check(value, value_type, variable, override=None): + """Check value is of type value_type, or is override""" + + sys.tracebacklimit = None + if not isinstance(value, value_type) and value is not override: + if override is not False: + raise TypeError( + "Excepted {} or {} for {}, received {}".format(value_type, + override, + variable, + type(value))) + else: + raise TypeError( + "Expected {} for {}, received {}".format(value_type, + variable, + type(value))) + return True + + +def value_check(value, min_value, max_value, variable, override=None): + """Check if value is inside allowed range, or override""" + + sys.tracebacklimit = None + if value != override and not (min_value <= value <= max_value): + if override is not False: + raise ValueError( + "Expected {} <= {} <= {} or {}, received {}".format( + min_value, variable, max_value, override, value)) + else: + raise ValueError( + "Expected {} <= {} <= {}, received {}".format( + min_value, variable, max_value, value)) + + return True class TypedList(collections.MutableSequence): @@ -384,48 +391,48 @@ def __get__(self, cls, owner): return self.fget.__get__(None, owner)() -class Validator(object): - - def __init__(self): - self.errors = {} - - def validate(self, obs): - if not isinstance(obs, observation.Observation): - self.errors['observation'] = 'not an Observation instance' - return - self._validate_planes(obs.planes) - if len(self.errors) > 0: - return False - return True - - def _validate_planes(self, planes): - for product_id, _plane in planes.iteritems(): - if not isinstance(_plane, plane.Plane): - self.errors['plane'].append("not a Plane instance") - continue - if product_id != _plane.product_id: - self.errors['plane'].append("plane productIDs do not match") - self._validate_artifacts(_plane.artifacts) - - def _validate_artifacts(self, artifacts): - for uri, _artifact in artifacts.iteritems(): - if not isinstance(_artifact, artifact.Artifact): - self.errors['artifact'].append("not an Artifact instance") - continue - if uri != _artifact.uri: - self.errors['artifact'].append("artifact uris do not match") - self._validate_parts(_artifact.parts) - - def _validate_parts(self, parts): - for name, _part in parts.iteritems(): - if not isinstance(_part, part.Part): - self.errors['part'].append("not a Part instance") - continue - if name != _part.name: - self.errors['part'].append("part names do not match") - self._validate_chunks(_part.chunks) - - def _validate_chunks(self, chunks): - for _chunk in chunks: - if not isinstance(_chunk, chunk.Chunk): - self.errors['chunk'].append("not a chunk instance") +# class Validator(object): +# +# def __init__(self): +# self.errors = {} +# +# def validate(self, obs): +# if not isinstance(obs, observation.Observation): +# self.errors['observation'] = 'not an Observation instance' +# return +# self._validate_planes(obs.planes) +# if len(self.errors) > 0: +# return False +# return True +# +# def _validate_planes(self, planes): +# for product_id, _plane in planes.iteritems(): +# if not isinstance(_plane, plane.Plane): +# self.errors['plane'].append("not a Plane instance") +# continue +# if product_id != _plane.product_id: +# self.errors['plane'].append("plane productIDs do not match") +# self._validate_artifacts(_plane.artifacts) +# +# def _validate_artifacts(self, artifacts): +# for uri, _artifact in artifacts.iteritems(): +# if not isinstance(_artifact, artifact.Artifact): +# self.errors['artifact'].append("not an Artifact instance") +# continue +# if uri != _artifact.uri: +# self.errors['artifact'].append("artifact uris do not match") +# self._validate_parts(_artifact.parts) +# +# def _validate_parts(self, parts): +# for name, _part in parts.iteritems(): +# if not isinstance(_part, part.Part): +# self.errors['part'].append("not a Part instance") +# continue +# if name != _part.name: +# self.errors['part'].append("part names do not match") +# self._validate_chunks(_part.chunks) +# +# def _validate_chunks(self, chunks): +# for _chunk in chunks: +# if not isinstance(_chunk, chunk.Chunk): +# self.errors['chunk'].append("not a chunk instance") diff --git a/caom2tools/caom2/chunk.py b/caom2tools/caom2/chunk.py index ae40745f..5ca4a125 100644 --- a/caom2tools/caom2/chunk.py +++ b/caom2tools/caom2/chunk.py @@ -74,8 +74,8 @@ import artifact import caom_object +import caom_util import plane -from caom_util import Util import wcs @@ -148,7 +148,7 @@ def product_type(self, value): if isinstance(value, str) and value in artifact.ProductType.names(): ## be helpful value = artifact.ProductType('value') - Util.type_check(value, artifact.ProductType, 'product_type') + caom_util.type_check(value, artifact.ProductType, 'product_type') self._product_type = value @property @@ -163,8 +163,8 @@ def naxis(self): @naxis.setter def naxis(self, value): - Util.type_check(value, int, 'naxis') - Util.value_check(value, 0, 5, 'naxis') + caom_util.type_check(value, int, 'naxis') + caom_util.value_check(value, 0, 5, 'naxis') self._naxis = value @property @@ -181,7 +181,7 @@ def position_axis_1(self): @position_axis_1.setter def position_axis_1(self, value): - Util.type_check(value, int, 'position_axis_1') + caom_util.type_check(value, int, 'position_axis_1') # util.valueCheck(value, 0, self.naxis, 'position_axis_1') self._position_axis_1 = value @@ -200,7 +200,7 @@ def position_axis_2(self): @position_axis_2.setter def position_axis_2(self, value): - Util.type_check(value, int, 'position_axis_2') + caom_util.type_check(value, int, 'position_axis_2') # util.valueCheck(value, 0, self.naxis, 'position_axis_2') self._position_axis_2 = value @@ -220,7 +220,7 @@ def energy_axis(self): @energy_axis.setter def energy_axis(self, value): - Util.type_check(value, int, 'energy_axis') + caom_util.type_check(value, int, 'energy_axis') # util.valueCheck(value, 0, self.naxis, 'energy_axis') self._energy_axis = value @@ -238,7 +238,7 @@ def time_axis(self): @time_axis.setter def time_axis(self, value): - Util.type_check(value, int, 'polarization_axis') + caom_util.type_check(value, int, 'polarization_axis') # util.valueCheck(value, 0, self._naxis, 'polarization_axis') self._time_axis = value @@ -256,7 +256,7 @@ def polarization_axis(self): @polarization_axis.setter def polarization_axis(self, value): - Util.type_check(value, int, 'polarization_axis') + caom_util.type_check(value, int, 'polarization_axis') # util.valueCheck(value, 0, self._naxis, 'polariztion_axis') self._polarization_axis = value @@ -271,7 +271,7 @@ def observable_axis(self): @observable_axis.setter def observable_axis(self, value): - Util.type_check(value, int, 'obserable_axis') + caom_util.type_check(value, int, 'obserable_axis') # util.valueCheck(value, 0, 1E10, 'observable_axis') self._observable_axis = value @@ -286,7 +286,7 @@ def observable(self): @observable.setter def observable(self, value): - Util.type_check(value, ObservableAxis, 'observable_axis') + caom_util.type_check(value, ObservableAxis, 'observable_axis') self._observable = value @property @@ -303,7 +303,7 @@ def position(self): @position.setter def position(self, value): - Util.type_check(value, SpatialWCS, 'position') + caom_util.type_check(value, SpatialWCS, 'position') self._position = value @property @@ -321,7 +321,7 @@ def energy(self): @energy.setter def energy(self, value): - Util.type_check(value, SpectralWCS, 'energy') + caom_util.type_check(value, SpectralWCS, 'energy') self._energy = value @property @@ -338,7 +338,7 @@ def time(self): @time.setter def time(self, value): - Util.type_check(value, TemporalWCS, 'time') + caom_util.type_check(value, TemporalWCS, 'time') self._time = value @property @@ -354,7 +354,7 @@ def polarization(self): @polarization.setter def polarization(self, value): - Util.type_check(value, PolarizationWCS, 'polarization') + caom_util.type_check(value, PolarizationWCS, 'polarization') self._polarization = value @@ -413,7 +413,7 @@ def dependent(self): @dependent.setter def dependent(self, value): - Util.type_check(value, wcs.Slice, 'dependent', override=False) + caom_util.type_check(value, wcs.Slice, 'dependent', override=False) self._dependent = value @property @@ -428,7 +428,7 @@ def independent(self): @independent.setter def independent(self, value): - Util.type_check(value, wcs.Slice, "independent") + caom_util.type_check(value, wcs.Slice, "independent") self._independent = value @@ -464,7 +464,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, wcs.CoordAxis2D, 'axis', override=False) + caom_util.type_check(value, wcs.CoordAxis2D, 'axis', override=False) self._axis = value @property @@ -480,7 +480,7 @@ def coordsys(self): @coordsys.setter def coordsys(self, value): - Util.type_check(value, str, 'coordsys') + caom_util.type_check(value, str, 'coordsys') self._coordsys = value @property @@ -497,8 +497,8 @@ def equinox(self): @equinox.setter def equinox(self, value): - Util.type_check(value, float, 'equinox') - Util.value_check(value, 1800, 2500, 'equinox') + caom_util.type_check(value, float, 'equinox') + caom_util.value_check(value, 1800, 2500, 'equinox') self._equinox = value @property @@ -513,8 +513,8 @@ def resolution(self): @resolution.setter def resolution(self, value): - Util.type_check(value, float, 'resolution') - Util.value_check(value, 0, 360 * 3600.0, 'resolution') + caom_util.type_check(value, float, 'resolution') + caom_util.value_check(value, 0, 360 * 3600.0, 'resolution') self._resolution = value @@ -577,7 +577,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) self._axis = value @property @@ -593,7 +593,7 @@ def specsys(self): @specsys.setter def specsys(self, value): - Util.type_check(value, str, 'specsys', override=False) + caom_util.type_check(value, str, 'specsys', override=False) self._specsys = value @property @@ -613,7 +613,7 @@ def ssysobs(self): @ssysobs.setter def ssysobs(self, value): - Util.type_check(value, str, 'ssysobs') + caom_util.type_check(value, str, 'ssysobs') self._ssysobs = value @property @@ -627,7 +627,7 @@ def ssyssrc(self): @ssyssrc.setter def ssyssrc(self, value): - Util.type_check(value, str, 'ssyssrc') + caom_util.type_check(value, str, 'ssyssrc') self._ssyssrc = value @property @@ -641,7 +641,7 @@ def restfrq(self): @restfrq.setter def restfrq(self, value): - Util.type_check(value, float, 'restfrq') + caom_util.type_check(value, float, 'restfrq') self._restfrq = value @property @@ -657,7 +657,7 @@ def restwav(self): @restwav.setter def restwav(self, value): - Util.type_check(value, float, 'restwav') + caom_util.type_check(value, float, 'restwav') self._restwav = value @property @@ -676,7 +676,7 @@ def velosys(self): @velosys.setter def velosys(self, value): - Util.type_check(value, float, 'velosys') + caom_util.type_check(value, float, 'velosys') self._velosys = value @property @@ -692,8 +692,8 @@ def zsource(self): @zsource.setter def zsource(self, value): - Util.type_check(value, float, 'zsource') - Util.value_check(value, -0.5, 1200, 'zsource') + caom_util.type_check(value, float, 'zsource') + caom_util.value_check(value, -0.5, 1200, 'zsource') self._zsource = value @property @@ -703,7 +703,7 @@ def velang(self): @velang.setter def velang(self, value): - Util.type_check(value, float, 'velang') + caom_util.type_check(value, float, 'velang') self._velang = value @property @@ -717,7 +717,7 @@ def bandpass_name(self): @bandpass_name.setter def bandpass_name(self, value): - Util.type_check(value, str, 'bandpass_name') + caom_util.type_check(value, str, 'bandpass_name') self._bandpass_name = value @property @@ -730,7 +730,7 @@ def transition(self): @transition.setter def transition(self, value): - Util.type_check(value, plane.EnergyTransition, "transition") + caom_util.type_check(value, plane.EnergyTransition, "transition") self._transition = value @property @@ -746,8 +746,8 @@ def resolving_power(self): @resolving_power.setter def resolving_power(self, value): - Util.type_check(value, float, 'resolving_power') - Util.value_check(value, 0, 1E8, 'resolving_power') + caom_util.type_check(value, float, 'resolving_power') + caom_util.value_check(value, 0, 1E8, 'resolving_power') self._resolving_power = value @@ -783,7 +783,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) self._axis = value @property @@ -797,7 +797,7 @@ def timesys(self): @timesys.setter def timesys(self, value): - Util.type_check(value, str, 'timesys') + caom_util.type_check(value, str, 'timesys') self._timesys = value @property @@ -813,7 +813,7 @@ def trefpos(self): @trefpos.setter def trefpos(self, value): - Util.type_check(value, str, 'trefpos') + caom_util.type_check(value, str, 'trefpos') self._trefpos = value @property @@ -834,9 +834,9 @@ def mjdref(self): @mjdref.setter def mjdref(self, value): - Util.type_check(value, float, 'mjdref') + caom_util.type_check(value, float, 'mjdref') ### set the limits to be after 1800 but before year 2050 - Util.value_check(value, -22000, 70000, 'mjdref') + caom_util.value_check(value, -22000, 70000, 'mjdref') self._mjdref = value @property @@ -853,8 +853,8 @@ def exposure(self): @exposure.setter def exposure(self, value): - Util.type_check(value, float, "exposure") - Util.value_check(value, 0, 30 * 24 * 3600.0, "exposure") + caom_util.type_check(value, float, "exposure") + caom_util.value_check(value, 0, 30 * 24 * 3600.0, "exposure") self._exposure = value @property @@ -875,8 +875,8 @@ def resolution(self): @resolution.setter def resolution(self, value): - Util.type_check(value, float, 'resolution') - Util.value_check(value, 0, 100 * 365 * 24 * 3600.0, "resolution") + caom_util.type_check(value, float, 'resolution') + caom_util.value_check(value, 0, 100 * 365 * 24 * 3600.0, "resolution") self._resolution = value @@ -905,7 +905,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) + caom_util.type_check(value, wcs.CoordAxis1D, 'axis', override=False) if value.axis.ctype != 'STOKES': raise ValueError('CTYPE must be STOKES') self._axis = value diff --git a/caom2tools/caom2/obs_reader_writer.py b/caom2tools/caom2/obs_reader_writer.py index d55890ca..a0181703 100644 --- a/caom2tools/caom2/obs_reader_writer.py +++ b/caom2tools/caom2/obs_reader_writer.py @@ -76,19 +76,19 @@ from lxml import etree import artifact +import caom_util import chunk -import shape import observation import part import plane +import shape import wcs -from caom_util import Util -CAOM2_PKG = 'caom2' +CAOM2_PKG = 'caom2tools' -CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' -CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' -CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' +CAOM20_SCHEMA_FILE = 'caom2/CAOM-2.0.xsd' +CAOM21_SCHEMA_FILE = 'caom2/CAOM-2.1.xsd' +CAOM22_SCHEMA_FILE = 'caom2/CAOM-2.2.xsd' CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' @@ -147,11 +147,11 @@ def _set_entity_attributes(self, element, ns, caom2_entity): if expect_uuid: uid = uuid.UUID(element_id) else: - uid = Util.long2uuid(long(element_id)) + uid = caom_util.long2uuid(long(element_id)) caom2_entity._id = uid if element_last_modified: - caom2_entity._last_modified = Util.str2ivoa(element_last_modified) + caom2_entity._last_modified = caom_util.str2ivoa(element_last_modified) def _get_child_element(self, element_tag, parent, ns, required): for element in list(parent): @@ -233,7 +233,7 @@ def _get_meta_release(self, element_tag, parent, ns, required): else: # TODO: need to catch exceptions, # what kind of exceptions are thrown? - return Util.str2ivoa(el.text) + return caom_util.str2ivoa(el.text) def _get_proposal(self, element_tag, parent, ns, required): """Build a Proposal object from an XML representation @@ -487,7 +487,7 @@ def _get_provenance(self, element_tag, parent, ns, required): reference = self._get_child_text("reference", el, ns, False) if reference: prov.reference = reference - prov.last_executed = Util.str2ivoa( + prov.last_executed = caom_util.str2ivoa( self._get_child_text("lastExecuted", el, ns, False)) keywords = self._get_child_text("keywords", el, ns, False) if keywords is not None: @@ -1270,9 +1270,9 @@ def _add_planes(self, planes, parent, ns): for plane_element in el.iterchildren("{" + ns + "}plane"): _plane = plane.Plane( self._get_child_text("productID", plane_element, ns, True)) - _plane.meta_release = Util.str2ivoa( + _plane.meta_release = caom_util.str2ivoa( self._get_child_text("metaRelease", plane_element, ns, False)) - _plane.data_release = Util.str2ivoa( + _plane.data_release = caom_util.str2ivoa( self._get_child_text("dataRelease", plane_element, ns, False)) data_product_type = \ self._get_child_text("dataProductType", plane_element, ns, False) @@ -1333,7 +1333,7 @@ def read(self, source): self._get_child_text("type", root, ns, False) intent = self._get_child_text("intent", root, ns, False) if intent: - obs.intent = obs.ObservationIntentType.getByValue(intent) + obs.intent = observation.ObservationIntentType.getByValue(intent) obs.meta_release = \ self._get_meta_release("metaRelease", root, ns, False) obs.proposal = \ @@ -1351,7 +1351,7 @@ def read(self, source): obs.requirements = \ self._get_requirements("requirements", root, ns, False) self._add_planes(obs.planes, root, ns) - if isinstance(obs, obs.CompositeObservation): + if isinstance(obs, observation.CompositeObservation): self._add_members(obs.members, root, ns) self._set_entity_attributes(root, ns, obs) @@ -1447,14 +1447,14 @@ def write(self, obs, out): def _add_enity_attributes(self, entity, element): if self._output_version == 20: - uid = Util.uuid2long(entity._id) + uid = caom_util.uuid2long(entity._id) self._add_attribute("id", str(uid), element) else: self._add_attribute("id", str(entity._id), element) if entity._last_modified is not None: self._add_attribute( - "lastModified", Util.date2ivoa(entity._last_modified), element) + "lastModified", caom_util.date2ivoa(entity._last_modified), element) def _add_algorithm_element(self, algorithm, parent): if algorithm is None: @@ -1980,7 +1980,7 @@ def _add_datetime_element(self, name, value, parent): if value is None: return element = self._get_caom_element(name, parent) - element.text = Util.date2ivoa(value) + element.text = caom_util.date2ivoa(value) def _add_list_element(self, name, collection, parent): if collection is None or \ diff --git a/caom2tools/caom2/observation.py b/caom2tools/caom2/observation.py index 5d41a2cd..3281b459 100644 --- a/caom2tools/caom2/observation.py +++ b/caom2tools/caom2/observation.py @@ -72,13 +72,13 @@ from datetime import datetime from urlparse import SplitResult +from urlparse import urlsplit import caom_object +import caom_util import plane import shape -import caom_util from enum import Enum -from caom_util import Util ObservationIntentType = Enum('ObservationIntentType', CALIBRATION="calibration", @@ -188,7 +188,7 @@ def __init__(self, self.requirements = requirements self.meta_release = meta_release if planes is None: - planes = Util.TypedOrderedDict((plane.Plane),) + planes = caom_util.TypedOrderedDict((plane.Plane),) self.planes = planes # Properties @@ -203,7 +203,7 @@ def collection(self): @collection.setter def collection(self, value): - Util.type_check(value, str, 'collection', override=False) + caom_util.type_check(value, str, 'collection', override=False) self._collection = value @property @@ -217,7 +217,7 @@ def observation_id(self): @observation_id.setter def observation_id(self, value): - Util.type_check(value, str, 'observation_id', override=False) + caom_util.type_check(value, str, 'observation_id', override=False) self._observation_id = value @property @@ -231,7 +231,7 @@ def uri(self): @uri.setter def uri(self, value): - Util.type_check(value, ObservationURI, 'uri') + caom_util.type_check(value, ObservationURI, 'uri') self._uri = value @property @@ -249,7 +249,7 @@ def planes(self): @planes.setter def planes(self, value): - Util.type_check(value, caom_util.TypedOrderedDict, 'planes') + caom_util.type_check(value, caom_util.TypedOrderedDict, 'planes') self._planes = value @property @@ -264,7 +264,7 @@ def algorithm(self): def algorithm(self, value): if isinstance(value, str): value = Algorithm(value) - Util.type_check(value, Algorithm, 'algorithm') + caom_util.type_check(value, Algorithm, 'algorithm') self._algorithm = value @property @@ -282,7 +282,7 @@ def intent(self): def intent(self, value): if isinstance(value, str): value = ObservationIntentType(value) - Util.type_check(value, ObservationIntentType, 'intent') + caom_util.type_check(value, ObservationIntentType, 'intent') self._intent = value @property @@ -294,7 +294,7 @@ def sequence_number(self): @sequence_number.setter def sequence_number(self, value): - Util.type_check(value, int, 'sequence_number') + caom_util.type_check(value, int, 'sequence_number') self._sequence_number = value @property @@ -308,7 +308,7 @@ def obs_type(self): @obs_type.setter def obs_type(self, value): - Util.type_check(value, str, 'obs_type') + caom_util.type_check(value, str, 'obs_type') self._obs_type = value @property @@ -324,7 +324,7 @@ def proposal(self): @proposal.setter def proposal(self, value): - Util.type_check(value, Proposal, "proposal") + caom_util.type_check(value, Proposal, "proposal") self._proposal = value @property @@ -338,7 +338,7 @@ def telescope(self): @telescope.setter def telescope(self, value): - Util.type_check(value, Telescope, 'telescope') + caom_util.type_check(value, Telescope, 'telescope') self._telescope = value @property @@ -354,7 +354,7 @@ def instrument(self): def instrument(self, value): if isinstance(value, str): value = Instrument(str) - Util.type_check(value, Instrument, "instrument") + caom_util.type_check(value, Instrument, "instrument") self._instrument = value @property @@ -370,7 +370,7 @@ def target(self): def target(self, value): if isinstance(value, str): value = Target(str) - Util.type_check(value, Target, 'target') + caom_util.type_check(value, Target, 'target') self._target = value @property @@ -385,7 +385,7 @@ def environment(self): @environment.setter def environment(self, value): - Util.type_check(value, Environment, 'environment') + caom_util.type_check(value, Environment, 'environment') self._environment = value @property @@ -400,7 +400,7 @@ def target_position(self): @target_position.setter def target_position(self, value): - Util.type_check(value, TargetPosition, 'target_position') + caom_util.type_check(value, TargetPosition, 'target_position') self._target_position = value @property @@ -415,7 +415,7 @@ def requirements(self): @requirements.setter def requirements(self, value): - Util.type_check(value, Requirements, 'requirements') + caom_util.type_check(value, Requirements, 'requirements') self._requirements = value @property @@ -435,7 +435,7 @@ def meta_release(self): @meta_release.setter def meta_release(self, value): - Util.type_check(value, datetime, 'meta_release') + caom_util.type_check(value, datetime, 'meta_release') self._meta_release = value @@ -451,7 +451,7 @@ def __init__(self, uri): Arguments: uri : URI corresponding to observation """ - tmp = Util.urlsplit(uri) + tmp = urlsplit(uri) if tmp.scheme != ObservationURI._SCHEME: raise ValueError( @@ -467,12 +467,12 @@ def __init__(self, uri): raise ValueError( "uri did not contain a collection part. received: {}" .format(uri)) - Util.validate_path_component(self, "collection", collection) + caom_util.validate_path_component(self, "collection", collection) if observation_id is None: raise ValueError( "uri did not contain an observation_id part. received: {}" .format(uri)) - Util.validate_path_component(self, "observation_id", observation_id) + caom_util.validate_path_component(self, "observation_id", observation_id) (self._collection, self._observation_id) = (collection, observation_id) self._print_attributes = ['uri', 'collection', 'observation_id'] @@ -497,11 +497,11 @@ def get_observation_uri(cls, collection, observation_id): observation_id : ID of the observation """ - Util.type_check(collection, str, "collection", override=False) - Util.type_check(observation_id, str, "observation_id", override=False) + caom_util.type_check(collection, str, "collection", override=False) + caom_util.type_check(observation_id, str, "observation_id", override=False) - Util.validate_path_component(cls, "collection", collection) - Util.validate_path_component(cls, "observation_id", observation_id) + caom_util.validate_path_component(cls, "collection", collection) + caom_util.validate_path_component(cls, "observation_id", observation_id) uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + observation_id, "", "").geturl() @@ -533,7 +533,44 @@ def observation_id(self): return self._observation_id -class SimpleObservation(observation.Observation): +class Algorithm(caom_object.CaomObject): + """ + The concept of Algorithm is to provide a way for users to find all + composite observation sets that have been built using a particular + grouping algorithm (eg. the MegaPipe stacks). For simple + observations the algorithm is 'exposure'. + """ + + def __init__(self, name): + """ + Initializes an Algorithm instance + + Arguments: + name : name of the algorithm. Should be 'exposure' if this is a + simple observation, otherwise name of algorithm that selected + composite members or just 'composite' works too. + """ + caom_util.type_check(name, str, "name", override=False) + self._name = name + + def _key(self): + return (self._name) + + def __ne__(self, y): + return not self.__eq__(y) + + # Properties + + @property + def name(self): + """ + algorithm that defines the composite grouping; 'exposure' for + simple observations + """ + return self._name + + +class SimpleObservation(Observation): """A convenience class for building Observations where algorithm='exposure'. @@ -609,14 +646,14 @@ def algorithm(self, value=_ALGORITHM): # build an Algorithm type if passed a string... if isinstance(value, str): value = Algorithm(value) - Util.type_check(value, Algorithm, 'algorithm', override=False) - Util.value_check(value, None, None, + caom_util.type_check(value, Algorithm, 'algorithm', override=False) + caom_util.value_check(value, None, None, 'algorithm', override=self._ALGORITHM) self._algorithm = value -class CompositeObservation(observation.Observation): +class CompositeObservation(Observation): """ Composite Observation @@ -679,43 +716,6 @@ def members(self): return self._members -class Algorithm(caom_object.CaomObject): - """ - The concept of Algorithm is to provide a way for users to find all - composite observation sets that have been built using a particular - grouping algorithm (eg. the MegaPipe stacks). For simple - observations the algorithm is 'exposure'. - """ - - def __init__(self, name): - """ - Initializes an Algorithm instance - - Arguments: - name : name of the algorithm. Should be 'exposure' if this is a - simple observation, otherwise name of algorithm that selected - composite members or just 'composite' works too. - """ - Util.type_check(name, str, "name", override=False) - self._name = name - - def _key(self): - return (self._name) - - def __ne__(self, y): - return not self.__eq__(y) - - # Properties - - @property - def name(self): - """ - algorithm that defines the composite grouping; 'exposure' for - simple observations - """ - return self._name - - class Environment(caom_object.CaomObject): """A CAOM2 Environment Object. @@ -748,8 +748,8 @@ def seeing(self): @seeing.setter def seeing(self, value): - Util.type_check(value, float, 'seeing') - Util.value_check(value, 0, 360 * 3600.0, 'seeing') + caom_util.type_check(value, float, 'seeing') + caom_util.value_check(value, 0, 360 * 3600.0, 'seeing') self._seeing = value @property @@ -763,8 +763,8 @@ def humidity(self): @humidity.setter def humidity(self, value): # set the humidity to value, which must be +ve fraction less than 200 - Util.type_check(value, float, 'humidity') - Util.value_check(value, 0, 200, 'humidity') + caom_util.type_check(value, float, 'humidity') + caom_util.value_check(value, 0, 200, 'humidity') self._humidity = value @property @@ -777,8 +777,8 @@ def elevation(self): @elevation.setter def elevation(self, value): - Util.type_check(value, float, 'elevation') - Util.value_check(value, 0, 90, 'elevation') + caom_util.type_check(value, float, 'elevation') + caom_util.value_check(value, 0, 90, 'elevation') self._elevation = value @property @@ -793,8 +793,8 @@ def tau(self): @tau.setter def tau(self, value): - Util.type_check(value, float, 'tau') - Util.value_check(value, 0, 1, 'tau') + caom_util.type_check(value, float, 'tau') + caom_util.value_check(value, 0, 1, 'tau') self._tau = value @property @@ -809,8 +809,8 @@ def wavelength_tau(self): @wavelength_tau.setter def wavelength_tau(self, value): - Util.type_check(value, float, 'wavelength_tau') - Util.value_check(value, 0, 1E3, 'wavelength_tau') + caom_util.type_check(value, float, 'wavelength_tau') + caom_util.value_check(value, 0, 1E3, 'wavelength_tau') self._wavelength_tau = value @property @@ -823,8 +823,8 @@ def ambient_temp(self): @ambient_temp.setter def ambient_temp(self, value): - Util.type_check(value, float, 'ambient_temp') - Util.value_check(value, -100, 100, 'ambient_temp') + caom_util.type_check(value, float, 'ambient_temp') + caom_util.value_check(value, -100, 100, 'ambient_temp') self._ambient_temp = value @property @@ -835,7 +835,7 @@ def photometric(self): @photometric.setter def photometric(self, value): - Util.type_check(value, bool, 'photometric') + caom_util.type_check(value, bool, 'photometric') self._photometric = value @@ -859,7 +859,7 @@ def __init__(self, name): Arguments: name - name of the instrument """ - Util.type_check(name, str, 'name', override='none') + caom_util.type_check(name, str, 'name', override='none') self._name = name self._keywords = set() @@ -926,7 +926,7 @@ def id(self): @id.setter def proposal_id(self, value): - Util.type_check(value, str, 'id') + caom_util.type_check(value, str, 'id') self._proposal_id = value @property @@ -944,7 +944,7 @@ def keywords(self): @keywords.setter def keywords(self, value): - Util.type_check(value, set, 'keywords', override=False) + caom_util.type_check(value, set, 'keywords', override=False) self._keywords = value @property @@ -958,7 +958,7 @@ def pi_name(self): @pi_name.setter def pi_name(self, value): - Util.type_check(value, str, 'pi_name') + caom_util.type_check(value, str, 'pi_name') self._pi_name = value @property @@ -971,7 +971,7 @@ def project(self): @project.setter def project(self, value): - Util.type_check(value, str, 'project') + caom_util.type_check(value, str, 'project') self._project = value @property @@ -984,7 +984,7 @@ def title(self): @title.setter def title(self, value): - Util.type_check(value, str, 'title') + caom_util.type_check(value, str, 'title') self._title = value @@ -1007,7 +1007,7 @@ def flag(self): @flag.setter def flag(self, value): - Util.type_check(value, Status, "flag") + caom_util.type_check(value, Status, "flag") self._flag = value @@ -1051,7 +1051,7 @@ def name(self): @name.setter def name(self, value): - Util.type_check(value, str, "name", override=False) + caom_util.type_check(value, str, "name", override=False) self._name = value @property @@ -1069,7 +1069,7 @@ def target_type(self): def target_type(self, value): if isinstance(value, str): value = TargetType(value) - Util.type_check(value, TargetType, "target_type") + caom_util.type_check(value, TargetType, "target_type") self._type = value @property @@ -1084,7 +1084,7 @@ def keywords(self): @keywords.setter def keywords(self, value): - Util.type_check(value, set, 'keywords', override=False) + caom_util.type_check(value, set, 'keywords', override=False) self._keywords = value @property @@ -1099,7 +1099,7 @@ def standard(self): @standard.setter def standard(self, value): - Util.type_check(value, bool, 'standard') + caom_util.type_check(value, bool, 'standard') self._standard = value @property @@ -1114,8 +1114,8 @@ def redshift(self): @redshift.setter def redshift(self, value): - Util.type_check(value, float, 'redshift') - Util.value_check(value, -0.5, 1200, 'redshift') + caom_util.type_check(value, float, 'redshift') + caom_util.value_check(value, -0.5, 1200, 'redshift') self._redshift = value @property @@ -1130,7 +1130,7 @@ def moving(self): @moving.setter def moving(self, value): - Util.type_check(value, bool, 'moving') + caom_util.type_check(value, bool, 'moving') self._moving = value @@ -1159,7 +1159,7 @@ def coordinates(self): @coordinates.setter def coordinates(self, value): - Util.type_check(value, shape.Point, "coordinates") + caom_util.type_check(value, shape.Point, "coordinates") self._coordinates = value @property @@ -1169,7 +1169,7 @@ def coordsys(self): @coordsys.setter def coordsys(self, value): - Util.type_check(value, str, "coordsys") + caom_util.type_check(value, str, "coordsys") self._coordsys = value @property @@ -1179,7 +1179,7 @@ def equinox(self): @equinox.setter def equinox(self, value): - Util.type_check(value, float, "equinox") + caom_util.type_check(value, float, "equinox") self._equinox = value @@ -1223,7 +1223,7 @@ def name(self): @name.setter def name(self, value): - Util.type_check(value, str, 'name', override=False) + caom_util.type_check(value, str, 'name', override=False) self._name = value @property @@ -1238,7 +1238,7 @@ def keywords(self): @keywords.setter def keywords(self, value): - Util.type_check(value, set, 'keywords', override=False) + caom_util.type_check(value, set, 'keywords', override=False) self._keywords = value @property @@ -1261,7 +1261,7 @@ def geo_location_x(self): @geo_location_x.setter def geo_location_x(self, value): - Util.type_check(value, float, 'geo_location_x') + caom_util.type_check(value, float, 'geo_location_x') self._geo_location_x = value @property @@ -1284,7 +1284,7 @@ def geo_location_y(self): @geo_location_y.setter def geo_location_y(self, value): - Util.type_check(value, float, 'geo_location_y') + caom_util.type_check(value, float, 'geo_location_y') self._geo_location_y = value @property @@ -1306,5 +1306,5 @@ def geo_location_z(self): @geo_location_z.setter def geo_location_z(self, value): - Util.type_check(value, float, 'geo_location_z') + caom_util.type_check(value, float, 'geo_location_z') self._geo_location_z = value diff --git a/caom2tools/caom2/part.py b/caom2tools/caom2/part.py index 744904a1..740cc587 100644 --- a/caom2tools/caom2/part.py +++ b/caom2tools/caom2/part.py @@ -73,9 +73,8 @@ import artifact import caom_object -import chunk import caom_util -from caom_util import Util +import chunk class Part(caom_object.AbstractCaomEntity): @@ -116,7 +115,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - Util.type_check(value, artifact.ProductType, "product_type") + caom_util.type_check(value, artifact.ProductType, "product_type") self._product_type = value @property @@ -129,7 +128,7 @@ def name(self): @name.setter def name(self, value): - Util.type_check(value, str, 'name', override=False) + caom_util.type_check(value, str, 'name', override=False) self._name = value @property @@ -144,5 +143,5 @@ def chunks(self): @chunks.setter def chunks(self, value): - Util.type_check(value, caom_util.TypedList, 'chunks', override=False) + caom_util.type_check(value, caom_util.TypedList, 'chunks', override=False) self._chunks = value diff --git a/caom2tools/caom2/plane.py b/caom2tools/caom2/plane.py index b928ae12..959bffa3 100644 --- a/caom2tools/caom2/plane.py +++ b/caom2tools/caom2/plane.py @@ -76,12 +76,11 @@ import artifact import caom_object +import caom_util import observation import shape -import caom_util import wcs from enum import Enum -from caom_util import Util CalibrationLevel = Enum('CalibrationLevel', RAW_INSTRUMENT=0, @@ -184,7 +183,7 @@ def product_id(self): @product_id.setter def product_id(self, value): - Util.type_check(value, str, 'product_id', override=False) + caom_util.type_check(value, str, 'product_id', override=False) self._product_id = value @property @@ -205,7 +204,7 @@ def artifacts(self): @artifacts.setter def artifacts(self, value): - Util.type_check(value, caom_util.TypedOrderedDict, 'artifacts', override=False) + caom_util.type_check(value, caom_util.TypedOrderedDict, 'artifacts', override=False) self._artifacts = value @property @@ -226,8 +225,8 @@ def meta_release(self): @meta_release.setter def meta_release(self, value): - Util.type_check(value, datetime, 'meta_release') - Util.value_check(value, + caom_util.type_check(value, datetime, 'meta_release') + caom_util.value_check(value, datetime(1800, 1, 1, 0, 0, 0), datetime(2050, 1, 1, 0, 0, 0), 'meta_release') @@ -250,8 +249,8 @@ def data_release(self): @data_release.setter def data_release(self, value): - Util.type_check(value, datetime, 'data_release') - Util.value_check(value, + caom_util.type_check(value, datetime, 'data_release') + caom_util.value_check(value, datetime(1800, 1, 1, 0, 0, 0), datetime(2050, 1, 1, 0, 0, 0), 'data_release') @@ -271,7 +270,7 @@ def data_product_type(self): @data_product_type.setter def data_product_type(self, value): - Util.type_check(value, DataProductType, 'data_product_type') + caom_util.type_check(value, DataProductType, 'data_product_type') self._data_product_type = value @property @@ -290,7 +289,7 @@ def calibration_level(self): @calibration_level.setter def calibration_level(self, value): - Util.type_check(value, CalibrationLevel, "calibration_level") + caom_util.type_check(value, CalibrationLevel, "calibration_level") self._calibration_level = value @property @@ -303,7 +302,7 @@ def provenance(self): @provenance.setter def provenance(self, value): - Util.type_check(value, Provenance, "provenance") + caom_util.type_check(value, Provenance, "provenance") self._provenance = value @property @@ -316,7 +315,7 @@ def metrics(self): @metrics.setter def metrics(self, value): - Util.type_check(value, Metrics, 'metrics') + caom_util.type_check(value, Metrics, 'metrics') self._metrics = value @property @@ -329,7 +328,7 @@ def quality(self): @quality.setter def quality(self, value): - Util.type_check(value, DataQuality, 'quality') + caom_util.type_check(value, DataQuality, 'quality') self._quality = value #@property @@ -437,10 +436,10 @@ def get_plane_uri(cls, observation_uri, product_id): observation_uri : the uri of the observation product_id : ID of the product """ - Util.type_check(observation_uri, observation.ObservationURI, "observation_uri", + caom_util.type_check(observation_uri, observation.ObservationURI, "observation_uri", override=False) - Util.type_check(product_id, str, "observation_uri", override=False) - Util.validate_path_component(cls, "product_id", product_id) + caom_util.type_check(product_id, str, "observation_uri", override=False) + caom_util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path uri = SplitResult(observation.ObservationURI._SCHEME, "", path + "/" + @@ -456,7 +455,7 @@ def uri(self): @uri.setter def uri(self, value): - Util.type_check(value, str, "uri", override=False) + caom_util.type_check(value, str, "uri", override=False) tmp = urlsplit(value) if tmp.scheme != observation.ObservationURI._SCHEME: @@ -507,7 +506,7 @@ def flag(self): @flag.setter def flag(self, value): - Util.type_check(value, Quality, "flag") + caom_util.type_check(value, Quality, "flag") self._flag = value @@ -539,8 +538,8 @@ def source_number_density(self): @source_number_density.setter def source_number_density(self, value): - Util.type_check(value, float, "source_number_density") - Util.value_check(value, 0, 1E10, "source_number_density") + caom_util.type_check(value, float, "source_number_density") + caom_util.value_check(value, 0, 1E10, "source_number_density") self._source_number_density = value @property @@ -554,8 +553,8 @@ def background(self): @background.setter def background(self, value): - Util.type_check(value, float, "background") - Util.value_check(value, 0, 1E10, "background") + caom_util.type_check(value, float, "background") + caom_util.value_check(value, 0, 1E10, "background") self._background = value @property @@ -570,8 +569,8 @@ def background_std_dev(self): @background_std_dev.setter def background_std_dev(self, value): - Util.type_check(value, float, "background_std_dev") - Util.value_check(value, 0, 1E10, "background") + caom_util.type_check(value, float, "background_std_dev") + caom_util.value_check(value, 0, 1E10, "background") self._background_std_dev = value @property @@ -587,8 +586,8 @@ def flux_density_limit(self): @flux_density_limit.setter def flux_density_limit(self, value): - Util.type_check(value, float, "flux_denisty_limit") - Util.value_check(value, 0, 1E10, "flux_density_limit") + caom_util.type_check(value, float, "flux_denisty_limit") + caom_util.value_check(value, 0, 1E10, "flux_density_limit") self._flux_density_limit = value @property @@ -604,8 +603,8 @@ def mag_limit(self): @mag_limit.setter def mag_limit(self, value): - Util.type_check(value, float, 'mag_limit') - Util.value_check(value, 0, 40, 'mag_limit') + caom_util.type_check(value, float, 'mag_limit') + caom_util.value_check(value, 0, 40, 'mag_limit') self._mag_limit = value @@ -654,7 +653,7 @@ def version(self): @version.setter def version(self, value): - Util.type_check(value, str, 'version') + caom_util.type_check(value, str, 'version') self._version = value @property @@ -664,7 +663,7 @@ def project(self): @project.setter def project(self, value): - Util.type_check(value, str, 'project') + caom_util.type_check(value, str, 'project') self._project = value @property @@ -674,7 +673,7 @@ def producer(self): @producer.setter def producer(self, value): - Util.type_check(value, str, 'producer') + caom_util.type_check(value, str, 'producer') self._producer = value @property @@ -684,7 +683,7 @@ def run_id(self): @run_id.setter def run_id(self, value): - Util.type_check(value, str, 'run_id') + caom_util.type_check(value, str, 'run_id') self._run_id = value @property @@ -694,7 +693,7 @@ def reference(self): @reference.setter def reference(self, value): - Util.type_check(value, str, 'version') + caom_util.type_check(value, str, 'version') if value is not None: tmp = urlsplit(value) assert tmp.geturl() == value, "Invalid URI: " + value @@ -707,7 +706,7 @@ def last_executed(self): @last_executed.setter def last_executed(self, value): - Util.type_check(value, datetime, 'last_executed') + caom_util.type_check(value, datetime, 'last_executed') self._last_executed = value @property @@ -933,8 +932,8 @@ def __init__(self, species, transition): species transition """ - Util.type_check(species, str, "species", override=False) - Util.type_check(transition, str, "transition", override=False) + caom_util.type_check(species, str, "species", override=False) + caom_util.type_check(transition, str, "transition", override=False) self._species = species self._transition = transition @@ -976,8 +975,8 @@ def dimension(self): @dimension.setter def dimension(self, value): - Util.type_check(value, int, 'dimension') - Util.value_check(value, 0, 1E10, 'dimension') + caom_util.type_check(value, int, 'dimension') + caom_util.value_check(value, 0, 1E10, 'dimension') self._dimension = value @@ -1018,7 +1017,7 @@ def value(self): @value.setter def value(self, value): - Util.type_check(value, float, 'value') + caom_util.type_check(value, float, 'value') self._value = value @property @@ -1036,7 +1035,7 @@ def bounds(self): @bounds.setter def bounds(self, value): - Util.type_check(value, shape.Interval, 'bounds') + caom_util.type_check(value, shape.Interval, 'bounds') self._bounds = value @property @@ -1051,7 +1050,7 @@ def dimension(self): @dimension.setter def dimension(self, value): - Util.type_check(value, long, 'dimension') + caom_util.type_check(value, long, 'dimension') self._dimension = value @property @@ -1071,7 +1070,7 @@ def resolution(self): @resolution.setter def resolution(self, value): - Util.type_check(value, float, 'resolution') + caom_util.type_check(value, float, 'resolution') self._resolution = value @property @@ -1083,7 +1082,7 @@ def sample_size(self): @sample_size.setter def sample_size(self, value): - Util.type_check(value, float, 'sample_size') + caom_util.type_check(value, float, 'sample_size') self._sample_size = value @property @@ -1093,6 +1092,6 @@ def exposure(self): @exposure.setter def exposure(self, value): - Util.type_check(value, float, 'exposure') + caom_util.type_check(value, float, 'exposure') self._exposure = value diff --git a/caom2tools/caom2/shape.py b/caom2tools/caom2/shape.py index 6730666e..2f39fedf 100644 --- a/caom2tools/caom2/shape.py +++ b/caom2tools/caom2/shape.py @@ -68,10 +68,9 @@ #*********************************************************************** # -from enum import Enum import caom_object -from caom_util import Util - +import caom_util +from enum import Enum SegmentType = Enum('SegmentType', CLOSE=0, @@ -113,7 +112,7 @@ def cval1(self): @cval1.setter def cval1(self, value): - Util.type_check(value, float, 'cval1', override=False) + caom_util.type_check(value, float, 'cval1', override=False) self._cval1 = value @property @@ -125,7 +124,7 @@ def cval2(self): @cval2.setter def cval2(self, value): - Util.type_check(value, float, 'cval2', override=False) + caom_util.type_check(value, float, 'cval2', override=False) self._cval2 = value diff --git a/caom2tools/caom2/test/__init__.py b/caom2tools/caom2/test/__init__.py index 425cb2f4..e96603b4 100644 --- a/caom2tools/caom2/test/__init__.py +++ b/caom2tools/caom2/test/__init__.py @@ -68,4 +68,6 @@ #*********************************************************************** # -""" Defines __init__ """ \ No newline at end of file +""" Defines __init__ """ + +from caom_test_instances import Caom2TestInstances diff --git a/caom2tools/caom2/test/caom_test_instances.py b/caom2tools/caom2/test/caom_test_instances.py index c2d62631..19411740 100644 --- a/caom2tools/caom2/test/caom_test_instances.py +++ b/caom2tools/caom2/test/caom_test_instances.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -73,13 +72,14 @@ import collections from datetime import datetime -import artifact -import chunk -import observation as obs -import part -import plane -import caom_util -import wcs +from caom2tools.caom2 import artifact +from caom2tools.caom2 import caom_util +from caom2tools.caom2 import chunk +from caom2tools.caom2 import observation +from caom2tools.caom2 import part +from caom2tools.caom2 import plane +from caom2tools.caom2 import shape +from caom2tools.caom2 import wcs class Caom2TestInstances(object): @@ -129,54 +129,54 @@ def caom_version(self, v): self._caom_version = v def get_simple_observation(self): - observation = \ - obs.SimpleObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id) + simple_observation = \ + observation.SimpleObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id) if self.complete: - observation.sequence_number = int(5) - observation.obs_type = "flat" - observation.intent = obs.ObservationIntentType.CALIBRATION - observation.meta_release = Caom2TestInstances._ivoa_date - observation.proposal = self.get_proposal() - observation.target = self.get_target() - observation.target_position = self.get_target_position() + simple_observation.sequence_number = int(5) + simple_observation.obs_type = "flat" + simple_observation.intent = observation.ObservationIntentType.CALIBRATION + simple_observation.meta_release = Caom2TestInstances._ivoa_date + simple_observation.proposal = self.get_proposal() + simple_observation.target = self.get_target() + simple_observation.target_position = self.get_target_position() if self.caom_version == 21: - observation.requirements = self.get_requirements() - observation.telescope = self.get_telescope() - observation.instrument = self.get_instrument() - observation.environment = self.get_environment() + simple_observation.requirements = self.get_requirements() + simple_observation.telescope = self.get_telescope() + simple_observation.instrument = self.get_instrument() + simple_observation.environment = self.get_environment() if self.depth > 1: - observation.planes.update(self.get_planes()) - return observation + simple_observation.planes.update(self.get_planes()) + return simple_observation def get_composite_observation(self): - observation = \ - obs.CompositeObservation(Caom2TestInstances._collection, - Caom2TestInstances._observation_id, - self.get_algorithm()) + composite_observation = \ + observation.CompositeObservation(Caom2TestInstances._collection, + Caom2TestInstances._observation_id, + self.get_algorithm()) if self.complete: - observation.sequence_number = int(10) - observation.obs_type = "filed" - observation.intent = obs.ObservationIntentType.SCIENCE - observation.meta_release = Caom2TestInstances._ivoa_date - observation.proposal = self.get_proposal() - observation.target = self.get_target() - observation.target_position = self.get_target_position() + composite_observation.sequence_number = int(10) + composite_observation.obs_type = "filed" + composite_observation.intent = observation.ObservationIntentType.SCIENCE + composite_observation.meta_release = Caom2TestInstances._ivoa_date + composite_observation.proposal = self.get_proposal() + composite_observation.target = self.get_target() + composite_observation.target_position = self.get_target_position() if self.caom_version == 21: - observation.requirements = self.get_requirements() - observation.telescope = self.get_telescope() - observation.instrument = self.get_instrument() - observation.environment = self.get_environment() + composite_observation.requirements = self.get_requirements() + composite_observation.telescope = self.get_telescope() + composite_observation.instrument = self.get_instrument() + composite_observation.environment = self.get_environment() if self.depth > 1: - observation.planes.update(self.get_planes()) - observation.members.update(self.get_members()) - return observation + composite_observation.planes.update(self.get_planes()) + composite_observation.members.update(self.get_members()) + return composite_observation def get_algorithm(self): - return obs.Algorithm("algorithmName") + return observation.Algorithm("algorithmName") def get_proposal(self): - proposal = obs.Proposal("proposalId") + proposal = observation.Proposal("proposalId") proposal.pi_name = "proposalPi" proposal.project = "proposalProject" proposal.title = "proposalTitle" @@ -184,24 +184,24 @@ def get_proposal(self): return proposal def get_target(self): - target = obs.Target("targetName") - target.target_type = obs.TargetType.OBJECT + target = observation.Target("targetName") + target.target_type = observation.TargetType.OBJECT target.standard = False target.redshift = 1.5 target.keywords.update(Caom2TestInstances._keywords) return target def get_target_position(self): - point = wcs.Point(1.0, 2.0) - target_position = obs.TargetPosition(point, "coordsys") + point = shape.Point(1.0, 2.0) + target_position = observation.TargetPosition(point, "coordsys") target_position.equinox = 3.0 return target_position def get_requirements(self): - return obs.Requirements(obs.Status.FAIL) + return observation.Requirements(observation.Status.FAIL) def get_telescope(self): - telescope = obs.Telescope("telescopeName") + telescope = observation.Telescope("telescopeName") telescope.geo_location_x = 1.0 telescope.geo_location_y = 2.0 telescope.geo_location_z = 3.0 @@ -209,12 +209,12 @@ def get_telescope(self): return telescope def get_instrument(self): - instrument = obs.Instrument("instrumentName") + instrument = observation.Instrument("instrumentName") instrument.keywords.update(Caom2TestInstances._keywords) return instrument def get_environment(self): - env = obs.Environment() + env = observation.Environment() env.seeing = 0.08 env.humidity = 0.35 env.elevation = 2.7 @@ -226,7 +226,7 @@ def get_environment(self): def get_members(self): members = caom_util.TypedSet( - obs.ObservationURI, obs.ObservationURI("caom:foo/bar")) + observation.ObservationURI, observation.ObservationURI("caom:foo/bar")) return members def get_planes(self): diff --git a/caom2tools/caom2/test/test_artifact.py b/caom2tools/caom2/test/test_artifact.py index 59225779..785b0778 100644 --- a/caom2tools/caom2/test/test_artifact.py +++ b/caom2tools/caom2/test/test_artifact.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -73,106 +72,124 @@ import unittest from urlparse import urlparse -from caom2tools.caom2.artifact import Artifact -from caom2tools.caom2.artifact import ProductType -from caom2tools.caom2.artifact import ReleaseType -from caom2tools.caom2.part import Part +from .. import artifact +from .. import part class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(ProductType.get("no_such_string"), None) - self.assertRaises(AttributeError, ProductType.get, None) - self.assertRaises(AttributeError, ProductType.get, 1) + self.assertEqual(artifact.ProductType.get("no_such_string"), None) + self.assertRaises(AttributeError, artifact.ProductType.get, None) + self.assertRaises(AttributeError, artifact.ProductType.get, 1) - self.assertEqual(ReleaseType.get("no_such_string"), None) - self.assertRaises(AttributeError, ReleaseType.get, None) - self.assertRaises(AttributeError, ReleaseType.get, 1) + self.assertEqual(artifact.ReleaseType.get("no_such_string"), None) + self.assertRaises(AttributeError, artifact.ReleaseType.get, None) + self.assertRaises(AttributeError, artifact.ReleaseType.get, 1) # test that we can get the object for each enum by name - self.assertEqual(ProductType.SCIENCE.name, "SCIENCE") - self.assertEqual(ProductType.get(ProductType.SCIENCE.name).name, "SCIENCE") - self.assertEqual(ProductType.get('SCIENCE').value, "science") - self.assertEqual(ProductType.get(ProductType.SCIENCE.name).value, "science") - self.assertEqual(ProductType.getByValue(ProductType.SCIENCE.value).value, "science") - self.assertEqual(ProductType.getByValue(ProductType.CALIBRATED.value).name, "SCIENCE") - - self.assertEqual(ProductType.SCIENCE.value, "science") - self.assertEqual(ProductType.CALIBRATION.value, "calibration") - self.assertEqual(ProductType.PREVIEW.value, "preview") - self.assertEqual(ProductType.INFO.value, "info") - self.assertEqual(ProductType.NOISE.value, "noise") - self.assertEqual(ProductType.WEIGHT.value, "weight") - self.assertEqual(ProductType.AUXILIARY.value, "auxiliary") - self.assertEqual(ProductType.THUMBNAIL.value, "thumbnail") - - self.assertEqual(ReleaseType.DATA.value, "data") - self.assertEqual(ReleaseType.META.value, "meta") + self.assertEqual(artifact.ProductType.SCIENCE.name, "SCIENCE") + self.assertEqual(artifact.ProductType.get( + artifact.ProductType.SCIENCE.name).name, "SCIENCE") + self.assertEqual(artifact.ProductType.get( + 'SCIENCE').value, "science") + self.assertEqual(artifact.ProductType.get( + artifact.ProductType.SCIENCE.name).value, "science") + self.assertEqual(artifact.ProductType.getByValue( + artifact.ProductType.SCIENCE.value).value, "science") + self.assertEqual(artifact.ProductType.getByValue( + artifact.ProductType.SCIENCE.value).name, "SCIENCE") + + self.assertEqual(artifact.ProductType.SCIENCE.value, "science") + self.assertEqual(artifact.ProductType.CALIBRATION.value, "calibration") + self.assertEqual(artifact.ProductType.PREVIEW.value, "preview") + self.assertEqual(artifact.ProductType.INFO.value, "info") + self.assertEqual(artifact.ProductType.NOISE.value, "noise") + self.assertEqual(artifact.ProductType.WEIGHT.value, "weight") + self.assertEqual(artifact.ProductType.AUXILIARY.value, "auxiliary") + self.assertEqual(artifact.ProductType.THUMBNAIL.value, "thumbnail") + + self.assertEqual(artifact.ReleaseType.DATA.value, "data") + self.assertEqual(artifact.ReleaseType.META.value, "meta") class TestArtifact(unittest.TestCase): def test_all(self): with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345") + test_artifact = artifact.Artifact("caom:GEMINI/12345") with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", ReleaseType('META'), ProductType('THUMBNAIL')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ReleaseType('META'), + artifact.ProductType('THUMBNAIL')) with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", ProductType('THUMBNAIL'), None) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ProductType('THUMBNAIL'), + None) with self.assertRaises(TypeError): - artifact = Artifact("caom:GEMINI/12345", None, ReleaseType('META')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + None, + artifact.ReleaseType('META')) - artifact = Artifact("caom:GEMINI/12345", ProductType('THUMBNAIL'), ReleaseType('META')) + test_artifact = artifact.Artifact("caom:GEMINI/12345", + artifact.ProductType('THUMBNAIL'), + artifact.ReleaseType('META')) urlparse("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", artifact.uri, "Artifact URI") - self.assertEqual(ProductType('THUMBNAIL'), artifact.product_type, "Artifact ProductType") - self.assertEqual(ReleaseType('META'), artifact.release_type, "Artifact ReleaseType") - - self.assertIsNone(artifact.content_type, "Default content type") - artifact.content_type = "FITS" - self.assertEquals("FITS", artifact.content_type, "Content type") - self.assertIsNone(artifact.content_length, "Default content length") - artifact.content_length = 23L - self.assertEquals(23L, artifact.content_length, "Content length") - artifact.product_type = ProductType.PREVIEW - self.assertEquals(ProductType.PREVIEW, artifact.product_type, "Product type") - self.assertEquals(0, len(artifact.parts), "Default parts") - part1 = Part("1") - artifact.parts["1"] = part1 - self.assertEquals(1, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) + self.assertEqual("caom:GEMINI/12345", + test_artifact.uri, + "Artifact URI") + self.assertEqual(artifact.ProductType('THUMBNAIL'), + test_artifact.product_type, + "Artifact ProductType") + self.assertEqual(artifact.ReleaseType('META'), + test_artifact.release_type, + "Artifact ReleaseType") + + self.assertIsNone(test_artifact.content_type, "Default content type") + test_artifact.content_type = "FITS" + self.assertEquals("FITS", test_artifact.content_type, "Content type") + self.assertIsNone(test_artifact.content_length, + "Default content length") + test_artifact.content_length = 23L + self.assertEquals(23L, test_artifact.content_length, "Content length") + test_artifact.product_type = artifact.ProductType.PREVIEW + self.assertEquals(artifact.ProductType.PREVIEW, + test_artifact.product_type, + "Product type") + self.assertEquals(0, len(test_artifact.parts), "Default parts") + part1 = part.Part("1") + test_artifact.parts["1"] = part1 + self.assertEquals(1, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) #add same part again - part2 = Part("2") - artifact.parts["2"] = part2 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + part2 = part.Part("2") + test_artifact.parts["2"] = part2 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) # try to add duplicates part3 = part1 - artifact.parts["1"] = part3 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + test_artifact.parts["1"] = part3 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) - part4 = Part("1") - artifact.parts["1"] = part4 - self.assertEquals(2, len(artifact.parts), "Parts") - self.assertTrue("1" in artifact.parts.keys()) - self.assertTrue("2" in artifact.parts.keys()) + part4 = part.Part("1") + test_artifact.parts["1"] = part4 + self.assertEquals(2, len(test_artifact.parts), "Parts") + self.assertTrue("1" in test_artifact.parts.keys()) + self.assertTrue("2" in test_artifact.parts.keys()) #incorrect URI exception = False try: - artifact = Artifact("caom://#observation://? something#//", ReleaseType('META'), ProductType('THUMBNAIL')) + test_artifact = artifact.Artifact( + "caom://#observation://? something#//", + artifact.ReleaseType('META'), + artifact.ProductType('THUMBNAIL')) print artifact.uri except ValueError: exception = True self.assertTrue(exception, "Missing exception") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/test/test_caom_object.py b/caom2tools/caom2/test/test_caom_object.py index bc4f8775..81249c89 100644 --- a/caom2tools/caom2/test/test_caom_object.py +++ b/caom2tools/caom2/test/test_caom_object.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -72,33 +71,34 @@ import unittest -from caom2tools.caom2.artifact import Artifact, ProductType, ReleaseType -from caom2tools.caom2.caom_object import AbstractCaomEntity -from caom2tools.caom2.chunk import Chunk -from caom2tools.caom2.observation import Algorithm -from caom2tools.caom2.observation import Observation -from caom2tools.caom2.part import Part -from caom2tools.caom2.plane import Plane +from .. import artifact +from .. import caom_object +from .. import chunk +from .. import observation +from .. import part +from .. import plane class TestCaom2IdGenerator(unittest.TestCase): def test_all(self): #Not much for now. Just to make sure that all the clients work - entity = AbstractCaomEntity() - print entity._id, entity._last_modified - artifact = Artifact("caom2:/blah/blah", ProductType.SCIENCE, ReleaseType.DATA) - print artifact._id, artifact._last_modified - chunk = Chunk() - print chunk._id, chunk._last_modified - algorithm = Algorithm("myAlg") - obs = Observation("colect", "obs", algorithm) - print obs._id, obs._last_modified - part = Part("part") - print part._id, part._last_modified - plane = Plane("prodid") - print plane._id, plane._last_modified + test_entity = caom_object.AbstractCaomEntity() + print test_entity._id, test_entity._last_modified + test_artifact = artifact.Artifact("caom2:/blah/blah", + artifact.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + print test_artifact._id, test_artifact._last_modified -if __name__ == '__main__': - unittest.main() + test_chunk = chunk.Chunk() + print test_chunk._id, test_chunk._last_modified + algorithm = observation.Algorithm("myAlg") + test_observation = observation.Observation("colect", "obs", algorithm) + print test_observation._id, test_observation._last_modified + + test_part = part.Part("part") + print test_part._id, test_part._last_modified + + test_plane = plane.Plane("prodid") + print test_plane._id, test_plane._last_modified diff --git a/caom2tools/caom2/test/test_caom_util.py b/caom2tools/caom2/test/test_caom_util.py index 249fb4c4..eac58ae7 100644 --- a/caom2tools/caom2/test/test_caom_util.py +++ b/caom2tools/caom2/test/test_caom_util.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -68,274 +67,255 @@ #*********************************************************************** # -""" Defines TestCaomUtil class """ - import unittest import uuid -from caom2tools.caom2.artifact import Artifact -from caom2tools.caom2.artifact import ProductType -from caom2tools.caom2.artifact import ReleaseType -from caom2tools.caom2.part import Part -from caom2tools.caom2.plane import Energy -from caom2tools.caom2.plane import Plane -from caom2tools.caom2.plane import PlaneURI -from caom2tools.caom2.caom_util import TypedList -from caom2tools.caom2.caom_util import TypedOrderedDict -from caom2tools.caom2.caom_util import TypedSet -from caom2tools.caom2.caom_util import Util +from .. import artifact +from .. import part +from .. import plane +from .. import caom_util class TestCaomUtil(unittest.TestCase): def test_typed_list(self): - mylist1 = TypedList((str), "Test1") - self.assertEquals(1, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") + my_list1 = caom_util.TypedList(str, "Test1") + self.assertEquals(1, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") - mylist1.append("Test2") - self.assertEquals(2, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") + my_list1.append("Test2") + self.assertEquals(2, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") # try to add the wrong type exception = False try: - mylist1.append(3) + my_list1.append(3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist1.extend([2, 4]) + my_list1.extend([2, 4]) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist2 = TypedList((int), 2) - mylist1.extend(mylist2) + my_list2 = caom_util.TypedList(int, 2) + my_list1.extend(my_list2) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist1.insert(1, 3) + my_list1.insert(1, 3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") exception = False try: - mylist2 = TypedList((str), 1, 3) + my_list2 = caom_util.TypedList(str, 1, 3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") - self.assertEquals(2, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") - - mylist2 = TypedList((str), "Test3", "Test4") - mylist1.extend(mylist2) - self.assertEquals(4, len(mylist1), "list1 length") - self.assertEqual("Test1", mylist1[0], "Non matching elements") - self.assertEqual("Test2", mylist1[1], "Non matching elements") - self.assertEqual("Test3", mylist1[2], "Non matching elements") - self.assertEqual("Test4", mylist1[3], "Non matching elements") - - mylist1.insert(0, "Test0") - self.assertEquals(5, len(mylist1), "list1 length") - self.assertEqual("Test0", mylist1[0], "Non matching elements") - self.assertEqual("Test1", mylist1[1], "Non matching elements") - self.assertEqual("Test2", mylist1[2], "Non matching elements") - self.assertEqual("Test3", mylist1[3], "Non matching elements") - self.assertEqual("Test4", mylist1[4], "Non matching elements") - - mylist2 = TypedList((Energy),) - self.assertEquals(0, len(mylist2), "list2 length") + self.assertEquals(2, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") + + my_list2 = caom_util.TypedList(str, "Test3", "Test4") + my_list1.extend(my_list2) + self.assertEquals(4, len(my_list1), "list1 length") + self.assertEqual("Test1", my_list1[0], "Non matching elements") + self.assertEqual("Test2", my_list1[1], "Non matching elements") + self.assertEqual("Test3", my_list1[2], "Non matching elements") + self.assertEqual("Test4", my_list1[3], "Non matching elements") + + my_list1.insert(0, "Test0") + self.assertEquals(5, len(my_list1), "list1 length") + self.assertEqual("Test0", my_list1[0], "Non matching elements") + self.assertEqual("Test1", my_list1[1], "Non matching elements") + self.assertEqual("Test2", my_list1[2], "Non matching elements") + self.assertEqual("Test3", my_list1[3], "Non matching elements") + self.assertEqual("Test4", my_list1[4], "Non matching elements") + + my_list2 = caom_util.TypedList(plane.Energy,) + self.assertEquals(0, len(my_list2), "list2 length") def test_validate_path_component(self): - energy = Energy() - Util.validate_path_component(energy, "something", "some:test\\path") + energy = plane.Energy() + caom_util.validate_path_component(energy, "something", "some:test\\path") exception = False try: - Util.validate_path_component(energy, "energyfield", "some:test path") + caom_util.validate_path_component(energy, "energyfield", "some:test path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - Util.validate_path_component(energy, "energyfield", "some:test/path") + caom_util.validate_path_component(energy, "energyfield", "some:test/path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - Util.validate_path_component(energy, "energyfield", "some:test||path") + caom_util.validate_path_component(energy, "energyfield", "some:test||path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - Util.validate_path_component(energy, "energyfield", "some:test %path") + caom_util.validate_path_component(energy, "energyfield", "some:test %path") except AssertionError: exception = True self.assertTrue(exception, "Missing exception") def test_typed_set(self): - myset = TypedSet((str),) + my_set = caom_util.TypedSet(str,) with self.assertRaises(AssertionError): - myset.add(float(1.0)) - myset.add(long(1)) - myset.add(bool(1)) + my_set.add(float(1.0)) + my_set.add(long(1)) + my_set.add(bool(1)) - self.assertRaises(AssertionError, TypedSet, (str), float(1.0)) + self.assertRaises(AssertionError, caom_util.TypedSet, str, float(1.0)) - myset = TypedSet((str), "Test1") - self.assertEquals(1, len(myset)) - self.assertEqual("Test1", myset.pop()) + my_set = caom_util.TypedSet(str, "Test1") + self.assertEquals(1, len(my_set)) + self.assertEqual("Test1", my_set.pop()) - myset.add("Test1") - myset.add("Test2") - self.assertEquals(2, len(myset), "set length") + my_set.add("Test1") + my_set.add("Test2") + self.assertEquals(2, len(my_set), "set length") with self.assertRaises(AssertionError): - myset.add(float(1.0)) - myset.add(long(1)) - myset.add(bool(1)) - myset.add("Test1") + my_set.add(float(1.0)) + my_set.add(long(1)) + my_set.add(bool(1)) + my_set.add("Test1") - myset = TypedSet((str),) - myset.add("Test1") - myset.add("Test1") - self.assertTrue(len(myset) == 1) + my_set = caom_util.TypedSet(str,) + my_set.add("Test1") + my_set.add("Test1") + self.assertTrue(len(my_set) == 1) def test_typed_ordered_dict(self): # test validation and constructor with an empty dictionary - testPlane10 = Plane('key10') - testArtifact66 = Artifact('caom:CFHT/55/66', ProductType.SCIENCE, ReleaseType.DATA) - testPart10 = Part("10") - testPlaneURI = PlaneURI('caom:CFHT/55/66') - myDictPlane = TypedOrderedDict((Plane),) + test_plane10 = plane.Plane('key10') + test_artifact66 = artifact.Artifact('caom:CFHT/55/66', + artifact.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_part10 = part.Part("10") + test_plane_uri = plane.PlaneURI('caom:CFHT/55/66') + my_dict_plane = caom_util.TypedOrderedDict(plane.Plane,) with self.assertRaises(ValueError): - myDictPlane['key11'] = testPlane10 - myDictArtifact = TypedOrderedDict((Artifact),) + my_dict_plane['key11'] = test_plane10 + my_dict_artifact = caom_util.TypedOrderedDict(artifact.Artifact,) with self.assertRaises(ValueError): - myDictArtifact['caom:CFHT/55/6'] = testArtifact66 - myDictPart = TypedOrderedDict((Part),) + my_dict_artifact['caom:CFHT/55/6'] = test_artifact66 + my_dict_part = caom_util.TypedOrderedDict(part.Part,) with self.assertRaises(ValueError): - myDictPart['11'] = testPart10 - myDictWrongType = TypedOrderedDict((PlaneURI),) + my_dict_part['11'] = test_part10 + my_dict_wrong_type = caom_util.TypedOrderedDict(plane.PlaneURI,) with self.assertRaises(AttributeError): - myDictWrongType['caom:CFHT/55/66'] = testPlaneURI + my_dict_wrong_type['caom:CFHT/55/66'] = test_plane_uri with self.assertRaises(TypeError): - myDictPlane['key2'] = 'value2' + my_dict_plane['key2'] = 'value2' with self.assertRaises(TypeError): - myDictPlane['key1'] = float(2.0) + my_dict_plane['key1'] = float(2.0) # test assignment - myDict = TypedOrderedDict((Plane),) - testPlane2 = Plane('key2') - testPlane1 = Plane('key1') - myDict['key2'] = testPlane2 - myDict['key1'] = testPlane1 - self.assertEqual(2, len(myDict), + my_dict = caom_util.TypedOrderedDict(plane.Plane,) + test_plane2 = plane.Plane('key2') + test_plane1 = plane.Plane('key1') + my_dict['key2'] = test_plane2 + my_dict['key1'] = test_plane1 + self.assertEqual(2, len(my_dict), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key2', myDict.keys()[0], + self.assertEqual('key2', my_dict.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key1', myDict.keys()[1], + self.assertEqual('key1', my_dict.keys()[1], 'key mismatch for 2nd key') - self.assertEqual(testPlane2, myDict.values()[0], + self.assertEqual(test_plane2, my_dict.values()[0], 'value mismatch for 1st value') - self.assertEqual(testPlane1, myDict.values()[1], + self.assertEqual(test_plane1, my_dict.values()[1], 'value mismatch for 2nd value') # test constructor with non-empty dictionary - testPlane1 = Plane('key1') - testPlane2 = Plane('key2') - myDict1 = TypedOrderedDict((Plane), ('key1', testPlane1), - ('key2', testPlane2)) - self.assertEqual(2, len(myDict1), + test_plane1 = plane.Plane('key1') + test_plane2 = plane.Plane('key2') + my_dict1 = caom_util.TypedOrderedDict(plane.Plane, ('key1', test_plane1), + ('key2', test_plane2)) + self.assertEqual(2, len(my_dict1), 'mismatch in the number of entries in dictionary.') # test assignment via setdefault - self.assertRaises(TypeError, myDict1.setdefault, + self.assertRaises(TypeError, my_dict1.setdefault, 'key3', 'wrong value') - myDict1.setdefault('key3', Plane('key3')) - self.assertEqual(3, len(myDict1), + my_dict1.setdefault('key3', plane.Plane('key3')) + self.assertEqual(3, len(my_dict1), 'mismatch in the number of entries in dictionary.') # test assignment via update - myDict1.update(myDict) - self.assertEqual(3, len(myDict1), + my_dict1.update(my_dict) + self.assertEqual(3, len(my_dict1), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key2', myDict.keys()[0], + self.assertEqual('key2', my_dict.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key1', myDict.keys()[1], + self.assertEqual('key1', my_dict.keys()[1], 'key mismatch for 2nd key') - #self.assertEqual(testPlane1, myDict.values()[0], - # 'value mismatch for 1st value') - #self.assertEqual(testPlane2, myDict.values()[1], - # 'value mismatch for 2nd value') # test add function - myDict1.add(Plane('key4')) - self.assertEqual(4, len(myDict1), + my_dict1.add(plane.Plane('key4')) + self.assertEqual(4, len(my_dict1), 'mismatch in the number of entries in dictionary.') - self.assertEqual('key1', myDict1.keys()[0], + self.assertEqual('key1', my_dict1.keys()[0], 'key mismatch for 1st key') - self.assertEqual('key2', myDict1.keys()[1], + self.assertEqual('key2', my_dict1.keys()[1], 'key mismatch for 2nd key') - self.assertEqual('key3', myDict1.keys()[2], + self.assertEqual('key3', my_dict1.keys()[2], 'key mismatch for 3rd key') - self.assertEqual('key4', myDict1.keys()[3], + self.assertEqual('key4', my_dict1.keys()[3], 'key mismatch for 4th key') - # self.assertEqual(testPlane1, myDict1.values()[0], - # 'value mismatch for 1st value') - #self.assertEqual(testPlane2, myDict1.values()[1], - # 'value mismatch for 2nd value') - plane5 = Plane("key5") - myDict1[plane5.key] = plane5 + + plane5 = plane.Plane("key5") + my_dict1[plane5.key] = plane5 with self.assertRaises(AttributeError): - myDict1.add(testPlaneURI) + my_dict1.add(test_plane_uri) - def testuuid2long(self): + def test_uuid2long(self): # > 64 bit uuid u = uuid.UUID('3d26e30b-10cc-4301-8193-f2e0c6b63302') try: - Util.uuid2long(u) + caom_util.uuid2long(u) self.fail("> 64 uuid should raise ValueError") except ValueError: pass u = uuid.UUID('00000000-0000-0000-0000-000000000001') - l = Util.uuid2long(u) + l = caom_util.uuid2long(u) self.assertEqual(1L, l) u = uuid.UUID('00000000-0000-0000-0000-000000bc614e') - l = Util.uuid2long(u) + l = caom_util.uuid2long(u) self.assertEqual(12345678L, l) - def testlong2uuid(self): + def test_long2uuid(self): # > 64 bit long l = 123456781234567812345678L try: - Util.long2uuid(l) + caom_util.long2uuid(l) self.fail("> 64 bit long should raise ValueError") except ValueError: pass l = 3296038095975885829 - uid = Util.long2uuid(l) + uid = caom_util.long2uuid(l) self.assertEqual('00000000-0000-0000-2dbd-e12f64cc2c05', str(uid)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/test/test_chunk.py b/caom2tools/caom2/test/test_chunk.py index fc281837..e311ff3a 100644 --- a/caom2tools/caom2/test/test_chunk.py +++ b/caom2tools/caom2/test/test_chunk.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -72,210 +71,106 @@ import unittest -from caom2tools.caom2.artifact import ProductType -from caom2tools.caom2.chunk import Chunk -from caom2tools.caom2.chunk import ObservableAxis -from caom2tools.caom2.chunk import PolarizationWCS -from caom2tools.caom2.chunk import SpatialWCS -from caom2tools.caom2.chunk import SpectralWCS -from caom2tools.caom2.chunk import TemporalWCS -from caom2tools.caom2.plane import EnergyTransition -from caom2tools.caom2.wcs import Axis -from caom2tools.caom2.wcs import CoordAxis1D -from caom2tools.caom2.wcs import CoordAxis2D -from caom2tools.caom2.wcs import Slice +from .. import artifact +from .. import chunk +from .. import plane +from .. import wcs class TestChunk(unittest.TestCase): def test_init(self): - chunk = Chunk() - self.assertIsNone(chunk.product_type) - self.assertIsNone(chunk.naxis) - #self.assertIsNone(chunk.observable_axis) - self.assertIsNone(chunk.position_axis_1) - self.assertIsNone(chunk.position_axis_2) - self.assertIsNone(chunk.energy_axis) - self.assertIsNone(chunk.time_axis) - self.assertIsNone(chunk.polarization_axis) - self.assertIsNone(chunk.observable) - self.assertIsNone(chunk.position) - self.assertIsNone(chunk.energy) - self.assertIsNone(chunk.time) - self.assertIsNone(chunk.polarization) + test_chunk = chunk.Chunk() + self.assertIsNone(test_chunk.product_type) + self.assertIsNone(test_chunk.naxis) + self.assertIsNone(test_chunk.position_axis_1) + self.assertIsNone(test_chunk.position_axis_2) + self.assertIsNone(test_chunk.energy_axis) + self.assertIsNone(test_chunk.time_axis) + self.assertIsNone(test_chunk.polarization_axis) + self.assertIsNone(test_chunk.observable) + self.assertIsNone(test_chunk.position) + self.assertIsNone(test_chunk.energy) + self.assertIsNone(test_chunk.time) + self.assertIsNone(test_chunk.polarization) def test_attributes(self): - chunk = Chunk() + test_chunk = chunk.Chunk() with self.assertRaises(TypeError): - chunk.product_type = float(1.0) - chunk.naxis = float(1.0) - #chunk.observable_axis = float(1.0) - chunk.position_axis_1 = float(1.0) - chunk.position_axis_2 = float(1.0) - chunk.energy_axis = float(1.0) - chunk.time_axis = float(1.0) - chunk.polarization_axis = float(1.0) - chunk.observable = float(1.0) - chunk.position = float(1.0) - chunk.energy = float(1.0) - chunk.time = float(1.0) - chunk.polarization = float(1.0) - - chunk.product_type = ProductType.SCIENCE - self.assertEqual(ProductType.SCIENCE, chunk.product_type) - - chunk.naxis = int(5) - self.assertEqual(int(5), chunk.naxis) - - #chunk.observable_axis = int(2) - #self.assertEqual(int(2), chunk.observable_axis) - - chunk.position_axis_1 = int(1) - self.assertEqual(int(1), chunk.position_axis_1) - - chunk.position_axis_2 = int(2) - self.assertEqual(int(2), chunk.position_axis_2) - - chunk.energy_axis = int(3) - self.assertEqual(int(3), chunk.energy_axis) - - chunk.time_axis = int(4) - self.assertEqual(int(4), chunk.time_axis) - - chunk.polarization_axis = int(5) - self.assertEqual(int(5), chunk.polarization_axis) - - axis = Axis("ctype", "cunit") - dependent = Slice(axis, long(1)) - observable = ObservableAxis(dependent) - chunk.observable = observable - self.assertEqual(observable, chunk.observable) - - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - position = SpatialWCS(axis_2d) - chunk.position = position - self.assertEqual(position, chunk.position) - - axis_1d = CoordAxis1D(axis) - energy = SpectralWCS(axis_1d, "specsys") - chunk.energy = energy - self.assertEqual(energy, chunk.energy) - - time = TemporalWCS(axis_1d) - chunk.time = time - self.assertEqual(time, chunk.time) - - polarization = PolarizationWCS(CoordAxis1D(Axis('STOKES'))) - chunk.polarization = polarization - self.assertEqual(polarization, chunk.polarization) - -# def test_compare_to(self): -# # test for chunk1 == chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 1 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() - -# chunk2 = Chunk() -# chunk2.naxis = 1 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() - - # test for chunk1 < chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 1 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() - -# chunk2 = Chunk() -# chunk2.naxis = 2 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() -# -# self.assertEqual(chunk1.compareTo(chunk2), -1, -# "compareTo equal failed") -# - # test for chunk1 > chunk2 -# chunk1 = Chunk() -# chunk1.naxis = 2 -# chunk1.observableAxis = 2 -# chunk1.positionAxis1 = 3 -# chunk1.positionAxis2 = 4 -# chunk1.energyAxis = 5 -# chunk1.timeAxis = 6 -# chunk1.polarizationAxis = 7 -# chunk1.observable = ObservableAxis() -# chunk1.position = SpatialWCS() -# chunk1.energy = SpectralWCS() -# chunk1.time = TemporalWCS() -# chunk1.polarization = PolarizationWCS() -# -# chunk2 = Chunk() -# chunk2.naxis = 1 -# chunk2.observableAxis = 2 -# chunk2.positionAxis1 = 3 -# chunk2.positionAxis2 = 4 -# chunk2.energyAxis = 5 -# chunk2.timeAxis = 6 -# chunk2.polarizationAxis = 7 -# chunk2.observable = ObservableAxis() -# chunk2.position = SpatialWCS() -# chunk2.energy = SpectralWCS() -# chunk2.time = TemporalWCS() -# chunk2.polarization = PolarizationWCS() + test_chunk.product_type = float(1.0) + test_chunk.naxis = float(1.0) + test_chunk.position_axis_1 = float(1.0) + test_chunk.position_axis_2 = float(1.0) + test_chunk.energy_axis = float(1.0) + test_chunk.time_axis = float(1.0) + test_chunk.polarization_axis = float(1.0) + test_chunk.observable = float(1.0) + test_chunk.position = float(1.0) + test_chunk.energy = float(1.0) + test_chunk.time = float(1.0) + test_chunk.polarization = float(1.0) + + test_chunk.product_type = artifact.ProductType.SCIENCE + self.assertEqual(artifact.ProductType.SCIENCE, test_chunk.product_type) + + test_chunk.naxis = int(5) + self.assertEqual(int(5), test_chunk.naxis) + + test_chunk.position_axis_1 = int(1) + self.assertEqual(int(1), test_chunk.position_axis_1) + + test_chunk.position_axis_2 = int(2) + self.assertEqual(int(2), test_chunk.position_axis_2) + + test_chunk.energy_axis = int(3) + self.assertEqual(int(3), test_chunk.energy_axis) + + test_chunk.time_axis = int(4) + self.assertEqual(int(4), test_chunk.time_axis) + + test_chunk.polarization_axis = int(5) + self.assertEqual(int(5), test_chunk.polarization_axis) + + axis = wcs.Axis("ctype", "cunit") + dependent = wcs.Slice(axis, long(1)) + observable = chunk.ObservableAxis(dependent) + test_chunk.observable = observable + self.assertEqual(observable, test_chunk.observable) + + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + position = chunk.SpatialWCS(axis_2d) + test_chunk.position = position + self.assertEqual(position, test_chunk.position) + + axis_1d = wcs.CoordAxis1D(axis) + energy = chunk.SpectralWCS(axis_1d, "specsys") + test_chunk.energy = energy + self.assertEqual(energy, test_chunk.energy) + + time = chunk.TemporalWCS(axis_1d) + test_chunk.time = time + self.assertEqual(time, test_chunk.time) + + polarization = chunk.PolarizationWCS(wcs.CoordAxis1D(wcs.Axis('STOKES'))) + test_chunk.polarization = polarization + self.assertEqual(polarization, test_chunk.polarization) class TestObservableAxis(unittest.TestCase): def test_init(self): - self.assertRaises(TypeError, ObservableAxis, None) - self.assertRaises(TypeError, ObservableAxis, int(1)) + self.assertRaises(TypeError, chunk.ObservableAxis, None) + self.assertRaises(TypeError, chunk.ObservableAxis, int(1)) - dependent = Slice(Axis("ctype1", "cunit1"), long(1)) - independent = Slice(Axis("ctype2", "cunit2"), long(2)) + dependent = wcs.Slice(wcs.Axis("ctype1", "cunit1"), long(1)) + independent = wcs.Slice(wcs.Axis("ctype2", "cunit2"), long(2)) - observable = ObservableAxis(dependent) + observable = chunk.ObservableAxis(dependent) self.assertEqual(observable.dependent, dependent) observable.independent = independent @@ -286,13 +181,13 @@ class TestSpatialWCS(unittest.TestCase): def test_init(self): - self.assertRaises(TypeError, SpatialWCS, None) - self.assertRaises(TypeError, SpatialWCS, int(1)) + self.assertRaises(TypeError, chunk.SpatialWCS, None) + self.assertRaises(TypeError, chunk.SpatialWCS, int(1)) - axis1 = Axis("ctype1", "cunit1") - axis2 = Axis("ctype2", "cunit2") - axis_2d = CoordAxis2D(axis1, axis2) - position = SpatialWCS(axis_2d) + axis1 = wcs.Axis("ctype1", "cunit1") + axis2 = wcs.Axis("ctype2", "cunit2") + axis_2d = wcs.CoordAxis2D(axis1, axis2) + position = chunk.SpatialWCS(axis_2d) self.assertEqual(position.axis, axis_2d) with self.assertRaises(TypeError): position.coordsys = float(1.0) @@ -314,16 +209,16 @@ class TestSpectralWCS(unittest.TestCase): def test_init(self): - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) - self.assertRaises(TypeError, SpectralWCS, None, None) - self.assertRaises(TypeError, SpectralWCS, None, str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, None) - self.assertRaises(TypeError, SpectralWCS, int(1), str("s")) - self.assertRaises(TypeError, SpectralWCS, axis_1d, int(1)) + self.assertRaises(TypeError, chunk.SpectralWCS, None, None) + self.assertRaises(TypeError, chunk.SpectralWCS, None, str("s")) + self.assertRaises(TypeError, chunk.SpectralWCS, axis_1d, None) + self.assertRaises(TypeError, chunk.SpectralWCS, int(1), str("s")) + self.assertRaises(TypeError, chunk.SpectralWCS, axis_1d, int(1)) - energy = SpectralWCS(axis_1d, "specsys") + energy = chunk.SpectralWCS(axis_1d, "specsys") self.assertEqual(energy.axis, axis_1d) self.assertEqual(energy.specsys, "specsys") with self.assertRaises(TypeError): @@ -369,7 +264,7 @@ def test_init(self): energy.bandpass_name = "bandpass_name" self.assertEqual(energy.bandpass_name, "bandpass_name") - transition = EnergyTransition("species", "transition") + transition = plane.EnergyTransition("species", "transition") energy.transition = transition self.assertEqual(energy.transition, transition) @@ -381,12 +276,12 @@ class TestTemporalWCS(unittest.TestCase): def test_init(self): - self.assertRaises(TypeError, TemporalWCS, None) - self.assertRaises(TypeError, TemporalWCS, int(1)) + self.assertRaises(TypeError, chunk.TemporalWCS, None) + self.assertRaises(TypeError, chunk.TemporalWCS, int(1)) - axis = Axis("ctype", "cunit") - axis_1d = CoordAxis1D(axis) - time = TemporalWCS(axis_1d) + axis = wcs.Axis("ctype", "cunit") + axis_1d = wcs.CoordAxis1D(axis) + time = chunk.TemporalWCS(axis_1d) self.assertEqual(time.axis, axis_1d) with self.assertRaises(TypeError): time.exposure = str("s") @@ -412,14 +307,10 @@ class TestPolarizationWCS(unittest.TestCase): def test_init(self): - self.assertRaises(TypeError, PolarizationWCS, None) - self.assertRaises(TypeError, PolarizationWCS, int(1)) + self.assertRaises(TypeError, chunk.PolarizationWCS, None) + self.assertRaises(TypeError, chunk.PolarizationWCS, int(1)) - axis = Axis('STOKES') - axis_1d = CoordAxis1D(axis) - polarization = PolarizationWCS(axis_1d) + axis = wcs.Axis('STOKES') + axis_1d = wcs.CoordAxis1D(axis) + polarization = chunk.PolarizationWCS(axis_1d) self.assertEqual(polarization.axis, axis_1d) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py index edd14d69..b8f40f3e 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -78,33 +77,28 @@ import shutil import unittest -from caom2tools.caom2.observation import CompositeObservation -from caom2tools.caom2.observation import SimpleObservation -from caom2tools.caom2.wcs import CoordCircle2D -from caom2tools.caom2.wcs import CoordPolygon2D -from caom2tools.caom2.obs_reader_writer import CAOM20_NAMESPACE -from caom2tools.caom2.obs_reader_writer import CAOM21_NAMESPACE -from caom2tools.caom2.obs_reader_writer import ObservationReader -from caom2tools.caom2.obs_reader_writer import ObservationWriter -from caom_test_instances import Caom2TestInstances +import caom_test_instances +from .. import obs_reader_writer +from .. import observation +from .. import wcs class TestObservationReaderWriter(unittest.TestCase): def test_invalid_long_id(self): print "Test Invalid long id " - observation = minimal_simple(1, False, 20) - writer = ObservationWriter( - False, False, "caom2", CAOM20_NAMESPACE) + simple_observation = minimal_simple(1, False, 20) + writer = obs_reader_writer.ObservationWriter( + False, False, "caom2", obs_reader_writer.CAOM20_NAMESPACE) output = StringIO.StringIO() - writer.write(observation, output) + writer.write(simple_observation, output) xml = output.getvalue() output.close() xml = xml.replace("caom2:id=\"", "caom2:id=\"x") f = open('/tmp/test.xml', 'w') f.write(xml) f.close() - reader = ObservationReader(False) + reader = obs_reader_writer.ObservationReader(False) try: reader.read('/tmp/test.xml') self.fail("invalid long id should throw ValueError") @@ -113,17 +107,17 @@ def test_invalid_long_id(self): def test_invalid_uuid(self): print "Test Invalid UUID id" - observation = minimal_simple(1, False, 21) - writer = ObservationWriter(False, False) # default writer is 2.1 + simple_observation = minimal_simple(1, False, 21) + writer = obs_reader_writer.ObservationWriter(False, False) # default writer is 2.1 output = StringIO.StringIO() - writer.write(observation, output) + writer.write(simple_observation, output) xml = output.getvalue() output.close() xml = xml.replace("0000", "xxxx", 1) f = open('/tmp/test.xml', 'w') f.write(xml) f.close() - reader = ObservationReader(False) + reader = obs_reader_writer.ObservationReader(False) try: reader.read('/tmp/test.xml') self.fail("invalid uuid id should throw ValueError") @@ -136,17 +130,17 @@ def test_minimal_simple(self): for i in range(1, 6): print "Test Minimal Simple {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D - observation = minimal_simple(i, True, version) + simple_observation = minimal_simple(i, True, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, simple_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, simple_observation, True, False, version) # CoordBounds2D as CoordPolygon2D - observation = minimal_simple(i, False, version) + simple_observation = minimal_simple(i, False, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, simple_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, simple_observation, True, False, version) def test_complete_simple(self): @@ -154,17 +148,17 @@ def test_complete_simple(self): for i in range(1, 6): print "Test Complete Simple {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D - observation = complete_simple(i, True, version) + simple_observation = complete_simple(i, True, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, simple_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, simple_observation, True, False, version) # CoordBounds2D as CoordPolygon2D - observation = complete_simple(i, False, version) + simple_observation = complete_simple(i, False, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, simple_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, simple_observation, True, False, version) def test_minimal_composite(self): @@ -172,17 +166,17 @@ def test_minimal_composite(self): for i in range(1, 6): print "Test Minimal Composite {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D - observation = minimal_composite(i, True, version) + composite_observation = minimal_composite(i, True, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, composite_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, composite_observation, True, False, version) # CoordBounds2D as CoordPolygon2D - observation = minimal_composite(i, False, version) + composite_observation = minimal_composite(i, False, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, composite_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, composite_observation, True, False, version) def test_complete_composite(self): @@ -190,40 +184,40 @@ def test_complete_composite(self): for i in range(1, 6): print "Test Complete Composite {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D - observation = complete_composite(i, True, version) + composite_observation = complete_composite(i, True, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, composite_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, composite_observation, True, False, version) # CoordBounds2D as CoordPolygon2D - observation = complete_composite(i, False, version) + composite_observation = complete_composite(i, False, version) # write empty elements - test_observation(self, observation, True, True, version) + test_observation(self, composite_observation, True, True, version) # do not write empty elements - test_observation(self, observation, True, False, version) + test_observation(self, composite_observation, True, False, version) def test_versions(self): - observation = complete_composite(6, True, 20) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) + composite_observation = complete_composite(6, True, 20) + test_observation(self, composite_observation, True, True, 20) + test_observation(self, composite_observation, True, True, 21) + test_observation(self, composite_observation, True, True, 22) - observation = complete_composite(6, True, 21) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) + composite_observation = complete_composite(6, True, 21) + test_observation(self, composite_observation, True, True, 20) + test_observation(self, composite_observation, True, True, 21) + test_observation(self, composite_observation, True, True, 22) - observation = complete_composite(6, True, 22) - test_observation(self, observation, True, True, 20) - test_observation(self, observation, True, True, 21) - test_observation(self, observation, True, True, 22) + composite_observation = complete_composite(6, True, 22) + test_observation(self, composite_observation, True, True, 20) + test_observation(self, composite_observation, True, True, 21) + test_observation(self, composite_observation, True, True, 22) class TestRoundTrip(unittest.TestCase): - TEST_FILE_SOURCE_DIR = '../caom2/test/data' + TEST_FILE_SOURCE_DIR = 'data' XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/pyCAOM2' + XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/caom2' def make_test_dir(self): try: @@ -233,8 +227,13 @@ def make_test_dir(self): raise def copy_files(self): + print glob.glob(os.path.join(TestRoundTrip. + TEST_FILE_SOURCE_DIR, + '*.xml')) for filename in glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, '*.xml')): + TEST_FILE_SOURCE_DIR, + '*.xml')): + print "copied file " + filename shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) def init(self): @@ -245,24 +244,23 @@ def cleanup(self): shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) def get_file_list(self): - return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR) \ + return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR) if f.endswith('.xml')] def do_test(self, reader, writer, filename): - sourceFilePath = (TestRoundTrip.XML_FILE_SOURCE_DIR + - '/' + filename) - print "test file: " + sourceFilePath - sourceXMLfp = open(sourceFilePath, 'r') - observation = reader.read(sourceFilePath) - sourceXMLfp.close() - destFilePath = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename - destXMLfp = open(destFilePath, 'w') - writer.write(observation, destXMLfp) - destXMLfp.close() - self.assertTrue(filecmp.cmp(sourceFilePath, destFilePath), + source_file_path = (TestRoundTrip.XML_FILE_SOURCE_DIR + '/' + filename) + print "test file: " + source_file_path + source_xml_fp = open(source_file_path, 'r') + obs = reader.read(source_file_path) + source_xml_fp.close() + dest_file_path = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename + dest_xml_fp = open(dest_file_path, 'w') + writer.write(obs, dest_xml_fp) + dest_xml_fp.close() + self.assertTrue(filecmp.cmp(source_file_path, dest_file_path), 'files are different, ' + - 'file from Java was: ' + sourceFilePath + ' ' - 'file from Python was: ' + destFilePath) + 'file from Java was: ' + source_file_path + ' ' + 'file from Python was: ' + dest_file_path) # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 @@ -284,10 +282,12 @@ def test_round_trip(self): if e.errno != errno.EEXIST: raise - reader = ObservationReader(True) - writer20 = ObservationWriter(True, False, "caom2", CAOM20_NAMESPACE) - writer21 = ObservationWriter(True, False, "caom2", CAOM21_NAMESPACE) - writer22 = ObservationWriter(True, False, "caom2") + reader = obs_reader_writer.ObservationReader(True) + writer20 = obs_reader_writer.ObservationWriter( + True, False, "caom2", obs_reader_writer.CAOM20_NAMESPACE) + writer21 = obs_reader_writer.ObservationWriter( + True, False, "caom2", obs_reader_writer.CAOM21_NAMESPACE) + writer22 = obs_reader_writer.ObservationWriter(True, False, "caom2") for filename in files: if filename.endswith("CAOM-2.2.xml"): self.do_test(reader, writer22, filename) @@ -304,7 +304,7 @@ def test_round_trip(self): def minimal_simple(depth, bounds_is_circle, version): - instances = Caom2TestInstances() + instances = caom_test_instances.Caom2TestInstances() instances.complete = False instances.depth = depth instances.bounds_is_circle = bounds_is_circle @@ -313,7 +313,7 @@ def minimal_simple(depth, bounds_is_circle, version): def complete_simple(depth, bounds_is_circle, version): - instances = Caom2TestInstances() + instances = caom_test_instances.Caom2TestInstances() instances.complete = True instances.depth = depth instances.bounds_is_circle = bounds_is_circle @@ -322,7 +322,7 @@ def complete_simple(depth, bounds_is_circle, version): def minimal_composite(depth, bounds_is_circle, version): - instances = Caom2TestInstances() + instances = caom_test_instances.Caom2TestInstances() instances.complete = False instances.depth = depth instances.bounds_is_circle = bounds_is_circle @@ -331,7 +331,7 @@ def minimal_composite(depth, bounds_is_circle, version): def complete_composite(depth, bounds_is_circle, version): - instances = Caom2TestInstances() + instances = caom_test_instances.Caom2TestInstances() instances.complete = True instances.depth = depth instances.bounds_is_circle = bounds_is_circle @@ -339,31 +339,35 @@ def complete_composite(depth, bounds_is_circle, version): return instances.get_composite_observation() -def test_observation(self, observation, validate, write_empty_collections, version): +def test_observation(self, obs, validate, write_empty_collections, version): if version == 20: - writer = ObservationWriter( - validate, write_empty_collections, "caom2", CAOM20_NAMESPACE) + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM20_NAMESPACE) elif version == 21: - writer = ObservationWriter( - validate, write_empty_collections, "caom2", CAOM21_NAMESPACE) + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM21_NAMESPACE) else: - writer = ObservationWriter(validate, write_empty_collections) - xmlfile = open('/tmp/test.xml', 'w') - writer.write(observation, xmlfile) - xmlfile.close() - reader = ObservationReader(True) + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections) + xml_file = open('/tmp/test.xml', 'w') + writer.write(obs, xml_file) + xml_file.close() + reader = obs_reader_writer.ObservationReader(True) returned = reader.read('/tmp/test.xml') - compare_observations(self, observation, returned, version) + compare_observations(self, obs, returned, version) def compare_observations(self, expected, actual, version): - assert ((isinstance(expected, SimpleObservation) and - isinstance(actual, SimpleObservation)) or - (isinstance(expected, CompositeObservation) and - isinstance(actual, CompositeObservation))), ( + assert ((isinstance(expected, observation.SimpleObservation) and + isinstance(actual, observation.SimpleObservation)) or + (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation))), ( "Observation types do not match 0 vs 1". - format(expected.__class__.__name__, actual.__class__.__name__)) + format(expected.__class__.__name__, + actual.__class__.__name__)) self.assertIsNotNone(expected.collection) self.assertIsNotNone(actual.collection) @@ -390,7 +394,8 @@ def compare_observations(self, expected, actual, version): self.assertEqual(expected.meta_release, actual.meta_release) compare_proposal(self, expected.proposal, actual.proposal) compare_target(self, expected.target, actual.target) - compare_target_position(self, expected.target_position, actual.target_position) + compare_target_position(self, expected.target_position, + actual.target_position) compare_telescope(self, expected.telescope, actual.telescope) compare_instrument(self, expected.instrument, actual.instrument) compare_environment(self, expected.environment, actual.environment) @@ -399,8 +404,8 @@ def compare_observations(self, expected, actual, version): compare_planes(self, expected.planes, actual.planes, version) - if (isinstance(expected, CompositeObservation) and - isinstance(actual, CompositeObservation)): + if (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation)): compare_members(self, expected.members, actual.members) @@ -541,9 +546,11 @@ def compare_planes(self, expected, actual, version): actual_plane.provenance) compare_metrics(self, expected_plane.metrics, actual_plane.metrics) if version == 21: - compare_quality(self, expected_plane.quality, actual_plane.quality) + compare_quality(self, expected_plane.quality, + actual_plane.quality) - compare_artifacts(self, expected_plane.artifacts, actual_plane.artifacts, version) + compare_artifacts(self, expected_plane.artifacts, + actual_plane.artifacts, version) def compare_provenance(self, expected, actual): @@ -565,7 +572,8 @@ def compare_metrics(self, expected, actual): return self.assertIsNotNone(expected) self.assertIsNotNone(actual) - self.assertEqual(expected.source_number_density, actual.source_number_density) + self.assertEqual(expected.source_number_density, + actual.source_number_density) self.assertEqual(expected.background, actual.background) self.assertEqual(expected.background_std_dev, actual.background_std_dev) self.assertEqual(expected.flux_density_limit, actual.flux_density_limit) @@ -607,14 +615,20 @@ def compare_artifacts(self, expected, actual, version): self.assertEqual(expected_artifact._id, actual_artifact._id) self.assertIsNotNone(expected_artifact._last_modified) self.assertIsNotNone(actual_artifact._last_modified) - self.assertEqual(expected_artifact._last_modified, actual_artifact._last_modified) + self.assertEqual(expected_artifact._last_modified, + actual_artifact._last_modified) self.assertEqual(expected_artifact.uri, actual_artifact.uri) - self.assertEqual(expected_artifact.content_type, actual_artifact.content_type) - self.assertEqual(expected_artifact.content_length, actual_artifact.content_length) - self.assertEqual(expected_artifact.product_type, actual_artifact.product_type) + self.assertEqual(expected_artifact.content_type, + actual_artifact.content_type) + self.assertEqual(expected_artifact.content_length, + actual_artifact.content_length) + self.assertEqual(expected_artifact.product_type, + actual_artifact.product_type) if version > 21: - self.assertEqual(expected_artifact.release_type, actual_artifact.release_type) - compare_parts(self, expected_artifact.parts, actual_artifact.parts, version) + self.assertEqual(expected_artifact.release_type, + actual_artifact.release_type) + compare_parts(self, expected_artifact.parts, + actual_artifact.parts, version) def compare_parts(self, expected, actual, version): @@ -672,7 +686,8 @@ def compare_chunks(self, expected, actual): actual_chunk.polarization_axis) compare_observable_axis(self, expected_chunk.observable, actual_chunk.observable) - compare_spatial_wcs(self, expected_chunk.position, actual_chunk.position) + compare_spatial_wcs(self, expected_chunk.position, + actual_chunk.position) compare_spectral_wcs(self, expected_chunk.energy, actual_chunk.energy) compare_temporal_wcs(self, expected_chunk.time, actual_chunk.time) compare_polarization_wcs(self, expected_chunk.polarization, @@ -811,11 +826,11 @@ def compare_coord_bounds2d(self, expected, actual): self.assertIsNone(actual) return self.assertIsNotNone(actual) - if (isinstance(expected, CoordCircle2D) and - isinstance(actual, CoordCircle2D)): + if (isinstance(expected, wcs.CoordCircle2D) and + isinstance(actual, wcs.CoordCircle2D)): compare_coord_circle2d(self, expected, actual) - elif (isinstance(expected, CoordPolygon2D) and - isinstance(actual, CoordPolygon2D)): + elif (isinstance(expected, wcs.CoordPolygon2D) and + isinstance(actual, wcs.CoordPolygon2D)): compare_coord_polygon2d(self, expected, actual) else: self.fail("CoordBounds2D expected and actual are different types.") @@ -946,7 +961,3 @@ def compare_point(self, expected, actual): self.assertIsNotNone(actual.cval2) self.assertEqual(expected.cval1, actual.cval1) self.assertEqual(expected.cval2, actual.cval2) - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/test/test_observation.py b/caom2tools/caom2/test/test_observation.py index a959e1ee..7724c274 100644 --- a/caom2tools/caom2/test/test_observation.py +++ b/caom2tools/caom2/test/test_observation.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -73,68 +72,54 @@ import unittest from datetime import datetime -from caom2tools.caom2.shape import Point -from caom2tools.caom2.observation import Algorithm -from caom2tools.caom2.observation import CompositeObservation -from caom2tools.caom2.observation import Environment -from caom2tools.caom2.observation import Instrument -from caom2tools.caom2.observation import Observation -from caom2tools.caom2.observation import ObservationIntentType -from caom2tools.caom2.observation import ObservationURI -from caom2tools.caom2.observation import Proposal -from caom2tools.caom2.observation import Requirements -from caom2tools.caom2.observation import SimpleObservation -from caom2tools.caom2.observation import Status -from caom2tools.caom2.observation import Target -from caom2tools.caom2.observation import TargetPosition -from caom2tools.caom2.observation import TargetType -from caom2tools.caom2.observation import Telescope -from caom2tools.caom2.plane import Plane -from caom2tools.caom2.caom_util import Util +from .. import caom_util +from .. import observation +from .. import plane +from .. import shape class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(ObservationIntentType.get("no_such_string"), None) - self.assertRaises(AttributeError, ObservationIntentType.get, None) - self.assertRaises(AttributeError, ObservationIntentType.get, 1) + self.assertEqual(observation.ObservationIntentType.get("no_such_string"), None) + self.assertRaises(AttributeError, observation.ObservationIntentType.get, None) + self.assertRaises(AttributeError, observation.ObservationIntentType.get, 1) - self.assertEqual(Status.get("no_such_string"), None) - self.assertRaises(AttributeError, Status.get, None) - self.assertRaises(AttributeError, Status.get, 1) + self.assertEqual(observation.Status.get("no_such_string"), None) + self.assertRaises(AttributeError, observation.Status.get, None) + self.assertRaises(AttributeError, observation.Status.get, 1) - self.assertEqual(TargetType.get("no_such_string"), None) - self.assertRaises(AttributeError, TargetType.get, None) - self.assertRaises(AttributeError, TargetType.get, 1) + self.assertEqual(observation.TargetType.get("no_such_string"), None) + self.assertRaises(AttributeError, observation.TargetType.get, None) + self.assertRaises(AttributeError, observation.TargetType.get, 1) # test that we can get the object for each enum by name - self.assertEqual(ObservationIntentType.CALIBRATION.value, "calibration") - self.assertEqual(ObservationIntentType.SCIENCE.value, "science") + self.assertEqual(observation.ObservationIntentType.CALIBRATION.value, "calibration") + self.assertEqual(observation.ObservationIntentType.SCIENCE.value, "science") - self.assertEqual(Status.FAIL.value, "fail") + self.assertEqual(observation.Status.FAIL.value, "fail") - self.assertEqual(TargetType.FIELD.value, "field") - self.assertEqual(TargetType.OBJECT.value, "object") + self.assertEqual(observation.TargetType.FIELD.value, "field") + self.assertEqual(observation.TargetType.OBJECT.value, "object") class TestObservation(unittest.TestCase): def test_all(self): - algorithm = Algorithm("myAlg") - obs = Observation("GSA", "A12345", algorithm) + algorithm = observation.Algorithm("myAlg") + obs = observation.Observation("GSA", "A12345", algorithm) self.assertEqual("GSA", obs.collection, "Collection") self.assertEqual("A12345", obs.observation_id, "Observation ID") self.assertEqual(algorithm, obs.algorithm, "Algorithm") - new_algorithm = Algorithm("myNewAlg") + new_algorithm = observation.Algorithm("myNewAlg") obs.algorithm = new_algorithm self.assertEquals(new_algorithm, obs.algorithm, "New algorithm") self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, obs.intent, "Observation intent") self.assertIsNone(obs.obs_type, "Default obs_type") @@ -143,40 +128,40 @@ def test_all(self): obs.obs_type, "obs type") self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") + proposal = observation.Proposal("ABC") obs.proposal = proposal self.assertEqual(proposal, obs.proposal, "Proposal") self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") + telescope = observation.Telescope("GSAGN") obs.telescope = telescope self.assertEqual(telescope, obs.telescope, "Telescope") self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") + instrument = observation.Instrument("NIRI") obs.instrument = instrument self.assertEqual(instrument, obs.instrument, "Instrument") self.assertIsNone(obs.target, "Default target") - target = Target("TGT") + target = observation.Target("TGT") obs.target = target self.assertEqual(target, obs.target, "Target") self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") obs.target_position = target_position self.assertEqual(target_position, obs.target_position, "TargetPosition") self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) + requirements = observation.Requirements(observation.Status.FAIL) obs.requirements = requirements self.assertEqual(requirements, obs.requirements, "Requirements") self.assertIsNone(obs.environment, "Default environment") - environment = Environment() + environment = observation.Environment() obs.environment = environment self.assertEqual(environment, obs.environment, "Environment") @@ -188,63 +173,64 @@ def test_all(self): obs.meta_release, "Metadata release") self.assertEqual(0, len(obs.planes), "Default planes") - plane1 = Plane("myPlaneID") + plane1 = plane.Plane("myPlaneID") obs.planes["myPlaneID"] = plane1 self.assertEqual(1, len(obs.planes), "Planes") self.assertTrue("myPlaneID" in obs.planes.keys()) - plane2 = Plane("myPlaneID2") + plane2 = plane.Plane("myPlaneID2") obs.planes["myPlaneID2"] = plane2 self.assertEqual(2, len(obs.planes), "Planes") self.assertTrue("myPlaneID" in obs.planes) self.assertTrue("myPlaneID2" in obs.planes.keys()) # test duplicates - plane3 = Plane("myPlaneID2") + plane3 = plane.Plane("myPlaneID2") obs.planes["myPlaneID2"] = plane3 self.assertEqual(2, len(obs.planes), "Planes") self.assertTrue("myPlaneID" in obs.planes) self.assertTrue("myPlaneID2" in obs.planes.keys()) - obs2 = Observation(obs.collection, - obs.observation_id, - obs.algorithm, - planes=obs.planes, - sequence_number=obs.sequence_number, - intent=obs.intent, - obs_type=obs.obs_type, - proposal=obs.proposal, - telescope=obs.telescope, - instrument=obs.instrument, - target=obs.target, - meta_release=obs.meta_release, - environment=obs.environment, - target_position=obs.target_position) + obs2 = observation.Observation( + obs.collection, + obs.observation_id, + obs.algorithm, + planes=obs.planes, + sequence_number=obs.sequence_number, + intent=obs.intent, + obs_type=obs.obs_type, + proposal=obs.proposal, + telescope=obs.telescope, + instrument=obs.instrument, + target=obs.target, + meta_release=obs.meta_release, + environment=obs.environment, + target_position=obs.target_position) class TestObservationURI(unittest.TestCase): def test_all(self): - obsURI = ObservationURI("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", obsURI.uri, "Observation URI") - self.assertEqual("GEMINI", obsURI.collection, "Collection") - self.assertEqual("12345", obsURI.observation_id, "Observation ID") + obs_uri = observation.ObservationURI("caom:GEMINI/12345") + self.assertEqual("caom:GEMINI/12345", obs_uri.uri, "Observation URI") + self.assertEqual("GEMINI", obs_uri.collection, "Collection") + self.assertEqual("12345", obs_uri.observation_id, "Observation ID") - obsURI = ObservationURI.get_observation_uri("CFHT", "654321") - self.assertEqual("caom:CFHT/654321", obsURI.uri, "Observation URI") - self.assertEqual("CFHT", obsURI.collection, "Collection") - self.assertEqual("654321", obsURI.observation_id, "Observation ID") + obs_uri = observation.ObservationURI.get_observation_uri("CFHT", "654321") + self.assertEqual("caom:CFHT/654321", obs_uri.uri, "Observation URI") + self.assertEqual("CFHT", obs_uri.collection, "Collection") + self.assertEqual("654321", obs_uri.observation_id, "Observation ID") exception = False try: - obsURI = ObservationURI.get_observation_uri(None, "123") + obs_uri = observation.ObservationURI.get_observation_uri(None, "123") except TypeError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - obsURI = ObservationURI.get_observation_uri("GEMINI", None) + obs_uri = observation.ObservationURI.get_observation_uri("GEMINI", None) except TypeError: exception = True self.assertTrue(exception, "Missing exception") @@ -253,8 +239,8 @@ def test_all(self): class TestSimpleObservation(unittest.TestCase): def test_all(self): - algorithm = SimpleObservation._ALGORITHM - obs = SimpleObservation("GSA", "A12345") + algorithm = observation.SimpleObservation._ALGORITHM + obs = observation.SimpleObservation("GSA", "A12345") self.assertEqual("GSA", obs.collection, "Collection") self.assertEqual("A12345", obs.observation_id, "Observation ID") @@ -265,15 +251,15 @@ def test_all(self): # try to set algorithm exception = False try: - obs.algorithm = Algorithm("myAlg") + obs.algorithm = observation.Algorithm("myAlg") except ValueError: exception = True self.assertTrue(exception, "Missing exception") # run the rest of the Observation tests self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, obs.intent, "Observation intent") self.assertIsNone(obs.obs_type, "Default obs_type") @@ -282,43 +268,43 @@ def test_all(self): obs.obs_type, "obs type") self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") + proposal = observation.Proposal("ABC") obs.proposal = proposal self.assertEqual(proposal, obs.proposal, "Proposal") self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") + telescope = observation.Telescope("GSAGN") obs.telescope = telescope self.assertEqual(telescope, obs.telescope, "Telescope") self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") + instrument = observation.Instrument("NIRI") obs.instrument = instrument self.assertEqual(instrument, obs.instrument, "Instrument") self.assertIsNone(obs.target, "Default target") - target = Target("TGT") + target = observation.Target("TGT") obs.target = target self.assertEqual(target, obs.target, "Target") self.assertIsNone(obs.environment, "Default environment") - environment = Environment() + environment = observation.Environment() obs.environment = environment self.assertEqual(environment, obs.environment, "Environment") self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") obs.target_position = target_position self.assertEqual(target_position, obs.target_position, "TargetPosition") self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) + requirements = observation.Requirements(observation.Status.FAIL) obs.requirements = requirements self.assertEquals(requirements, obs.requirements, "requirements") @@ -331,38 +317,39 @@ def test_all(self): # Test the complete constructor def test_complete_init(self): collection = str("CFHT") - observationID = str("543210") - algorithm = SimpleObservation._ALGORITHM + observation_id = str("543210") + algorithm = observation.SimpleObservation._ALGORITHM sequence_number = int(3) - intent = ObservationIntentType.SCIENCE + intent = observation.ObservationIntentType.SCIENCE obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") + proposal = observation.Proposal("123") + telescope = observation.Telescope("TEL") + instrument = observation.Instrument("INST") + target = observation.Target("LMC") meta_release = datetime.now() - planes = Util.TypedOrderedDict((Plane),) - environment = Environment() - - obs = SimpleObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment) + planes = caom_util.TypedOrderedDict(plane.Plane,) + environment = observation.Environment() + + obs = observation.SimpleObservation( + collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment) self.assertIsNotNone(obs.collection, "Collection") self.assertEqual(collection, obs.collection, "Collection") self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") + self.assertEqual(observation_id, obs.observation_id, "Observation ID") self.assertIsNotNone(obs.algorithm, "Algorithm") self.assertEqual(algorithm, obs.algorithm, "Algorithm") @@ -398,8 +385,8 @@ def test_complete_init(self): class TestCompositeObservation(unittest.TestCase): def test_all(self): - algorithm = Algorithm("mozaic") - obs = CompositeObservation("GSA", "A12345", algorithm) + algorithm = observation.Algorithm("mozaic") + obs = observation.CompositeObservation("GSA", "A12345", algorithm) self.assertEqual("GSA", obs.collection, "Collection") self.assertEqual("A12345", obs.observation_id, "Observation ID") self.assertEqual(algorithm, obs.algorithm, "Algorithm") @@ -409,7 +396,7 @@ def test_all(self): # try to set algorithm to an invalid value exception = False try: - obs.algorithm = SimpleObservation._ALGORITHM + obs.algorithm = observation.SimpleObservation._ALGORITHM except ValueError: exception = True self.assertTrue(exception, "Missing exception") @@ -423,28 +410,28 @@ def test_all(self): self.assertTrue(exception, "Missing exception") self.assertEqual(0, len(obs.members), "Members") - observationURI1 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI1) + observation_uri1 = observation.ObservationURI("caom:collection/obsID") + obs.members.add(observation_uri1) self.assertEqual(1, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) + self.assertTrue(observation_uri1 in obs.members) - observationURI2 = ObservationURI("caom:collection/obsID2") - obs.members.add(observationURI2) + observation_uri2 = observation.ObservationURI("caom:collection/obsID2") + obs.members.add(observation_uri2) self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) + self.assertTrue(observation_uri1 in obs.members) + self.assertTrue(observation_uri2 in obs.members) #duplicates - observationURI3 = ObservationURI("caom:collection/obsID") - obs.members.add(observationURI3) + observation_uri3 = observation.ObservationURI("caom:collection/obsID") + obs.members.add(observation_uri3) self.assertEqual(2, len(obs.members), "Members") - self.assertTrue(observationURI1 in obs.members) - self.assertTrue(observationURI2 in obs.members) + self.assertTrue(observation_uri1 in obs.members) + self.assertTrue(observation_uri2 in obs.members) # run the rest of the Observation tests self.assertIsNone(obs.intent, "Default intent") - obs.intent = ObservationIntentType.CALIBRATION - self.assertEqual(ObservationIntentType.CALIBRATION, + obs.intent = observation.ObservationIntentType.CALIBRATION + self.assertEqual(observation.ObservationIntentType.CALIBRATION, obs.intent, "Observation intent") self.assertIsNone(obs.obs_type, "Default obs_type") @@ -453,43 +440,43 @@ def test_all(self): obs.obs_type, "obs type") self.assertIsNone(obs.proposal, "Default proposal") - proposal = Proposal("ABC") + proposal = observation.Proposal("ABC") obs.proposal = proposal self.assertEqual(proposal, obs.proposal, "Proposal") self.assertIsNone(obs.telescope, "Default telescope") - telescope = Telescope("GSAGN") + telescope = observation.Telescope("GSAGN") obs.telescope = telescope self.assertEqual(telescope, obs.telescope, "Telescope") self.assertIsNone(obs.instrument, "Default instrument") - instrument = Instrument("NIRI") + instrument = observation.Instrument("NIRI") obs.instrument = instrument self.assertEqual(instrument, obs.instrument, "Instrument") self.assertIsNone(obs.target, "Default target") - target = Target("TGT") + target = observation.Target("TGT") obs.target = target self.assertEqual(target, obs.target, "Target") self.assertIsNone(obs.environment, "Default environment") - environment = Environment() + environment = observation.Environment() obs.environment = environment self.assertEqual(environment, obs.environment, "Environment") self.assertIsNone(obs.target_position, "Default target position") - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") obs.target_position = target_position self.assertEqual(target_position, obs.target_position, "TargetPosition") self.assertIsNone(obs.requirements, "Default requirements") - requirements = Requirements(Status.FAIL) + requirements = observation.Requirements(observation.Status.FAIL) obs.requirements = requirements self.assertEquals(requirements, obs.requirements, "requirements") @@ -502,40 +489,41 @@ def test_all(self): # Test the complete constructor def test_complete_init(self): collection = str("CFHT") - observationID = str("543210") + observation_id = str("543210") algorithm = str("algo") sequence_number = int(3) - intent = ObservationIntentType.SCIENCE + intent = observation.ObservationIntentType.SCIENCE obs_type = str("foo") - proposal = Proposal("123") - telescope = Telescope("TEL") - instrument = Instrument("INST") - target = Target("LMC") + proposal = observation.Proposal("123") + telescope = observation.Telescope("TEL") + instrument = observation.Instrument("INST") + target = observation.Target("LMC") meta_release = datetime.now() - planes = Util.TypedOrderedDict((Plane),) - environment = Environment() - target_position = TargetPosition(Point(1.0, 2.0), "coordsys") - - obs = CompositeObservation(collection, - observationID, - algorithm, - sequence_number, - intent, - obs_type, - proposal, - telescope, - instrument, - target, - meta_release, - planes, - environment, - target_position) + planes = caom_util.TypedOrderedDict(plane.Plane,) + environment = observation.Environment() + target_position = observation.TargetPosition(shape.Point(1.0, 2.0), "coordsys") + + obs = observation.CompositeObservation( + collection, + observation_id, + algorithm, + sequence_number, + intent, + obs_type, + proposal, + telescope, + instrument, + target, + meta_release, + planes, + environment, + target_position) self.assertIsNotNone(obs.collection, "Collection") self.assertEqual(collection, obs.collection, "Collection") self.assertIsNotNone(obs.observation_id, "Observation ID") - self.assertEqual(observationID, obs.observation_id, "Observation ID") + self.assertEqual(observation_id, obs.observation_id, "Observation ID") self.assertIsNotNone(obs.algorithm, "Algorithm") self.assertEqual(algorithm, obs.algorithm, "Algorithm") @@ -582,14 +570,14 @@ def test_complete_init(self): class TestAlgorithm(unittest.TestCase): def test_all(self): - algorithm = Algorithm("myAlgorithm") + algorithm = observation.Algorithm("myAlgorithm") self.assertEqual("myAlgorithm", algorithm.name, "Algorithm name") class TestEnvironment(unittest.TestCase): def test_all(self): - environment = Environment() + environment = observation.Environment() self.assertIsNone(environment.seeing, "Default seeing") environment.seeing = 123.321 @@ -619,7 +607,7 @@ def test_all(self): class TestIntrument(unittest.TestCase): def test_all(self): - instrument = Instrument("myInstrument") + instrument = observation.Instrument("myInstrument") self.assertEqual("myInstrument", instrument.name, "Instrument name") self.assertEqual(0, len(instrument.keywords), "Default number of keywords") @@ -635,7 +623,7 @@ def test_all(self): class TestProposal(unittest.TestCase): def test_all(self): - proposal = Proposal("myProposal") + proposal = observation.Proposal("myProposal") self.assertEqual("myProposal", proposal.proposal_id, "Proposal ID") self.assertEqual(0, len(proposal.keywords), "Default number of keywords") proposal.keywords.add("optical") @@ -655,20 +643,20 @@ def test_all(self): class TestRequirements(unittest.TestCase): def test_all(self): - self.assertRaises(TypeError, Requirements, "string") - requirements = Requirements(Status.FAIL) - self.assertEqual(Status.FAIL, requirements.flag, + self.assertRaises(TypeError, observation.Requirements, "string") + requirements = observation.Requirements(observation.Status.FAIL) + self.assertEqual(observation.Status.FAIL, requirements.flag, "Requirements flag") class TestTarget(unittest.TestCase): def test_all(self): - target = Target("myTarget") + target = observation.Target("myTarget") self.assertEqual("myTarget", target.name, "target name") - target.target_type = TargetType.FIELD - self.assertEqual(TargetType.FIELD, target.target_type, "target type") + target.target_type = observation.TargetType.FIELD + self.assertEqual(observation.TargetType.FIELD, target.target_type, "target type") self.assertEqual(0, len(target.keywords), "Default number of keywords") target.keywords.add("optical") @@ -687,9 +675,9 @@ def test_all(self): target.moving = True self.assertTrue(target.moving, "Moving") - target = Target("myOtherTarget", TargetType.OBJECT, False, 1.2, {"radio"}, False) + target = observation.Target("myOtherTarget", observation.TargetType.OBJECT, False, 1.2, {"radio"}, False) self.assertEquals("myOtherTarget", target.name, "target name") - self.assertEquals(TargetType.OBJECT, target.target_type, "target type") + self.assertEquals(observation.TargetType.OBJECT, target.target_type, "target type") self.assertFalse(target.standard, "Standard") self.assertEquals(1.2, target.redshift, "Redshift") self.assertEquals(1, len(target.keywords), "Keywords") @@ -700,9 +688,9 @@ def test_all(self): class TestTargetPosition(unittest.TestCase): def test_all(self): - self.assertRaises(TypeError, TargetPosition, "string") - point = Point(1.0, 2.0) - target_position = TargetPosition(point, "coordsys") + self.assertRaises(TypeError, observation.TargetPosition, "string") + point = shape.Point(1.0, 2.0) + target_position = observation.TargetPosition(point, "coordsys") self.assertIsNotNone(target_position.coordinates, "target position coordinates") self.assertEqual(point.cval1, target_position.coordinates.cval1, @@ -715,7 +703,7 @@ def test_all(self): self.assertIsNone(target_position.equinox, "target position equinox") - target_position = TargetPosition(point, "coordsys", 1.0) + target_position = observation.TargetPosition(point, "coordsys", 1.0) self.assertIsNotNone(target_position.equinox, "target position equinox") self.assertEqual(1.0, target_position.equinox, @@ -725,7 +713,7 @@ def test_all(self): class TestTelescope(unittest.TestCase): def test_all(self): - telescope = Telescope("myTelescope") + telescope = observation.Telescope("myTelescope") self.assertEqual("myTelescope", telescope.name, "telescope name") self.assertEqual(0, len(telescope.keywords), "Default number of keywords") @@ -744,8 +732,3 @@ def test_all(self): self.assertIsNone(telescope.geo_location_z, "Default geo location z") telescope.geo_location_z = 12.12 self.assertEqual(12.12, telescope.geo_location_z, "Geo location z") - - - -if __name__ == '__main__': - unittest.main() diff --git a/caom2tools/caom2/test/test_part.py b/caom2tools/caom2/test/test_part.py index c60268f7..026c9bef 100644 --- a/caom2tools/caom2/test/test_part.py +++ b/caom2tools/caom2/test/test_part.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -72,46 +71,27 @@ import unittest -from caom2tools.caom2.artifact import ProductType -from caom2tools.caom2.chunk import Chunk -from caom2tools.caom2.part import Part +from .. import artifact +from .. import chunk +from .. import part class TestPart(unittest.TestCase): - def testInit(self): + def test_init(self): - self.assertRaises(TypeError, Part, long(1)) + self.assertRaises(TypeError, part.Part, long(1)) - part = Part("partName") - self.assertEquals("partName", part.name, "Part name") - self.assertIsNone(part.product_type) - self.assertTrue(len(part.chunks) == 0) + test_part = part.Part("partName") + self.assertEquals("partName", test_part.name, "Part name") + self.assertIsNone(test_part.product_type) + self.assertTrue(len(test_part.chunks) == 0) - part.product_type = ProductType.SCIENCE - self.assertEqual(ProductType.SCIENCE, part.product_type) - - chunk = Chunk() - chunk.naxis = 5 - part.chunks.append(chunk) - self.assertTrue(len(part.chunks) == 1) - self.assertEqual(chunk, part.chunks.pop()) - -# # the set prevents adding the same object multiple times ... -# chunk_alias = chunk -# part.chunks.add(chunk_alias) -# part.chunks.add(chunk_alias) -# part.chunks.add(chunk_alias) -# self.assertTrue(len(part.chunks) == 1) -# -# # ... but everything else is not a duplicate -# chunk = Chunk() -# chunk.naxis = 33 -# part.chunks.add(chunk) -# self.assertTrue(len(part.chunks) == 2) - - - -if __name__ == '__main__': - unittest.main() + test_part.product_type = artifact.ProductType.SCIENCE + self.assertEqual(artifact.ProductType.SCIENCE, test_part.product_type) + test_chunk = chunk.Chunk() + test_chunk.naxis = 5 + test_part.chunks.append(test_chunk) + self.assertTrue(len(test_part.chunks) == 1) + self.assertEqual(test_chunk, test_part.chunks.pop()) diff --git a/caom2tools/caom2/test/test_plane.py b/caom2tools/caom2/test/test_plane.py index b16ac53d..7c46c71a 100644 --- a/caom2tools/caom2/test/test_plane.py +++ b/caom2tools/caom2/test/test_plane.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -73,155 +72,146 @@ import unittest from datetime import datetime -from caom2tools.caom2.artifact import Artifact -from caom2tools.caom2.artifact import ProductType, ReleaseType -from caom2tools.caom2.observation import ObservationURI -from caom2tools.caom2.plane import CalibrationLevel -from caom2tools.caom2.plane import DataProductType -from caom2tools.caom2.plane import DataQuality -from caom2tools.caom2.plane import Energy -from caom2tools.caom2.plane import EnergyBand -from caom2tools.caom2.plane import EnergyTransition -from caom2tools.caom2.plane import Metrics -from caom2tools.caom2.plane import Plane -from caom2tools.caom2.plane import PlaneURI -from caom2tools.caom2.plane import Polarization -from caom2tools.caom2.plane import PolarizationState -from caom2tools.caom2.plane import Position -from caom2tools.caom2.plane import Provenance -from caom2tools.caom2.plane import Quality -from caom2tools.caom2.plane import Time +from .. import artifact +from .. import observation +from .. import plane class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(CalibrationLevel.get(999), None) - self.assertRaises(AttributeError, CalibrationLevel.get, None) - self.assertRaises(AttributeError, CalibrationLevel.get, "foo") + self.assertEqual(plane.CalibrationLevel.get("no_such_string"), None) + self.assertRaises(AttributeError, plane.CalibrationLevel.get, None) + self.assertRaises(AttributeError, plane.CalibrationLevel.get, 999) - self.assertEqual(DataProductType.get("no_such_string"), None) - self.assertRaises(AttributeError, DataProductType.get, None) - self.assertRaises(AttributeError, DataProductType.get, 1) + self.assertEqual(plane.DataProductType.get("no_such_string"), None) + self.assertRaises(AttributeError, plane.DataProductType.get, None) + self.assertRaises(AttributeError, plane.DataProductType.get, 1) - self.assertEqual(EnergyBand.get("no_such_string"), None) - self.assertRaises(AttributeError, EnergyBand.get, None) - self.assertRaises(AttributeError, EnergyBand.get, 1) + self.assertEqual(plane.EnergyBand.get("no_such_string"), None) + self.assertRaises(AttributeError, plane.EnergyBand.get, None) + self.assertRaises(AttributeError, plane.EnergyBand.get, 1) - self.assertEqual(PolarizationState.get("no_such_string"), None) - self.assertRaises(AttributeError, PolarizationState.get, None) - self.assertRaises(AttributeError, PolarizationState.get, 1) + self.assertEqual(plane.PolarizationState.get("no_such_string"), None) + self.assertRaises(AttributeError, plane.PolarizationState.get, None) + self.assertRaises(AttributeError, plane.PolarizationState.get, 1) - self.assertEqual(Quality.get("no_such_string"), None) - self.assertRaises(AttributeError, Quality.get, None) - self.assertRaises(AttributeError, Quality.get, 1) + self.assertEqual(plane.Quality.get("no_such_string"), None) + self.assertRaises(AttributeError, plane.Quality.get, None) + self.assertRaises(AttributeError, plane.Quality.get, 1) # test that we can get the object for each enum by name - self.assertEqual(CalibrationLevel.RAW_INSTRUMENT.value, 0) - self.assertEqual(CalibrationLevel.RAW_STANDARD.value, 1) - self.assertEqual(CalibrationLevel.CALIBRATED.value, 2) - self.assertEqual(CalibrationLevel.PRODUCT.value, 3) - - self.assertEqual(DataProductType.IMAGE.value, "image") - self.assertEqual(DataProductType.CATALOG.value, "catalog") - self.assertEqual(DataProductType.CUBE.value, "cube") - self.assertEqual(DataProductType.EVENTLIST.value, "eventlist") - self.assertEqual(DataProductType.SPECTRUM.value, "spectrum") - self.assertEqual(DataProductType.TIMESERIES.value, "timeseries") - self.assertEqual(DataProductType.VISIBILITY.value, "visibility") - - self.assertEqual(EnergyBand.get('RADIO').value, "Radio") - self.assertEqual(EnergyBand.get('MILLIMETER').value, "Millimeter") - self.assertEqual(EnergyBand.get('INFRARED').value, "Infrared") - self.assertEqual(EnergyBand.get('OPTICAL').value, "Optical") - self.assertEqual(EnergyBand.get('UV').value, "UV") - self.assertEqual(EnergyBand.get('EUV').value, "EUV") - self.assertEqual(EnergyBand.get('XRAY').value, "X-ray") - self.assertEqual(EnergyBand.get('GAMMARAY').value, "Gamma-ray") - - self.assertEqual(PolarizationState.get('I').value, "I") - self.assertEqual(PolarizationState.get('Q').value, "Q") - self.assertEqual(PolarizationState.get('U').value, "U") - self.assertEqual(PolarizationState.get('V').value, "V") - self.assertEqual(PolarizationState.get('LL').value, "LL") - self.assertEqual(PolarizationState.get('LR').value, "LR") - self.assertEqual(PolarizationState.get('RL').value, "RL") - self.assertEqual(PolarizationState.get('RR').value, "RR") - self.assertEqual(PolarizationState.get('XX').value, "XX") - self.assertEqual(PolarizationState.get('XY').value, "XY") - self.assertEqual(PolarizationState.get('YX').value, "YX") - self.assertEqual(PolarizationState.get('YY').value, "YY") - - self.assertEqual(Quality.get('JUNK').value, "junk") + self.assertEqual(plane.CalibrationLevel.RAW_INSTRUMENT.value, 0) + self.assertEqual(plane.CalibrationLevel.RAW_STANDARD.value, 1) + self.assertEqual(plane.CalibrationLevel.CALIBRATED.value, 2) + self.assertEqual(plane.CalibrationLevel.PRODUCT.value, 3) + + self.assertEqual(plane.DataProductType.IMAGE.value, "image") + self.assertEqual(plane.DataProductType.CATALOG.value, "catalog") + self.assertEqual(plane.DataProductType.CUBE.value, "cube") + self.assertEqual(plane.DataProductType.EVENTLIST.value, "eventlist") + self.assertEqual(plane.DataProductType.SPECTRUM.value, "spectrum") + self.assertEqual(plane.DataProductType.TIMESERIES.value, "timeseries") + self.assertEqual(plane.DataProductType.VISIBILITY.value, "visibility") + + self.assertEqual(plane.EnergyBand.get('RADIO').value, "Radio") + self.assertEqual(plane.EnergyBand.get('MILLIMETER').value, "Millimeter") + self.assertEqual(plane.EnergyBand.get('INFRARED').value, "Infrared") + self.assertEqual(plane.EnergyBand.get('OPTICAL').value, "Optical") + self.assertEqual(plane.EnergyBand.get('UV').value, "UV") + self.assertEqual(plane.EnergyBand.get('EUV').value, "EUV") + self.assertEqual(plane.EnergyBand.get('XRAY').value, "X-ray") + self.assertEqual(plane.EnergyBand.get('GAMMARAY').value, "Gamma-ray") + + self.assertEqual(plane.PolarizationState.get('I').value, "I") + self.assertEqual(plane.PolarizationState.get('Q').value, "Q") + self.assertEqual(plane.PolarizationState.get('U').value, "U") + self.assertEqual(plane.PolarizationState.get('V').value, "V") + self.assertEqual(plane.PolarizationState.get('LL').value, "LL") + self.assertEqual(plane.PolarizationState.get('LR').value, "LR") + self.assertEqual(plane.PolarizationState.get('RL').value, "RL") + self.assertEqual(plane.PolarizationState.get('RR').value, "RR") + self.assertEqual(plane.PolarizationState.get('XX').value, "XX") + self.assertEqual(plane.PolarizationState.get('XY').value, "XY") + self.assertEqual(plane.PolarizationState.get('YX').value, "YX") + self.assertEqual(plane.PolarizationState.get('YY').value, "YY") + + self.assertEqual(plane.Quality.get('JUNK').value, "junk") class TestPlane(unittest.TestCase): def test_all(self): - plane = Plane("ProdID") - self.assertEqual("ProdID", plane.product_id, "Product ID") - self.assertEqual(0, len(plane.artifacts), + test_plane = plane.Plane("ProdID") + self.assertEqual("ProdID", test_plane.product_id, "Product ID") + self.assertEqual(0, len(test_plane.artifacts), "Default number of artifacts") - self.assertIsNone(plane.meta_release, "Default meta release date") + self.assertIsNone(test_plane.meta_release, "Default meta release date") date_now = datetime.now() - plane.meta_release = date_now - self.assertEqual(date_now, plane.meta_release, "Metadata release date") - self.assertIsNone(plane.data_release, "Default data release date") + test_plane.meta_release = date_now + self.assertEqual(date_now, test_plane.meta_release, "Metadata release date") + self.assertIsNone(test_plane.data_release, "Default data release date") date_now = datetime.now() - plane.data_release = date_now - self.assertEqual(date_now, plane.data_release, "Data release date") - self.assertIsNone(plane.data_product_type, "Default data product type") - plane.data_product_type = DataProductType.IMAGE - self.assertEqual(DataProductType.IMAGE, plane.data_product_type, + test_plane.data_release = date_now + self.assertEqual(date_now, test_plane.data_release, "Data release date") + self.assertIsNone(test_plane.data_product_type, "Default data product type") + test_plane.data_product_type = plane.DataProductType.IMAGE + self.assertEqual(plane.DataProductType.IMAGE, test_plane.data_product_type, "Data product type") - self.assertIsNone(plane.calibration_level, + self.assertIsNone(test_plane.calibration_level, "Default calibration level") - plane.calibration_level = CalibrationLevel.CALIBRATED - self.assertEqual(CalibrationLevel.CALIBRATED, - plane.calibration_level, "CalibrationLevel") - self.assertIsNone(plane.quality, + test_plane.calibration_level = plane.CalibrationLevel.CALIBRATED + self.assertEqual(plane.CalibrationLevel.CALIBRATED, + test_plane.calibration_level, "plane.CalibrationLevel") + self.assertIsNone(test_plane.quality, "Default quality") - quality = DataQuality(Quality.JUNK) - plane.quality = quality + quality = plane.DataQuality(plane.Quality.JUNK) + test_plane.quality = quality self.assertEqual(quality, - plane.quality, "Quality") - self.assertIsNone(plane.provenance, "Default provenance") - provenance = Provenance("myProv") - plane.provenance = provenance - self.assertEqual("myProv", plane.provenance.name, "Provenance - name") - self.assertIsNone(plane.metrics, "Default metrics") - metrics = Metrics() - plane.metrics = metrics - self.assertEqual(metrics, plane.metrics, "Provenance - metrics") + test_plane.quality, "plane.Quality") + self.assertIsNone(test_plane.provenance, "Default provenance") + provenance = plane.Provenance("myProv") + test_plane.provenance = provenance + self.assertEqual("myProv", test_plane.provenance.name, "Provenance - name") + self.assertIsNone(test_plane.metrics, "Default metrics") + metrics = plane.Metrics() + test_plane.metrics = metrics + self.assertEqual(metrics, test_plane.metrics, "Provenance - metrics") #self.assertIsNone(plane.observable, "Default observable") - self.assertIsNone(plane.position, "Default position") - self.assertIsNone(plane.energy, "Default energy") - self.assertIsNone(plane.time, "Default time") - self.assertIsNone(plane.polarization, "Default polarization") - - artifact1 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact1 - self.assertEquals(1, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - - artifact2 = Artifact("caom:CFHT/55/66", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:CFHT/55/66"] = artifact2 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) + self.assertIsNone(test_plane.position, "Default position") + self.assertIsNone(test_plane.energy, "Default energy") + self.assertIsNone(test_plane.time, "Default time") + self.assertIsNone(test_plane.polarization, "Default polarization") + + test_artifact1 = artifact.Artifact("caom:GEMINI/222/333", + artifact.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact1 + self.assertEquals(1, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + + test_artifact2 = artifact.Artifact("caom:CFHT/55/66", + artifact.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:CFHT/55/66"] = test_artifact2 + self.assertEquals(2, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in test_plane.artifacts.keys()) #try to append a duplicate artifact - artifact3 = Artifact("caom:GEMINI/222/333", ProductType.SCIENCE, ReleaseType.DATA) - plane.artifacts["caom:GEMINI/222/333"] = artifact3 - self.assertEquals(2, len(plane.artifacts), "Artifacts") - self.assertTrue("caom:GEMINI/222/333" in plane.artifacts.keys()) - self.assertTrue("caom:CFHT/55/66" in plane.artifacts.keys()) + test_artifact3 = artifact.Artifact("caom:GEMINI/222/333", + artifact.ProductType.SCIENCE, + artifact.ReleaseType.DATA) + test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact3 + self.assertEquals(2, len(test_plane.artifacts), "Artifacts") + self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) + self.assertTrue("caom:CFHT/55/66" in test_plane.artifacts.keys()) #Error cases exception = False try: - plane = Plane(None) + test_plane = plane.Plane(None) except TypeError: exception = True self.assertTrue(exception, "Null argument in initialize") @@ -244,7 +234,7 @@ def test_all(self): exception = False try: - plane.compute_energy() + test_plane.compute_energy() except NotImplementedError: exception = True self.assertTrue(exception, @@ -252,14 +242,14 @@ def test_all(self): exception = False try: - plane.compute_time() + test_plane.compute_time() except NotImplementedError: exception = True self.assertTrue(exception, "compute_time implemented - Testing needed") exception = False try: - plane.compute_polarization() + test_plane.compute_polarization() except NotImplementedError: exception = True self.assertTrue(exception, "compute_polarization implemented" @@ -269,35 +259,35 @@ def test_all(self): class TestPlaneURI(unittest.TestCase): def test_all(self): - planeURI = PlaneURI("caom:GEMINI/12345/3333") - self.assertEqual("caom:GEMINI/12345/3333", planeURI.uri, + plane_uri = plane.PlaneURI("caom:GEMINI/12345/3333") + self.assertEqual("caom:GEMINI/12345/3333", plane_uri.uri, "Plane URI") - self.assertEqual("GEMINI", planeURI.observation_uri.collection, + self.assertEqual("GEMINI", plane_uri.observation_uri.collection, "Collection") - self.assertEqual("12345", planeURI.observation_uri.observation_id, + self.assertEqual("12345", plane_uri.observation_uri.observation_id, "Observation ID") - self.assertEqual("3333", planeURI.product_id, "Product ID") + self.assertEqual("3333", plane_uri.product_id, "Product ID") - planeURI = PlaneURI.get_plane_uri(ObservationURI("caom:CFHT/654321"), + plane_uri = plane.PlaneURI.get_plane_uri(observation.ObservationURI("caom:CFHT/654321"), "555") - self.assertEqual("caom:CFHT/654321/555", planeURI.uri, + self.assertEqual("caom:CFHT/654321/555", plane_uri.uri, "Observation URI") - self.assertEqual("CFHT", planeURI.observation_uri.collection, + self.assertEqual("CFHT", plane_uri.observation_uri.collection, "Collection") - self.assertEqual("654321", planeURI.observation_uri.observation_id, + self.assertEqual("654321", plane_uri.observation_uri.observation_id, "Observation ID") - self.assertEqual("555", planeURI.product_id, "Product ID") + self.assertEqual("555", plane_uri.product_id, "Product ID") exception = False try: - planeURI = PlaneURI.get_plane_uri(None, "123") + plane_uri = plane.PlaneURI.get_plane_uri(None, "123") except TypeError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - planeURI = PlaneURI.get_plane_uri("GEMINI", None) + plane_uri = plane.PlaneURI.get_plane_uri("GEMINI", None) except TypeError: exception = True self.assertTrue(exception, "Missing exception") @@ -305,14 +295,14 @@ def test_all(self): #wrong scheme exception = False try: - planeURI = PlaneURI("somescheme:GEMINI/12345/3333") + plane_uri = plane.PlaneURI("somescheme:GEMINI/12345/3333") except ValueError: exception = True self.assertTrue(exception, "Missing exception") exception = False try: - planeURI = PlaneURI("caom:GEMINI/12345") + plane_uri = plane.PlaneURI("caom:GEMINI/12345") except ValueError: exception = True self.assertTrue(exception, "Missing exception") @@ -322,16 +312,16 @@ class TestDataQuality(unittest.TestCase): def test_all(self): - self.assertRaises(TypeError, DataQuality, "string") - quality = DataQuality(Quality.JUNK) - self.assertEqual(Quality.JUNK, quality.flag, + self.assertRaises(TypeError, plane.DataQuality, "string") + quality = plane.DataQuality(plane.Quality.JUNK) + self.assertEqual(plane.Quality.JUNK, quality.flag, "DataQuality flag") class TestMetrics(unittest.TestCase): def test_all(self): - metrics = Metrics() + metrics = plane.Metrics() self.assertIsNone(metrics.source_number_density, "Default source number density") @@ -359,7 +349,7 @@ def test_all(self): class TestProvenance(unittest.TestCase): def test_all(self): - provenance = Provenance("MyProvenance") + provenance = plane.Provenance("MyProvenance") self.assertEqual("MyProvenance", provenance.name, "Name") self.assertIsNone(provenance.version, "Default version") @@ -377,23 +367,23 @@ def test_all(self): self.assertIsNone(provenance.reference, "Default reference") self.assertEqual(0, len(provenance.inputs), "Default inputs") - planeURI1 = PlaneURI("caom:HST/11/00") - provenance.inputs.add(planeURI1) + plane_uri1 = plane.PlaneURI("caom:HST/11/00") + provenance.inputs.add(plane_uri1) self.assertEqual(1, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) + self.assertTrue(plane_uri1 in provenance.inputs) - planeURI2 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI2) + plane_uri2 = plane.PlaneURI("caom:HST/22/00") + provenance.inputs.add(plane_uri2) self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) + self.assertTrue(plane_uri1 in provenance.inputs) + self.assertTrue(plane_uri2 in provenance.inputs) # testing duplicates - planeURI3 = PlaneURI("caom:HST/22/00") - provenance.inputs.add(planeURI3) + plane_uri3 = plane.PlaneURI("caom:HST/22/00") + provenance.inputs.add(plane_uri3) self.assertEqual(2, len(provenance.inputs), "Default inputs") - self.assertTrue(planeURI1 in provenance.inputs) - self.assertTrue(planeURI2 in provenance.inputs) + self.assertTrue(plane_uri1 in provenance.inputs) + self.assertTrue(plane_uri2 in provenance.inputs) self.assertIsNone(provenance.last_executed, "Default last executed") now_date = datetime.now() @@ -410,13 +400,13 @@ def test_all(self): self.assertTrue("keyword2" in provenance.keywords, "Keyword not found") # test the full constructor - provenance = Provenance("MyOtherProvenance", - "Version2.0", - "JCMT", - "Mutt Lang", - "b32", - "caom:JCMT/33/00", - now_date) + provenance = plane.Provenance("MyOtherProvenance", + "Version2.0", + "JCMT", + "Mutt Lang", + "b32", + "caom:JCMT/33/00", + now_date) self.assertIsNotNone(provenance.name) self.assertIsNotNone(provenance.version) @@ -438,7 +428,7 @@ def test_all(self): class TestPosition(unittest.TestCase): def test_all(self): - position = Position() + position = plane.Position() self.assertIsNone(position.bounds, "Default bounds") #position.bounds = 123 @@ -460,7 +450,7 @@ def test_all(self): class TestEnergy(unittest.TestCase): def test_all(self): - energy = Energy() + energy = plane.Energy() self.assertIsNone(energy.value, "Default energy value") energy.value = 33.33 self.assertEqual(33.33, energy.value, "Energy value") @@ -482,8 +472,8 @@ def test_all(self): energy.bandpass_name = "EBN" self.assertEqual("EBN", energy.bandpass_name, "Energy bandpass name") self.assertIsNone(energy.em_band, "Default energy em band") - energy.em_band = EnergyBand.OPTICAL - self.assertEqual(EnergyBand.OPTICAL, energy.em_band, "Energy band") + energy.em_band = plane.EnergyBand.OPTICAL + self.assertEqual(plane.EnergyBand.OPTICAL, energy.em_band, "Energy band") self.assertIsNone(energy.transition, "Default energy transition") #TODO replace with EnergyTransistion #energy.transition = "BLAH" @@ -493,19 +483,19 @@ class TestEnergyTransition(unittest.TestCase): def test__init__(self): # test for invalid values - self.assertRaises(TypeError, EnergyTransition, None, None) - self.assertRaises(TypeError, EnergyTransition, 'aString', None) - self.assertRaises(TypeError, EnergyTransition, None, 'aString') - self.assertRaises(TypeError, EnergyTransition, 1, 'aString') - self.assertRaises(TypeError, EnergyTransition, 'aString', 2) + self.assertRaises(TypeError, plane.EnergyTransition, None, None) + self.assertRaises(TypeError, plane.EnergyTransition, 'aString', None) + self.assertRaises(TypeError, plane.EnergyTransition, None, 'aString') + self.assertRaises(TypeError, plane.EnergyTransition, 1, 'aString') + self.assertRaises(TypeError, plane.EnergyTransition, 'aString', 2) # test for happy path - transition = EnergyTransition("aSpecies", "aTransition") + transition = plane.EnergyTransition("aSpecies", "aTransition") self.assertEqual(transition._species, "aSpecies") self.assertEqual(transition._transition, "aTransition") def test_setters(self): # test that we cannot change the attribute values - transition = EnergyTransition("aSpecies", "aTransition") + transition = plane.EnergyTransition("aSpecies", "aTransition") try: transition.species = "newSpecies" transition.transition = "newTransition" @@ -518,11 +508,11 @@ def test_setters(self): class TestPolarizaton(unittest.TestCase): def test_all(self): - polarization = Polarization() + polarization = plane.Polarization() self.assertIsNone(polarization.dimension, "Default polarization dimension") - energy = Energy() + energy = plane.Energy() energy.bandpass_name = '123' self.assertEqual('123', energy.bandpass_name, "Polarization dimension") @@ -532,7 +522,7 @@ def test_all(self): class TestTime(unittest.TestCase): def test_all(self): - time = Time() + time = plane.Time() self.assertIsNone(time.value, "Default value") self.assertIsNone(time.bounds, "Default bounds") self.assertIsNone(time.dimension, "Default dimension") @@ -550,8 +540,3 @@ def test_all(self): self.assertEqual(12.34, time.sample_size, "Sample size") time.exposure = 55.55 self.assertEqual(55.55, time.exposure, "Exposure") - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/test/test_shape.py b/caom2tools/caom2/test/test_shape.py index 3457f097..39fbbb51 100644 --- a/caom2tools/caom2/test/test_shape.py +++ b/caom2tools/caom2/test/test_shape.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -70,16 +69,16 @@ import unittest -from caom2tools.caom2 import shape +from .. import shape class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(shape.SegmentType.get(999), None) + self.assertEqual(shape.SegmentType.get("foo"), None) self.assertRaises(AttributeError, shape.SegmentType.get, None) - self.assertRaises(AttributeError, shape.SegmentType.get, "foo") + self.assertRaises(AttributeError, shape.SegmentType.get, 999) self.assertEqual(shape.SegmentType.CLOSE.value, 0) self.assertEqual(shape.SegmentType.LINE.value, 1) diff --git a/caom2tools/caom2/test/test_wcs.py b/caom2tools/caom2/test/test_wcs.py index 585c7e5a..19ef2132 100644 --- a/caom2tools/caom2/test/test_wcs.py +++ b/caom2tools/caom2/test/test_wcs.py @@ -1,4 +1,3 @@ -#!/usr/bin/env python # -*- coding: utf-8 -*- #*********************************************************************** #****************** CANADIAN ASTRONOMY DATA CENTRE ******************* @@ -70,7 +69,7 @@ import unittest -from caom2tools.caom2 import wcs +from .. import wcs class TestAxis(unittest.TestCase): @@ -454,8 +453,3 @@ def test_init(self): self.assertIsNotNone(value_coord2d) self.assertEqual(value_coord2d.coord1, float(1)) self.assertEqual(value_coord2d.coord2, float(2)) - - -if __name__ == '__main__': - unittest.main() - diff --git a/caom2tools/caom2/wcs.py b/caom2tools/caom2/wcs.py index 6a320e03..23aa7b75 100644 --- a/caom2tools/caom2/wcs.py +++ b/caom2tools/caom2/wcs.py @@ -71,7 +71,6 @@ import caom_object import caom_util -from caom_util import Util class Axis(caom_object.CaomObject): @@ -94,7 +93,7 @@ def ctype(self): @ctype.setter def ctype(self, value): - Util.type_check(value, str, 'ctype', override=False) + caom_util.type_check(value, str, 'ctype', override=False) self._ctype = value @property @@ -109,7 +108,7 @@ def cunit(self): @cunit.setter def cunit(self, value): - Util.type_check(value, str, 'cunit') + caom_util.type_check(value, str, 'cunit') self._cunit = value @@ -133,7 +132,7 @@ def coord1(self): @coord1.setter def coord1(self, value): - Util.type_check(value, RefCoord, 'coord1', override=False) + caom_util.type_check(value, RefCoord, 'coord1', override=False) self._coord1 = value @property @@ -146,7 +145,7 @@ def coord2(self): @coord2.setter def coord2(self, value): - Util.type_check(value, RefCoord, 'coord2', override=False) + caom_util.type_check(value, RefCoord, 'coord2', override=False) self._coord2 = value @@ -177,7 +176,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, Axis, "Axis", override=False) + caom_util.type_check(value, Axis, "Axis", override=False) self._axis = value @property @@ -192,7 +191,7 @@ def error(self): @error.setter def error(self, value): - Util.type_check(value, CoordError, 'error') + caom_util.type_check(value, CoordError, 'error') self._error = value @property @@ -209,7 +208,7 @@ def range(self): @range.setter def range(self, value): - Util.type_check(value, CoordRange1D, 'range') + caom_util.type_check(value, CoordRange1D, 'range') self._range = value @property @@ -224,7 +223,7 @@ def bounds(self): @bounds.setter def bounds(self, value): - Util.type_check(value, CoordBounds1D, "bounds") + caom_util.type_check(value, CoordBounds1D, "bounds") self._bounds = value @property @@ -241,7 +240,7 @@ def function(self): @function.setter def function(self, value): - Util.type_check(value, CoordFunction1D, 'function') + caom_util.type_check(value, CoordFunction1D, 'function') self._function = value @@ -276,7 +275,7 @@ def axis1(self): @axis1.setter def axis1(self, value): - Util.type_check(value, Axis, "axis1", override=False) + caom_util.type_check(value, Axis, "axis1", override=False) self._axis1 = value @property @@ -291,7 +290,7 @@ def axis2(self): @axis2.setter def axis2(self, value): - Util.type_check(value, Axis, "axis2", override=False) + caom_util.type_check(value, Axis, "axis2", override=False) self._axis2 = value @property @@ -306,7 +305,7 @@ def error1(self): @error1.setter def error1(self, value): - Util.type_check(value, CoordError, 'error1') + caom_util.type_check(value, CoordError, 'error1') self._error1 = value @property @@ -321,7 +320,7 @@ def error2(self): @error2.setter def error2(self, value): - Util.type_check(value, CoordError, "error2") + caom_util.type_check(value, CoordError, "error2") self._error2 = value @property @@ -334,7 +333,7 @@ def range(self): @range.setter def range(self, value): - Util.type_check(value, CoordRange2D, 'range') + caom_util.type_check(value, CoordRange2D, 'range') self._range = value @property @@ -348,7 +347,7 @@ def bounds(self): @bounds.setter def bounds(self, value): - Util.type_check(value, (CoordCircle2D, CoordPolygon2D), 'bounds') + caom_util.type_check(value, (CoordCircle2D, CoordPolygon2D), 'bounds') self._bounds = value @property @@ -363,7 +362,7 @@ def function(self): @function.setter def function(self, value): - Util.type_check(value, CoordFunction2D, 'function') + caom_util.type_check(value, CoordFunction2D, 'function') self._function = value @@ -393,7 +392,7 @@ def samples(self): @samples.setter def samples(self, value): - Util.type_check(value, + caom_util.type_check(value, caom_util.TypedList, 'samples', override=False) @@ -452,7 +451,7 @@ def center(self): @center.setter def center(self, value): - Util.type_check(value, ValueCoord2D, 'center', override=False) + caom_util.type_check(value, ValueCoord2D, 'center', override=False) self._center = value @property @@ -468,8 +467,8 @@ def radius(self): @radius.setter def radius(self, value): - Util.type_check(value, float, 'radius', override=False) - Util.value_check(value, 0, 1E10, 'radius') + caom_util.type_check(value, float, 'radius', override=False) + caom_util.value_check(value, 0, 1E10, 'radius') self._radius = value @@ -504,7 +503,7 @@ def syser(self): @syser.setter def syser(self, value): - Util.type_check(value, float, "syser", override=False) + caom_util.type_check(value, float, "syser", override=False) self._syser = value @property @@ -518,7 +517,7 @@ def rnder(self): @rnder.setter def rnder(self, value): - Util.type_check(value, float, "rnder", override=False) + caom_util.type_check(value, float, "rnder", override=False) self._rnder = value @@ -552,7 +551,7 @@ def naxis(self): @naxis.setter def naxis(self, value): - Util.type_check(value, long, 'naxis', override=False) + caom_util.type_check(value, long, 'naxis', override=False) self._naxis = value @property @@ -567,7 +566,7 @@ def delta(self): @delta.setter def delta(self, value): - Util.type_check(value, float, 'delta', override=False) + caom_util.type_check(value, float, 'delta', override=False) self._delta = value @property @@ -582,7 +581,7 @@ def ref_coord(self): @ref_coord.setter def ref_coord(self, value): - Util.type_check(value, RefCoord, 'ref_coord', override=False) + caom_util.type_check(value, RefCoord, 'ref_coord', override=False) self._ref_coord = value @@ -613,7 +612,7 @@ def dimension(self): @dimension.setter def dimension(self, value): - Util.type_check(value, Dimension2D, 'dimension', override=False) + caom_util.type_check(value, Dimension2D, 'dimension', override=False) self._dimension = value @property @@ -628,7 +627,7 @@ def ref_coord(self): @ref_coord.setter def ref_coord(self, value): - Util.type_check(value, Coord2D, 'ref_coord', override=False) + caom_util.type_check(value, Coord2D, 'ref_coord', override=False) self._ref_coord = value @property @@ -644,7 +643,7 @@ def cd11(self): @cd11.setter def cd11(self, value): - Util.type_check(value, float, 'cd11', override=False) + caom_util.type_check(value, float, 'cd11', override=False) self._cd11 = value @property @@ -660,7 +659,7 @@ def cd12(self): @cd12.setter def cd12(self, value): - Util.type_check(value, float, 'cd12', override=False) + caom_util.type_check(value, float, 'cd12', override=False) self._cd12 = value @property @@ -676,7 +675,7 @@ def cd21(self): @cd21.setter def cd21(self, value): - Util.type_check(value, float, 'cd21', override=False) + caom_util.type_check(value, float, 'cd21', override=False) self._cd21 = value @property @@ -692,7 +691,7 @@ def cd22(self): @cd22.setter def cd22(self, value): - Util.type_check(value, float, 'cd22', override=False) + caom_util.type_check(value, float, 'cd22', override=False) self._cd22 = value @@ -728,7 +727,7 @@ def vertices(self): @vertices.setter def vertices(self, value): - Util.type_check(value, caom_util.TypedList, 'vertices', override=False) + caom_util.type_check(value, caom_util.TypedList, 'vertices', override=False) self._vertices = value @@ -754,7 +753,7 @@ def start(self): @start.setter def start(self, value): - Util.type_check(value, RefCoord, "start", override=False) + caom_util.type_check(value, RefCoord, "start", override=False) self._start = value @property @@ -769,7 +768,7 @@ def end(self): @end.setter def end(self, value): - Util.type_check(value, RefCoord, "end", override=False) + caom_util.type_check(value, RefCoord, "end", override=False) self._end = value @@ -795,7 +794,7 @@ def start(self): @start.setter def start(self, value): - Util.type_check(value, Coord2D, 'start', override=False) + caom_util.type_check(value, Coord2D, 'start', override=False) self._start = value @property @@ -808,7 +807,7 @@ def end(self): @end.setter def end(self, value): - Util.type_check(value, Coord2D, 'end', override=False) + caom_util.type_check(value, Coord2D, 'end', override=False) self._end = value @@ -835,8 +834,8 @@ def naxis1(self): @naxis1.setter def naxis1(self, value): - Util.type_check(value, long, 'naxis1', override=False) - Util.value_check(value, 0, 1E10, 'naxis1', override=False) + caom_util.type_check(value, long, 'naxis1', override=False) + caom_util.value_check(value, 0, 1E10, 'naxis1', override=False) self._naxis1 = value @property @@ -852,8 +851,8 @@ def naxis2(self): @naxis2.setter def naxis2(self, value): - Util.type_check(value, long, 'naxis2', override=False) - Util.value_check(value, 0, 1E10, 'naxis2', override=False) + caom_util.type_check(value, long, 'naxis2', override=False) + caom_util.value_check(value, 0, 1E10, 'naxis2', override=False) self._naxis2 = value @@ -883,7 +882,7 @@ def pix(self): @pix.setter def pix(self, value): - Util.type_check(value, float, 'pix', override=False) + caom_util.type_check(value, float, 'pix', override=False) self._pix = value @property @@ -898,7 +897,7 @@ def val(self): @val.setter def val(self, value): - Util.type_check(value, float, 'val', override=False) + caom_util.type_check(value, float, 'val', override=False) self._val = value @@ -926,7 +925,7 @@ def axis(self): @axis.setter def axis(self, value): - Util.type_check(value, Axis, 'axis', override=False) + caom_util.type_check(value, Axis, 'axis', override=False) self._axis = value @property @@ -941,7 +940,7 @@ def bin(self): @bin.setter def bin(self, value): - Util.type_check(value, long, 'long', override=False) + caom_util.type_check(value, long, 'long', override=False) self._bin = value @@ -959,7 +958,7 @@ def coord1(self): @coord1.setter def coord1(self, value): - Util.type_check(value, float, 'coord1', override=False) + caom_util.type_check(value, float, 'coord1', override=False) self._coord1 = value @property @@ -969,7 +968,7 @@ def coord2(self): @coord2.setter def coord2(self, value): - Util.type_check(value, float, 'coord2', override=False) + caom_util.type_check(value, float, 'coord2', override=False) self._coord2 = value @@ -984,8 +983,8 @@ def __init__(self, species, transition): species transition """ - Util.type_check(species, str, "species", override=False) - Util.type_check(transition, str, "transition", override=False) + caom_util.type_check(species, str, "species", override=False) + caom_util.type_check(transition, str, "transition", override=False) self._species = species self._transition = transition diff --git a/caom2tools/setup.py b/caom2tools/setup.py index 2eb8cb4e..88d4aca6 100755 --- a/caom2tools/setup.py +++ b/caom2tools/setup.py @@ -47,8 +47,8 @@ print 'The caom2 package is only compatible with Python version 2.n' sys.exit(-1) -setup(name='pyCAOM2', - version='2.2.1', +setup(name='caom2tools', + version='2.3.0', description='CAOM-2.2 library', url='This is a Home-page.', author='Canadian Astronomy Data Centre', From 384c4bfe04a6be81147341b262cef2dad5e253f0 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 16 Nov 2016 19:44:35 -0800 Subject: [PATCH 11/54] Created the util subpackage --- caom2repoClient/COPYING | 661 ------------------ caom2repoClient/MANIFEST.in | 1 - caom2repoClient/README | 7 - caom2repoClient/build.xml | 137 ---- caom2repoClient/caom2repoClient/__init__.py | 74 -- .../caom2repoClient/caom2repoClient.py | 373 ---------- caom2repoClient/makefile | 298 -------- caom2repoClient/scripts/caom2repo.py | 79 --- caom2repoClient/setup.cfg | 9 - caom2repoClient/setup.py | 63 -- caom2repoClient/test/data/CAOM-2.0.xsd | 523 -------------- caom2repoClient/test/data/simple.xml | 22 - .../test/scripts/test_caom2repo.sh | 285 -------- caom2tools/caom2/__init__.py | 5 +- 14 files changed, 2 insertions(+), 2535 deletions(-) delete mode 100644 caom2repoClient/COPYING delete mode 100644 caom2repoClient/MANIFEST.in delete mode 100644 caom2repoClient/README delete mode 100644 caom2repoClient/build.xml delete mode 100755 caom2repoClient/caom2repoClient/__init__.py delete mode 100755 caom2repoClient/caom2repoClient/caom2repoClient.py delete mode 100644 caom2repoClient/makefile delete mode 100755 caom2repoClient/scripts/caom2repo.py delete mode 100644 caom2repoClient/setup.cfg delete mode 100755 caom2repoClient/setup.py delete mode 100644 caom2repoClient/test/data/CAOM-2.0.xsd delete mode 100644 caom2repoClient/test/data/simple.xml delete mode 100755 caom2repoClient/test/scripts/test_caom2repo.sh diff --git a/caom2repoClient/COPYING b/caom2repoClient/COPYING deleted file mode 100644 index dba13ed2..00000000 --- a/caom2repoClient/COPYING +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/caom2repoClient/MANIFEST.in b/caom2repoClient/MANIFEST.in deleted file mode 100644 index 8b137891..00000000 --- a/caom2repoClient/MANIFEST.in +++ /dev/null @@ -1 +0,0 @@ - diff --git a/caom2repoClient/README b/caom2repoClient/README deleted file mode 100644 index b1f2a4c7..00000000 --- a/caom2repoClient/README +++ /dev/null @@ -1,7 +0,0 @@ - -This is a simple client for interacting with the CAOM-2.0 repository at CADC. It can -get, put, update, and delete observations from the repository. - -Note: The CAOM-2.0.xsd file found here is a copy of the definitive one, which is located in the -caom2 (java) library. If there is a discrepancy the file here is likely out of date. This file -is not currently used but validation may be added at some point. diff --git a/caom2repoClient/build.xml b/caom2repoClient/build.xml deleted file mode 100644 index b98f740b..00000000 --- a/caom2repoClient/build.xml +++ /dev/null @@ -1,137 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/caom2repoClient/caom2repoClient/__init__.py b/caom2repoClient/caom2repoClient/__init__.py deleted file mode 100755 index c74efab3..00000000 --- a/caom2repoClient/caom2repoClient/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -from caom2repoClient import CAOM2RepoClient - -__all__ = ['caom2repoClient'] - diff --git a/caom2repoClient/caom2repoClient/caom2repoClient.py b/caom2repoClient/caom2repoClient/caom2repoClient.py deleted file mode 100755 index c2bdb883..00000000 --- a/caom2repoClient/caom2repoClient/caom2repoClient.py +++ /dev/null @@ -1,373 +0,0 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -import base64 -import errno -import httplib -import logging -import netrc -import os -import sys -import time -from argparse import ArgumentParser -from httplib import HTTPSConnection, HTTPConnection -from urlparse import urlparse - -__author__ = 'jenkinsd' - - -class CAOM2RepoClient: - - """Client script to access the CAOM-2 repository Observations.""" - - CAOM2REPO_REGISTRY_PROP_DIR_VAR = "CADC_ROOT" - - # - # Main function for execution. This function will delegate to proper functions. - # - def main(self): - # Some constants. - parser = ArgumentParser(description="CAOM-2 Observation Repository client.") - - parser.add_argument('--version', action='version', version='%(prog)s 1.0') - parser.add_argument('-v', '--verbose', required=False, action="store_true", - dest="verbose") - parser.add_argument('-d', '--debug', required=False, action="store_true", - dest="debug") - parser.add_argument('-g', '--get', required=False, dest="get_action", - nargs=2, metavar=("", ""), - help="Get observation (in the form caom:/) from the repository and write to ") - parser.add_argument('-p', '--put', required=False, dest='create_action', - nargs=2, metavar=("", ""), - help="Create observation (in the form caom:/) in the repository using ") - parser.add_argument('-u', '--update', required=False, dest='update_action', - nargs=2, metavar=("", ""), - help="Update observation (in the form caom:/) in the repository using ") - parser.add_argument('-r', '--remove', required=False, dest='delete_action', - nargs=1, metavar="", - help="Remove observation (in the form caom:/) from the repository") - parser.add_argument('--retry', required=False, nargs='?', const=3, - metavar=(""), - help="Retry the command on transient errors. Default is 3 retries unless a value is specified") - parser.epilog = 'Environment:\n' \ - + 'CADC_ROOT: location of lib/python-2.7/site-packages [REQUIRED]\n' \ - + 'CAOM2_REPO_HOST : force a specific server for caom2 repository [OPTIONAL]\n' - - arguments = parser.parse_args(sys.argv[1:]) - - if arguments.verbose: - logging.basicConfig(level=logging.INFO) - - if arguments.debug: - logging.basicConfig(level=logging.DEBUG) - - # Doing retries? - self.retries = None - if arguments.retry: - self.retries = int(arguments.retry) - - self.SERVICE_PROTOCOL = 'https' - self.SERVICE_URL = 'https://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' - repoHost = os.getenv('CAOM2_REPO_HOST') - if repoHost is not None: - url = urlparse(self.SERVICE_URL) - self.SERVICE_URL = url.scheme + '://' + repoHost + url.path - logging.info("Service URL: '%s'" % self.SERVICE_URL) - - if arguments.get_action: - logging.info("GET ACTION") - self.get(arguments.get_action[0], arguments.get_action[1]) - elif arguments.create_action: - logging.info("PUT ACTION") - self.put(arguments.create_action[0], arguments.create_action[1]) - elif arguments.update_action: - logging.info("UPDATE ACTION") - self.update(arguments.update_action[0], arguments.update_action[1]) - elif arguments.delete_action: - logging.info("REMOVE ACTION") - self.remove(arguments.delete_action[0]) - else: - parser.print_help() - print - - - # - # Obtain the CAOM-2 Observation instance from the CAOM-2 service. - # - # @param observationURI - The URI of the CAOM-2 Observation - # @param filename - The full path to the XML File to construct an - # Observation. - # - def get(self, observationURI, filename): - logging.info("GET " + observationURI) - - response = self.send_request("GET", observationURI, {}, '') - - status = response.status - - if status == 503 and self.retries: - status = self.retry("GET", observationURI, {}, '') - - if status == 404: - logging.error('No such Observation found with URI \'%s\'.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - logging.error('Unable to retrieve Observation with URI \'%s\'.\n' % observationURI) - logging.error('Server Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + response.read()) - sys.exit(errno.ENOEXEC) - else: - f = open(filename, 'w') - f.write(response.read()) - f.close() - logging.info("Successfully saved Observation at '%s'" % filename) - # - # Create a new Observation resource. - # - # @param observationURI - The URI of the CAOM-2 Observation - # @param filename - The full path to the XML File to construct an - # Observation. - # - def put(self, observationURI, filename): - logging.debug("PUT " + filename) - xmlfile = None - - try: - - xmlfile = open(filename) - response = self.send_request("PUT", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - status = response.status - - if status == 503 and self.retries: - status = self.retry("PUT", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - - if status == 404: - logging.error('No such collection found for URI \'%s\'' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - msg = '' - for hmsg in response.msg.headers: - msg = msg + hmsg - logging.error('Unable to create Observation from file ' + filename - + '\nServer Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + msg + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully created Observation\n') - - except IOError as ioerr: - logging.error('\nAborting due to error!\nUnable to read file ' - + filename + '\n' + str(ioerr) + '\n') - sys.exit(errno.EIO) - finally: - if not xmlfile is None: - xmlfile.close() - - # - # Update an existing CAOM-2 Observation. - # - # @param observationURI - The URI of the Observation to update. - # @param filename - The full path to the XML File of the Observation. - # - def update(self, observationURI, filename): - logging.debug("POST " + observationURI + " with filename " + filename) - xmlfile = None - - try: - xmlfile = open(filename) - response = self.send_request("POST", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - status = response.status - - if status == 503 and self.retries: - status = self.retry("POST", observationURI, {'Content-Type': 'text/xml'}, xmlfile.read()) - - if status == 404: - logging.error('Observation with URI \'%s\' does not exist.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - msg = '' - for hmsg in response.msg.headers: - msg = msg + hmsg - logging.error('Unable to update Observation from file ' + filename - + '\nServer Returned: ' + httplib.responses[status] + ' (' - + str(status) + ')\n' + msg + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully updated Observation\n') - - except IOError as ioerr: - logging.error('Aborting due to error!\nUnable to read file ' + filename + '\n' + str(ioerr) + '\n') - sys.exit(errno.EIO) - finally: - if not xmlfile is None: - xmlfile.close() - # - # Permanently remove an Observation resource. - # - # @param observationURI - The URI of the Observation to delete. - # - def remove(self, observationURI): - logging.debug("DELETE " + observationURI) - response = self.send_request("DELETE", observationURI, {}, '') - status = response.status - - if status == 503 and self.retries: - status = self.retry("DELETE", observationURI, {}, '') - - if status == 404: - logging.error('No such Observation found with URI \'%s\'.\n' % observationURI) - sys.exit(errno.ENOENT) - elif status >= 400: - logging.error('Unable to remove Observation with URI \'' + observationURI - + '\'.\n\n' + httplib.responses[status] + ' (' + str(status) - + ')\n' + response.read()) - sys.exit(errno.ENOEXEC) - else: - logging.info('Successfully removed Observation %s' % observationURI + '\n') - - # - # Send the HTTP(S) request. - # - # @param method - The HTTP Method to use (String). - # @param path - The path of the URL (After the host). Should begin - # with a slash ('/') (String). - # @param headers - Any custom headers. This is a dictionary. - # @param payload - The payload to send for a write operation (String). - # - # @return The httplib.HTTPResponse object. - # - def send_request(self, method, observationURI, headers, payload): - parseResult = urlparse(observationURI) - serviceURLResult = urlparse(self.SERVICE_URL) - path = parseResult.path - logging.debug("Found path: " + path) - - if self.SERVICE_PROTOCOL == 'https': - try: - with open(os.path.join(os.environ['HOME'], '.ssl/cadcproxy.pem')) as certfile: - logging.info('certfile {}'.format(certfile)) - conn = HTTPSConnection(serviceURLResult.hostname, 443, None, certfile.name) - conn.request(method, serviceURLResult.path + '/pub/' + path, payload, headers) - logging.debug("Making request to " + self.SERVICE_URL + '/pub/' + path) - return conn.getresponse() - except IOError as e: - logging.error('No usable credentials to connect to ' + self.SERVICE_URL + '/' + path + '\n') - logging.error(str(e) + "\n") - sys.exit(errno.EACCES) - elif self.SERVICE_PROTOCOL == 'http': - try: - netrcfile = netrc.netrc() - auth = netrcfile.authenticators(serviceURLResult.hostname) - except netrc.NetrcParseError as err: - logging.error('Unable to read netrc file.\n') - logging.error(str(err) + "\n") - sys.exit(errno.EIO) - - conn = HTTPConnection(serviceURLResult.hostname) - username = auth[0] - password = auth[2] - base64string = base64.encodestring('%s:%s' % (username, password)).replace('\n', '') - - if not headers or not len(headers): - headers = {'Authorization': 'Basic %s' % base64string} - elif not headers.has_key('Authorization'): - headers.update({'Authorization': 'Basic %s' % base64string}) - - conn.request(method, serviceURLResult.path + '/auth/' + path, payload, headers) - logging.debug('Making request to ' + self.SERVICE_URL + '/auth/' + path) - - return conn.getresponse() - else: - logging.error("Unknown protocol '%s'" % self.SERVICE_PROTOCOL) - - # - # Retry a HTTP(S) request. - # - # @param method - The HTTP Method to use (String). - # @param path - The path of the URL (After the host). Should begin - # with a slash ('/') (String). - # @param headers - Any custom headers. This is a dictionary. - # @param payload - The payload to send for a write operation (String). - # - # @return The httplib.HTTPResponse object. - # - def retry(self, method, observationURI, headers, payload): - num_retries = int(0); - sleep_time = int(1) - status = 503 - while status == 503: - num_retries += 1 - if num_retries > self.retries: - break - sleep_time = sleep_time * 2 - logging.info('Sleeping ' + str(sleep_time) + ', retry ' + str(num_retries)) - time.sleep(sleep_time) - response = self.send_request(method, observationURI, headers, payload) - status = response.status - return status diff --git a/caom2repoClient/makefile b/caom2repoClient/makefile deleted file mode 100644 index a19b032e..00000000 --- a/caom2repoClient/makefile +++ /dev/null @@ -1,298 +0,0 @@ -# -# This makefile was generated by mm. -# - - -# Project-specific definitions -PROJECT := myproject - -# Another perverted GNU make trick - recursive wildcard evaluation -# Usage is $(call rwildcard,dirpath,pattern) -# Return is a list of files matching pattern in the directory tree rooted at dirpath -# See http://blog.jgc.org/2011/07/gnu-make-recursive-wildcard-function.html -rwildcard=$(foreach d,$(wildcard $1*),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d)) - -PROJECTROOT := $(abspath $(dir $(firstword $(wildcard setup.py ../setup.py ../../setup.py ../../../setup.py)))) -LOCALROOT := $(abspath .) -THISMAKEFILE := $(abspath $(firstword $(MAKEFILE_LIST))) - -# Specific version of python to be used for the installation -# PYTHON can be over ruled from the command line, or in sub-makes -PYTHON := python -# The list of python versions can be restricted (or extended) in makestart -PYTHONLIST := python2.5 python2.6 python2.7 - -# Default style checker -CHECKSTYLE = pep8 -r - -# Checks that python modules are in allowed locations -PYTHON_MODULES = $(A)/scripts/python_modules.py --report=path - -# generates Python documentation -DOCGEN = pydoc -w >&/dev/null - -# use rsync to copy files around -RSYNC = rsync -Cqpotr - -LIB := $(PROJECTROOT)/lib.local/ -# System-specified directories -ifeq ($(T),) - # Environment does not define T, so assume a non-CADC platform - RPS := $(wildcard ~/ ) - A = $(RPS) - INSTALLSWITCH = -else - # Envirnment defines T, so assume a CADC platform - INSTALLSWITCH = --install-base=$(LIB) -endif -LOGS := $(PROJECTROOT)/logs -DOCAPI = $(PROJECTROOT)/www/doc/api/$(PROJECT) - -PACKAGEPATHLIST := $(abspath $(subst /__init__.py,,$(call rwildcard,$(PROJECTROOT)/,__init__.py))) -PACKAGENAMELIST := $(notdir $(PACKAGEPATHLIST)) - -# Mangle python path names into doc names -PYLIST := $(filter-out test% lib.local% www% logs% setup.py,$(subst $(PROJECTROOT)/,,$(call rwildcard,$(PROJECTROOT)/,*.py))) -DOCPATHLIST := $(subst /__init__.py,,$(PYLIST)) -DOCSOURCELIST := $(subst ..,,$(subst /,.,$(basename $(DOCPATHLIST)))) -DOCLIST := $(addsuffix .html,$(DOCSOURCELIST)) - -SCRIPTLIST := $(notdir $(wildcard $(PROJECTROOT)/scripts/*)) -SCRIPTDOCLIST := $(filter %.py,$(SCRIPTLIST)) - -TESTLIST := $(notdir $(wildcard $(PROJECTROOT)/test/*)) -TESTPATH := $(foreach t,$(TESTLIST),$(wildcard $(PROJECTROOT)/test/$(t)/test*.py)) - -CHECKLIST = $(addprefix check,$(notdir $(PYLIST))) - -PYTHON := python2.7 -PYTHONLIST := python2.7 - -project := caom2repoClient - -TARGETS = x86_linux -TARGET_BLACKLIST = x86_fedora5_32 -# -# makestart end -# - -CURRENT_TRANSITION=current.transition -include $(A)/compilers/$(CURRENT_TRANSITION) - -local: -L=$(RPS)/lib.$(T) -#ifndef REL_TARGETS -ifeq ($(REL_TARGETS),) - REL_TARGETS = $(TARGETS) -endif -release: -ifeq ($(STREAM),current) - @echo "Error: Cannot do make release in the \"current\" stream." - @exit 1 -endif - @$(MAKE) RELEASE_BUILD=T $(REL_TARGETS) -makemake: test_targets - -CCFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -CFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -FFLAGS += $(addprefix -I, $(INCLUDE_PATH)) -LINTFLAGS := $(addprefix -I, $(INCLUDE_PATH)) $(LINTFLAGS) - -.PHONY: test -test: - echo $(xx) - -buildpaths: - @echo "lib path : $(LIBPATH)" - @echo "include path : $(INCLUDE_PATH)" - -ifneq (,$(findstring -b,$(FLAGS))) -x := $(shell mkdir -p bin.$(T) obj.$(T)) -endif - -ifneq (,$(findstring -l,$(FLAGS))) -x := $(shell mkdir -p lib.$(T) obj.$(T)) -endif - -objects: $(OBJECTS) - - -T_TARGETS = $(shell echo $(REL_TARGETS) | sed -e 's/\([ ^]*[^_ ][^_ ]*_[^_ $$]*\)[^ ]*/\1/g') -test_targets: - @echo "rel targets $(REL_TARGETS)" - @echo "t targets $(T_TARGETS)" -ifneq ($(words $(TARGETS)),$(words $(sort $(TARGETS)))) - @echo "Makestart setup error:" - @echo " There are duplicate targets in the TARGETS make symbol." - @exit 1 -endif -ifneq ($(words $(TARGETS)),$(words $(sort $(TARGETS) $(REL_TARGETS)))) - @echo "Makestart setup error:" - @echo " There are targets in REL_TARGETS not in the TARGETS list." - @exit 1 -endif -# -# commented out for fedora8 testing only - SGo -# -#ifneq ($(words $(T_TARGETS)),$(words $(sort $(T_TARGETS)))) -#ifeq ($(findstring -b,$(FLAGS)),-b) -## @echo "Makestart setup error:" -# @echo " There is more than one target in REL_TARGETS that release " -# @echo " to the same architecture (or REL_TARGETS is not defined)." -# @exit 1 -#endif -#endif - - -# -# The following targets cause libraries to be built when the library -# test program is built, or cause objects files to be built when the -# program test program is built. -# - -ifeq ($(notdir $(PWD)),test) -ifeq ($(wildcard ../lib.$(T) ),../lib.$(T)) -local: buildlib -buildlib: - @cd ..; $(MAKE) local -endif -ifeq ($(wildcard ../bin.$(T) ),../bin.$(T)) -local: buildobj -buildobj: - @cd ..; $(MAKE) objects -endif -endif - -DEFAULT_TARGET=$(firstword $(TARGETS)) -DEFAULT_HOST=$(shell echo $(DEFAULT_TARGET)_HOST | tr '[a-z]' '[A-Z]') -showDepend: -ifeq (,$(findstring $(T),$(TARGETS))) - ssh -n $($(DEFAULT_HOST)) "setenv PROJECT $(PROJECT); setenv STREAM $(STREAM); source $(M)/dev.rc; cd $(shell pwd); make -nd RELEASE_ROOT=$(RELEASE_ROOT) MODULE_VERSION=$(MODULE_VERSION) T=$(DEFAULT_TARGET) local" -else - make -nd local -endif - -show_rel_targets: - @echo "$(REL_TARGETS)" - - -.PHONY: local lint all release test_targets show_rel_targets -.PHONY: local default clean init build test - -# run make on all platforms -ifeq ($(T),) -.PHONY: all -all: local -else -.PHONY: all -all: $(TARGETS) -endif - -.PNONY: $(TARGETS) -$(TARGETS): - ssh $$$(shell echo $@ | tr '[:lower:]' '[:upper:]')_HOST 'cd $(PWD); make local' - -# run make for all versions of python -local: $(PYTHONLIST) - -# By default, run make for every version of python separately -.PHONY: $(PYTHONLIST) -$(PYTHONLIST): - $(MAKE) -f $(THISMAKEFILE) PYTHON=$@ PROJECTROOT=$(PROJECTROOT) default - -default: init build - -.PHONY: show -show: - @echo PROJECTROOT = $(PROJECTROOT) - @echo LOCALROOT = $(LOCALROOT) - @echo THISMAKEFILE = $(THISMAKEFILE) - @echo PYLIST = $(PYLIST) - @echo DOCLIST = $(DOCLIST) - @echo TESTLIST = $(TESTLIST) - @echo TESTPATH = $(TESTPATH) - @echo CHECKLIST = $(CHECKLIST) - -.PHONY: init -init: clean - mkdir -p $(LIB) - mkdir -p $(LOGS) - mkdir -p $(DOCAPI) - -.PHONY: clean -clean: - /bin/rm -fr $(LIB) - /bin/rm -fr $(LOGS) - /bin/rm -fr $(DOCAPI) - -#---------------------------------- -# BUILD TARGETS -#---------------------------------- -.PHONY: build compile build_python build_doc build_scripts build_config build_dtd - -# compile is a synonym for build -compile: build - -build: build_python build_doc - -build_python: - cd $(PROJECTROOT)/; $(PYTHON) setup.py build --build-base=$(LIB) - -#---------------------------------- -# BUILD_DOC TARGETS -#---------------------------------- -#.PHONY: build_doc -build_doc: build_python $(addprefix $(DOCAPI)/,$(DOCLIST)) $(addprefix $(DOCAPI)/,$(addsuffix .html,$(basename $(SCRIPTDOCLIST)))) - -# Create document targets for each individual package and module -define doc_template -$(DOCAPI)/$(1).html: $(wildcard $(subst .,/,$(1)).py $(subst .,/,$(1))/__init__.py) - cd $(DOCAPI); export PYTHONPATH=$(abspath $(LIB)/lib); $(DOCGEN) $(1) -endef -$(foreach p,$(DOCSOURCELIST),$(eval $(call doc_template,$(p)))) - -define scriptdoc_template -$(DOCAPI)/$(2).html: $(PROJECTROOT)/scripts/$(1) - cd $(DOCAPI); export PYTHONPATH=$(abspath $(LIB)/lib); $(DOCGEN) $^ -# /bin/rm $(PROJECTROOT)/scripts/*.pyc -endef -$(foreach p,$(SCRIPTDOCLIST),$(eval $(call scriptdoc_template,$(p),$(basename $(p))))) - -#---------------------------------- -# TEST TARGETS -#---------------------------------- -.PHONY: test $(addsuffix Test,$(TESTLIST)) - -define generate_tests -$(1)Test: $(2) - -.PHONY: $(2) -$(2): - cd $(PROJECTROOT)/test/$(1); export PYTHONPATH=$(abspath $(LIB)/lib); $(PYTHON) $$@ -endef -$(foreach t,$(TESTLIST),$(eval $(call generate_tests,$(t),$(strip $(notdir $(wildcard $(PROJECTROOT)/test/$(t)/test*.py)))))) - -#---------------------------------- -# CHECKSTYLE TARGETS -#---------------------------------- -.PHONY: checkstyle $(CHECKLIST) -checkstyle: $(CHECKLIST) - -define generate_checks -.PHONY: $(2) - -$(2): - -$(CHECKSTYLE) $(1) -endef - -$(foreach c,$(PYLIST),$(eval $(call generate_checks,$(c),$(addprefix check,$(notdir $(c)))))) - -#---------------------------------- -# CLASSPATH TARGETS -#---------------------------------- -.PHONY: classpath -classpath: - export PYTHONPATH=$(LIB)/lib; \ - $(PYTHON_MODULES) $(PACKAGEPATHLIST) \ - $(addprefix $(PROJECTROOT)/scripts/,$(SCRIPTDOCLIST)) \ - $(TESTPATH) diff --git a/caom2repoClient/scripts/caom2repo.py b/caom2repoClient/scripts/caom2repo.py deleted file mode 100755 index 33fc2054..00000000 --- a/caom2repoClient/scripts/caom2repo.py +++ /dev/null @@ -1,79 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -import caom2repoClient - -__author__ = 'jenkinsd' - -"""Client script to access the CAOM-2 Observation Repository""" - -if __name__ == '__main__': - client = caom2repoClient.CAOM2RepoClient() - client.main() diff --git a/caom2repoClient/setup.cfg b/caom2repoClient/setup.cfg deleted file mode 100644 index e8551e6f..00000000 --- a/caom2repoClient/setup.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[global] -verbose=0 - -description = "CAOM2RepoClient Class libraries" - -[install] -install-purelib=$base/lib/python$py_version_short/site-packages -install-platlib=$base/lib/python$py_version_short/site-packages -install_headers=$base/include/python$py_version_short/$dist_name diff --git a/caom2repoClient/setup.py b/caom2repoClient/setup.py deleted file mode 100755 index 185c8628..00000000 --- a/caom2repoClient/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2repoClient -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -# Use "distribute" -from setuptools import setup, find_packages -import sys - -if sys.version_info[0] > 2: - print 'The caom2repoClient package is only compatible with Python version 2.n' - sys.exit(-1) - -setup(name="caom2repoClient", - version='0.5.2', - description='Client application to the CAOM2 Repository', - long_description='The caom2repo client allows the caller to get/put/update/delete CAOM2 Observations in a central repository.', - url='http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo', - author='Canadian Astronomy Data Centre', - author_email='cadc@hia.nrc.ca', - license='GPLv3', - packages=find_packages(), - scripts=['scripts/caom2repo.py'], - include_package_data=True, - provides=['caom2repoClient'], - install_requires = ['distribute'], - zip_safe=False -) - diff --git a/caom2repoClient/test/data/CAOM-2.0.xsd b/caom2repoClient/test/data/CAOM-2.0.xsd deleted file mode 100644 index e2d91ace..00000000 --- a/caom2repoClient/test/data/CAOM-2.0.xsd +++ /dev/null @@ -1,523 +0,0 @@ - - - - - - - - - - - - - - The metaRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The observationURI must be constructed as follows: - caom:{collection}/{observationID} - - TODO: formally specify the ObservationURI type - - - - - - - - - - - - - - - - - - - - - The metaRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - The dataRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - The dataRelease date is expected to be in IVOA date format: - yyyy-MM-dd'T'HH:mm:ss.SSS - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The planeURI must be constructed as follows: - caom:{collection}/{observationID}/{productID} - which is based on the observationURI syntax, e.g.: - {observationURI}/{productID} - - TODO: formally specify the PlaneURI type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/caom2repoClient/test/data/simple.xml b/caom2repoClient/test/data/simple.xml deleted file mode 100644 index 4b524d97..00000000 --- a/caom2repoClient/test/data/simple.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - TEST - TESTBOGUS_CAOM2REPOCLIENT - - exposure - - - - productIDFromXML - - - ad:foo/bar - false - - - - - diff --git a/caom2repoClient/test/scripts/test_caom2repo.sh b/caom2repoClient/test/scripts/test_caom2repo.sh deleted file mode 100755 index 96fe8e3d..00000000 --- a/caom2repoClient/test/scripts/test_caom2repo.sh +++ /dev/null @@ -1,285 +0,0 @@ -#!/bin/bash -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c) 2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: caom2repo.py -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -PYTHON=$(/usr/bin/which python) -TEST_SUBJECT="../../scripts/caom2repo.py -v" -VERSION_OUTPUT_1=$(${TEST_SUBJECT} --version 2>&1) - -if [[ ! $VERSION_OUTPUT_1 = 'caom2repo.py 1.0' ]] -then - echo "Failed version test." - echo "Expected 'caom2repo.py 1.0', but got '${VERSION_OUTPUT_1}'" - exit -1 -fi - -HELP_OUTPUT_1=$(${TEST_SUBJECT} 2>&1 | head -2 | tail -1) - -if [[ ! $HELP_OUTPUT_1 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (1)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_1}'" - exit -1 -fi - -HELP_OUTPUT_2=$(${TEST_SUBJECT} -h 2>&1 | head -1) - -if [[ ! $HELP_OUTPUT_2 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (2)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_2}'" - exit -1 -fi - -HELP_OUTPUT_3=$(${TEST_SUBJECT} --help 2>&1 | head -1) - -if [[ ! $HELP_OUTPUT_3 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed help test (3)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${HELP_OUTPUT_3}'" - exit -1 -fi - -# Get tests -# -GET_OUTPUT_1=$(${TEST_SUBJECT} -g 2>&1 | tail -1) - -if [[ ! $GET_OUTPUT_1 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (1)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_1}'" - exit -1 -fi - -GET_OUTPUT_2=$(${TEST_SUBJECT} --get 2>&1 | tail -1) - -if [[ ! $GET_OUTPUT_2 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (2)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_2}'" - exit -1 -fi - -GET_OUTPUT_3=$(${TEST_SUBJECT} -g caom:TEST/BOGUSOBSERVATION 2>&1 | tail -1 2>&1) - -if [[ ! $GET_OUTPUT_3 = 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)' ]] -then - echo "Failed get test (3)." - echo "Expected 'caom2repo.py: error: argument -g/--get: expected 2 argument(s)', but got '${GET_OUTPUT_3}'" - exit -1 -fi - -${TEST_SUBJECT} -g caom:IRIS/f212h000 /tmp/out.xml - -GET_OUTPUT_4=$(cat /tmp/out.xml | sed 's/\r//' | head -1) -GET_OUTPUT_4_2=$(cat /tmp/out.xml | sed 's/\r//' | head -5 | tail -1) - -if [[ ! ${GET_OUTPUT_4} = "" ]] -then - echo "Failed get test (4)." - echo "Expected '', but got '${GET_OUTPUT_4}'" - exit -1 -else - if [[ ! ${GET_OUTPUT_4_2} = ' 2004-12-06T00:00:00.000' ]] - then - echo "Failed get test (4.2)." - echo "Expected ' 2004-12-06T00:00:00.000', but got '${GET_OUTPUT_4_2}'" - exit -1 - fi -fi - -# Quick remove before a PUT -echo "" -echo "Issuing clean up delete in case test failed before final deletion. Ignore any error message here." -${TEST_SUBJECT} -r caom:TEST/TESTBOGUS_CAOM2REPOCLIENT -echo "OK, pay attention again." - -# Create tests -# -PUT_OUTPUT_1=$(${TEST_SUBJECT} -p 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_1 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (1)." - echo "Expected caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_1}'" - exit -1 -fi - -PUT_OUTPUT_2=$(${TEST_SUBJECT} --put 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_2 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (2)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_2}'" - exit -1 -fi - -PUT_OUTPUT_3=$(${TEST_SUBJECT} -p caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_3 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (3)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_3}'" - exit -1 -fi - -PUT_OUTPUT_4=$(${TEST_SUBJECT} --put caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_4 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (4)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_4}'" - exit -1 -fi - -PUT_OUTPUT_5=$(${TEST_SUBJECT} -p ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_5 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (5)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_5}'" - exit -1 -fi - -PUT_OUTPUT_6=$(${TEST_SUBJECT} --put ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $PUT_OUTPUT_6 = 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)' ]] -then - echo "Failed put test (6)." - echo "Expected 'caom2repo.py: error: argument -p/--put: expected 2 argument(s)', but got '${PUT_OUTPUT_6}'" - exit -1 -fi - -PUT_OUTPUT_7=$(${TEST_SUBJECT} -p caom:TEST/TESTBOGUS_CAOM2REPOCLIENT ../data/simple.xml 2>&1 | head -4 | tail -1) - -if [[ ! $PUT_OUTPUT_7 = 'INFO:root:Successfully created Observation' ]] -then - echo "Failed put test (7)." - echo "Expected 'INFO:root:Successfully created Observation', but got '${PUT_OUTPUT_7}'" - exit -1 -fi - -# Update tests -# -POST_OUTPUT_1=$(${TEST_SUBJECT} -u 2>&1 | head -1) - -if [[ ! $POST_OUTPUT_1 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed post test (1)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${POST_OUTPUT_1}'" - exit -1 -fi - -POST_OUTPUT_2=$(${TEST_SUBJECT} --update 2>&1 | head -1) - -if [[ ! $POST_OUTPUT_2 = 'usage: caom2repo.py [-h] [--version] [-v] [-d]' ]] -then - echo "Failed post test (2)." - echo "Expected 'usage: caom2repo.py [-h] [--version] [-v] [-d]', but got '${POST_OUTPUT_2}'" - exit -1 -fi - -POST_OUTPUT_3=$(${TEST_SUBJECT} -u caom:TEST/TESTBOGUS_CAOM2REPOCLIENT 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_3 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (3)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_3}'" - exit -1 -fi - -POST_OUTPUT_4=$(${TEST_SUBJECT} --update caom:TEST/TESTOBS 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_4 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (4)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_4}'" - exit -1 -fi - -POST_OUTPUT_5=$(${TEST_SUBJECT} -u ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_5 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (5)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_5}'" - exit -1 -fi - -POST_OUTPUT_6=$(${TEST_SUBJECT} --update ../data/simple.xml 2>&1 | tail -1) - -if [[ ! $POST_OUTPUT_6 = 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)' ]] -then - echo "Failed post test (6)." - echo "Expected 'caom2repo.py: error: argument -u/--update: expected 2 argument(s)', but got '${POST_OUTPUT_6}'" - exit -1 -fi - -POST_OUTPUT_7=$(${TEST_SUBJECT} -u caom:TEST/TESTBOGUS_CAOM2REPOCLIENT ../data/simple.xml 2>&1 | head -4 | tail -1) - -if [[ ! $POST_OUTPUT_7 = 'INFO:root:Successfully updated Observation' ]] -then - echo "Failed post test (7)." - echo "Expected 'INFO:root:Successfully updated Observation', but got '${POST_OUTPUT_7}'" - exit -1 -fi - -# Delete tests. -# -REMOVE_OUTPUT_1=$(${TEST_SUBJECT} -r caom:TEST/NOSUCHOBS 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_1 = "ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'." ]] -then - echo "Failed remove test (1)." - echo "Expected 'ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'.', but got '${REMOVE_OUTPUT_1}'" - exit -1 -fi - -REMOVE_OUTPUT_2=$(${TEST_SUBJECT} --remove caom:TEST/NOSUCHOBS 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_2 = "ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'." ]] -then - echo "Failed remove test (2)." - echo "Expected 'ERROR:root:No such Observation found with URI 'caom:TEST/NOSUCHOBS'.', but got '${REMOVE_OUTPUT_2}'" - exit -1 -fi - -REMOVE_OUTPUT_3=$(${TEST_SUBJECT} --remove caom:TEST/TESTBOGUS_CAOM2REPOCLIENT 2>&1 | head -3 | tail -1) - -if [[ ! $REMOVE_OUTPUT_3 = "INFO:root:Successfully removed Observation caom:TEST/TESTBOGUS_CAOM2REPOCLIENT" ]] -then - echo "Failed remove test (3)." - echo "Expected 'INFO:root:Successfully removed Observation caom:TEST/TESTBOGUS_CAOM2REPOCLIEN', but got '${REMOVE_OUTPUT_3}'" - exit -1 -fi - -echo "All tests passed." diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index 7cc3bcae..d6137cba 100644 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -81,7 +81,7 @@ # from caom_util import Util as Util # -# from .caom_object import CaomObject +from .caom_object import CaomObject # from .caom_object import AbstractCaomEntity # Util classes @@ -172,8 +172,7 @@ # from .observation import TargetType # observation reader and writer -# from .obs_reader_writer import ObservationReader -# from .obs_reader_writer import ObservationWriter +from .obs_reader_writer import ObservationReader, ObservationWriter # from .obs_reader_writer import CAOM20_NAMESPACE # from .obs_reader_writer import CAOM21_NAMESPACE # from .obs_reader_writer import CAOM22_NAMESPACE From 7ce8e3372f6931d5f85e3151569f20de69025c33 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 16 Nov 2016 19:48:40 -0800 Subject: [PATCH 12/54] Created the util subpackage --- caom2tools/util/__init__.py | 0 caom2tools/util/_astropy_init.py | 138 +++++++++ caom2tools/util/caom2repo.py | 319 +++++++++++++++++++++ caom2tools/util/conftest.py | 38 +++ caom2tools/util/tests/__init__.py | 169 +++++++++++ caom2tools/util/tests/test_caom2repo.py | 362 ++++++++++++++++++++++++ 6 files changed, 1026 insertions(+) create mode 100755 caom2tools/util/__init__.py create mode 100644 caom2tools/util/_astropy_init.py create mode 100755 caom2tools/util/caom2repo.py create mode 100644 caom2tools/util/conftest.py create mode 100755 caom2tools/util/tests/__init__.py create mode 100644 caom2tools/util/tests/test_caom2repo.py diff --git a/caom2tools/util/__init__.py b/caom2tools/util/__init__.py new file mode 100755 index 00000000..e69de29b diff --git a/caom2tools/util/_astropy_init.py b/caom2tools/util/_astropy_init.py new file mode 100644 index 00000000..6d94a38b --- /dev/null +++ b/caom2tools/util/_astropy_init.py @@ -0,0 +1,138 @@ +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +__all__ = ['__version__', '__githash__', 'test'] + +# this indicates whether or not we are in the package's setup.py +try: + _ASTROPY_SETUP_ +except NameError: + from sys import version_info + if version_info[0] >= 3: + import builtins + else: + import __builtin__ as builtins + builtins._ASTROPY_SETUP_ = False + +try: + from .version import version as __version__ +except ImportError: + __version__ = '' +try: + from .version import githash as __githash__ +except ImportError: + __githash__ = '' + +# set up the test command +def _get_test_runner(): + import os + from astropy.tests.helper import TestRunner + return TestRunner(os.path.dirname(__file__)) + +def test(package=None, test_path=None, args=None, plugins=None, + verbose=False, pastebin=None, remote_data=False, pep8=False, + pdb=False, coverage=False, open_files=False, **kwargs): + """ + Run the tests using `py.test `__. A proper set + of arguments is constructed and passed to `pytest.main`_. + + .. _py.test: http://pytest.org/latest/ + .. _pytest.main: http://pytest.org/latest/builtin.html#pytest.main + + Parameters + ---------- + package : str, optional + The name of a specific package to test, e.g. 'io.fits' or 'utils'. + If nothing is specified all default tests are run. + + test_path : str, optional + Specify location to test by path. May be a single file or + directory. Must be specified absolutely or relative to the + calling directory. + + args : str, optional + Additional arguments to be passed to pytest.main_ in the ``args`` + keyword argument. + + plugins : list, optional + Plugins to be passed to pytest.main_ in the ``plugins`` keyword + argument. + + verbose : bool, optional + Convenience option to turn on verbose output from py.test_. Passing + True is the same as specifying ``'-v'`` in ``args``. + + pastebin : {'failed','all',None}, optional + Convenience option for turning on py.test_ pastebin output. Set to + ``'failed'`` to upload info for failed tests, or ``'all'`` to upload + info for all tests. + + remote_data : bool, optional + Controls whether to run tests marked with @remote_data. These + tests use online data and are not run by default. Set to True to + run these tests. + + pep8 : bool, optional + Turn on PEP8 checking via the `pytest-pep8 plugin + `_ and disable normal + tests. Same as specifying ``'--pep8 -k pep8'`` in ``args``. + + pdb : bool, optional + Turn on PDB post-mortem analysis for failing tests. Same as + specifying ``'--pdb'`` in ``args``. + + coverage : bool, optional + Generate a test coverage report. The result will be placed in + the directory htmlcov. + + open_files : bool, optional + Fail when any tests leave files open. Off by default, because + this adds extra run time to the test suite. Requires the + `psutil `_ package. + + parallel : int, optional + When provided, run the tests in parallel on the specified + number of CPUs. If parallel is negative, it will use the all + the cores on the machine. Requires the + `pytest-xdist `_ plugin + installed. Only available when using Astropy 0.3 or later. + + kwargs + Any additional keywords passed into this function will be passed + on to the astropy test runner. This allows use of test-related + functionality implemented in later versions of astropy without + explicitly updating the package template. + + """ + test_runner = _get_test_runner() + return test_runner.run_tests( + package=package, test_path=test_path, args=args, + plugins=plugins, verbose=verbose, pastebin=pastebin, + remote_data=remote_data, pep8=pep8, pdb=pdb, + coverage=coverage, open_files=open_files, **kwargs) + +if not _ASTROPY_SETUP_: + import os + from warnings import warn + from astropy import config + + # add these here so we only need to cleanup the namespace at the end + config_dir = None + + if not os.environ.get('ASTROPY_SKIP_CONFIG_UPDATE', False): + config_dir = os.path.dirname(__file__) + config_template = os.path.join(config_dir, __package__ + ".cfg") + if os.path.isfile(config_template): + try: + config.configuration.update_default_config( + __package__, config_dir, version=__version__) + except TypeError as orig_error: + try: + config.configuration.update_default_config( + __package__, config_dir) + except config.configuration.ConfigurationDefaultMissingError as e: + wmsg = (e.args[0] + " Cannot install default profile. If you are " + "importing from source, this is expected.") + warn(config.configuration.ConfigurationDefaultMissingWarning(wmsg)) + del e + except: + raise orig_error diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py new file mode 100755 index 00000000..d5276d2f --- /dev/null +++ b/caom2tools/util/caom2repo.py @@ -0,0 +1,319 @@ +## -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# +import sys +print('\n'.join(sys.path)) +from datetime import datetime +import errno +import logging +import httplib +import imp +import os +import os.path +#TODO to be changed to io.StringIO when caom2 is prepared for python3 +from StringIO import StringIO +import urllib + +from cadctools.net import ws + +from ..caom2 import ObservationReader, ObservationWriter + +BATCH_SIZE = int(10000) +SERVICE_URI = 'ivo://cadc.nrc.ca/caom2repo' +DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat + +class CAOM2RepoClient: + + """Class to do CRUD + visitor actions on a CAOM2 collection repo.""" + + def __init__(self, plugin, collection=None, start=None, end=None, retries=0, server=None): + + if retries is not None: + self.retries = int(retries) + else: + self.retries = 0 + + self.collection_uri = SERVICE_URI + '/' +\ + self.collection + # repo client to use + self._repo_client = ws.BaseWsServer(server) + logging.info('Service URL: {}'.format(self._repo_client.SERVICE_URL)) + + + def visit(self, plugin, collection=None, start=None, end=None): + """ + Main processing function that iterates through the observations of + the collection and updates them according to the algorithm + of the plugin function + """ + if not os.path.isfile(plugin): + raise Exception('Cannot find plugin file ' + plugin) + if start is not None: + assert type(start) is datetime + if end is not None: + assert type(end) is datetime + self._load_plugin_class(plugin) + count = 0 + observations = self._get_observations(collection, start, end) + while len(observations) > 0: + for observationID in observations: + observation = self._get_observation(observationID) + logging.info("Process observation: " + observation.observation_id) + self.plugin.update(observation) + self._persist_observation(observationID, observation) + count = count + 1 + if len(observations) == BATCH_SIZE: + observations = self._get_observations() + else: + # the last batch was smaller so it must have been the last + break; + return count + + def _get_observations(self, collection, start=None, end=None): + """ + Returns a list of datasets from the collection + """ + assert collection is not None + observations = [] + params = {'MAXREC':BATCH_SIZE} + if start: + params['START'] = start.strftime(DATE_FORMAT) + if end: + params['END'] = end.strftime(DATE_FORMAT) + + #self._repo_client.get(collection) + response = self._repo_client.send_request("GET", "/{}".format(self.collection), + {"Content-type": "application/x-www-form-urlencoded"}, + urllib.urlencode(params)) #TODO use BaseWs + if response.status != 200: + logging.error('Cannot find the %s collection at %s. \n' % + (self.collection, self._repo_client.SERVICE_URL)) + raise IOError(errno.ENOENT) + elif response.status >= 400: + logging.error( + 'Unable to retrieve list of observations from \'%s\'.\n' % + self.collection_uri) + logging.error('Server Returned: ' +\ + httplib.responses[response.status] + ' (' + + str(response.status) + ')\n' + response.read()) + raise IOError(errno.ENOEXEC) + else: + data = response.read() + last_datetime = None + for line in data.splitlines(): + (obs, last_datetime) = line.split(',') + observations.append(obs) + if last_datetime is not None: + self.current_start = datetime.strptime(last_datetime, DATE_FORMAT) + return observations + + + def _load_plugin_class(self, filepath): + expected_class = 'ObservationUpdater' + + mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1]) + + if file_ext.lower() == '.py': + py_mod = imp.load_source(mod_name, filepath) + + elif file_ext.lower() == '.pyc': + py_mod = imp.load_compiled(mod_name, filepath) + + if hasattr(py_mod, expected_class): + self.plugin = getattr(py_mod, expected_class)() + else: + raise Exception( + 'Cannot find ObservationUpdater class in pluging file ' +\ + filepath) + + if not hasattr(self.plugin, 'update'): + raise Exception('Cannot find update method in plugin class ' +\ + filepath) + + + def _get_observation(self, observationID): + logging.debug("GET " + observationID) + uri = '/' + self.collection + '/' + observationID + response = self._repo_client.send_request("GET", uri, {}, '') + + logging.debug("GET status: " + str(response.status)) + if response.status == 503 and (self.retries > 0): + response = self._repo_client.retry("GET", uri, {}, '') + + if response.status == 404: + logging.error('No such Observation found with URI \'%s\'.\n' % uri) + raise IOError(errno.ENOENT) + elif response.status >= 400: + logging.error('Unable to retrieve Observation with URI \'%s\'.\n' % uri) + logging.error('Server Returned: ' +\ + httplib.responses[response.status] + ' (' + + str(response.status) + ')\n' + response.read()) + raise IOError(errno.ENOEXEC) + else: + obs_reader = ObservationReader() + content = response.read() + if len(content) == 0: + logging.error(response.status) + response.close() + raise Exception("Got empty response for uri: " + uri) + return obs_reader.read(StringIO(content)) + + def _persist_observation(self, observationID, observation): + uri = '/' + self.collection + '/' + observationID + ibuffer = StringIO() + ObservationWriter().write(observation, ibuffer) + obs_xml = ibuffer.getvalue() + response = self._repo_client.send_request( + "POST", uri, {'Content-Type': 'text/xml'}, obs_xml) + + if response.status == 503 and (self.retries > 0): + response = self._repo_client.retry( + "POST", uri, {'Content-Type': 'text/xml'}, obs_xml) + + if response.status == 404: + logging.error('Observation with URI \'%s\' does not exist.\n' % uri) + raise IOError(errno.ENOENT) + elif response.status >= 400: + msg = '' + for hmsg in response.msg.headers: + msg = msg + hmsg + logging.error('Unable to update Observation ' + str(observationID) + + '\nServer Returned: ' +\ + httplib.responses[response.status] + ' (' + + str(response.status) + ')\n' + msg + response.read()) + raise IOError(errno.ENOEXEC) + else: + logging.debug('Successfully updated Observation\n') + + +def run(): + + parser = CommonParser(description=description, + formatter_class=argparse.RawTextHelpFormatter) + + parser.add_argument('--plugin', required=True, + metavar=(''), + help='Pluging class to update each observation') + parser.add_argument('--start', metavar='', + type=parse_date, + help='oldest dataset to visit (UTC %%Y-%%m-%%d format)'); + parser.add_argument('--end', metavar='', + type=parse_date, + help='earliest dataset to visit (UTC %%Y-%%m-%%d format)'); + parser.add_argument('--retries', metavar='', + type=int, + help='number of tries with transient server errors'); + parser.add_argument("-s", "--server", metavar=(''), + help="URL of the CAOM2 repo server") + + parser.add_argument('collection', metavar='', type=str, + help='data collection in CAOM2 repo') + parser.epilog =\ +""" +Minimum plugin file format: +---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation +---- +""" + + args = parser.parse_args() + + + if args.verbose: + logging.basicConfig(level=logging.INFO) + + if args.debug: + logging.basicConfig(level=logging.DEBUG) + + plugin = args.plugin + if not os.path.isfile(args.plugin): + logging.error('Cannot find plugin file ' + plugin) + sys.exit(-1) + + start = args.start + end = args.end + retries = args.retries + collection = args.collection + + logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". + format(plugin, start, end, collection, retries)) + client = CAOM2Visitor(plugin=plugin, start=start, end=end, + collection=collection, retries=retries, server=args.server) + client.process() + logging.debug("debug") + + print("DONE") + + diff --git a/caom2tools/util/conftest.py b/caom2tools/util/conftest.py new file mode 100644 index 00000000..e0465fef --- /dev/null +++ b/caom2tools/util/conftest.py @@ -0,0 +1,38 @@ +# this contains imports plugins that configure py.test for astropy tests. +# by importing them here in conftest.py they are discoverable by py.test +# no matter how it is invoked within the source tree. + +from astropy.tests.pytest_plugins import * + +## Uncomment the following line to treat all DeprecationWarnings as +## exceptions +# enable_deprecations_as_exceptions() + +## Uncomment and customize the following lines to add/remove entries from +## the list of packages for which version numbers are displayed when running +## the tests. Making it pass for KeyError is essential in some cases when +## the package uses other astropy affiliated packages. +# try: +# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' +# del PYTEST_HEADER_MODULES['h5py'] +# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 +# pass + +## Uncomment the following lines to display the version number of the +## package rather than the version number of Astropy in the top line when +## running the tests. +import os + +# This is to figure out the affiliated package version, rather than +# using Astropy's +try: + from .version import version +except ImportError: + version = 'dev' + +try: + packagename = os.path.basename(os.path.dirname(__file__)) + TESTED_VERSIONS[packagename] = version +except NameError: # Needed to support Astropy <= 1.0.0 + pass diff --git a/caom2tools/util/tests/__init__.py b/caom2tools/util/tests/__init__.py new file mode 100755 index 00000000..b7f9797a --- /dev/null +++ b/caom2tools/util/tests/__init__.py @@ -0,0 +1,169 @@ +# +# -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2010. (c) 2010. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +""" Deines __init__ """ + +# +from caom_object import CaomObject +from caom_object import AbstractCaomEntity + +# Util classes +from util import Util +from util import TypedList +from util import TypedSet +from util import TypedOrderedDict +from util import ClassProperty +from util import Validator + +# WCS data types +from wcs import Axis +from wcs import Coord2D +from wcs import CoordAxis1D +from wcs import CoordAxis2D +from wcs import CoordBounds1D +from wcs import CoordBounds2D +from wcs import CoordCircle2D +from wcs import CoordError +from wcs import CoordFunction1D +from wcs import CoordFunction2D +from wcs import CoordPolygon2D +from wcs import CoordRange1D +from wcs import CoordRange2D +from wcs import Dimension2D +from wcs import RefCoord +from wcs import Slice +from wcs import ValueCoord2D +from wcs import EnergyTransition + +# Discovery data types +from shape import Box +from shape import Circle +from shape import Interval +from shape import Point +from shape import Polygon +from shape import Vertex + +# Chunk level classes +from chunk import Chunk +from chunk import ObservableAxis +from chunk import SpatialWCS +from chunk import SpectralWCS +from chunk import TemporalWCS +from chunk import PolarizationWCS + +# Part level classes +from part import Part + +# Artifact level classes +from artifact import Artifact + +# Plane level classes +from plane import Plane +from plane import PlaneURI +from plane import DataQuality +from plane import Metrics +from plane import Provenance +from plane import Position +from plane import Energy +from plane import EnergyTransition +from plane import Polarization +from plane import Time + +# Observation level classes +from observation import Observation +from observation import ObservationURI +from observation import SimpleObservation +from observation import CompositeObservation +from observation import Algorithm +from observation import Environment +from observation import Proposal +from observation import Requirements +from observation import Target +from observation import TargetPosition +from observation import Telescope + +# enums +from artifact import ProductType +from artifact import ReleaseType +from plane import CalibrationLevel +from plane import DataProductType +from plane import EnergyBand +from plane import PolarizationState +from plane import Quality +from observation import ObservationIntentType +from observation import Status +from observation import TargetType + +# observation reader and writer +from obs_reader_writer import ObservationReader +from obs_reader_writer import ObservationWriter +from obs_reader_writer import CAOM20_NAMESPACE +from obs_reader_writer import CAOM21_NAMESPACE +from obs_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/util/tests/test_caom2repo.py b/caom2tools/util/tests/test_caom2repo.py new file mode 100644 index 00000000..9500d6ae --- /dev/null +++ b/caom2tools/util/tests/test_caom2repo.py @@ -0,0 +1,362 @@ +## -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +import unittest +import copy +import sys +import os +from mock import Mock, patch, MagicMock +#TODO to be changed to io.StringIO when caom2 is prepared for python3 +from StringIO import StringIO +from datetime import datetime + +from caom2tools.util.caom2repo import CAOM2RepoClient, DATE_FORMAT +from caom2tools.caom2.observation import SimpleObservation +from caom2tools.caom2 import ObservationReader, ObservationWriter + +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + +class TestCAOM2Repo(unittest.TestCase): + + """Test the Caom2Visitor class""" + + + def test_plugin_class(self): + + + + # plugin class does not change the observation + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + obs = SimpleObservation('cfht', '7000000o') + expect_obs = copy.deepcopy(obs) + visitor.plugin.update(obs) + self.assertEquals(expect_obs, obs) + + # plugin class adds a plane to the observation + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'addplaneplugin.py'), 'cfht') + obs = SimpleObservation('cfht', '7000000o') + expect_obs = copy.deepcopy(obs) + visitor.plugin.update(obs) + self.assertNotEquals(expect_obs, obs) + self.assertEquals(len(expect_obs.planes) + 1, len(obs.planes)) + + # non-existent the plugin file + with self.assertRaises(Exception): + visitor = CAOM2RepoClient('blah.py', 'cfht') + + # non-existent ObservationUpdater class in the plugin file + with self.assertRaises(Exception): + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'test_visitor.py'), 'cfht') + + # non-existent update method in ObservationUpdater class + with self.assertRaises(Exception): + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'noupdateplugin.py'), 'cfht') + + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) + @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) + @patch('caom2repoClient.caom2repoClient.HTTPSConnection') + def test_get_observation(self, mock_conn): + + obs = SimpleObservation('cfht', '7000000o') + writer = ObservationWriter() + ibuffer = StringIO() + writer.write(obs, ibuffer) + response = MagicMock() + response.status = 200 + response.read.return_value = ibuffer.getvalue() + conn = mock_conn.return_value + conn.getresponse.return_value = response + ibuffer.seek(0) # reposition the buffer for reading + + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + + self.assertEquals( + 'ivo://cadc.nrc.ca/caom2repo/cfht', visitor.collection_uri) + + self.assertEquals(obs, visitor._get_observation('700000o')) + conn.request.assert_called_once_with( + 'GET', '/caom2repo/pub/cfht/700000o', '', + {}) + + # signal some problems + response.status = 404 + with self.assertRaises(IOError): + visitor._get_observation('700000o') + + response.status = 405 + with self.assertRaises(IOError): + visitor._get_observation('700000o') + + # transient problem no retries + response.status = 503 + with self.assertRaises(IOError): + visitor._get_observation('700000o') + + # permanent transient problem with 2 retries + response.status = 503 + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + with self.assertRaises(IOError): + visitor._get_observation('700000o') + + # temporary transient problem. Succeeds after 2 retries + response.status = 200 + ibuffer.seek(0) # reposition the buffer for reading + transient_response = MagicMock() + transient_response.status = 503 + conn = MagicMock() + conn.getresponse.side_effect = [transient_response, transient_response, response] + mock_conn.return_value = conn + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + self.assertEquals(obs, visitor._get_observation('700000o')) + + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) + @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) + @patch('caom2visitor.visitor.CAOM2RepoClient') + def test_get_observations(self, mock_repo): + # This is almost similar to the previous test except that it gets + # observations matching a collection and start/end criteria + # Also, patch the CAOM2RepoClient now. + + response = MagicMock() + response.status = 200 + last_datetime = '2000-10-10T12:30:00.333' + response.read.return_value = '700000o,2000-10-10T12:20:11.123\n700001o,' +\ + last_datetime + repo = mock_repo.return_value + repo.send_request.return_value = response + + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + + self.assertEquals(None, visitor.start) + self.assertEquals(None, visitor.end) + self.assertEquals(None, visitor.current_start) + end_date = datetime.strptime(last_datetime, DATE_FORMAT) + + expect_observations = ['700000o', '700001o'] + self.assertEquals(expect_observations, visitor._get_observations()) + self.assertEquals(end_date, visitor.current_start) + repo.send_request.assert_called_once_with('GET', + '/cfht', + {"Content-type": "application/x-www-form-urlencoded"}, + 'MAXREC=10000') + + repo.reset_mock() + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', + end=datetime.strptime('2000-11-11', '%Y-%m-%d')) + visitor._get_observations() + repo.send_request.assert_called_once_with('GET', + '/cfht', + {"Content-type": "application/x-www-form-urlencoded"}, + 'END=2000-11-11T00%3A00%3A00.000000&MAXREC=10000') + + repo.reset_mock() + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', + start=datetime.strptime('2000-11-11', '%Y-%m-%d'), + end=datetime.strptime('2000-11-12', '%Y-%m-%d')) + visitor._get_observations() + repo.send_request.assert_called_once_with('GET', + '/cfht', + {"Content-type": "application/x-www-form-urlencoded"}, + 'START=2000-11-11T00%3A00%3A00.000000&' +\ + 'END=2000-11-12T00%3A00%3A00.000000&MAXREC=10000') + + # signal some problems + response.status = 404 + with self.assertRaises(IOError): + visitor._get_observations() + + response.status = 405 + with self.assertRaises(IOError): + visitor._get_observations() + + # transient problem no retries + response.status = 503 + with self.assertRaises(IOError): + visitor._get_observations() + + # permanent transient problem with 2 retries + response.status = 503 + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + repo.retry.return_value = response + with self.assertRaises(IOError): + visitor._get_observations() + + # temporary transient problem. Succeeds after 2 retries + repo.reset_mock() + response.status = 200 + transient_response = MagicMock() + transient_response.status = 503 + repo.send_request.return_value = transient_response + repo.retry.return_value = response + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + self.assertEquals(expect_observations, visitor._get_observations()) + self.assertEquals(end_date, visitor.current_start) + repo.send_request.assert_called_once_with('GET', + '/cfht', + {"Content-type": "application/x-www-form-urlencoded"}, + 'MAXREC=10000') + repo.retry.assert_called_once_with('GET', + '/cfht', + {"Content-type": "application/x-www-form-urlencoded"}, + 'MAXREC=10000') + + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) + @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) + @patch('caom2repoClient.caom2repoClient.HTTPSConnection') + def test_persist_observation(self, mock_conn): + obs = SimpleObservation('cfht', '7000000o') + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + response = MagicMock() + response.status = 200 + conn = mock_conn.return_value + conn.getresponse.return_value = response + #mock_conn.return_value = conn + iobuffer = StringIO() + ObservationWriter().write(obs, iobuffer) + obsxml = iobuffer.getvalue() + + visitor._persist_observation('700000o', obs) + + conn.request.assert_called_once_with( + 'POST', '/caom2repo/pub/cfht/700000o', obsxml, + {'Content-Type': 'text/xml'}) + + conn.reset_mock() + + # signal some problems + response.status = 404 + with self.assertRaises(IOError): + visitor._persist_observation('700000o', obs) + + response.status = 405 + with self.assertRaises(IOError): + visitor._persist_observation('700000o', obs) + + # transient problem no retries + response.status = 503 + with self.assertRaises(IOError): + visitor._persist_observation('700000o', obs) + + # permanent transient problem with 2 retries + response.status = 503 + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + with self.assertRaises(IOError): + visitor._persist_observation('700000o', obs) + + # temporary transient problem. Succeeds after 2 retries + response.status = 200 + transient_response = MagicMock() + transient_response.status = 503 + conn = MagicMock() + conn.getresponse.side_effect = [transient_response, transient_response, response] + mock_conn.return_value = conn + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht', retries=2) + visitor._persist_observation('700000o', obs) + conn.request.assert_called_with( + 'POST', '/caom2repo/pub/cfht/700000o', obsxml, + {'Content-Type': 'text/xml'}) + + + @patch('test_visitor.CAOM2Visitor._get_observation', MagicMock(), create = True) + @patch('test_visitor.CAOM2Visitor._persist_observation', MagicMock(), create = True) + @patch('test_visitor.CAOM2Visitor._get_observations') + def test_process(self, mock_obs): + CAOM2RepoClient.visitor.BATCH_SIZE = 3 # size of the batch is 3 + mock_obs.side_effect = [['a', 'b', 'c'], ['d'], []] + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + visitor.plugin = MagicMock() + self.assertEquals(4, visitor.process()) + + mock_obs.side_effect = [['a', 'b', 'c'], ['d', 'e', 'f'], []] + visitor = CAOM2RepoClient(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht') + visitor.plugin = MagicMock() + self.assertEquals(6, visitor.process()) From 4222050b84968e00e7420a69d3eba4d92418e805 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 17 Nov 2016 10:30:10 -0800 Subject: [PATCH 13/54] s1950: cleanup setup files --- caom2tools/COPYING | 661 ------------------------------------ caom2tools/Dependencies.txt | 47 --- caom2tools/MANIFEST.in | 2 - caom2tools/build.xml | 150 -------- caom2tools/requirements.txt | 3 - caom2tools/setup.cfg | 10 - caom2tools/setup.py | 65 ---- setup.cfg | 8 +- setup.py | 6 +- 9 files changed, 7 insertions(+), 945 deletions(-) delete mode 100644 caom2tools/COPYING delete mode 100644 caom2tools/Dependencies.txt delete mode 100644 caom2tools/MANIFEST.in delete mode 100644 caom2tools/build.xml delete mode 100644 caom2tools/requirements.txt delete mode 100644 caom2tools/setup.cfg delete mode 100755 caom2tools/setup.py diff --git a/caom2tools/COPYING b/caom2tools/COPYING deleted file mode 100644 index dba13ed2..00000000 --- a/caom2tools/COPYING +++ /dev/null @@ -1,661 +0,0 @@ - GNU AFFERO GENERAL PUBLIC LICENSE - Version 3, 19 November 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU Affero General Public License is a free, copyleft license for -software and other kinds of works, specifically designed to ensure -cooperation with the community in the case of network server software. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -our General Public Licenses are intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - Developers that use our General Public Licenses protect your rights -with two steps: (1) assert copyright on the software, and (2) offer -you this License which gives you legal permission to copy, distribute -and/or modify the software. - - A secondary benefit of defending all users' freedom is that -improvements made in alternate versions of the program, if they -receive widespread use, become available for other developers to -incorporate. Many developers of free software are heartened and -encouraged by the resulting cooperation. However, in the case of -software used on network servers, this result may fail to come about. -The GNU General Public License permits making a modified version and -letting the public access it on a server without ever releasing its -source code to the public. - - The GNU Affero General Public License is designed specifically to -ensure that, in such cases, the modified source code becomes available -to the community. It requires the operator of a network server to -provide the source code of the modified version running there to the -users of that server. Therefore, public use of a modified version, on -a publicly accessible server, gives the public access to the source -code of the modified version. - - An older license, called the Affero General Public License and -published by Affero, was designed to accomplish similar goals. This is -a different license, not a version of the Affero GPL, but Affero has -released a new version of the Affero GPL which permits relicensing under -this license. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU Affero General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Remote Network Interaction; Use with the GNU General Public License. - - Notwithstanding any other provision of this License, if you modify the -Program, your modified version must prominently offer all users -interacting with it remotely through a computer network (if your version -supports such interaction) an opportunity to receive the Corresponding -Source of your version by providing access to the Corresponding Source -from a network server at no charge, through some standard or customary -means of facilitating copying of software. This Corresponding Source -shall include the Corresponding Source for any work covered by version 3 -of the GNU General Public License that is incorporated pursuant to the -following paragraph. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the work with which it is combined will remain governed by version -3 of the GNU General Public License. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU Affero General Public License from time to time. Such new versions -will be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU Affero General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU Affero General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU Affero General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU Affero General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU Affero General Public License for more details. - - You should have received a copy of the GNU Affero General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If your software can interact with users remotely through a computer -network, you should also make sure that it provides a way for users to -get its source. For example, if your program is a web application, its -interface could display a "Source" link that leads users to an archive -of the code. There are many ways you could offer source, and different -solutions will be better for different programs; see section 13 for the -specific requirements. - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU AGPL, see -. diff --git a/caom2tools/Dependencies.txt b/caom2tools/Dependencies.txt deleted file mode 100644 index 7923b46b..00000000 --- a/caom2tools/Dependencies.txt +++ /dev/null @@ -1,47 +0,0 @@ -# -# -*- coding: utf-8 -*- -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2 -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -Files required for the pyCAOM2 project -==================================================== - -Name in build.xml Versioned Name Project URL ------------------ -------------------- ----------- - diff --git a/caom2tools/MANIFEST.in b/caom2tools/MANIFEST.in deleted file mode 100644 index 5d7be42c..00000000 --- a/caom2tools/MANIFEST.in +++ /dev/null @@ -1,2 +0,0 @@ -include caom2/*.xsd -include caom2/tests/data/*.xml diff --git a/caom2tools/build.xml b/caom2tools/build.xml deleted file mode 100644 index bb37ad87..00000000 --- a/caom2tools/build.xml +++ /dev/null @@ -1,150 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/caom2tools/requirements.txt b/caom2tools/requirements.txt deleted file mode 100644 index dc67614a..00000000 --- a/caom2tools/requirements.txt +++ /dev/null @@ -1,3 +0,0 @@ -lxml -requests -urllib3 diff --git a/caom2tools/setup.cfg b/caom2tools/setup.cfg deleted file mode 100644 index 2216d825..00000000 --- a/caom2tools/setup.cfg +++ /dev/null @@ -1,10 +0,0 @@ -[global] -verbose=0 - -version = 0.6.3 -description = "CAOM2 Class libraries" - -[install] -install-purelib=$base/lib/python$py_version_short/site-packages -install-platlib=$base/lib/python$py_version_short/site-packages -install_headers=$base/include/python$py_version_short/$dist_name diff --git a/caom2tools/setup.py b/caom2tools/setup.py deleted file mode 100755 index 88d4aca6..00000000 --- a/caom2tools/setup.py +++ /dev/null @@ -1,65 +0,0 @@ -#!/usr/bin/env python2.7 -# -*- coding: utf-8 -*- -#/*+ -#************************************************************************ -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#* -#* (c) 2012. (c)2012. -#* National Research Council Conseil national de recherches -#* Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -#* All rights reserved Tous droits reserves -#* -#* NRC disclaims any warranties, Le CNRC denie toute garantie -#* expressed, implied, or statu- enoncee, implicite ou legale, -#* tory, of any kind with respect de quelque nature que se soit, -#* to the software, including concernant le logiciel, y com- -#* without limitation any war- pris sans restriction toute -#* ranty of merchantability or garantie de valeur marchande -#* fitness for a particular pur- ou de pertinence pour un usage -#* pose. NRC shall not be liable particulier. Le CNRC ne -#* in any event for any damages, pourra en aucun cas etre tenu -#* whether direct or indirect, responsable de tout dommage, -#* special or general, consequen- direct ou indirect, particul- -#* tial or incidental, arising ier ou general, accessoire ou -#* from the use of the software. fortuit, resultant de l'utili- -#* sation du logiciel. -#* -#************************************************************************ -#* -#* Script Name: setup.py -#* -#* Purpose: -#* Distutils setup script for caom2 -#* -#* Functions: -#* -#* -#* -#**** C A N A D I A N A S T R O N O M Y D A T A C E N T R E ***** -#************************************************************************ -#-*/ - -# Use "distribute" -from setuptools import setup, find_packages -import sys - -if sys.version_info[0] > 2: - print 'The caom2 package is only compatible with Python version 2.n' - sys.exit(-1) - -setup(name='caom2tools', - version='2.3.0', - description='CAOM-2.2 library', - url='This is a Home-page.', - author='Canadian Astronomy Data Centre', - author_email='cadc@nrc.ca', - license='GPLv3', - long_description='Python library for the CAOM-2.2 data model', - # packages=find_packages(exclude=['caom2.test']), - package_data={'caom2': ['CAOM-2.0.xsd', 'CAOM-2.1.xsd', 'CAOM-2.2.xsd'], 'caom2.tests.data': ['*.xml']}, - include_package_data=True, - requires=['lxml', 'requests'], - provides=['caom2tools'], - zip_safe=False -) - diff --git a/setup.cfg b/setup.cfg index 8eef705f..16151e43 100644 --- a/setup.cfg +++ b/setup.cfg @@ -22,16 +22,16 @@ auto_use = True [metadata] package_name = caom2tools -description = Astropy affiliated package -long_description = This is a package for handling Common Archive Observation Model (CAOM2). CAOM2 is a general purpose data model for use as the core data model of an astronomical data centre. +description = CAOM-2.2 library +long_description = Python library for the CAOM-2.2 data model author = Canadian Astronomy Data Centre author_email = cadc@nrc-cnrc.gc.ca -license = BSD +license = AGPLv3 url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 edit_on_github = False github_project = opencadc/caom2tools # version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -version = 0.1.dev +version = 2.2.2 [entry_points] astropy-package-template-example = caom2tools.example_mod:main diff --git a/setup.py b/setup.py index e3f4adc0..fc15d3b8 100755 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ import ah_bootstrap from setuptools import setup -#A dirty hack to get around some early import/configurations ambiguities +# A dirty hack to get around some early import/configurations ambiguities if sys.version_info[0] >= 3: import builtins else: @@ -47,7 +47,7 @@ builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME # VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -VERSION = metadata.get('version', '0.0.dev') +VERSION = metadata.get('version', '2.2.2') # Indicates if this version is a release version RELEASE = 'dev' not in VERSION @@ -106,7 +106,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['astropy'], + install_requires=['lxml', 'astropy', 'requests'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, From eb4e47855b8e2616629e6eaffda2a51d8140fe3a Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 17 Nov 2016 13:01:22 -0800 Subject: [PATCH 14/54] s1950: sort out astropy setup and config files --- caom2tools/__init__.py | 6 +- caom2tools/caom2/test/__init__.py | 73 -------------- caom2tools/conftest.py | 28 +++--- caom2tools/util/conftest.py | 38 -------- caom2tools/util/{tests => test}/__init__.py | 97 ------------------- .../util/{tests => test}/test_caom2repo.py | 0 6 files changed, 17 insertions(+), 225 deletions(-) delete mode 100644 caom2tools/util/conftest.py rename caom2tools/util/{tests => test}/__init__.py (60%) rename caom2tools/util/{tests => test}/test_caom2repo.py (100%) diff --git a/caom2tools/__init__.py b/caom2tools/__init__.py index 22a75cf8..e7359a5f 100644 --- a/caom2tools/__init__.py +++ b/caom2tools/__init__.py @@ -7,10 +7,10 @@ # Affiliated packages may add whatever they like to this file, but # should keep this content at the top. # ---------------------------------------------------------------------------- -# from ._astropy_init import * +from ._astropy_init import * # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -# if not _ASTROPY_SETUP_: +if not _ASTROPY_SETUP_: # from .caom2tools import * -# pass + pass diff --git a/caom2tools/caom2/test/__init__.py b/caom2tools/caom2/test/__init__.py index e96603b4..e69de29b 100644 --- a/caom2tools/caom2/test/__init__.py +++ b/caom2tools/caom2/test/__init__.py @@ -1,73 +0,0 @@ -# -# -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** -# -# (c) 2010. (c) 2010. -# Government of Canada Gouvernement du Canada -# National Research Council Conseil national de recherches -# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 -# All rights reserved Tous droits réservés -# -# NRC disclaims any warranties, Le CNRC dénie toute garantie -# expressed, implied, or énoncée, implicite ou légale, -# statutory, of any kind with de quelque nature que ce -# respect to the software, soit, concernant le logiciel, -# including without limitation y compris sans restriction -# any warranty of merchantability toute garantie de valeur -# or fitness for a particular marchande ou de pertinence -# purpose. NRC shall not be pour un usage particulier. -# liable in any event for any Le CNRC ne pourra en aucun cas -# damages, whether direct or être tenu responsable de tout -# indirect, special or general, dommage, direct ou indirect, -# consequential or incidental, particulier ou général, -# arising from the use of the accessoire ou fortuit, résultant -# software. Neither the name de l'utilisation du logiciel. Ni -# of the National Research le nom du Conseil National de -# Council of Canada nor the Recherches du Canada ni les noms -# names of its contributors may de ses participants ne peuvent -# be used to endorse or promote être utilisés pour approuver ou -# products derived from this promouvoir les produits dérivés -# software without specific prior de ce logiciel sans autorisation -# written permission. préalable et particulière -# par écrit. -# -# This file is part of the Ce fichier fait partie du projet -# OpenCADC project. OpenCADC. -# -# OpenCADC is free software: OpenCADC est un logiciel libre ; -# you can redistribute it and/or vous pouvez le redistribuer ou le -# modify it under the terms of modifier suivant les termes de -# the GNU Affero General Public la “GNU Affero General Public -# License as published by the License” telle que publiée -# Free Software Foundation, par la Free Software Foundation -# either version 3 of the : soit la version 3 de cette -# License, or (at your option) licence, soit (à votre gré) -# any later version. toute version ultérieure. -# -# OpenCADC is distributed in the OpenCADC est distribué -# hope that it will be useful, dans l’espoir qu’il vous -# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE -# without even the implied GARANTIE : sans même la garantie -# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ -# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF -# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence -# General Public License for Générale Publique GNU Affero -# more details. pour plus de détails. -# -# You should have received Vous devriez avoir reçu une -# a copy of the GNU Affero copie de la Licence Générale -# General Public License along Publique GNU Affero avec -# with OpenCADC. If not, see OpenCADC ; si ce n’est -# . pas le cas, consultez : -# . -# -# $Revision: 4 $ -# -#*********************************************************************** -# - -""" Defines __init__ """ - -from caom_test_instances import Caom2TestInstances diff --git a/caom2tools/conftest.py b/caom2tools/conftest.py index e0465fef..829ba1d7 100644 --- a/caom2tools/conftest.py +++ b/caom2tools/conftest.py @@ -22,17 +22,17 @@ ## Uncomment the following lines to display the version number of the ## package rather than the version number of Astropy in the top line when ## running the tests. -import os - -# This is to figure out the affiliated package version, rather than -# using Astropy's -try: - from .version import version -except ImportError: - version = 'dev' - -try: - packagename = os.path.basename(os.path.dirname(__file__)) - TESTED_VERSIONS[packagename] = version -except NameError: # Needed to support Astropy <= 1.0.0 - pass +# import os +# +# # This is to figure out the affiliated package version, rather than +# # using Astropy's +# try: +# from .version import version +# except ImportError: +# version = 'dev' +# +# try: +# packagename = os.path.basename(os.path.dirname(__file__)) +# TESTED_VERSIONS[packagename] = version +# except NameError: # Needed to support Astropy <= 1.0.0 +# pass diff --git a/caom2tools/util/conftest.py b/caom2tools/util/conftest.py deleted file mode 100644 index e0465fef..00000000 --- a/caom2tools/util/conftest.py +++ /dev/null @@ -1,38 +0,0 @@ -# this contains imports plugins that configure py.test for astropy tests. -# by importing them here in conftest.py they are discoverable by py.test -# no matter how it is invoked within the source tree. - -from astropy.tests.pytest_plugins import * - -## Uncomment the following line to treat all DeprecationWarnings as -## exceptions -# enable_deprecations_as_exceptions() - -## Uncomment and customize the following lines to add/remove entries from -## the list of packages for which version numbers are displayed when running -## the tests. Making it pass for KeyError is essential in some cases when -## the package uses other astropy affiliated packages. -# try: -# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' -# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' -# del PYTEST_HEADER_MODULES['h5py'] -# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 -# pass - -## Uncomment the following lines to display the version number of the -## package rather than the version number of Astropy in the top line when -## running the tests. -import os - -# This is to figure out the affiliated package version, rather than -# using Astropy's -try: - from .version import version -except ImportError: - version = 'dev' - -try: - packagename = os.path.basename(os.path.dirname(__file__)) - TESTED_VERSIONS[packagename] = version -except NameError: # Needed to support Astropy <= 1.0.0 - pass diff --git a/caom2tools/util/tests/__init__.py b/caom2tools/util/test/__init__.py similarity index 60% rename from caom2tools/util/tests/__init__.py rename to caom2tools/util/test/__init__.py index b7f9797a..2a4a293e 100755 --- a/caom2tools/util/tests/__init__.py +++ b/caom2tools/util/test/__init__.py @@ -70,100 +70,3 @@ """ Deines __init__ """ -# -from caom_object import CaomObject -from caom_object import AbstractCaomEntity - -# Util classes -from util import Util -from util import TypedList -from util import TypedSet -from util import TypedOrderedDict -from util import ClassProperty -from util import Validator - -# WCS data types -from wcs import Axis -from wcs import Coord2D -from wcs import CoordAxis1D -from wcs import CoordAxis2D -from wcs import CoordBounds1D -from wcs import CoordBounds2D -from wcs import CoordCircle2D -from wcs import CoordError -from wcs import CoordFunction1D -from wcs import CoordFunction2D -from wcs import CoordPolygon2D -from wcs import CoordRange1D -from wcs import CoordRange2D -from wcs import Dimension2D -from wcs import RefCoord -from wcs import Slice -from wcs import ValueCoord2D -from wcs import EnergyTransition - -# Discovery data types -from shape import Box -from shape import Circle -from shape import Interval -from shape import Point -from shape import Polygon -from shape import Vertex - -# Chunk level classes -from chunk import Chunk -from chunk import ObservableAxis -from chunk import SpatialWCS -from chunk import SpectralWCS -from chunk import TemporalWCS -from chunk import PolarizationWCS - -# Part level classes -from part import Part - -# Artifact level classes -from artifact import Artifact - -# Plane level classes -from plane import Plane -from plane import PlaneURI -from plane import DataQuality -from plane import Metrics -from plane import Provenance -from plane import Position -from plane import Energy -from plane import EnergyTransition -from plane import Polarization -from plane import Time - -# Observation level classes -from observation import Observation -from observation import ObservationURI -from observation import SimpleObservation -from observation import CompositeObservation -from observation import Algorithm -from observation import Environment -from observation import Proposal -from observation import Requirements -from observation import Target -from observation import TargetPosition -from observation import Telescope - -# enums -from artifact import ProductType -from artifact import ReleaseType -from plane import CalibrationLevel -from plane import DataProductType -from plane import EnergyBand -from plane import PolarizationState -from plane import Quality -from observation import ObservationIntentType -from observation import Status -from observation import TargetType - -# observation reader and writer -from obs_reader_writer import ObservationReader -from obs_reader_writer import ObservationWriter -from obs_reader_writer import CAOM20_NAMESPACE -from obs_reader_writer import CAOM21_NAMESPACE -from obs_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/util/tests/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py similarity index 100% rename from caom2tools/util/tests/test_caom2repo.py rename to caom2tools/util/test/test_caom2repo.py From 7f474b1d1a42b58fe8fb920fd5a87fa6e049ff16 Mon Sep 17 00:00:00 2001 From: andamian Date: Thu, 17 Nov 2016 13:03:52 -0800 Subject: [PATCH 15/54] Implemented caom2repo --- caom2tools/util/caom2repo.py | 183 +++++----- caom2tools/util/tests/test_caom2repo.py | 436 ++++++++++++------------ 2 files changed, 308 insertions(+), 311 deletions(-) diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py index d5276d2f..fb8bc74a 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2tools/util/caom2repo.py @@ -66,46 +66,44 @@ # #*********************************************************************** # -import sys -print('\n'.join(sys.path)) from datetime import datetime -import errno import logging -import httplib +import argparse import imp import os +import sys import os.path #TODO to be changed to io.StringIO when caom2 is prepared for python3 -from StringIO import StringIO -import urllib - +from StringIO import StringIO from cadctools.net import ws +from cadctools.util import util from ..caom2 import ObservationReader, ObservationWriter BATCH_SIZE = int(10000) -SERVICE_URI = 'ivo://cadc.nrc.ca/caom2repo' +SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat class CAOM2RepoClient: """Class to do CRUD + visitor actions on a CAOM2 collection repo.""" - def __init__(self, plugin, collection=None, start=None, end=None, retries=0, server=None): + def __init__(self, start=None, end=None, retries=0, server=None): if retries is not None: self.retries = int(retries) else: self.retries = 0 - self.collection_uri = SERVICE_URI + '/' +\ - self.collection # repo client to use - self._repo_client = ws.BaseWsServer(server) - logging.info('Service URL: {}'.format(self._repo_client.SERVICE_URL)) + if server is not None: + self._repo_client = ws.BaseWsClient(server) + else: + self._repo_client = ws.BaseWsClient(SERVICE_URL) + logging.info('Service URL: {}'.format(self._repo_client.base_url)) - def visit(self, plugin, collection=None, start=None, end=None): + def visit(self, plugin, collection, start=None, end=None): """ Main processing function that iterates through the observations of the collection and updates them according to the algorithm @@ -113,25 +111,27 @@ def visit(self, plugin, collection=None, start=None, end=None): """ if not os.path.isfile(plugin): raise Exception('Cannot find plugin file ' + plugin) + assert collection is not None if start is not None: assert type(start) is datetime if end is not None: assert type(end) is datetime self._load_plugin_class(plugin) + self._start = start # this is updated by _get_observations with the timestamp of last observation in the batch count = 0 - observations = self._get_observations(collection, start, end) + observations = self._get_observations(collection, self._start, end) while len(observations) > 0: for observationID in observations: - observation = self._get_observation(observationID) + observation = self.get_observation(collection, observationID) logging.info("Process observation: " + observation.observation_id) self.plugin.update(observation) - self._persist_observation(observationID, observation) + self.post_observation(collection, observationID, observation) count = count + 1 if len(observations) == BATCH_SIZE: observations = self._get_observations() else: # the last batch was smaller so it must have been the last - break; + break return count def _get_observations(self, collection, start=None, end=None): @@ -141,35 +141,17 @@ def _get_observations(self, collection, start=None, end=None): assert collection is not None observations = [] params = {'MAXREC':BATCH_SIZE} - if start: + if start is not None: params['START'] = start.strftime(DATE_FORMAT) - if end: + if end is not None: params['END'] = end.strftime(DATE_FORMAT) - #self._repo_client.get(collection) - response = self._repo_client.send_request("GET", "/{}".format(self.collection), - {"Content-type": "application/x-www-form-urlencoded"}, - urllib.urlencode(params)) #TODO use BaseWs - if response.status != 200: - logging.error('Cannot find the %s collection at %s. \n' % - (self.collection, self._repo_client.SERVICE_URL)) - raise IOError(errno.ENOENT) - elif response.status >= 400: - logging.error( - 'Unable to retrieve list of observations from \'%s\'.\n' % - self.collection_uri) - logging.error('Server Returned: ' +\ - httplib.responses[response.status] + ' (' - + str(response.status) + ')\n' + response.read()) - raise IOError(errno.ENOEXEC) - else: - data = response.read() - last_datetime = None - for line in data.splitlines(): - (obs, last_datetime) = line.split(',') - observations.append(obs) + response = self._repo_client.get(collection, params=params) + for line in response.content.splitlines(): + (obs, last_datetime) = line.split(',') + observations.append(obs) if last_datetime is not None: - self.current_start = datetime.strptime(last_datetime, DATE_FORMAT) + self._start = datetime.strptime(last_datetime, DATE_FORMAT) return observations @@ -196,65 +178,78 @@ def _load_plugin_class(self, filepath): filepath) - def _get_observation(self, observationID): - logging.debug("GET " + observationID) - uri = '/' + self.collection + '/' + observationID - response = self._repo_client.send_request("GET", uri, {}, '') - - logging.debug("GET status: " + str(response.status)) - if response.status == 503 and (self.retries > 0): - response = self._repo_client.retry("GET", uri, {}, '') - - if response.status == 404: - logging.error('No such Observation found with URI \'%s\'.\n' % uri) - raise IOError(errno.ENOENT) - elif response.status >= 400: - logging.error('Unable to retrieve Observation with URI \'%s\'.\n' % uri) - logging.error('Server Returned: ' +\ - httplib.responses[response.status] + ' (' - + str(response.status) + ')\n' + response.read()) - raise IOError(errno.ENOEXEC) - else: - obs_reader = ObservationReader() - content = response.read() - if len(content) == 0: - logging.error(response.status) - response.close() - raise Exception("Got empty response for uri: " + uri) - return obs_reader.read(StringIO(content)) - - def _persist_observation(self, observationID, observation): - uri = '/' + self.collection + '/' + observationID + def get_observation(self, collection, observationID): + assert collection is not None + assert observationID is not None + resource = '/{}/{}'.format(collection, observationID) + logging.debug('GET '.format(resource)) + + response = self._repo_client.get(resource) + obs_reader = ObservationReader() + content = response.content + if len(content) == 0: + logging.error(response.status) + response.close() + raise Exception('Got empty response for resource: {}'.format(resource)) + return obs_reader.read(StringIO(content)) + + + def post_observation(self, collection, observationID, observation): + assert collection is not None + assert observationID is not None + resource = '/{}/{}'.format(collection, observationID) + logging.debug('POST {}'.format(resource)) + ibuffer = StringIO() ObservationWriter().write(observation, ibuffer) obs_xml = ibuffer.getvalue() - response = self._repo_client.send_request( - "POST", uri, {'Content-Type': 'text/xml'}, obs_xml) - - if response.status == 503 and (self.retries > 0): - response = self._repo_client.retry( - "POST", uri, {'Content-Type': 'text/xml'}, obs_xml) - - if response.status == 404: - logging.error('Observation with URI \'%s\' does not exist.\n' % uri) - raise IOError(errno.ENOENT) - elif response.status >= 400: - msg = '' - for hmsg in response.msg.headers: - msg = msg + hmsg - logging.error('Unable to update Observation ' + str(observationID) - + '\nServer Returned: ' +\ - httplib.responses[response.status] + ' (' - + str(response.status) + ')\n' + msg + response.read()) - raise IOError(errno.ENOEXEC) - else: - logging.debug('Successfully updated Observation\n') + headers = {'Content-Type': 'application/xml'} + response = self._repo_client.post( + resource, headers=headers, data=obs_xml) + logging.debug('Successfully updated Observation\n') + obs_reader = ObservationReader() + content = response.content + if len(content) == 0: + logging.error(response.status) + response.close() + raise Exception('Got empty response for resource: {}'.format(resource)) + return obs_reader.read(StringIO(content)) + + + def put_observation(self, collection, observation): + assert collection is not None + resource = '/{}'.format(collection) + logging.debug('PUT {}'.format(resource)) + + ibuffer = StringIO() + ObservationWriter().write(observation, ibuffer) + obs_xml = ibuffer.getvalue() + headers = {'Content-Type': 'application/xml'} + response = self._repo_client.put( + resource, headers=headers, data=obs_xml) + logging.debug('Successfully put Observation\n') + obs_reader = ObservationReader() + content = response.content + if len(content) == 0: + logging.error(response.status) + response.close() + raise Exception('Got empty response for resource: {}'.format(resource)) + return obs_reader.read(StringIO(content)) + + + def delete_observation(self, collection, observationID): + assert observationID is not None + resource = '/{}/{}'.format(collection, observationID) + logging.debug('DELETE {}'.format(resource)) + response = self._repo_client.delete(resource) + logging.debug('Successfully deleted Observation\n') def run(): - parser = CommonParser(description=description, + parser = util.BaseParser(description=description, formatter_class=argparse.RawTextHelpFormatter) + parser.description = description parser.add_argument('--plugin', required=True, metavar=(''), diff --git a/caom2tools/util/tests/test_caom2repo.py b/caom2tools/util/tests/test_caom2repo.py index 9500d6ae..f5754044 100644 --- a/caom2tools/util/tests/test_caom2repo.py +++ b/caom2tools/util/tests/test_caom2repo.py @@ -71,11 +71,13 @@ import copy import sys import os +import requests from mock import Mock, patch, MagicMock #TODO to be changed to io.StringIO when caom2 is prepared for python3 from StringIO import StringIO from datetime import datetime +from caom2tools.util import caom2repo from caom2tools.util.caom2repo import CAOM2RepoClient, DATE_FORMAT from caom2tools.caom2.observation import SimpleObservation from caom2tools.caom2 import ObservationReader, ObservationWriter @@ -88,275 +90,275 @@ class TestCAOM2Repo(unittest.TestCase): def test_plugin_class(self): - - - # plugin class does not change the observation - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') - obs = SimpleObservation('cfht', '7000000o') + collection = 'cfht' + observation_id = '7000000o' + visitor = CAOM2RepoClient() + obs = SimpleObservation(collection, observation_id) expect_obs = copy.deepcopy(obs) + visitor._load_plugin_class(os.path.join(THIS_DIR, 'passplugin.py')) visitor.plugin.update(obs) self.assertEquals(expect_obs, obs) # plugin class adds a plane to the observation - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'addplaneplugin.py'), 'cfht') + visitor = CAOM2RepoClient() obs = SimpleObservation('cfht', '7000000o') expect_obs = copy.deepcopy(obs) + visitor._load_plugin_class(os.path.join(THIS_DIR, 'addplaneplugin.py')) visitor.plugin.update(obs) self.assertNotEquals(expect_obs, obs) self.assertEquals(len(expect_obs.planes) + 1, len(obs.planes)) # non-existent the plugin file with self.assertRaises(Exception): - visitor = CAOM2RepoClient('blah.py', 'cfht') + visitor._load_plugin_class(os.path.join(THIS_DIR, 'blah.py')) # non-existent ObservationUpdater class in the plugin file with self.assertRaises(Exception): - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'test_visitor.py'), 'cfht') + visitor._load_plugin_class(os.path.join(THIS_DIR, 'test_visitor.py')) # non-existent update method in ObservationUpdater class with self.assertRaises(Exception): - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'noupdateplugin.py'), 'cfht') + visitor._load_plugin_class(os.path.join(THIS_DIR, 'noupdateplugin.py')) # patch sleep to stop the test from sleeping and slowing down execution - @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) - @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) - @patch('caom2repoClient.caom2repoClient.HTTPSConnection') - def test_get_observation(self, mock_conn): - - obs = SimpleObservation('cfht', '7000000o') + @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.open', MagicMock(), create=True) + @patch('cadctools.net.ws.Session.send') + def test_get_observation(self, mock_get): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + obs = SimpleObservation(collection, observation_id) writer = ObservationWriter() ibuffer = StringIO() writer.write(obs, ibuffer) response = MagicMock() - response.status = 200 - response.read.return_value = ibuffer.getvalue() - conn = mock_conn.return_value - conn.getresponse.return_value = response + response.status_code = 200 + response.content = ibuffer.getvalue() + mock_get.return_value = response ibuffer.seek(0) # reposition the buffer for reading + visitor = CAOM2RepoClient(server=service_url) + self.assertEquals(obs, visitor.get_observation(collection, observation_id)) - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') - - self.assertEquals( - 'ivo://cadc.nrc.ca/caom2repo/cfht', visitor.collection_uri) - - self.assertEquals(obs, visitor._get_observation('700000o')) - conn.request.assert_called_once_with( - 'GET', '/caom2repo/pub/cfht/700000o', '', - {}) - - # signal some problems - response.status = 404 - with self.assertRaises(IOError): - visitor._get_observation('700000o') + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.get_observation(collection, observation_id) - response.status = 405 - with self.assertRaises(IOError): - visitor._get_observation('700000o') - - # transient problem no retries - response.status = 503 - with self.assertRaises(IOError): - visitor._get_observation('700000o') - - # permanent transient problem with 2 retries - response.status = 503 - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - with self.assertRaises(IOError): - visitor._get_observation('700000o') - - # temporary transient problem. Succeeds after 2 retries - response.status = 200 - ibuffer.seek(0) # reposition the buffer for reading - transient_response = MagicMock() - transient_response.status = 503 - conn = MagicMock() - conn.getresponse.side_effect = [transient_response, transient_response, response] - mock_conn.return_value = conn - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - self.assertEquals(obs, visitor._get_observation('700000o')) + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.get_observation(collection, observation_id) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + def raise_error(): raise http_error + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.get_observation(collection, observation_id) # patch sleep to stop the test from sleeping and slowing down execution - @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) - @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) - @patch('caom2visitor.visitor.CAOM2RepoClient') - def test_get_observations(self, mock_repo): + @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.open', MagicMock(), create=True) + @patch('caom2tools.util.caom2repo.ws.BaseWsClient.get') + def test_get_observations(self, mock_get): # This is almost similar to the previous test except that it gets # observations matching a collection and start/end criteria # Also, patch the CAOM2RepoClient now. response = MagicMock() - response.status = 200 + response.status_code = 200 last_datetime = '2000-10-10T12:30:00.333' - response.read.return_value = '700000o,2000-10-10T12:20:11.123\n700001o,' +\ + response.content = '700000o,2000-10-10T12:20:11.123\n700001o,' +\ last_datetime - repo = mock_repo.return_value - repo.send_request.return_value = response - - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') + mock_get.return_value = response - self.assertEquals(None, visitor.start) - self.assertEquals(None, visitor.end) - self.assertEquals(None, visitor.current_start) + visitor = CAOM2RepoClient() end_date = datetime.strptime(last_datetime, DATE_FORMAT) expect_observations = ['700000o', '700001o'] - self.assertEquals(expect_observations, visitor._get_observations()) - self.assertEquals(end_date, visitor.current_start) - repo.send_request.assert_called_once_with('GET', - '/cfht', - {"Content-type": "application/x-www-form-urlencoded"}, - 'MAXREC=10000') - - repo.reset_mock() - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', - end=datetime.strptime('2000-11-11', '%Y-%m-%d')) - visitor._get_observations() - repo.send_request.assert_called_once_with('GET', - '/cfht', - {"Content-type": "application/x-www-form-urlencoded"}, - 'END=2000-11-11T00%3A00%3A00.000000&MAXREC=10000') - - repo.reset_mock() - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', - start=datetime.strptime('2000-11-11', '%Y-%m-%d'), - end=datetime.strptime('2000-11-12', '%Y-%m-%d')) - visitor._get_observations() - repo.send_request.assert_called_once_with('GET', - '/cfht', - {"Content-type": "application/x-www-form-urlencoded"}, - 'START=2000-11-11T00%3A00%3A00.000000&' +\ - 'END=2000-11-12T00%3A00%3A00.000000&MAXREC=10000') - - # signal some problems - response.status = 404 - with self.assertRaises(IOError): - visitor._get_observations() - - response.status = 405 - with self.assertRaises(IOError): - visitor._get_observations() - - # transient problem no retries - response.status = 503 - with self.assertRaises(IOError): - visitor._get_observations() - - # permanent transient problem with 2 retries - response.status = 503 - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - repo.retry.return_value = response - with self.assertRaises(IOError): - visitor._get_observations() - - # temporary transient problem. Succeeds after 2 retries - repo.reset_mock() - response.status = 200 - transient_response = MagicMock() - transient_response.status = 503 - repo.send_request.return_value = transient_response - repo.retry.return_value = response - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - self.assertEquals(expect_observations, visitor._get_observations()) - self.assertEquals(end_date, visitor.current_start) - repo.send_request.assert_called_once_with('GET', - '/cfht', - {"Content-type": "application/x-www-form-urlencoded"}, - 'MAXREC=10000') - repo.retry.assert_called_once_with('GET', - '/cfht', - {"Content-type": "application/x-www-form-urlencoded"}, - 'MAXREC=10000') - + self.assertEquals(expect_observations, visitor._get_observations('cfht')) + self.assertEquals(end_date, visitor._start) + mock_get.assert_called_once_with('cfht', params={'MAXREC':caom2repo.BATCH_SIZE}) + + mock_get.reset_mock() + visitor._get_observations('cfht', end=datetime.strptime('2000-11-11', '%Y-%m-%d')) + mock_get.assert_called_once_with('cfht', params={'END':'2000-11-11T00:00:00.000000', + 'MAXREC': caom2repo.BATCH_SIZE}) + + mock_get.reset_mock() + visitor._get_observations('cfht', + start=datetime.strptime('2000-11-11', '%Y-%m-%d'), + end=datetime.strptime('2000-11-12', '%Y-%m-%d')) + mock_get.assert_called_once_with('cfht', params={'START':'2000-11-11T00:00:00.000000', + 'END': '2000-11-12T00:00:00.000000', + 'MAXREC': caom2repo.BATCH_SIZE}) + # patch sleep to stop the test from sleeping and slowing down execution - @patch('caom2repoClient.caom2repoClient.time.sleep', MagicMock(), create=True) - @patch('caom2repoClient.caom2repoClient.open', MagicMock(), create=True) - @patch('caom2repoClient.caom2repoClient.HTTPSConnection') - def test_persist_observation(self, mock_conn): - obs = SimpleObservation('cfht', '7000000o') - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') + @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.Session.send') + def test_post_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(server=service_url) response = MagicMock() response.status = 200 - conn = mock_conn.return_value - conn.getresponse.return_value = response - #mock_conn.return_value = conn + mock_conn.return_value = response iobuffer = StringIO() ObservationWriter().write(obs, iobuffer) obsxml = iobuffer.getvalue() + response.content = obsxml - visitor._persist_observation('700000o', obs) - - conn.request.assert_called_once_with( - 'POST', '/caom2repo/pub/cfht/700000o', obsxml, - {'Content-Type': 'text/xml'}) - - conn.reset_mock() - - # signal some problems - response.status = 404 - with self.assertRaises(IOError): - visitor._persist_observation('700000o', obs) - - response.status = 405 - with self.assertRaises(IOError): - visitor._persist_observation('700000o', obs) - - # transient problem no retries - response.status = 503 - with self.assertRaises(IOError): - visitor._persist_observation('700000o', obs) - - # permanent transient problem with 2 retries - response.status = 503 - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - with self.assertRaises(IOError): - visitor._persist_observation('700000o', obs) - - # temporary transient problem. Succeeds after 2 retries + self.assertEqual(obs, visitor.post_observation(collection, observation_id, obs)) + self.assertEqual('POST', mock_conn.call_args[0][0].method) + self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) + self.assertEqual(obsxml, mock_conn.call_args[0][0].body) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.post_observation(collection, observation_id, obs) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.post_observation(collection, observation_id, obs) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + def raise_error(): raise http_error + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.post_observation(collection, observation_id, obs) + + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.Session.send') + def test_put_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(server=service_url) + response = MagicMock() response.status = 200 - transient_response = MagicMock() - transient_response.status = 503 - conn = MagicMock() - conn.getresponse.side_effect = [transient_response, transient_response, response] - mock_conn.return_value = conn - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht', retries=2) - visitor._persist_observation('700000o', obs) - conn.request.assert_called_with( - 'POST', '/caom2repo/pub/cfht/700000o', obsxml, - {'Content-Type': 'text/xml'}) - + mock_conn.return_value = response + iobuffer = StringIO() + ObservationWriter().write(obs, iobuffer) + obsxml = iobuffer.getvalue() + response.content = obsxml + + self.assertEqual(obs, visitor.put_observation(collection, obs)) + self.assertEqual('PUT', mock_conn.call_args[0][0].method) + self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) + self.assertEqual(obsxml, mock_conn.call_args[0][0].body) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.put_observation(collection, obs) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.put_observation(collection, obs) - @patch('test_visitor.CAOM2Visitor._get_observation', MagicMock(), create = True) - @patch('test_visitor.CAOM2Visitor._persist_observation', MagicMock(), create = True) - @patch('test_visitor.CAOM2Visitor._get_observations') + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.put_observation(collection, obs) + + # patch sleep to stop the test from sleeping and slowing down execution + @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.Session.send') + def test_delete_observation(self, mock_conn): + collection = 'cfht' + observation_id = '7000000o' + service_url = 'www.cadc.nrc.ca/caom2repo' + + obs = SimpleObservation(collection, observation_id) + visitor = CAOM2RepoClient(server=service_url) + response = MagicMock() + response.status = 200 + mock_conn.return_value = response + + visitor.delete_observation(collection, observation_id) + self.assertEqual('DELETE', mock_conn.call_args[0][0].method) + + # signal problems + http_error = requests.HTTPError() + response.status_code = 500 + http_error.response = response + response.raise_for_status.side_effect = [http_error] + with self.assertRaises(requests.HTTPError): + visitor.delete_observation(collection, observation_id) + + # temporary transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + response.raise_for_status.side_effect = [http_error, None] + visitor.delete_observation(collection, observation_id) + + # permanent transient errors + http_error = requests.HTTPError() + response.status_code = 503 + http_error.response = response + + def raise_error(): raise http_error + + response.raise_for_status.side_effect = raise_error + with self.assertRaises(requests.HTTPError): + visitor.delete_observation(collection, observation_id) + + + @patch('test_caom2repo.CAOM2RepoClient._get_observations') def test_process(self, mock_obs): - CAOM2RepoClient.visitor.BATCH_SIZE = 3 # size of the batch is 3 - mock_obs.side_effect = [['a', 'b', 'c'], ['d'], []] - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') - visitor.plugin = MagicMock() - self.assertEquals(4, visitor.process()) - - mock_obs.side_effect = [['a', 'b', 'c'], ['d', 'e', 'f'], []] - visitor = CAOM2RepoClient(os.path.join( - THIS_DIR, 'passplugin.py'), 'cfht') - visitor.plugin = MagicMock() - self.assertEquals(6, visitor.process()) + caom2repo.BATCH_SIZE = 3 # size of the batch is 3 + obs = [['a', 'b', 'c'], ['d'], []] + visitor = CAOM2RepoClient() + visitor.get_observation = MagicMock(return_value=MagicMock(spec=SimpleObservation)) + visitor.post_observation = MagicMock() + visitor._get_observations = MagicMock(side_effect=obs) + + self.assertEquals(4, visitor.visit(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht')) + + obs = [['a', 'b', 'c'], ['d', 'e', 'f'], []] + visitor._get_observations = MagicMock(side_effect=obs) + self.assertEquals(6, visitor.visit(os.path.join( + THIS_DIR, 'passplugin.py'), 'cfht')) From 5646612f6dcf514ed73fbfdc5bf78d205b9b8ec5 Mon Sep 17 00:00:00 2001 From: andamian Date: Thu, 17 Nov 2016 13:04:34 -0800 Subject: [PATCH 16/54] Implemented caom2repo --- caom2tools/util/tests/addplaneplugin.py | 86 +++++++++++++++++++++++++ caom2tools/util/tests/passplugin.py | 83 ++++++++++++++++++++++++ 2 files changed, 169 insertions(+) create mode 100755 caom2tools/util/tests/addplaneplugin.py create mode 100755 caom2tools/util/tests/passplugin.py diff --git a/caom2tools/util/tests/addplaneplugin.py b/caom2tools/util/tests/addplaneplugin.py new file mode 100755 index 00000000..3bacc25d --- /dev/null +++ b/caom2tools/util/tests/addplaneplugin.py @@ -0,0 +1,86 @@ +## -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +from caom2tools.caom2.observation import Observation +from caom2tools.caom2.plane import Plane + +class ObservationUpdater: + + """ObservationUpdater that adds a plane to the observation.""" + + def update(self, observation): + """ + Processes an observation and updates it + """ + assert isinstance(observation, Observation), ( + "observation %s is not an Observation".format(observation)) + observation.planes.add(Plane('PREVIEW')) + + + diff --git a/caom2tools/util/tests/passplugin.py b/caom2tools/util/tests/passplugin.py new file mode 100755 index 00000000..cdd33143 --- /dev/null +++ b/caom2tools/util/tests/passplugin.py @@ -0,0 +1,83 @@ +## -*- coding: utf-8 -*- +#*********************************************************************** +#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# +# (c) 2016. (c) 2016. +# Government of Canada Gouvernement du Canada +# National Research Council Conseil national de recherches +# Ottawa, Canada, K1A 0R6 Ottawa, Canada, K1A 0R6 +# All rights reserved Tous droits réservés +# +# NRC disclaims any warranties, Le CNRC dénie toute garantie +# expressed, implied, or énoncée, implicite ou légale, +# statutory, of any kind with de quelque nature que ce +# respect to the software, soit, concernant le logiciel, +# including without limitation y compris sans restriction +# any warranty of merchantability toute garantie de valeur +# or fitness for a particular marchande ou de pertinence +# purpose. NRC shall not be pour un usage particulier. +# liable in any event for any Le CNRC ne pourra en aucun cas +# damages, whether direct or être tenu responsable de tout +# indirect, special or general, dommage, direct ou indirect, +# consequential or incidental, particulier ou général, +# arising from the use of the accessoire ou fortuit, résultant +# software. Neither the name de l'utilisation du logiciel. Ni +# of the National Research le nom du Conseil National de +# Council of Canada nor the Recherches du Canada ni les noms +# names of its contributors may de ses participants ne peuvent +# be used to endorse or promote être utilisés pour approuver ou +# products derived from this promouvoir les produits dérivés +# software without specific prior de ce logiciel sans autorisation +# written permission. préalable et particulière +# par écrit. +# +# This file is part of the Ce fichier fait partie du projet +# OpenCADC project. OpenCADC. +# +# OpenCADC is free software: OpenCADC est un logiciel libre ; +# you can redistribute it and/or vous pouvez le redistribuer ou le +# modify it under the terms of modifier suivant les termes de +# the GNU Affero General Public la “GNU Affero General Public +# License as published by the License” telle que publiée +# Free Software Foundation, par la Free Software Foundation +# either version 3 of the : soit la version 3 de cette +# License, or (at your option) licence, soit (à votre gré) +# any later version. toute version ultérieure. +# +# OpenCADC is distributed in the OpenCADC est distribué +# hope that it will be useful, dans l’espoir qu’il vous +# but WITHOUT ANY WARRANTY; sera utile, mais SANS AUCUNE +# without even the implied GARANTIE : sans même la garantie +# warranty of MERCHANTABILITY implicite de COMMERCIALISABILITÉ +# or FITNESS FOR A PARTICULAR ni d’ADÉQUATION À UN OBJECTIF +# PURPOSE. See the GNU Affero PARTICULIER. Consultez la Licence +# General Public License for Générale Publique GNU Affero +# more details. pour plus de détails. +# +# You should have received Vous devriez avoir reçu une +# a copy of the GNU Affero copie de la Licence Générale +# General Public License along Publique GNU Affero avec +# with OpenCADC. If not, see OpenCADC ; si ce n’est +# . pas le cas, consultez : +# . +# +# $Revision: 4 $ +# +#*********************************************************************** +# + +from caom2tools.caom2.observation import Observation + +class ObservationUpdater: + + """Plugin that does not update the observation""" + + def update(self, observation): + """ + Processes an observation and updates it + """ + assert isinstance(observation, Observation), ( + "observation %s is not an Observation".format(observation)) + + From 3824782d5c79b6c4893316964e47b4fc0c65d4a3 Mon Sep 17 00:00:00 2001 From: andamian Date: Thu, 17 Nov 2016 13:53:46 -0800 Subject: [PATCH 17/54] Fixed unit tests in caom2repo --- caom2tools/util/{tests => test}/addplaneplugin.py | 0 caom2tools/util/{tests => test}/passplugin.py | 0 caom2tools/util/test/test_caom2repo.py | 3 +-- 3 files changed, 1 insertion(+), 2 deletions(-) rename caom2tools/util/{tests => test}/addplaneplugin.py (100%) rename caom2tools/util/{tests => test}/passplugin.py (100%) diff --git a/caom2tools/util/tests/addplaneplugin.py b/caom2tools/util/test/addplaneplugin.py similarity index 100% rename from caom2tools/util/tests/addplaneplugin.py rename to caom2tools/util/test/addplaneplugin.py diff --git a/caom2tools/util/tests/passplugin.py b/caom2tools/util/test/passplugin.py similarity index 100% rename from caom2tools/util/tests/passplugin.py rename to caom2tools/util/test/passplugin.py diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py index f5754044..10f9f856 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2tools/util/test/test_caom2repo.py @@ -346,8 +346,7 @@ def raise_error(): raise http_error visitor.delete_observation(collection, observation_id) - @patch('test_caom2repo.CAOM2RepoClient._get_observations') - def test_process(self, mock_obs): + def test_process(self): caom2repo.BATCH_SIZE = 3 # size of the batch is 3 obs = [['a', 'b', 'c'], ['d'], []] visitor = CAOM2RepoClient() From 2769a9bf1d277f6cd5627cb6be57e9d1ba02c22a Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Fri, 18 Nov 2016 08:21:28 -0800 Subject: [PATCH 18/54] Added the caom2-client method --- caom2tools/util/caom2repo.py | 128 ++++++++++++++++--------- caom2tools/util/test/test_caom2repo.py | 39 ++++++-- setup.cfg | 2 +- 3 files changed, 113 insertions(+), 56 deletions(-) diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py index fb8bc74a..382d04e7 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2tools/util/caom2repo.py @@ -88,18 +88,15 @@ class CAOM2RepoClient: """Class to do CRUD + visitor actions on a CAOM2 collection repo.""" - def __init__(self, start=None, end=None, retries=0, server=None): - - if retries is not None: - self.retries = int(retries) - else: - self.retries = 0 + def __init__(self, anon=True, cert_file=None, verify=False, server=None): # repo client to use + serv = SERVICE_URL if server is not None: - self._repo_client = ws.BaseWsClient(server) - else: - self._repo_client = ws.BaseWsClient(SERVICE_URL) + serv = server + agent = 'CAOM2RepoClient' #TODO add version + self._repo_client = ws.BaseWsClient(serv, anon=anon, cert_file=cert_file, + agent=agent, verify=verify, retry=True) logging.info('Service URL: {}'.format(self._repo_client.base_url)) @@ -194,10 +191,10 @@ def get_observation(self, collection, observationID): return obs_reader.read(StringIO(content)) - def post_observation(self, collection, observationID, observation): - assert collection is not None - assert observationID is not None - resource = '/{}/{}'.format(collection, observationID) + def post_observation(self, observation): + assert observation.collection is not None + assert observation.observation_id is not None + resource = '/{}/{}'.format(observation.collection, observation.observation_id) logging.debug('POST {}'.format(resource)) ibuffer = StringIO() @@ -216,9 +213,9 @@ def post_observation(self, collection, observationID, observation): return obs_reader.read(StringIO(content)) - def put_observation(self, collection, observation): - assert collection is not None - resource = '/{}'.format(collection) + def put_observation(self, observation): + assert observation.collection is not None + resource = '/{}'.format(observation.collection) logging.debug('PUT {}'.format(resource)) ibuffer = StringIO() @@ -245,30 +242,49 @@ def delete_observation(self, collection, observationID): logging.debug('Successfully deleted Observation\n') -def run(): +def main(): + + parser = util.BaseParser() - parser = util.BaseParser(description=description, - formatter_class=argparse.RawTextHelpFormatter) - parser.description = description + parser.description = ('Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) ' + 'operations it also implements a visitor operation that allows for updating ' + 'multiple observations in a collection') + parser.formatter_class = argparse.RawTextHelpFormatter - parser.add_argument('--plugin', required=True, + subparsers = parser.add_subparsers(dest='cmd') + create_parser = subparsers.add_parser('create', description='Create a new observation') + create_parser.add_argument('observation', metavar='', type=file) + + update_parser = subparsers.add_parser('update', description='Update an existing observation') + update_parser.add_argument('observation', metavar='', type=file) + + read_parser = subparsers.add_parser('read', description='Read an existing observation') + read_parser.add_argument('--output', '-o', metavar='', required=False) + read_parser.add_argument('observation', metavar='', type=file) + + delete_parser = subparsers.add_parser('delete', description='Update an existing observation') + delete_parser.add_argument('--collection', metavar='', type=file, required=True) + delete_parser.add_argument('observationID', metavar='', type=file) + + visit_parser = subparsers.add_parser('visit', description='Visit observations in a collection') + visit_parser.add_argument('--plugin', required=True, type=file, metavar=(''), help='Pluging class to update each observation') - parser.add_argument('--start', metavar='', - type=parse_date, + visit_parser.add_argument('--start', metavar='', + type=util.str2ivoa, help='oldest dataset to visit (UTC %%Y-%%m-%%d format)'); - parser.add_argument('--end', metavar='', - type=parse_date, + visit_parser.add_argument('--end', metavar='', + type=util.str2ivoa, help='earliest dataset to visit (UTC %%Y-%%m-%%d format)'); - parser.add_argument('--retries', metavar='', + visit_parser.add_argument('--retries', metavar='', type=int, help='number of tries with transient server errors'); - parser.add_argument("-s", "--server", metavar=(''), + visit_parser.add_argument("-s", "--server", metavar=(''), help="URL of the CAOM2 repo server") - parser.add_argument('collection', metavar='', type=str, + visit_parser.add_argument('collection', metavar='', type=str, help='data collection in CAOM2 repo') - parser.epilog =\ + visit_parser.epilog =\ """ Minimum plugin file format: ---- @@ -292,22 +308,44 @@ def update(self, observation): if args.debug: logging.basicConfig(level=logging.DEBUG) - plugin = args.plugin - if not os.path.isfile(args.plugin): - logging.error('Cannot find plugin file ' + plugin) - sys.exit(-1) - - start = args.start - end = args.end - retries = args.retries - collection = args.collection - - logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". - format(plugin, start, end, collection, retries)) - client = CAOM2Visitor(plugin=plugin, start=start, end=end, - collection=collection, retries=retries, server=args.server) - client.process() - logging.debug("debug") + client = CAOM2RepoClient(server=args.server) + if args.cmd == 'visit': + print ("Visit") + + plugin = args.plugin + start = args.start + end = args.end + retries = args.retries + collection = args.collection + logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". + format(plugin, start, end, collection, retries)) + client.visit(plugin, collection, start=start, end=end) + + elif args.cmd == 'create': + print("Create") + with open(args.observation, 'r') as obsfile: + obs_reader = ObservationReader() + client.put_observation(obs_reader.read(StringIO(obsfile.read()))) #TODO not sure if need to read in string first + elif args.cmd == 'read': + print("Read") + observation = client.get_observation(args.collection, args.observationID) + observation_writer = ObservationWriter() + ibuffer = StringIO() + ObservationWriter.write(observation, ibuffer) + obs_xml = ibuffer.getvalue() + if args.output: + with open(args.output, 'w') as obsfile: + obsfile.write(obs_xml) + else: + print obs_xml + elif args.cmd == 'update': + print("Update") + with open(args.observation, 'r') as obsfile: + obs_reader = ObservationReader() + client.post_observation(obs_reader.read(StringIO(obsfile.read()))) #TODO not sure if need to read in string first + else: + print("Delete") + client.delete_observation(collection=args.collection, observation=args.observationID) print("DONE") diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py index 10f9f856..3b136955 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2tools/util/test/test_caom2repo.py @@ -84,6 +84,10 @@ THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + +class MyExitError(Exception): + pass + class TestCAOM2Repo(unittest.TestCase): """Test the Caom2Visitor class""" @@ -211,7 +215,8 @@ def test_get_observations(self, mock_get): def test_post_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' - service_url = 'www.cadc.nrc.ca/caom2repo' + service = 'caom2repo' + service_url = 'www.cadc.nrc.ca/{}'.format(service) obs = SimpleObservation(collection, observation_id) visitor = CAOM2RepoClient(server=service_url) @@ -223,8 +228,10 @@ def test_post_observation(self, mock_conn): obsxml = iobuffer.getvalue() response.content = obsxml - self.assertEqual(obs, visitor.post_observation(collection, observation_id, obs)) + self.assertEqual(obs, visitor.post_observation(obs)) self.assertEqual('POST', mock_conn.call_args[0][0].method) + self.assertEqual('/{}/{}/{}'.format(service, collection, observation_id), + mock_conn.call_args[0][0].path_url) self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) self.assertEqual(obsxml, mock_conn.call_args[0][0].body) @@ -234,14 +241,14 @@ def test_post_observation(self, mock_conn): http_error.response = response response.raise_for_status.side_effect = [http_error] with self.assertRaises(requests.HTTPError): - visitor.post_observation(collection, observation_id, obs) + visitor.post_observation(obs) # temporary transient errors http_error = requests.HTTPError() response.status_code = 503 http_error.response = response response.raise_for_status.side_effect = [http_error, None] - visitor.post_observation(collection, observation_id, obs) + visitor.post_observation(obs) # permanent transient errors http_error = requests.HTTPError() @@ -250,7 +257,7 @@ def test_post_observation(self, mock_conn): def raise_error(): raise http_error response.raise_for_status.side_effect = raise_error with self.assertRaises(requests.HTTPError): - visitor.post_observation(collection, observation_id, obs) + visitor.post_observation(obs) # patch sleep to stop the test from sleeping and slowing down execution @@ -259,7 +266,8 @@ def raise_error(): raise http_error def test_put_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' - service_url = 'www.cadc.nrc.ca/caom2repo' + service = 'caom2repo' + service_url = 'www.cadc.nrc.ca/{}'.format(service) obs = SimpleObservation(collection, observation_id) visitor = CAOM2RepoClient(server=service_url) @@ -271,8 +279,10 @@ def test_put_observation(self, mock_conn): obsxml = iobuffer.getvalue() response.content = obsxml - self.assertEqual(obs, visitor.put_observation(collection, obs)) + self.assertEqual(obs, visitor.put_observation(obs)) self.assertEqual('PUT', mock_conn.call_args[0][0].method) + self.assertEqual('/{}/{}'.format(service, collection), + mock_conn.call_args[0][0].path_url) self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) self.assertEqual(obsxml, mock_conn.call_args[0][0].body) @@ -282,14 +292,14 @@ def test_put_observation(self, mock_conn): http_error.response = response response.raise_for_status.side_effect = [http_error] with self.assertRaises(requests.HTTPError): - visitor.put_observation(collection, obs) + visitor.put_observation(obs) # temporary transient errors http_error = requests.HTTPError() response.status_code = 503 http_error.response = response response.raise_for_status.side_effect = [http_error, None] - visitor.put_observation(collection, obs) + visitor.put_observation(obs) # permanent transient errors http_error = requests.HTTPError() @@ -300,7 +310,7 @@ def raise_error(): raise http_error response.raise_for_status.side_effect = raise_error with self.assertRaises(requests.HTTPError): - visitor.put_observation(collection, obs) + visitor.put_observation(obs) # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @@ -361,3 +371,12 @@ def test_process(self): visitor._get_observations = MagicMock(side_effect=obs) self.assertEquals(6, visitor.visit(os.path.join( THIS_DIR, 'passplugin.py'), 'cfht')) + + + + @patch('sys.argv') + @patch('sys.exit', Mock(side_effect=[MyExitError])) + def test_main(self, mock_argv): + mock_argv.return_value = ["caom2-client", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() diff --git a/setup.cfg b/setup.cfg index 16151e43..40887f0f 100644 --- a/setup.cfg +++ b/setup.cfg @@ -34,4 +34,4 @@ github_project = opencadc/caom2tools version = 2.2.2 [entry_points] -astropy-package-template-example = caom2tools.example_mod:main +caom2-client = caom2tools.util.caom2repo:main From 2a2b20d86f9b7753060e069188340cf472475179 Mon Sep 17 00:00:00 2001 From: andamian Date: Mon, 21 Nov 2016 07:00:55 -0800 Subject: [PATCH 19/54] Added more unit tests --- caom2tools/util/caom2repo.py | 20 +-- caom2tools/util/test/test_caom2repo.py | 238 ++++++++++++++++++++++++- 2 files changed, 242 insertions(+), 16 deletions(-) diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py index 382d04e7..7a4f90e7 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2tools/util/caom2repo.py @@ -255,18 +255,20 @@ def main(): create_parser = subparsers.add_parser('create', description='Create a new observation') create_parser.add_argument('observation', metavar='', type=file) - update_parser = subparsers.add_parser('update', description='Update an existing observation') - update_parser.add_argument('observation', metavar='', type=file) - read_parser = subparsers.add_parser('read', description='Read an existing observation') read_parser.add_argument('--output', '-o', metavar='', required=False) read_parser.add_argument('observation', metavar='', type=file) - delete_parser = subparsers.add_parser('delete', description='Update an existing observation') + update_parser = subparsers.add_parser('update', description='Update an existing observation') + update_parser.add_argument('observation', metavar='', type=file) + + delete_parser = subparsers.add_parser('delete', description='Delete an existing observation') delete_parser.add_argument('--collection', metavar='', type=file, required=True) delete_parser.add_argument('observationID', metavar='', type=file) - visit_parser = subparsers.add_parser('visit', description='Visit observations in a collection') + # Note: RawTextHelpFormatter allows for the use of newline in epilog + visit_parser = subparsers.add_parser('visit', formatter_class=argparse.RawTextHelpFormatter, + description='Visit observations in a collection') visit_parser.add_argument('--plugin', required=True, type=file, metavar=(''), help='Pluging class to update each observation') @@ -298,7 +300,6 @@ def update(self, observation): # custom code to update the observation ---- """ - args = parser.parse_args() @@ -308,7 +309,7 @@ def update(self, observation): if args.debug: logging.basicConfig(level=logging.DEBUG) - client = CAOM2RepoClient(server=args.server) + client = CAOM2RepoClient(server=args.host) if args.cmd == 'visit': print ("Visit") @@ -323,9 +324,8 @@ def update(self, observation): elif args.cmd == 'create': print("Create") - with open(args.observation, 'r') as obsfile: - obs_reader = ObservationReader() - client.put_observation(obs_reader.read(StringIO(obsfile.read()))) #TODO not sure if need to read in string first + obs_reader = ObservationReader() + client.put_observation(obs_reader.read(args.observation)) elif args.cmd == 'read': print("Read") observation = client.get_observation(args.collection, args.observationID) diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py index 3b136955..3adf4238 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2tools/util/test/test_caom2repo.py @@ -373,10 +373,236 @@ def test_process(self): THIS_DIR, 'passplugin.py'), 'cfht')) + @patch('caom2tools.util.caom2repo.CAOM2RepoClient') + def test_main(self, client_mock): - @patch('sys.argv') - @patch('sys.exit', Mock(side_effect=[MyExitError])) - def test_main(self, mock_argv): - mock_argv.return_value = ["caom2-client", "--help"] - with self.assertRaises(MyExitError): - caom2repo.main() + + collection = 'cfht' + observation_id = '7000000o' + service = 'caom2repo' + ifile = '/tmp/inputobs' + + obs = SimpleObservation(collection, observation_id) + iobuffer = StringIO() + with open(ifile, 'w') as infile: + ObservationWriter().write(obs, infile) + + put_mock = Mock(id='Mymock') + client_mock.return_value = Mock(id='mmm') + client_mock.put_observation = put_mock + sys.argv = ["caom2tools", "create", ifile] + caom2repo.main() + put_mock.assert_called_with('blah') + + + @patch('sys.exit', Mock(side_effect=[MyExitError, MyExitError, MyExitError, + MyExitError, MyExitError, MyExitError])) + def test_help(self): + """ Tests the helper displays for commands and subcommands in main""" + + # expected helper messages + usage=\ +"""usage: caom2-client [-h] [--certfile CERTFILE] [--anonymous] [--host HOST] + [--verbose] [--debug] [--quiet] + {create,read,update,delete,visit} ... + +Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) operations it also implements a visitor operation that allows for updating multiple observations in a collection + +positional arguments: + {create,read,update,delete,visit} + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + create_usage=\ +"""usage: caom2-client create [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Create a new observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + read_usage =\ +"""usage: caom2-client read [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + [--output ] + + +Read an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --output , -o +""" + + update_usage =\ +"""usage: caom2-client update [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Update an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" + + delete_usage =\ +"""usage: caom2-client delete [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --collection + + +Delete an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --collection +""" + + visit_usage =\ +"""usage: caom2-client visit [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --plugin + [--start ] + [--end ] + [--retries ] + [-s ] + + +Visit observations in a collection + +positional arguments: + data collection in CAOM2 repo + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --plugin + Pluging class to update each observation + --start + oldest dataset to visit (UTC %Y-%m-%d format) + --end + earliest dataset to visit (UTC %Y-%m-%d format) + --retries + number of tries with transient server errors + -s , --server + URL of the CAOM2 repo server + +Minimum plugin file format: +---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation +---- +""" + + + # --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(usage, stdout_mock.getvalue()) + + # create --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "create", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(create_usage, stdout_mock.getvalue()) + + # read --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "read", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(read_usage, stdout_mock.getvalue()) + + # update --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "update", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(update_usage, stdout_mock.getvalue()) + + # delete --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "delete", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(delete_usage, stdout_mock.getvalue()) + + # visit --help + with patch('sys.stdout', new_callable=StringIO) as stdout_mock: + sys.argv = ["caom2-client", "visit", "--help"] + with self.assertRaises(MyExitError): + caom2repo.main() + self.assertEqual(visit_usage, stdout_mock.getvalue()) \ No newline at end of file From 2b86dc2c4820fa3e6a26fb5af9e3b22d0f1b049b Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 21 Nov 2016 09:06:52 -0800 Subject: [PATCH 20/54] s1950: moved CAOM schema files from caom2tools/caom2 to caom2tools/data. --- caom2tools/caom2/__init__.py | 109 +- caom2tools/caom2/obs_reader_writer.py | 26 +- caom2tools/caom2/test/data/__init__.py | 0 .../caom2/test/test_obs_reader_writer.py | 1366 ++++++++--------- caom2tools/{caom2 => data}/CAOM-2.0.xsd | 0 caom2tools/{caom2 => data}/CAOM-2.1.xsd | 0 caom2tools/{caom2 => data}/CAOM-2.2.xsd | 0 caom2tools/data/__init__.py | 0 setup.py | 1 + 9 files changed, 692 insertions(+), 810 deletions(-) create mode 100644 caom2tools/caom2/test/data/__init__.py rename caom2tools/{caom2 => data}/CAOM-2.0.xsd (100%) rename caom2tools/{caom2 => data}/CAOM-2.1.xsd (100%) rename caom2tools/{caom2 => data}/CAOM-2.2.xsd (100%) create mode 100644 caom2tools/data/__init__.py diff --git a/caom2tools/caom2/__init__.py b/caom2tools/caom2/__init__.py index d6137cba..bce7761e 100644 --- a/caom2tools/caom2/__init__.py +++ b/caom2tools/caom2/__init__.py @@ -70,6 +70,17 @@ """ Defines __init__ """ +# import os +# +# _ROOT = os.path.abspath(os.path.dirname(__file__)) +# +# +# def get_data(path): +# # return os.path.join(_ROOT, 'data', path) +# foo = os.path.join(_ROOT, 'data', path) +# print "path to " + path + " is " + foo +# return foo + # import artifact as artifact # import caom_object as caom_object # import chunk as chunk @@ -78,101 +89,3 @@ # import plane as plane # import caom_util as caom_util # import wcs as wcs -# from caom_util import Util as Util - -# -from .caom_object import CaomObject -# from .caom_object import AbstractCaomEntity - -# Util classes -# from util import Util -# from .util import TypedList -# from .util import TypedSet -# from .util import TypedOrderedDict -# from .util import ClassProperty -# from .util import Validator - -# WCS data types -# from .wcs import Axis -# from .wcs import Coord2D -# from .wcs import CoordAxis1D -# from .wcs import CoordAxis2D -# from .wcs import CoordBounds1D -# from .wcs import CoordBounds2D -# from .wcs import CoordCircle2D -# from .wcs import CoordError -# from .wcs import CoordFunction1D -# from .wcs import CoordFunction2D -# from .wcs import CoordPolygon2D -# from .wcs import CoordRange1D -# from .wcs import CoordRange2D -# from .wcs import Dimension2D -# from .wcs import RefCoord -# from .wcs import Slice -# from .wcs import ValueCoord2D -# from .wcs import EnergyTransition - -# Discovery data types -# from .shape import Box -# from .shape import Circle -# from .shape import Interval -# from .shape import Point -# from .shape import Polygon -# from .shape import Vertex - -# Chunk level classes -# from .chunk import Chunk -# from .chunk import ObservableAxis -# from .chunk import SpatialWCS -# from .chunk import SpectralWCS -# from .chunk import TemporalWCS -# from .chunk import PolarizationWCS - -# Part level classes -# from .part import Part - -# Artifact level classes -# from .artifact import Artifact - -# Plane level classes -# from .plane import Plane -# from .plane import PlaneURI -# from .plane import DataQuality -# from .plane import Metrics -# from .plane import Provenance -# from .plane import Position -# from .plane import Energy -# from .plane import EnergyTransition -# from .plane import Polarization -# from .plane import Time - -# Observation level classes -# from .observation import Observation -# from .observation import ObservationURI -# from .observation import SimpleObservation -# from .observation import CompositeObservation -# from .observation import Algorithm -# from .observation import Environment -# from .observation import Proposal -# from .observation import Requirements -# from .observation import Target -# from .observation import TargetPosition -# from .observation import Telescope - -# enums -# from .artifact import ProductType -# from .artifact import ReleaseType -# from .plane import CalibrationLevel -# from .plane import DataProductType -# from .plane import EnergyBand -# from .plane import PolarizationState -# from .plane import Quality -# from .observation import ObservationIntentType -# from .observation import Status -# from .observation import TargetType - -# observation reader and writer -from .obs_reader_writer import ObservationReader, ObservationWriter -# from .obs_reader_writer import CAOM20_NAMESPACE -# from .obs_reader_writer import CAOM21_NAMESPACE -# from .obs_reader_writer import CAOM22_NAMESPACE diff --git a/caom2tools/caom2/obs_reader_writer.py b/caom2tools/caom2/obs_reader_writer.py index a0181703..d5e50445 100644 --- a/caom2tools/caom2/obs_reader_writer.py +++ b/caom2tools/caom2/obs_reader_writer.py @@ -84,11 +84,11 @@ import shape import wcs -CAOM2_PKG = 'caom2tools' +DATA_PKG = 'caom2tools.data' -CAOM20_SCHEMA_FILE = 'caom2/CAOM-2.0.xsd' -CAOM21_SCHEMA_FILE = 'caom2/CAOM-2.1.xsd' -CAOM22_SCHEMA_FILE = 'caom2/CAOM-2.2.xsd' +CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' +CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' +CAOM22_SCHEMA_FILE = 'CAOM-2.2.xsd' CAOM20_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.0' CAOM21_NAMESPACE = 'vos://cadc.nrc.ca!vospace/CADC/xml/CAOM/v2.1' @@ -117,7 +117,7 @@ def __init__(self, valididate=False): if self._validate: caom20_schema_path = pkg_resources.resource_filename( - CAOM2_PKG, CAOM20_SCHEMA_FILE) + DATA_PKG, CAOM20_SCHEMA_FILE) parser = etree.XMLParser(remove_blank_text=True) xsd = etree.parse(caom20_schema_path, parser) @@ -582,7 +582,7 @@ def _get_axis(self, element_tag, parent, ns, required): if el is None: return None else: - return shape.Axis(self._get_child_text("ctype", el, ns, True), + return wcs.Axis(self._get_child_text("ctype", el, ns, True), self._get_child_text("cunit", el, ns, False)) def _get_slice(self, element_tag, parent, ns, required): @@ -601,7 +601,7 @@ def _get_slice(self, element_tag, parent, ns, required): if el is None: return None else: - return shape.Slice(self._get_axis("axis", el, ns, True), + return wcs.Slice(self._get_axis("axis", el, ns, True), self._get_child_text_as_long("bin", el, ns, True)) def _get_observable_axis(self, element_tag, parent, ns, required): @@ -905,7 +905,7 @@ def _get_spatial_wcs(self, element_tag, parent, ns, required): if el is None: return None else: - position = wcs.SpatialWCS(self._get_coord_axis2d("axis", el, ns, False)) + position = chunk.SpatialWCS(self._get_coord_axis2d("axis", el, ns, False)) position.coordsys = self._get_child_text("coordsys", el, ns, False) position.equinox = \ self._get_child_text_as_float("equinox", el, ns, False) @@ -1399,7 +1399,7 @@ def __init__(self, validate=False, write_empty_collections=False, else: schema_file = CAOM22_SCHEMA_FILE schema_path = pkg_resources.resource_filename( - CAOM2_PKG, schema_file) + DATA_PKG, schema_file) xmlschema_doc = etree.parse(schema_path) self._xmlschema = etree.XMLSchema(xmlschema_doc) @@ -1758,7 +1758,7 @@ def _add_polarization_wcs_element(self, polarization, parent): element = self._get_caom_element("polarization", parent) self._add_coord_axis1d_element("axis", polarization.axis, element) - #/*+ CAOM2 Types #-*/ + # /*+ CAOM2 Types #-*/ def _add_point_element(self, name, point, parent): """ Builds a representation of a Point and adds it to the @@ -1770,7 +1770,7 @@ def _add_point_element(self, name, point, parent): self._add_element("cval1", point.cval1, element) self._add_element("cval2", point.cval2, element) - #/*+ WCS Types #-*/ + # /*+ WCS Types #-*/ def _add_axis_element(self, name, axis, parent): """ Builds a representation of a Axis and adds it to the @@ -1850,7 +1850,8 @@ def _add_coord_bounds2d_element(self, name, bounds, parent): if isinstance(bounds, wcs.CoordCircle2D): self._add_coord_circle2d_element("circle", wcs.CoordCircle2D(bounds.center, - bounds.radius), element) + bounds.radius), + element) elif isinstance(bounds, wcs.CoordPolygon2D): self._add_coord_polygon2d_element("polygon", bounds, element) else: @@ -2010,4 +2011,3 @@ def _get_caom_element(self, tag, parent): class ObservationParsingException(Exception): pass - diff --git a/caom2tools/caom2/test/data/__init__.py b/caom2tools/caom2/test/data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py index b8f40f3e..e942f462 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -74,6 +74,7 @@ import filecmp import glob import os +import pkg_resources import shutil import unittest @@ -83,6 +84,42 @@ from .. import wcs +def minimal_simple(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = False + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_simple_observation() + + +def complete_simple(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = True + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_simple_observation() + + +def minimal_composite(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = False + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_composite_observation() + + +def complete_composite(depth, bounds_is_circle, version): + instances = caom_test_instances.Caom2TestInstances() + instances.complete = True + instances.depth = depth + instances.bounds_is_circle = bounds_is_circle + instances.caom_version = version + return instances.get_composite_observation() + + class TestObservationReaderWriter(unittest.TestCase): def test_invalid_long_id(self): @@ -125,92 +162,668 @@ def test_invalid_uuid(self): pass def test_minimal_simple(self): - for version in (20, 21): for i in range(1, 6): print "Test Minimal Simple {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D simple_observation = minimal_simple(i, True, version) # write empty elements - test_observation(self, simple_observation, True, True, version) + self.observation_test(simple_observation, True, True, version) # do not write empty elements - test_observation(self, simple_observation, True, False, version) + self.observation_test(simple_observation, True, False, version) # CoordBounds2D as CoordPolygon2D simple_observation = minimal_simple(i, False, version) # write empty elements - test_observation(self, simple_observation, True, True, version) + self.observation_test(simple_observation, True, True, version) # do not write empty elements - test_observation(self, simple_observation, True, False, version) + self.observation_test(simple_observation, True, False, version) def test_complete_simple(self): - for version in (20, 21, 22): for i in range(1, 6): print "Test Complete Simple {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D simple_observation = complete_simple(i, True, version) # write empty elements - test_observation(self, simple_observation, True, True, version) + self.observation_test(simple_observation, True, True, version) # do not write empty elements - test_observation(self, simple_observation, True, False, version) + self.observation_test(simple_observation, True, False, version) # CoordBounds2D as CoordPolygon2D simple_observation = complete_simple(i, False, version) # write empty elements - test_observation(self, simple_observation, True, True, version) + self.observation_test(simple_observation, True, True, version) # do not write empty elements - test_observation(self, simple_observation, True, False, version) + self.observation_test(simple_observation, True, False, version) def test_minimal_composite(self): - for version in (20, 21, 22): for i in range(1, 6): print "Test Minimal Composite {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D composite_observation = minimal_composite(i, True, version) # write empty elements - test_observation(self, composite_observation, True, True, version) + self.observation_test(composite_observation, True, True, version) # do not write empty elements - test_observation(self, composite_observation, True, False, version) + self.observation_test(composite_observation, True, False, version) # CoordBounds2D as CoordPolygon2D composite_observation = minimal_composite(i, False, version) # write empty elements - test_observation(self, composite_observation, True, True, version) + self.observation_test(composite_observation, True, True, version) # do not write empty elements - test_observation(self, composite_observation, True, False, version) + self.observation_test(composite_observation, True, False, version) def test_complete_composite(self): - for version in (20, 21, 22): for i in range(1, 6): print "Test Complete Composite {} version {}".format(i, version) # CoordBounds2D as CoordCircle2D composite_observation = complete_composite(i, True, version) # write empty elements - test_observation(self, composite_observation, True, True, version) + self.observation_test(composite_observation, True, True, version) # do not write empty elements - test_observation(self, composite_observation, True, False, version) + self.observation_test(composite_observation, True, False, version) # CoordBounds2D as CoordPolygon2D composite_observation = complete_composite(i, False, version) # write empty elements - test_observation(self, composite_observation, True, True, version) + self.observation_test(composite_observation, True, True, version) # do not write empty elements - test_observation(self, composite_observation, True, False, version) + self.observation_test(composite_observation, True, False, version) def test_versions(self): composite_observation = complete_composite(6, True, 20) - test_observation(self, composite_observation, True, True, 20) - test_observation(self, composite_observation, True, True, 21) - test_observation(self, composite_observation, True, True, 22) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) composite_observation = complete_composite(6, True, 21) - test_observation(self, composite_observation, True, True, 20) - test_observation(self, composite_observation, True, True, 21) - test_observation(self, composite_observation, True, True, 22) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) composite_observation = complete_composite(6, True, 22) - test_observation(self, composite_observation, True, True, 20) - test_observation(self, composite_observation, True, True, 21) - test_observation(self, composite_observation, True, True, 22) + self.observation_test(composite_observation, True, True, 20) + self.observation_test(composite_observation, True, True, 21) + self.observation_test(composite_observation, True, True, 22) + + def observation_test(self, obs, validate, write_empty_collections, version): + if version == 20: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM20_NAMESPACE) + elif version == 21: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections, "caom2", + obs_reader_writer.CAOM21_NAMESPACE) + else: + writer = obs_reader_writer.ObservationWriter( + validate, write_empty_collections) + xml_file = open('/tmp/test.xml', 'w') + writer.write(obs, xml_file) + xml_file.close() + reader = obs_reader_writer.ObservationReader(True) + returned = reader.read('/tmp/test.xml') + self.compare_observations(obs, returned, version) + + def compare_observations(self, expected, actual, version): + + assert ((isinstance(expected, observation.SimpleObservation) and + isinstance(actual, observation.SimpleObservation)) or + (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation))), ( + "Observation types do not match 0 vs 1". + format(expected.__class__.__name__, + actual.__class__.__name__)) + + self.assertIsNotNone(expected.collection) + self.assertIsNotNone(actual.collection) + self.assertEqual(expected.collection, actual.collection) + + self.assertIsNotNone(expected.observation_id) + self.assertIsNotNone(actual.observation_id) + self.assertEqual(expected.observation_id, actual.observation_id) + + self.assertIsNotNone(expected._id) + self.assertIsNotNone(actual._id) + self.assertEqual(expected._id, actual._id) + + self.assertIsNotNone(expected._last_modified) + self.assertIsNotNone(actual._last_modified) + self.assertEqual(expected._last_modified, actual._last_modified) + + self.assertIsNotNone(expected.algorithm) + self.assertIsNotNone(actual.algorithm) + self.assertEqual(expected.algorithm.name, actual.algorithm.name) + + self.assertEqual(expected.sequence_number, actual.sequence_number) + self.assertEqual(expected.intent, actual.intent) + self.assertEqual(expected.meta_release, actual.meta_release) + self.compare_proposal(expected.proposal, actual.proposal) + self.compare_target(expected.target, actual.target) + self.compare_target_position(expected.target_position, + actual.target_position) + self.compare_telescope(expected.telescope, actual.telescope) + self.compare_instrument(expected.instrument, actual.instrument) + self.compare_environment(expected.environment, actual.environment) + if version == 21: + self.compare_requirements(expected.requirements, actual.requirements) + + self.compare_planes(expected.planes, actual.planes, version) + + if (isinstance(expected, observation.CompositeObservation) and + isinstance(actual, observation.CompositeObservation)): + self.compare_members(expected.members, actual.members) + + def compare_proposal(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.proposal_id, actual.proposal_id) + self.assertEqual(expected.pi_name, actual.pi_name) + self.assertEqual(expected.project, actual.project) + self.assertEqual(expected.title, actual.title) + self.assertEqual(len(expected.keywords), len(actual.keywords)) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_target(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + self.assertEqual(expected.target_type, actual.target_type) + self.assertEqual(expected.redshift, actual.redshift) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_target_position(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.coordinates) + self.assertIsNotNone(actual.coordsys) + self.compare_point(expected.coordinates, actual.coordinates) + self.assertEqual(expected.coordsys, actual.coordsys) + self.assertEqual(expected.equinox, actual.equinox) + + def compare_telescope(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + self.assertEqual(expected.geo_location_x, actual.geo_location_x) + self.assertEqual(expected.geo_location_y, actual.geo_location_y) + self.assertEqual(expected.geo_location_z, actual.geo_location_z) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_instrument(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.name, actual.name) + for keyword in expected.keywords: + self.assertTrue(keyword in actual.keywords) + + def compare_environment(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.seeing, actual.seeing) + self.assertEqual(expected.humidity, actual.humidity) + self.assertEqual(expected.elevation, actual.elevation) + self.assertEqual(expected.tau, actual.tau) + self.assertEqual(expected.wavelength_tau, actual.wavelength_tau) + self.assertEqual(expected.ambient_temp, actual.ambient_temp) + self.assertEqual(expected.photometric, actual.photometric) + + def compare_members(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_member, actual_member in zip(expected, actual): + self.compare_observation_uri(expected_member, actual_member) + + def compare_observation_uri(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEquals(expected.uri, actual.uri) + self.assertEquals(expected.collection, actual.collection) + self.assertEquals(expected.observation_id, actual.observation_id) + + def compare_requirements(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEquals(expected.flag, actual.flag) + + def compare_planes(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_plane = expected[key] + actual_plane = actual[key] + self.assertIsNotNone(expected_plane) + self.assertIsNotNone(actual_plane) + self.assertEqual(expected_plane.product_id, actual_plane.product_id) + self.assertIsNotNone(expected_plane._id) + self.assertIsNotNone(actual_plane._id) + self.assertEqual(expected_plane._id, actual_plane._id) + self.assertIsNotNone(expected_plane._last_modified) + self.assertIsNotNone(actual_plane._last_modified) + self.assertEqual(expected_plane._last_modified, + actual_plane._last_modified) + self.assertEqual(expected_plane.meta_release, + actual_plane.meta_release) + self.assertEqual(expected_plane.data_release, + actual_plane.data_release) + self.assertEqual(expected_plane.data_product_type, + actual_plane.data_product_type) + self.assertEqual(expected_plane.calibration_level, + actual_plane.calibration_level) + self.compare_provenance(expected_plane.provenance, + actual_plane.provenance) + self.compare_metrics(expected_plane.metrics, actual_plane.metrics) + if version == 21: + self.compare_quality(expected_plane.quality, + actual_plane.quality) + + self.compare_artifacts(expected_plane.artifacts, + actual_plane.artifacts, version) + + def compare_provenance(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.version, actual.version) + self.assertEqual(expected.project, actual.project) + self.assertEqual(expected.producer, actual.producer) + self.assertEqual(expected.run_id, actual.run_id) + self.assertEqual(expected.reference, actual.reference) + self.assertEqual(expected.last_executed, actual.last_executed) + self.compare_inputs(expected.inputs, actual.inputs) + + def compare_metrics(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.source_number_density, + actual.source_number_density) + self.assertEqual(expected.background, actual.background) + self.assertEqual(expected.background_std_dev, actual.background_std_dev) + self.assertEqual(expected.flux_density_limit, actual.flux_density_limit) + self.assertEqual(expected.mag_limit, actual.mag_limit) + + def compare_quality(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(expected.flag, actual.flag) + + def compare_inputs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_plane_uri, actual_plane_uri in zip(expected, actual): + self.assertEqual(expected_plane_uri, actual_plane_uri) + + def compare_artifacts(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_artifact = expected[key] + actual_artifact = actual[key] + self.assertIsNotNone(expected_artifact) + self.assertIsNotNone(actual_artifact) + self.assertIsNotNone(expected_artifact._id) + self.assertIsNotNone(actual_artifact._id) + self.assertEqual(expected_artifact._id, actual_artifact._id) + self.assertIsNotNone(expected_artifact._last_modified) + self.assertIsNotNone(actual_artifact._last_modified) + self.assertEqual(expected_artifact._last_modified, + actual_artifact._last_modified) + self.assertEqual(expected_artifact.uri, actual_artifact.uri) + self.assertEqual(expected_artifact.content_type, + actual_artifact.content_type) + self.assertEqual(expected_artifact.content_length, + actual_artifact.content_length) + self.assertEqual(expected_artifact.product_type, + actual_artifact.product_type) + if version > 21: + self.assertEqual(expected_artifact.release_type, + actual_artifact.release_type) + self.compare_parts(expected_artifact.parts, + actual_artifact.parts, version) + + def compare_parts(self, expected, actual, version): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for key in expected: + self.assertTrue(key in actual) + expected_part = expected[key] + actual_part = actual[key] + self.assertIsNotNone(expected_part) + self.assertIsNotNone(actual_part) + self.assertIsNotNone(expected_part._id) + self.assertIsNotNone(actual_part._id) + self.assertEqual(expected_part._id, actual_part._id) + self.assertIsNotNone(expected_part._last_modified) + self.assertIsNotNone(actual_part._last_modified) + self.assertEqual(expected_part._last_modified, + actual_part._last_modified) + self.assertEqual(expected_part.name, actual_part.name) + self.assertEqual(expected_part.product_type, actual_part.product_type) + self.compare_chunks(expected_part.chunks, actual_part.chunks) + + def compare_chunks(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.assertEqual(len(expected), len(actual)) + for expected_chunk, actual_chunk in zip(expected, actual): + self.assertIsNotNone(expected_chunk) + self.assertIsNotNone(actual_chunk) + self.assertIsNotNone(expected_chunk._id) + self.assertIsNotNone(actual_chunk._id) + self.assertEqual(expected_chunk._id, actual_chunk._id) + self.assertIsNotNone(expected_chunk._last_modified) + self.assertIsNotNone(actual_chunk._last_modified) + self.assertEqual(expected_chunk._last_modified, + actual_chunk._last_modified) + self.assertEqual(expected_chunk.product_type, + actual_chunk.product_type) + self.assertEqual(expected_chunk.naxis, actual_chunk.naxis) + self.assertEqual(expected_chunk.observable_axis, + actual_chunk.observable_axis) + self.assertEqual(expected_chunk.position_axis_1, + actual_chunk.position_axis_1) + self.assertEqual(expected_chunk.position_axis_2, + actual_chunk.position_axis_2) + self.assertEqual(expected_chunk.energy_axis, actual_chunk.energy_axis) + self.assertEqual(expected_chunk.time_axis, actual_chunk.time_axis) + self.assertEqual(expected_chunk.polarization_axis, + actual_chunk.polarization_axis) + self.compare_observable_axis(expected_chunk.observable, + actual_chunk.observable) + self.compare_spatial_wcs(expected_chunk.position, + actual_chunk.position) + self.compare_spectral_wcs(expected_chunk.energy, actual_chunk.energy) + self.compare_temporal_wcs(expected_chunk.time, actual_chunk.time) + self.compare_polarization_wcs(expected_chunk.polarization, + actual_chunk.polarization) + + def compare_observable_axis(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_slice(expected.dependent, actual.dependent) + self.compare_slice(expected.independent, actual.independent) + + def compare_spatial_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis2d(expected.axis, actual.axis) + self.assertEqual(expected.coordsys, actual.coordsys) + self.assertEqual(expected.equinox, actual.equinox) + self.assertEqual(expected.resolution, actual.resolution) + + def compare_spectral_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + self.assertEqual(expected.bandpass_name, actual.bandpass_name) + self.assertEqual(expected.resolving_power, actual.resolving_power) + self.assertEqual(expected.restfrq, actual.restfrq) + self.assertEqual(expected.restwav, actual.restwav) + self.assertEqual(expected.specsys, actual.specsys) + self.assertEqual(expected.ssysobs, actual.ssysobs) + self.assertEqual(expected.ssyssrc, actual.ssyssrc) + self.assertEqual(expected.velang, actual.velang) + self.assertEqual(expected.velosys, actual.velosys) + self.assertEqual(expected.zsource, actual.zsource) + + def compare_temporal_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + self.assertEqual(expected.exposure, actual.exposure) + self.assertEqual(expected.resolution, actual.resolution) + self.assertEqual(expected.timesys, actual.timesys) + self.assertEqual(expected.trefpos, actual.trefpos) + self.assertEqual(expected.mjdref, actual.mjdref) + + def compare_polarization_wcs(self, expected, actual): + if expected is None and actual is None: + return + self.assertIsNotNone(expected) + self.assertIsNotNone(actual) + self.compare_coord_axis1d(expected.axis, actual.axis) + + def compare_axis(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.ctype) + self.assertIsNotNone(actual.cunit) + self.assertEqual(expected.ctype, actual.ctype) + self.assertEqual(expected.cunit, actual.cunit) + + def compare_coord2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_ref_coord(expected.coord1, actual.coord1) + self.compare_ref_coord(expected.coord2, actual.coord2) + + def compare_value_coord2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.coord1, actual.coord1) + self.assertEqual(expected.coord2, actual.coord2) + + def compare_coord_axis1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_coord_error(expected.error, actual.error) + self.compare_coord_range1d(expected.range, actual.range) + self.compare_coord_bounds1d(expected.bounds, actual.bounds) + self.compare_coord_function1d(expected.function, actual.function) + + def compare_coord_axis2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.axis1) + self.assertIsNotNone(actual.axis2) + self.compare_axis(expected.axis1, actual.axis1) + self.compare_axis(expected.axis2, actual.axis2) + self.compare_coord_error(expected.error1, actual.error1) + self.compare_coord_error(expected.error2, actual.error2) + self.compare_coord_range2d(expected.range, actual.range) + self.compare_coord_bounds2d(expected.bounds, actual.bounds) + self.compare_coord_function2d(expected.function, actual.function) + + def compare_coord_bounds1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(expected.samples) + self.assertIsNotNone(actual.samples) + self.assertEqual(len(expected.samples), len(actual.samples)) + for expected_range, actual_range in zip(expected.samples, actual.samples): + self.compare_coord_range1d(expected_range, actual_range) + + def compare_coord_bounds2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + if (isinstance(expected, wcs.CoordCircle2D) and + isinstance(actual, wcs.CoordCircle2D)): + self.compare_coord_circle2d(expected, actual) + elif (isinstance(expected, wcs.CoordPolygon2D) and + isinstance(actual, wcs.CoordPolygon2D)): + self.compare_coord_polygon2d(expected, actual) + else: + self.fail("CoordBounds2D expected and actual are different types.") + + def compare_coord_circle2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.center) + self.assertIsNotNone(actual.radius) + self.compare_value_coord2d(expected.center, actual.center) + self.assertEqual(expected.radius, actual.radius) + + def compare_coord_error(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + + self.assertIsNotNone(actual) + if expected.syser: + self.assertIsNotNone(actual.syser) + self.assertEqual(expected.syser, actual.syser) + if expected.rnder: + self.assertIsNotNone(actual.rnder) + self.assertEqual(expected.rnder, actual.rnder) + + def compare_coord_function1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.naxis, actual.naxis) + self.assertEqual(expected.delta, actual.delta) + self.compare_ref_coord(expected.ref_coord, actual.ref_coord) + + def compare_coord_function2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.dimension) + self.assertIsNotNone(actual.ref_coord) + self.assertIsNotNone(actual.cd11) + self.assertIsNotNone(actual.cd12) + self.assertIsNotNone(actual.cd21) + self.assertIsNotNone(actual.cd22) + self.compare_dimension2d(expected.dimension, actual.dimension) + self.compare_coord2d(expected.ref_coord, actual.ref_coord) + self.assertEqual(expected.cd11, actual.cd11, 0.0) + self.assertEqual(expected.cd12, actual.cd12, 0.0) + self.assertEqual(expected.cd21, actual.cd21, 0.0) + self.assertEqual(expected.cd22, actual.cd22, 0.0) + + def compare_coord_polygon2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(expected.vertices) + self.assertIsNotNone(actual.vertices) + self.assertEqual(len(expected.vertices), len(actual.vertices)) + for expected_coord_2d, actual_coord_2d in zip(expected.vertices, + actual.vertices): + self.compare_value_coord2d(expected_coord_2d, actual_coord_2d) + + def compare_coord_range1d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.compare_ref_coord(expected.start, actual.start) + self.compare_ref_coord(expected.end, actual.end) + + def compare_coord_range2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.start) + self.assertIsNotNone(actual.end) + self.compare_coord2d(expected.start, actual.start) + self.compare_coord2d(expected.end, actual.end) + + def compare_dimension2d(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.naxis1, actual.naxis1) + self.assertEqual(expected.naxis2, actual.naxis2) + + def compare_ref_coord(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertEqual(expected.pix, actual.pix) + self.assertEqual(expected.val, actual.val) + + def compare_slice(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.bin) + self.assertIsNotNone(actual.axis) + self.assertEqual(expected.bin, actual.bin) + self.compare_axis(expected.axis, actual.axis) + + def compare_point(self, expected, actual): + if expected is None: + self.assertIsNone(actual) + return + self.assertIsNotNone(actual) + self.assertIsNotNone(actual.cval1) + self.assertIsNotNone(actual.cval2) + self.assertEqual(expected.cval1, actual.cval1) + self.assertEqual(expected.cval2, actual.cval2) class TestRoundTrip(unittest.TestCase): @@ -227,14 +840,29 @@ def make_test_dir(self): raise def copy_files(self): - print glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, - '*.xml')) - for filename in glob.glob(os.path.join(TestRoundTrip. - TEST_FILE_SOURCE_DIR, - '*.xml')): - print "copied file " + filename - shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) + # print os.path.join(TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml') + # print glob.glob(os.path.join( + # TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml')) + # for filename in glob.glob(os.path.join( + # TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml')): + # print "copied file " + filename + # shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) + + # file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") + # # print file_list + # for filename in file_list: + # if filename.endswith(".xml"): + # print "copied " + filename + # shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) + + test_data = pkg_resources.resource_filename("caom2tools.caom2.test", "data") + print os.path.join(test_data, '*.xml') + file_list = glob.glob(os.path.join(test_data, '*.xml')) + for filename in file_list: + print filename + test_file = pkg_resources.resource_filename("caom2tools.caom2.test.data", filename) + print test_file + shutil.copy(test_file, TestRoundTrip.XML_FILE_SOURCE_DIR) def init(self): self.make_test_dir() @@ -259,8 +887,8 @@ def do_test(self, reader, writer, filename): dest_xml_fp.close() self.assertTrue(filecmp.cmp(source_file_path, dest_file_path), 'files are different, ' + - 'file from Java was: ' + source_file_path + ' ' - 'file from Python was: ' + dest_file_path) + 'file from Java was: ' + source_file_path + + ' file from Python was: ' + dest_file_path) # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 @@ -301,663 +929,3 @@ def test_round_trip(self): except Exception as e: #if e.errno != errno.EEXIST: raise - - -def minimal_simple(depth, bounds_is_circle, version): - instances = caom_test_instances.Caom2TestInstances() - instances.complete = False - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_simple_observation() - - -def complete_simple(depth, bounds_is_circle, version): - instances = caom_test_instances.Caom2TestInstances() - instances.complete = True - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_simple_observation() - - -def minimal_composite(depth, bounds_is_circle, version): - instances = caom_test_instances.Caom2TestInstances() - instances.complete = False - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_composite_observation() - - -def complete_composite(depth, bounds_is_circle, version): - instances = caom_test_instances.Caom2TestInstances() - instances.complete = True - instances.depth = depth - instances.bounds_is_circle = bounds_is_circle - instances.caom_version = version - return instances.get_composite_observation() - - -def test_observation(self, obs, validate, write_empty_collections, version): - if version == 20: - writer = obs_reader_writer.ObservationWriter( - validate, write_empty_collections, "caom2", - obs_reader_writer.CAOM20_NAMESPACE) - elif version == 21: - writer = obs_reader_writer.ObservationWriter( - validate, write_empty_collections, "caom2", - obs_reader_writer.CAOM21_NAMESPACE) - else: - writer = obs_reader_writer.ObservationWriter( - validate, write_empty_collections) - xml_file = open('/tmp/test.xml', 'w') - writer.write(obs, xml_file) - xml_file.close() - reader = obs_reader_writer.ObservationReader(True) - returned = reader.read('/tmp/test.xml') - compare_observations(self, obs, returned, version) - - -def compare_observations(self, expected, actual, version): - - assert ((isinstance(expected, observation.SimpleObservation) and - isinstance(actual, observation.SimpleObservation)) or - (isinstance(expected, observation.CompositeObservation) and - isinstance(actual, observation.CompositeObservation))), ( - "Observation types do not match 0 vs 1". - format(expected.__class__.__name__, - actual.__class__.__name__)) - - self.assertIsNotNone(expected.collection) - self.assertIsNotNone(actual.collection) - self.assertEqual(expected.collection, actual.collection) - - self.assertIsNotNone(expected.observation_id) - self.assertIsNotNone(actual.observation_id) - self.assertEqual(expected.observation_id, actual.observation_id) - - self.assertIsNotNone(expected._id) - self.assertIsNotNone(actual._id) - self.assertEqual(expected._id, actual._id) - - self.assertIsNotNone(expected._last_modified) - self.assertIsNotNone(actual._last_modified) - self.assertEqual(expected._last_modified, actual._last_modified) - - self.assertIsNotNone(expected.algorithm) - self.assertIsNotNone(actual.algorithm) - self.assertEqual(expected.algorithm.name, actual.algorithm.name) - - self.assertEqual(expected.sequence_number, actual.sequence_number) - self.assertEqual(expected.intent, actual.intent) - self.assertEqual(expected.meta_release, actual.meta_release) - compare_proposal(self, expected.proposal, actual.proposal) - compare_target(self, expected.target, actual.target) - compare_target_position(self, expected.target_position, - actual.target_position) - compare_telescope(self, expected.telescope, actual.telescope) - compare_instrument(self, expected.instrument, actual.instrument) - compare_environment(self, expected.environment, actual.environment) - if version == 21: - compare_requirements(self, expected.requirements, actual.requirements) - - compare_planes(self, expected.planes, actual.planes, version) - - if (isinstance(expected, observation.CompositeObservation) and - isinstance(actual, observation.CompositeObservation)): - compare_members(self, expected.members, actual.members) - - -def compare_proposal(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.proposal_id, actual.proposal_id) - self.assertEqual(expected.pi_name, actual.pi_name) - self.assertEqual(expected.project, actual.project) - self.assertEqual(expected.title, actual.title) - self.assertEqual(len(expected.keywords), len(actual.keywords)) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - -def compare_target(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - self.assertEqual(expected.target_type, actual.target_type) - self.assertEqual(expected.redshift, actual.redshift) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - - -def compare_target_position(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.coordinates) - self.assertIsNotNone(actual.coordsys) - compare_point(self, expected.coordinates, actual.coordinates) - self.assertEqual(expected.coordsys, actual.coordsys) - self.assertEqual(expected.equinox, actual.equinox) - - -def compare_telescope(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - self.assertEqual(expected.geo_location_x, actual.geo_location_x) - self.assertEqual(expected.geo_location_y, actual.geo_location_y) - self.assertEqual(expected.geo_location_z, actual.geo_location_z) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - - -def compare_instrument(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.name, actual.name) - for keyword in expected.keywords: - self.assertTrue(keyword in actual.keywords) - - -def compare_environment(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.seeing, actual.seeing) - self.assertEqual(expected.humidity, actual.humidity) - self.assertEqual(expected.elevation, actual.elevation) - self.assertEqual(expected.tau, actual.tau) - self.assertEqual(expected.wavelength_tau, actual.wavelength_tau) - self.assertEqual(expected.ambient_temp, actual.ambient_temp) - self.assertEqual(expected.photometric, actual.photometric) - - -def compare_members(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_member, actual_member in zip(expected, actual): - compare_observation_uri(self, expected_member, actual_member) - - -def compare_observation_uri(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEquals(expected.uri, actual.uri) - self.assertEquals(expected.collection, actual.collection) - self.assertEquals(expected.observation_id, actual.observation_id) - - -def compare_requirements(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEquals(expected.flag, actual.flag) - - -def compare_planes(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_plane = expected[key] - actual_plane = actual[key] - self.assertIsNotNone(expected_plane) - self.assertIsNotNone(actual_plane) - self.assertEqual(expected_plane.product_id, actual_plane.product_id) - self.assertIsNotNone(expected_plane._id) - self.assertIsNotNone(actual_plane._id) - self.assertEqual(expected_plane._id, actual_plane._id) - self.assertIsNotNone(expected_plane._last_modified) - self.assertIsNotNone(actual_plane._last_modified) - self.assertEqual(expected_plane._last_modified, - actual_plane._last_modified) - self.assertEqual(expected_plane.meta_release, - actual_plane.meta_release) - self.assertEqual(expected_plane.data_release, - actual_plane.data_release) - self.assertEqual(expected_plane.data_product_type, - actual_plane.data_product_type) - self.assertEqual(expected_plane.calibration_level, - actual_plane.calibration_level) - compare_provenance(self, expected_plane.provenance, - actual_plane.provenance) - compare_metrics(self, expected_plane.metrics, actual_plane.metrics) - if version == 21: - compare_quality(self, expected_plane.quality, - actual_plane.quality) - - compare_artifacts(self, expected_plane.artifacts, - actual_plane.artifacts, version) - - -def compare_provenance(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.version, actual.version) - self.assertEqual(expected.project, actual.project) - self.assertEqual(expected.producer, actual.producer) - self.assertEqual(expected.run_id, actual.run_id) - self.assertEqual(expected.reference, actual.reference) - self.assertEqual(expected.last_executed, actual.last_executed) - compare_inputs(self, expected.inputs, actual.inputs) - - -def compare_metrics(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.source_number_density, - actual.source_number_density) - self.assertEqual(expected.background, actual.background) - self.assertEqual(expected.background_std_dev, actual.background_std_dev) - self.assertEqual(expected.flux_density_limit, actual.flux_density_limit) - self.assertEqual(expected.mag_limit, actual.mag_limit) - - -def compare_quality(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(expected.flag, actual.flag) - - -def compare_inputs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_plane_uri, actual_plane_uri in zip(expected, actual): - self.assertEqual(expected_plane_uri, actual_plane_uri) - - -def compare_artifacts(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_artifact = expected[key] - actual_artifact = actual[key] - self.assertIsNotNone(expected_artifact) - self.assertIsNotNone(actual_artifact) - self.assertIsNotNone(expected_artifact._id) - self.assertIsNotNone(actual_artifact._id) - self.assertEqual(expected_artifact._id, actual_artifact._id) - self.assertIsNotNone(expected_artifact._last_modified) - self.assertIsNotNone(actual_artifact._last_modified) - self.assertEqual(expected_artifact._last_modified, - actual_artifact._last_modified) - self.assertEqual(expected_artifact.uri, actual_artifact.uri) - self.assertEqual(expected_artifact.content_type, - actual_artifact.content_type) - self.assertEqual(expected_artifact.content_length, - actual_artifact.content_length) - self.assertEqual(expected_artifact.product_type, - actual_artifact.product_type) - if version > 21: - self.assertEqual(expected_artifact.release_type, - actual_artifact.release_type) - compare_parts(self, expected_artifact.parts, - actual_artifact.parts, version) - - -def compare_parts(self, expected, actual, version): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for key in expected: - self.assertTrue(key in actual) - expected_part = expected[key] - actual_part = actual[key] - self.assertIsNotNone(expected_part) - self.assertIsNotNone(actual_part) - self.assertIsNotNone(expected_part._id) - self.assertIsNotNone(actual_part._id) - self.assertEqual(expected_part._id, actual_part._id) - self.assertIsNotNone(expected_part._last_modified) - self.assertIsNotNone(actual_part._last_modified) - self.assertEqual(expected_part._last_modified, - actual_part._last_modified) - self.assertEqual(expected_part.name, actual_part.name) - self.assertEqual(expected_part.product_type, actual_part.product_type) - compare_chunks(self, expected_part.chunks, actual_part.chunks) - - -def compare_chunks(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - self.assertEqual(len(expected), len(actual)) - for expected_chunk, actual_chunk in zip(expected, actual): - self.assertIsNotNone(expected_chunk) - self.assertIsNotNone(actual_chunk) - self.assertIsNotNone(expected_chunk._id) - self.assertIsNotNone(actual_chunk._id) - self.assertEqual(expected_chunk._id, actual_chunk._id) - self.assertIsNotNone(expected_chunk._last_modified) - self.assertIsNotNone(actual_chunk._last_modified) - self.assertEqual(expected_chunk._last_modified, - actual_chunk._last_modified) - self.assertEqual(expected_chunk.product_type, - actual_chunk.product_type) - self.assertEqual(expected_chunk.naxis, actual_chunk.naxis) - self.assertEqual(expected_chunk.observable_axis, - actual_chunk.observable_axis) - self.assertEqual(expected_chunk.position_axis_1, - actual_chunk.position_axis_1) - self.assertEqual(expected_chunk.position_axis_2, - actual_chunk.position_axis_2) - self.assertEqual(expected_chunk.energy_axis, actual_chunk.energy_axis) - self.assertEqual(expected_chunk.time_axis, actual_chunk.time_axis) - self.assertEqual(expected_chunk.polarization_axis, - actual_chunk.polarization_axis) - compare_observable_axis(self, expected_chunk.observable, - actual_chunk.observable) - compare_spatial_wcs(self, expected_chunk.position, - actual_chunk.position) - compare_spectral_wcs(self, expected_chunk.energy, actual_chunk.energy) - compare_temporal_wcs(self, expected_chunk.time, actual_chunk.time) - compare_polarization_wcs(self, expected_chunk.polarization, - actual_chunk.polarization) - - -def compare_observable_axis(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compare_slice(self, expected.dependent, actual.dependent) - compare_slice(self, expected.independent, actual.independent) - - -def compare_spatial_wcs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compare_coord_axis2d(self, expected.axis, actual.axis) - self.assertEqual(expected.coordsys, actual.coordsys) - self.assertEqual(expected.equinox, actual.equinox) - self.assertEqual(expected.resolution, actual.resolution) - - -def compare_spectral_wcs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compare_coord_axis1d(self, expected.axis, actual.axis) - self.assertEqual(expected.bandpass_name, actual.bandpass_name) - self.assertEqual(expected.resolving_power, actual.resolving_power) - self.assertEqual(expected.restfrq, actual.restfrq) - self.assertEqual(expected.restwav, actual.restwav) - self.assertEqual(expected.specsys, actual.specsys) - self.assertEqual(expected.ssysobs, actual.ssysobs) - self.assertEqual(expected.ssyssrc, actual.ssyssrc) - self.assertEqual(expected.velang, actual.velang) - self.assertEqual(expected.velosys, actual.velosys) - self.assertEqual(expected.zsource, actual.zsource) - - -def compare_temporal_wcs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compare_coord_axis1d(self, expected.axis, actual.axis) - self.assertEqual(expected.exposure, actual.exposure) - self.assertEqual(expected.resolution, actual.resolution) - self.assertEqual(expected.timesys, actual.timesys) - self.assertEqual(expected.trefpos, actual.trefpos) - self.assertEqual(expected.mjdref, actual.mjdref) - - -def compare_polarization_wcs(self, expected, actual): - if expected is None and actual is None: - return - self.assertIsNotNone(expected) - self.assertIsNotNone(actual) - compare_coord_axis1d(self, expected.axis, actual.axis) - - -def compare_axis(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.ctype) - self.assertIsNotNone(actual.cunit) - self.assertEqual(expected.ctype, actual.ctype) - self.assertEqual(expected.cunit, actual.cunit) - - -def compare_coord2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compare_ref_coord(self, expected.coord1, actual.coord1) - compare_ref_coord(self, expected.coord2, actual.coord2) - - -def compare_value_coord2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.coord1, actual.coord1) - self.assertEqual(expected.coord2, actual.coord2) - - -def compare_coord_axis1d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compare_coord_error(self, expected.error, actual.error) - compare_coord_range1d(self, expected.range, actual.range) - compare_coord_bounds1d(self, expected.bounds, actual.bounds) - compare_coord_function1d(self, expected.function, actual.function) - - -def compare_coord_axis2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.axis1) - self.assertIsNotNone(actual.axis2) - compare_axis(self, expected.axis1, actual.axis1) - compare_axis(self, expected.axis2, actual.axis2) - compare_coord_error(self, expected.error1, actual.error1) - compare_coord_error(self, expected.error2, actual.error2) - compare_coord_range2d(self, expected.range, actual.range) - compare_coord_bounds2d(self, expected.bounds, actual.bounds) - compare_coord_function2d(self, expected.function, actual.function) - - -def compare_coord_bounds1d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(expected.samples) - self.assertIsNotNone(actual.samples) - self.assertEqual(len(expected.samples), len(actual.samples)) - for expected_range, actual_range in zip(expected.samples, actual.samples): - compare_coord_range1d(self, expected_range, actual_range) - - -def compare_coord_bounds2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - if (isinstance(expected, wcs.CoordCircle2D) and - isinstance(actual, wcs.CoordCircle2D)): - compare_coord_circle2d(self, expected, actual) - elif (isinstance(expected, wcs.CoordPolygon2D) and - isinstance(actual, wcs.CoordPolygon2D)): - compare_coord_polygon2d(self, expected, actual) - else: - self.fail("CoordBounds2D expected and actual are different types.") - - -def compare_coord_circle2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.center) - self.assertIsNotNone(actual.radius) - compare_value_coord2d(self, expected.center, actual.center) - self.assertEqual(expected.radius, actual.radius) - - -def compare_coord_error(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - - self.assertIsNotNone(actual) - if expected.syser: - self.assertIsNotNone(actual.syser) - self.assertEqual(expected.syser, actual.syser) - if expected.rnder: - self.assertIsNotNone(actual.rnder) - self.assertEqual(expected.rnder, actual.rnder) - - -def compare_coord_function1d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.naxis, actual.naxis) - self.assertEqual(expected.delta, actual.delta) - compare_ref_coord(self, expected.ref_coord, actual.ref_coord) - - -def compare_coord_function2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.dimension) - self.assertIsNotNone(actual.ref_coord) - self.assertIsNotNone(actual.cd11) - self.assertIsNotNone(actual.cd12) - self.assertIsNotNone(actual.cd21) - self.assertIsNotNone(actual.cd22) - compare_dimension2d(self, expected.dimension, actual.dimension) - compare_coord2d(self, expected.ref_coord, actual.ref_coord) - self.assertEqual(expected.cd11, actual.cd11, 0.0) - self.assertEqual(expected.cd12, actual.cd12, 0.0) - self.assertEqual(expected.cd21, actual.cd21, 0.0) - self.assertEqual(expected.cd22, actual.cd22, 0.0) - - -def compare_coord_polygon2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(expected.vertices) - self.assertIsNotNone(actual.vertices) - self.assertEqual(len(expected.vertices), len(actual.vertices)) - for expected_coord_2d, actual_coord_2d in zip(expected.vertices, - actual.vertices): - compare_value_coord2d(self, expected_coord_2d, actual_coord_2d) - - -def compare_coord_range1d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - compare_ref_coord(self, expected.start, actual.start) - compare_ref_coord(self, expected.end, actual.end) - - -def compare_coord_range2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.start) - self.assertIsNotNone(actual.end) - compare_coord2d(self, expected.start, actual.start) - compare_coord2d(self, expected.end, actual.end) - - -def compare_dimension2d(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.naxis1, actual.naxis1) - self.assertEqual(expected.naxis2, actual.naxis2) - - -def compare_ref_coord(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertEqual(expected.pix, actual.pix) - self.assertEqual(expected.val, actual.val) - - -def compare_slice(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.bin) - self.assertIsNotNone(actual.axis) - self.assertEqual(expected.bin, actual.bin) - compare_axis(self, expected.axis, actual.axis) - - -def compare_point(self, expected, actual): - if expected is None: - self.assertIsNone(actual) - return - self.assertIsNotNone(actual) - self.assertIsNotNone(actual.cval1) - self.assertIsNotNone(actual.cval2) - self.assertEqual(expected.cval1, actual.cval1) - self.assertEqual(expected.cval2, actual.cval2) diff --git a/caom2tools/caom2/CAOM-2.0.xsd b/caom2tools/data/CAOM-2.0.xsd similarity index 100% rename from caom2tools/caom2/CAOM-2.0.xsd rename to caom2tools/data/CAOM-2.0.xsd diff --git a/caom2tools/caom2/CAOM-2.1.xsd b/caom2tools/data/CAOM-2.1.xsd similarity index 100% rename from caom2tools/caom2/CAOM-2.1.xsd rename to caom2tools/data/CAOM-2.1.xsd diff --git a/caom2tools/caom2/CAOM-2.2.xsd b/caom2tools/data/CAOM-2.2.xsd similarity index 100% rename from caom2tools/caom2/CAOM-2.2.xsd rename to caom2tools/data/CAOM-2.2.xsd diff --git a/caom2tools/data/__init__.py b/caom2tools/data/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/setup.py b/setup.py index fc15d3b8..9c3f13c0 100755 --- a/setup.py +++ b/setup.py @@ -77,6 +77,7 @@ # Add the project-global data package_info['package_data'].setdefault(PACKAGENAME, []) package_info['package_data'][PACKAGENAME].append('data/*') +package_info['package_data'][PACKAGENAME].append('caom2/test/data/*') # Define entry points for command-line scripts entry_points = {'console_scripts': []} From 54d381c0c02b06429271fd0aca760da240856ff0 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 21 Nov 2016 11:43:04 -0800 Subject: [PATCH 21/54] s1950: fix the ObservationReader/Writer roundtrip test --- .../caom2/test/test_obs_reader_writer.py | 26 +++---------------- 1 file changed, 4 insertions(+), 22 deletions(-) diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py index e942f462..8008ad0a 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -840,29 +840,11 @@ def make_test_dir(self): raise def copy_files(self): - # print os.path.join(TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml') - # print glob.glob(os.path.join( - # TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml')) - # for filename in glob.glob(os.path.join( - # TestRoundTrip.TEST_FILE_SOURCE_DIR, '*.xml')): - # print "copied file " + filename - # shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) - - # file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") - # # print file_list - # for filename in file_list: - # if filename.endswith(".xml"): - # print "copied " + filename - # shutil.copy(filename, TestRoundTrip.XML_FILE_SOURCE_DIR) - - test_data = pkg_resources.resource_filename("caom2tools.caom2.test", "data") - print os.path.join(test_data, '*.xml') - file_list = glob.glob(os.path.join(test_data, '*.xml')) + file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") for filename in file_list: - print filename - test_file = pkg_resources.resource_filename("caom2tools.caom2.test.data", filename) - print test_file - shutil.copy(test_file, TestRoundTrip.XML_FILE_SOURCE_DIR) + if filename.endswith(".xml"): + the_file = pkg_resources.resource_stream("caom2tools.caom2.test.data", filename) + shutil.copy(the_file.name, TestRoundTrip.XML_FILE_SOURCE_DIR) def init(self): self.make_test_dir() From 9096d3638293b443eaa4818dc7bbf6ae2715bdd0 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 21 Nov 2016 11:44:24 -0800 Subject: [PATCH 22/54] s1950: cleanup test imports --- caom2tools/caom2/test/test_obs_reader_writer.py | 1 - 1 file changed, 1 deletion(-) diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py index 8008ad0a..d24050d9 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -72,7 +72,6 @@ import StringIO import errno import filecmp -import glob import os import pkg_resources import shutil From 843e1d6ec9c1b7e2bc3c45c9b19b8be67344d469 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Mon, 21 Nov 2016 14:20:31 -0800 Subject: [PATCH 23/54] Added more unit tests --- caom2tools/util/caom2repo.py | 45 ++++++++++------------ caom2tools/util/test/test_caom2repo.py | 53 +++++++++++++++++++++----- 2 files changed, 64 insertions(+), 34 deletions(-) diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py index 7a4f90e7..16807cd4 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2tools/util/caom2repo.py @@ -78,7 +78,7 @@ from cadctools.net import ws from cadctools.util import util -from ..caom2 import ObservationReader, ObservationWriter +from ..caom2.obs_reader_writer import ObservationReader, ObservationWriter BATCH_SIZE = int(10000) SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it @@ -122,10 +122,10 @@ def visit(self, plugin, collection, start=None, end=None): observation = self.get_observation(collection, observationID) logging.info("Process observation: " + observation.observation_id) self.plugin.update(observation) - self.post_observation(collection, observationID, observation) - count = count + 1 + self.post_observation(observation) + count += 1 if len(observations) == BATCH_SIZE: - observations = self._get_observations() + observations = self._get_observations(collection) else: # the last batch was smaller so it must have been the last break @@ -144,6 +144,7 @@ def _get_observations(self, collection, start=None, end=None): params['END'] = end.strftime(DATE_FORMAT) response = self._repo_client.get(collection, params=params) + last_datetime = None for line in response.content.splitlines(): (obs, last_datetime) = line.split(',') observations.append(obs) @@ -156,12 +157,11 @@ def _load_plugin_class(self, filepath): expected_class = 'ObservationUpdater' mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1]) - - if file_ext.lower() == '.py': - py_mod = imp.load_source(mod_name, filepath) - - elif file_ext.lower() == '.pyc': + + if file_ext.lower() == '.pyc': py_mod = imp.load_compiled(mod_name, filepath) + else: + py_mod = imp.load_source(mod_name, filepath) if hasattr(py_mod, expected_class): self.plugin = getattr(py_mod, expected_class)() @@ -256,15 +256,16 @@ def main(): create_parser.add_argument('observation', metavar='', type=file) read_parser = subparsers.add_parser('read', description='Read an existing observation') + read_parser.add_argument('--collection', metavar='', required=True) read_parser.add_argument('--output', '-o', metavar='', required=False) - read_parser.add_argument('observation', metavar='', type=file) + read_parser.add_argument('observation', metavar='') update_parser = subparsers.add_parser('update', description='Update an existing observation') update_parser.add_argument('observation', metavar='', type=file) delete_parser = subparsers.add_parser('delete', description='Delete an existing observation') - delete_parser.add_argument('--collection', metavar='', type=file, required=True) - delete_parser.add_argument('observationID', metavar='', type=file) + delete_parser.add_argument('--collection', metavar='', required=True) + delete_parser.add_argument('observationID', metavar='') # Note: RawTextHelpFormatter allows for the use of newline in epilog visit_parser = subparsers.add_parser('visit', formatter_class=argparse.RawTextHelpFormatter, @@ -274,13 +275,13 @@ def main(): help='Pluging class to update each observation') visit_parser.add_argument('--start', metavar='', type=util.str2ivoa, - help='oldest dataset to visit (UTC %%Y-%%m-%%d format)'); + help='oldest dataset to visit (UTC %%Y-%%m-%%d format)') visit_parser.add_argument('--end', metavar='', type=util.str2ivoa, - help='earliest dataset to visit (UTC %%Y-%%m-%%d format)'); + help='earliest dataset to visit (UTC %%Y-%%m-%%d format)') visit_parser.add_argument('--retries', metavar='', type=int, - help='number of tries with transient server errors'); + help='number of tries with transient server errors') visit_parser.add_argument("-s", "--server", metavar=(''), help="URL of the CAOM2 repo server") @@ -328,21 +329,17 @@ def update(self, observation): client.put_observation(obs_reader.read(args.observation)) elif args.cmd == 'read': print("Read") - observation = client.get_observation(args.collection, args.observationID) + observation = client.get_observation(args.collection, args.observation) observation_writer = ObservationWriter() - ibuffer = StringIO() - ObservationWriter.write(observation, ibuffer) - obs_xml = ibuffer.getvalue() if args.output: with open(args.output, 'w') as obsfile: - obsfile.write(obs_xml) + observation_writer.write(observation, obsfile) else: - print obs_xml + observation_writer.write(observation, sys.stdout) elif args.cmd == 'update': print("Update") - with open(args.observation, 'r') as obsfile: - obs_reader = ObservationReader() - client.post_observation(obs_reader.read(StringIO(obsfile.read()))) #TODO not sure if need to read in string first + obs_reader = ObservationReader() + client.post_observation(obs_reader.read(args.observation)) #TODO not sure if need to read in string first else: print("Delete") client.delete_observation(collection=args.collection, observation=args.observationID) diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py index 3adf4238..3fcdacf5 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2tools/util/test/test_caom2repo.py @@ -72,15 +72,16 @@ import sys import os import requests -from mock import Mock, patch, MagicMock +from mock import Mock, patch, MagicMock, ANY #TODO to be changed to io.StringIO when caom2 is prepared for python3 from StringIO import StringIO from datetime import datetime +from cadctools import util from caom2tools.util import caom2repo from caom2tools.util.caom2repo import CAOM2RepoClient, DATE_FORMAT from caom2tools.caom2.observation import SimpleObservation -from caom2tools.caom2 import ObservationReader, ObservationWriter +from caom2tools.caom2.obs_reader_writer import ObservationReader, ObservationWriter THIS_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -375,24 +376,54 @@ def test_process(self): @patch('caom2tools.util.caom2repo.CAOM2RepoClient') def test_main(self, client_mock): - - collection = 'cfht' observation_id = '7000000o' service = 'caom2repo' ifile = '/tmp/inputobs' obs = SimpleObservation(collection, observation_id) - iobuffer = StringIO() + + # test create with open(ifile, 'w') as infile: ObservationWriter().write(obs, infile) - - put_mock = Mock(id='Mymock') - client_mock.return_value = Mock(id='mmm') - client_mock.put_observation = put_mock sys.argv = ["caom2tools", "create", ifile] caom2repo.main() - put_mock.assert_called_with('blah') + client_mock.return_value.put_observation.assert_called_with(obs) + + # test update + sys.argv = ["caom2tools", "update", ifile] + caom2repo.main() + client_mock.return_value.post_observation.assert_called_with(obs) + + + # test read + sys.argv = ["caom2tools", "read", "--collection", collection, observation_id] + client_mock.return_value.get_observation.return_value = obs + caom2repo.main() + client_mock.return_value.get_observation.assert_called_with(collection, observation_id) + # repeat with outout argument + sys.argv = ["caom2tools", "read", "--collection", collection, "--output", ifile, observation_id] + client_mock.return_value.get_observation.return_value = obs + caom2repo.main() + client_mock.return_value.get_observation.assert_called_with(collection, observation_id) + os.remove(ifile) + + # test delete + sys.argv = ["caom2tools", "delete", "--collection", collection, observation_id] + caom2repo.main() + client_mock.return_value.delete_observation.assert_called_with(collection=collection, + observation=observation_id) + + # test visit + # get the absolute path to be able to run the tests with the astropy frameworks + plugin_file = THIS_DIR + "/passplugin.py" + sys.argv = ["caom2tools", "visit", "--plugin", plugin_file, "--start", "2012-01-01T11:22:33.44", + "--end", "2013-01-01T11:33:22.443", collection] + with open(plugin_file, 'r') as infile: + caom2repo.main() + client_mock.return_value.visit.assert_called_with(ANY, collection, + start=util.str2ivoa("2012-01-01T11:22:33.44"), + end=util.str2ivoa("2013-01-01T11:33:22.443")) @patch('sys.exit', Mock(side_effect=[MyExitError, MyExitError, MyExitError, @@ -447,6 +478,7 @@ def test_help(self): read_usage =\ """usage: caom2-client read [-h] [--certfile CERTFILE] [--anonymous] [--host HOST] [--verbose] [--debug] [--quiet] + --collection [--output ] @@ -466,6 +498,7 @@ def test_help(self): --verbose verbose messages --debug debug messages --quiet run quietly + --collection --output , -o """ From d2dba57a96ff42cac2793531f9b378374bcf6ede Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 21 Nov 2016 14:35:17 -0800 Subject: [PATCH 24/54] s1950: updated the reader/writer test xml files to use a single keyword value --- .../caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml | 8 ++++---- .../caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml | 8 ++++---- caom2tools/caom2/test/data/CompleteCompositeCircle.xml | 8 ++++---- .../caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml | 8 ++++---- .../caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml | 8 ++++---- caom2tools/caom2/test/data/CompleteCompositePolygon.xml | 8 ++++---- .../caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml | 8 ++++---- .../caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml | 8 ++++---- caom2tools/caom2/test/data/CompleteSimpleCircle.xml | 8 ++++---- .../caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml | 8 ++++---- .../caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml | 8 ++++---- caom2tools/caom2/test/data/CompleteSimplePolygon.xml | 8 ++++---- 12 files changed, 48 insertions(+), 48 deletions(-) diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml index 7e250326..e6b84306 100644 --- a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml +++ b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml index fad972de..2e0b3506 100644 --- a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml +++ b/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle.xml b/caom2tools/caom2/test/data/CompleteCompositeCircle.xml index db2f1467..3dc12e60 100644 --- a/caom2tools/caom2/test/data/CompleteCompositeCircle.xml +++ b/caom2tools/caom2/test/data/CompleteCompositeCircle.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml index 596d97fb..4408806e 100644 --- a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml +++ b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml index 647cefed..8dfd6c7c 100644 --- a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml +++ b/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon.xml b/caom2tools/caom2/test/data/CompleteCompositePolygon.xml index e431778e..cdc68e0e 100644 --- a/caom2tools/caom2/test/data/CompleteCompositePolygon.xml +++ b/caom2tools/caom2/test/data/CompleteCompositePolygon.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml index 1b061723..8e1fcc92 100644 --- a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml +++ b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml index b3043373..dc4af87e 100644 --- a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml +++ b/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle.xml b/caom2tools/caom2/test/data/CompleteSimpleCircle.xml index 4a6b8189..d27ead15 100644 --- a/caom2tools/caom2/test/data/CompleteSimpleCircle.xml +++ b/caom2tools/caom2/test/data/CompleteSimpleCircle.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml index 885d01fe..592c2627 100644 --- a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml +++ b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml index 96fdd25a..f30d5e63 100644 --- a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml +++ b/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -40,7 +40,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -65,7 +65,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon.xml b/caom2tools/caom2/test/data/CompleteSimplePolygon.xml index 0297191b..d075ef52 100644 --- a/caom2tools/caom2/test/data/CompleteSimplePolygon.xml +++ b/caom2tools/caom2/test/data/CompleteSimplePolygon.xml @@ -14,7 +14,7 @@ proposalPi proposalProject proposalTitle - keyword1 keyword2 + keyword targetName @@ -22,7 +22,7 @@ false 1.5 false - keyword1 keyword2 + keyword coordsys @@ -37,7 +37,7 @@ 1.0 2.0 3.0 - keyword1 keyword2 + keyword 0.08 @@ -62,7 +62,7 @@ run_id http://foo/bar 2012-07-11T13:26:37.000 - keyword1 keyword2 + keyword caom:foo/bar/plane2 caom:foo/bar/plane1 From be5936a4d88b6652237033cc2d46b893fa67fb9f Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 22 Nov 2016 10:27:04 -0800 Subject: [PATCH 25/54] s1950: updated round-trip test using xml files to read from test/data directory and write to StringIO --- .../caom2/test/test_obs_reader_writer.py | 84 ++++++++----------- 1 file changed, 37 insertions(+), 47 deletions(-) diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2tools/caom2/test/test_obs_reader_writer.py index d24050d9..3ac60c3e 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2tools/caom2/test/test_obs_reader_writer.py @@ -70,13 +70,13 @@ """ Defines TestObservationReaderWriter class """ import StringIO -import errno -import filecmp import os -import pkg_resources -import shutil import unittest +import pkg_resources +from lxml import etree +from xml_compare import xml_compare + import caom_test_instances from .. import obs_reader_writer from .. import observation @@ -827,49 +827,48 @@ def compare_point(self, expected, actual): class TestRoundTrip(unittest.TestCase): - TEST_FILE_SOURCE_DIR = 'data' - XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/caom2' - - def make_test_dir(self): - try: - os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) - except OSError as exception: - if exception.errno != errno.EEXIST: - raise - - def copy_files(self): - file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") - for filename in file_list: - if filename.endswith(".xml"): - the_file = pkg_resources.resource_stream("caom2tools.caom2.test.data", filename) - shutil.copy(the_file.name, TestRoundTrip.XML_FILE_SOURCE_DIR) + TEST_PACKAGE = 'caom2tools.caom2.test' + TEST_DATA_PACKAGE = 'caom2tools.caom2.test.data' + TEST_DATA_DIR = 'data' + # XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' + # XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/caom2' + + # def make_test_dir(self): + # try: + # os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) + # except OSError as exception: + # if exception.errno != errno.EEXIST: + # raise + # + # def copy_files(self): + # file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") + # for filename in file_list: + # if filename.endswith(".xml"): + # the_file = pkg_resources.resource_stream("caom2tools.caom2.test.data", filename) + # shutil.copy(the_file.name, TestRoundTrip.XML_FILE_SOURCE_DIR) def init(self): - self.make_test_dir() - self.copy_files() - - def cleanup(self): - shutil.rmtree(TestRoundTrip.XML_FILE_SOURCE_DIR) + pass def get_file_list(self): - return [f for f in os.listdir(TestRoundTrip.XML_FILE_SOURCE_DIR) - if f.endswith('.xml')] + file_list = pkg_resources.resource_listdir(TestRoundTrip.TEST_PACKAGE, + TestRoundTrip.TEST_DATA_DIR) + return [f for f in file_list if f.endswith('.xml')] def do_test(self, reader, writer, filename): - source_file_path = (TestRoundTrip.XML_FILE_SOURCE_DIR + '/' + filename) + source_file = pkg_resources.resource_stream(TestRoundTrip.TEST_DATA_PACKAGE, filename) + source_file_path = os.path.abspath(source_file.name) print "test file: " + source_file_path source_xml_fp = open(source_file_path, 'r') obs = reader.read(source_file_path) source_xml_fp.close() - dest_file_path = TestRoundTrip.XML_FILE_DEST_DIR + '/' + filename - dest_xml_fp = open(dest_file_path, 'w') - writer.write(obs, dest_xml_fp) - dest_xml_fp.close() - self.assertTrue(filecmp.cmp(source_file_path, dest_file_path), - 'files are different, ' + - 'file from Java was: ' + source_file_path + - ' file from Python was: ' + dest_file_path) + dest_file = StringIO.StringIO() + writer.write(obs, dest_file) + + source_dom = etree.parse(source_file_path).getroot() + dest_dom = etree.fromstring(dest_file.getvalue()) + self.assertTrue(xml_compare(source_dom, dest_dom), + 'files are different') # This test reads each file in XML_FILE_SOURCE_DIR, creates the CAOM2 # objects and writes a file in XML_FILE_DEST_DIR based on the CAOM2 @@ -883,13 +882,7 @@ def test_round_trip(self): try: self.init() files = self.get_file_list() - self.assertTrue(len(files) > 0, 'No XML files in ' + - TestRoundTrip.XML_FILE_SOURCE_DIR) - try: - os.makedirs(TestRoundTrip.XML_FILE_DEST_DIR) - except OSError as e: - if e.errno != errno.EEXIST: - raise + self.assertTrue(len(files) > 0, 'No XML files in test data directory') reader = obs_reader_writer.ObservationReader(True) writer20 = obs_reader_writer.ObservationWriter( @@ -905,8 +898,5 @@ def test_round_trip(self): else: self.do_test(reader, writer20, filename) - #finally: - # self.cleanup() except Exception as e: - #if e.errno != errno.EEXIST: raise From 201b3ed119c7157da5934f72b753aa9609c49843 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 22 Nov 2016 10:33:43 -0800 Subject: [PATCH 26/54] s1950: fixed enum.py doctest error --- caom2tools/caom2/enum.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/caom2tools/caom2/enum.py b/caom2tools/caom2/enum.py index f3893b71..652c700d 100644 --- a/caom2tools/caom2/enum.py +++ b/caom2tools/caom2/enum.py @@ -241,8 +241,7 @@ def Enum(classname, **kargs): >>> Numbers('phi') Traceback (most recent call last): ... - - ValueError: 'phi' is not a valid enum name + ValueError: 'phi' is not a valid enum name \ (Must be one of: ['e', 'pi']) From b6d3d1a0f8cf28b7fff20f419b4af27975c08432 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 22 Nov 2016 14:08:31 -0800 Subject: [PATCH 27/54] Added more pydocs --- caom2tools/util/caom2repo.py | 57 ++++++++++++++++++++++---- caom2tools/util/test/test_caom2repo.py | 7 ++-- dev_requirements.txt | 6 +++ setup.py | 2 +- 4 files changed, 59 insertions(+), 13 deletions(-) create mode 100644 dev_requirements.txt diff --git a/caom2tools/util/caom2repo.py b/caom2tools/util/caom2repo.py index 16807cd4..ad0d93a5 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2tools/util/caom2repo.py @@ -88,23 +88,34 @@ class CAOM2RepoClient: """Class to do CRUD + visitor actions on a CAOM2 collection repo.""" - def __init__(self, anon=True, cert_file=None, verify=False, server=None): + def __init__(self, anon=True, cert_file=None, server=None): + """ + Instance of a CAOM2RepoClient + :param anon: True if anonymous access, False otherwise + :param cert_file: Location of X509 certificate used for authentication + :param server: Host server for the caom2repo service + """ # repo client to use - serv = SERVICE_URL + s = SERVICE_URL if server is not None: - serv = server + s = server agent = 'CAOM2RepoClient' #TODO add version - self._repo_client = ws.BaseWsClient(serv, anon=anon, cert_file=cert_file, - agent=agent, verify=verify, retry=True) + self._repo_client = ws.BaseWsClient(s, anon=anon, cert_file=cert_file, agent=agent, retry=True) logging.info('Service URL: {}'.format(self._repo_client.base_url)) def visit(self, plugin, collection, start=None, end=None): """ Main processing function that iterates through the observations of - the collection and updates them according to the algorithm + the collection and updates them according to the algorithm of the plugin function + :param plugin: path to python file that contains the algorithm to be applied to visited + observations + :param collection: name of the CAOM2 collection + :param start: optional earliest date-time of the targeted observation set + :param end: optional latest date-time of the targeted observation set + :return: number of visited observations """ if not os.path.isfile(plugin): raise Exception('Cannot find plugin file ' + plugin) @@ -134,6 +145,10 @@ def visit(self, plugin, collection, start=None, end=None): def _get_observations(self, collection, start=None, end=None): """ Returns a list of datasets from the collection + :param collection: name of the collection + :param start: earliest observation + :param end: latest observation + :return: """ assert collection is not None observations = [] @@ -154,6 +169,10 @@ def _get_observations(self, collection, start=None, end=None): def _load_plugin_class(self, filepath): + """ + Loads the plugin method and sets the self.plugin to refer to it. + :param filepath: path to the file containing the python function + """ expected_class = 'ObservationUpdater' mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1]) @@ -167,8 +186,7 @@ def _load_plugin_class(self, filepath): self.plugin = getattr(py_mod, expected_class)() else: raise Exception( - 'Cannot find ObservationUpdater class in pluging file ' +\ - filepath) + 'Cannot find ObservationUpdater class in pluging file ' + filepath) if not hasattr(self.plugin, 'update'): raise Exception('Cannot find update method in plugin class ' +\ @@ -176,6 +194,12 @@ def _load_plugin_class(self, filepath): def get_observation(self, collection, observationID): + """ + Get an observation from the CAOM2 repo + :param collection: name of the collection + :param observationID: the ID of the observation + :return: the caom2.observation.Observation object + """ assert collection is not None assert observationID is not None resource = '/{}/{}'.format(collection, observationID) @@ -192,6 +216,11 @@ def get_observation(self, collection, observationID): def post_observation(self, observation): + """ + Updates an observation in the CAOM2 repo + :param observation: observation to update + :return: updated observation + """ assert observation.collection is not None assert observation.observation_id is not None resource = '/{}/{}'.format(observation.collection, observation.observation_id) @@ -214,6 +243,11 @@ def post_observation(self, observation): def put_observation(self, observation): + """ + Add an observation to the CAOM2 repo + :param observation: observation to add to the CAOM2 repo + :return: Added observation + """ assert observation.collection is not None resource = '/{}'.format(observation.collection) logging.debug('PUT {}'.format(resource)) @@ -235,6 +269,11 @@ def put_observation(self, observation): def delete_observation(self, collection, observationID): + """ + Delete an observation from the CAOM2 repo + :param collection: Name of the collection + :param observationID: ID of the observation + """ assert observationID is not None resource = '/{}/{}'.format(collection, observationID) logging.debug('DELETE {}'.format(resource)) @@ -310,7 +349,7 @@ def update(self, observation): if args.debug: logging.basicConfig(level=logging.DEBUG) - client = CAOM2RepoClient(server=args.host) + client = CAOM2RepoClient(anon=args.anonymous, cert_file=args.certfile, server=args.host) if args.cmd == 'visit': print ("Visit") diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2tools/util/test/test_caom2repo.py index 3fcdacf5..ef1eb533 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2tools/util/test/test_caom2repo.py @@ -212,6 +212,7 @@ def test_get_observations(self, mock_get): # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadctools.net.ws.auth.get_user_password', Mock(return_value=('usr', 'passwd'))) @patch('cadctools.net.ws.Session.send') def test_post_observation(self, mock_conn): collection = 'cfht' @@ -220,7 +221,7 @@ def test_post_observation(self, mock_conn): service_url = 'www.cadc.nrc.ca/{}'.format(service) obs = SimpleObservation(collection, observation_id) - visitor = CAOM2RepoClient(server=service_url) + visitor = CAOM2RepoClient(anon=False, server=service_url) response = MagicMock() response.status = 200 mock_conn.return_value = response @@ -231,7 +232,7 @@ def test_post_observation(self, mock_conn): self.assertEqual(obs, visitor.post_observation(obs)) self.assertEqual('POST', mock_conn.call_args[0][0].method) - self.assertEqual('/{}/{}/{}'.format(service, collection, observation_id), + self.assertEqual('/{}/auth/{}/{}'.format(service, collection, observation_id), mock_conn.call_args[0][0].path_url) self.assertEqual('application/xml', mock_conn.call_args[0][0].headers['Content-Type']) self.assertEqual(obsxml, mock_conn.call_args[0][0].body) @@ -271,7 +272,7 @@ def test_put_observation(self, mock_conn): service_url = 'www.cadc.nrc.ca/{}'.format(service) obs = SimpleObservation(collection, observation_id) - visitor = CAOM2RepoClient(server=service_url) + visitor = CAOM2RepoClient(cert_file='somefile.pem', server=service_url) response = MagicMock() response.status = 200 mock_conn.return_value = response diff --git a/dev_requirements.txt b/dev_requirements.txt new file mode 100644 index 00000000..e3c187eb --- /dev/null +++ b/dev_requirements.txt @@ -0,0 +1,6 @@ +astropy==1.2.1 +cadctools==0.1.dev11 +-e . +funcsigs==1.0.2 +mock==2.0.0 +xml-compare==1.0.5 diff --git a/setup.py b/setup.py index 9c3f13c0..dc1730db 100755 --- a/setup.py +++ b/setup.py @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['lxml', 'astropy', 'requests'], + install_requires=['lxml', 'requests'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, From 4ef0113ffb5d43258e79ad883763f87991e5fad9 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 22 Nov 2016 14:44:42 -0800 Subject: [PATCH 28/54] Modified dev requirements --- dev_requirements.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/dev_requirements.txt b/dev_requirements.txt index e3c187eb..0d69562b 100644 --- a/dev_requirements.txt +++ b/dev_requirements.txt @@ -1,3 +1,4 @@ +numpy==1.12.0b1 astropy==1.2.1 cadctools==0.1.dev11 -e . From 6cc48c1114650b2a396bb0a7c81283257b3012e4 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 23 Nov 2016 15:59:04 -0800 Subject: [PATCH 29/54] Major re-arrangement of the packages --- README.md | 2 - LICENSE => caom2/LICENSE | 0 MANIFEST.in => caom2/MANIFEST.in | 0 caom2/README.md | 2 + ah_bootstrap.py => caom2/ah_bootstrap.py | 0 astropy_helpers => caom2/astropy_helpers | 0 {caom2tools => caom2}/caom2/__init__.py | 33 +- {caom2tools => caom2/caom2}/_astropy_init.py | 0 {caom2tools => caom2}/caom2/artifact.py | 0 {caom2tools => caom2}/caom2/caom_object.py | 0 {caom2tools => caom2}/caom2/caom_util.py | 0 {caom2tools => caom2}/caom2/chunk.py | 0 {caom2tools => caom2/caom2}/conftest.py | 0 {caom2tools => caom2/caom2}/data/CAOM-2.0.xsd | 0 {caom2tools => caom2/caom2}/data/CAOM-2.1.xsd | 0 {caom2tools => caom2/caom2}/data/CAOM-2.2.xsd | 0 .../test => caom2/caom2/data}/__init__.py | 0 {caom2tools => caom2}/caom2/enum.py | 0 .../caom2/obs_reader_writer.py | 2 +- {caom2tools => caom2}/caom2/observation.py | 0 {caom2tools => caom2}/caom2/part.py | 0 {caom2tools => caom2}/caom2/plane.py | 0 {caom2tools => caom2}/caom2/shape.py | 0 .../data => caom2/caom2/test}/__init__.py | 0 .../caom2/test/caom_test_instances.py | 16 +- .../data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../test/data/CompleteCompositeCircle.xml | 0 .../CompleteCompositePolygon-CAOM-2.1.xml | 0 .../CompleteCompositePolygon-CAOM-2.2.xml | 0 .../test/data/CompleteCompositePolygon.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../caom2/test/data/CompleteSimpleCircle.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../caom2/test/data/CompleteSimplePolygon.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../test/data/MinimalCompositeCircle.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../test/data/MinimalCompositePolygon.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../caom2/test/data/MinimalSimpleCircle.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../caom2/test/data/MinimalSimplePolygon.xml | 0 .../caom2/test}/data/__init__.py | 0 .../caom2/test/test_artifact.py | 0 .../caom2/test/test_caom_object.py | 0 .../caom2/test/test_caom_util.py | 0 .../caom2/test/test_chunk.py | 0 .../caom2/test/test_obs_reader_writer.py | 10 +- .../caom2/test/test_observation.py | 0 {caom2tools => caom2}/caom2/test/test_part.py | 0 .../caom2/test/test_plane.py | 0 .../caom2/test/test_shape.py | 0 {caom2tools => caom2}/caom2/test/test_wcs.py | 0 {caom2tools => caom2}/caom2/wcs.py | 0 .../dev_requirements.txt | 0 {docs => caom2/docs}/Makefile | 0 .../docs}/_templates/autosummary/base.rst | 0 .../docs}/_templates/autosummary/class.rst | 0 .../docs}/_templates/autosummary/module.rst | 0 {docs => caom2/docs}/conf.py | 0 {docs => caom2/docs}/index.rst | 0 {docs => caom2/docs}/make.bat | 0 ez_setup.py => caom2/ez_setup.py | 0 setup.cfg => caom2/setup.cfg | 5 +- caom2/setup.py | 121 +++ caom2repo/LICENSE | 661 ++++++++++++ caom2repo/MANIFEST.in | 40 + caom2repo/README.md | 2 + caom2repo/ah_bootstrap.py | 987 ++++++++++++++++++ caom2repo/astropy_helpers | 1 + .../caom2repo}/__init__.py | 3 +- .../caom2repo}/_astropy_init.py | 0 caom2repo/caom2repo/conftest.py | 38 + .../caom2repo/core.py | 2 +- .../caom2repo}/test/__init__.py | 0 .../caom2repo}/test/addplaneplugin.py | 4 +- .../caom2repo}/test/passplugin.py | 2 +- .../caom2repo/test/test_core.py | 44 +- caom2repo/dev_requirements.txt | 7 + caom2repo/docs/Makefile | 133 +++ .../docs/_templates/autosummary/base.rst | 2 + .../docs/_templates/autosummary/class.rst | 2 + .../docs/_templates/autosummary/module.rst | 2 + caom2repo/docs/conf.py | 172 +++ .../__init__.py => caom2repo/docs/index.rst | 0 caom2repo/docs/make.bat | 170 +++ caom2repo/ez_setup.py | 425 ++++++++ caom2repo/setup.cfg | 37 + setup.py => caom2repo/setup.py | 2 +- caom2tools/test/__init__.py | 4 - caom2tools/test/coveragerc | 31 - caom2tools/test/setup_package.py | 3 - 99 files changed, 2862 insertions(+), 103 deletions(-) delete mode 100644 README.md rename LICENSE => caom2/LICENSE (100%) rename MANIFEST.in => caom2/MANIFEST.in (100%) create mode 100644 caom2/README.md rename ah_bootstrap.py => caom2/ah_bootstrap.py (100%) rename astropy_helpers => caom2/astropy_helpers (100%) rename {caom2tools => caom2}/caom2/__init__.py (88%) rename {caom2tools => caom2/caom2}/_astropy_init.py (100%) rename {caom2tools => caom2}/caom2/artifact.py (100%) rename {caom2tools => caom2}/caom2/caom_object.py (100%) rename {caom2tools => caom2}/caom2/caom_util.py (100%) rename {caom2tools => caom2}/caom2/chunk.py (100%) rename {caom2tools => caom2/caom2}/conftest.py (100%) rename {caom2tools => caom2/caom2}/data/CAOM-2.0.xsd (100%) rename {caom2tools => caom2/caom2}/data/CAOM-2.1.xsd (100%) rename {caom2tools => caom2/caom2}/data/CAOM-2.2.xsd (100%) rename {caom2tools/caom2/test => caom2/caom2/data}/__init__.py (100%) rename {caom2tools => caom2}/caom2/enum.py (100%) rename {caom2tools => caom2}/caom2/obs_reader_writer.py (99%) rename {caom2tools => caom2}/caom2/observation.py (100%) rename {caom2tools => caom2}/caom2/part.py (100%) rename {caom2tools => caom2}/caom2/plane.py (100%) rename {caom2tools => caom2}/caom2/shape.py (100%) rename {caom2tools/caom2/test/data => caom2/caom2/test}/__init__.py (100%) rename {caom2tools => caom2}/caom2/test/caom_test_instances.py (98%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositeCircle.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteCompositePolygon.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimpleCircle.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/CompleteSimplePolygon.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositeCircle.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalCompositePolygon.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimpleCircle.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename {caom2tools => caom2}/caom2/test/data/MinimalSimplePolygon.xml (100%) rename {caom2tools => caom2/caom2/test}/data/__init__.py (100%) rename {caom2tools => caom2}/caom2/test/test_artifact.py (100%) rename {caom2tools => caom2}/caom2/test/test_caom_object.py (100%) rename {caom2tools => caom2}/caom2/test/test_caom_util.py (100%) rename {caom2tools => caom2}/caom2/test/test_chunk.py (100%) rename {caom2tools => caom2}/caom2/test/test_obs_reader_writer.py (99%) rename {caom2tools => caom2}/caom2/test/test_observation.py (100%) rename {caom2tools => caom2}/caom2/test/test_part.py (100%) rename {caom2tools => caom2}/caom2/test/test_plane.py (100%) rename {caom2tools => caom2}/caom2/test/test_shape.py (100%) rename {caom2tools => caom2}/caom2/test/test_wcs.py (100%) rename {caom2tools => caom2}/caom2/wcs.py (100%) rename dev_requirements.txt => caom2/dev_requirements.txt (100%) rename {docs => caom2/docs}/Makefile (100%) rename {docs => caom2/docs}/_templates/autosummary/base.rst (100%) rename {docs => caom2/docs}/_templates/autosummary/class.rst (100%) rename {docs => caom2/docs}/_templates/autosummary/module.rst (100%) rename {docs => caom2/docs}/conf.py (100%) rename {docs => caom2/docs}/index.rst (100%) rename {docs => caom2/docs}/make.bat (100%) rename ez_setup.py => caom2/ez_setup.py (100%) rename setup.cfg => caom2/setup.cfg (86%) create mode 100755 caom2/setup.py create mode 100644 caom2repo/LICENSE create mode 100644 caom2repo/MANIFEST.in create mode 100644 caom2repo/README.md create mode 100644 caom2repo/ah_bootstrap.py create mode 160000 caom2repo/astropy_helpers rename {caom2tools => caom2repo/caom2repo}/__init__.py (98%) mode change 100644 => 100755 rename {caom2tools/util => caom2repo/caom2repo}/_astropy_init.py (100%) create mode 100644 caom2repo/caom2repo/conftest.py rename caom2tools/util/caom2repo.py => caom2repo/caom2repo/core.py (99%) rename {caom2tools/util => caom2repo/caom2repo}/test/__init__.py (100%) rename {caom2tools/util => caom2repo/caom2repo}/test/addplaneplugin.py (98%) rename {caom2tools/util => caom2repo/caom2repo}/test/passplugin.py (99%) rename caom2tools/util/test/test_caom2repo.py => caom2repo/caom2repo/test/test_core.py (97%) create mode 100644 caom2repo/dev_requirements.txt create mode 100644 caom2repo/docs/Makefile create mode 100644 caom2repo/docs/_templates/autosummary/base.rst create mode 100644 caom2repo/docs/_templates/autosummary/class.rst create mode 100644 caom2repo/docs/_templates/autosummary/module.rst create mode 100644 caom2repo/docs/conf.py rename caom2tools/util/__init__.py => caom2repo/docs/index.rst (100%) mode change 100755 => 100644 create mode 100644 caom2repo/docs/make.bat create mode 100644 caom2repo/ez_setup.py create mode 100644 caom2repo/setup.cfg rename setup.py => caom2repo/setup.py (98%) delete mode 100644 caom2tools/test/__init__.py delete mode 100644 caom2tools/test/coveragerc delete mode 100644 caom2tools/test/setup_package.py diff --git a/README.md b/README.md deleted file mode 100644 index ad442c2a..00000000 --- a/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# caom2tools -Common Archive Observation Model - data engineering tools diff --git a/LICENSE b/caom2/LICENSE similarity index 100% rename from LICENSE rename to caom2/LICENSE diff --git a/MANIFEST.in b/caom2/MANIFEST.in similarity index 100% rename from MANIFEST.in rename to caom2/MANIFEST.in diff --git a/caom2/README.md b/caom2/README.md new file mode 100644 index 00000000..9181d329 --- /dev/null +++ b/caom2/README.md @@ -0,0 +1,2 @@ +# caom2 +Common Archive Observation Model - data model library diff --git a/ah_bootstrap.py b/caom2/ah_bootstrap.py similarity index 100% rename from ah_bootstrap.py rename to caom2/ah_bootstrap.py diff --git a/astropy_helpers b/caom2/astropy_helpers similarity index 100% rename from astropy_helpers rename to caom2/astropy_helpers diff --git a/caom2tools/caom2/__init__.py b/caom2/caom2/__init__.py similarity index 88% rename from caom2tools/caom2/__init__.py rename to caom2/caom2/__init__.py index bce7761e..d06b3005 100644 --- a/caom2tools/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -68,24 +68,19 @@ #*********************************************************************** # -""" Defines __init__ """ +# Licensed under a 3-clause BSD style license - see LICENSE.rst -# import os -# -# _ROOT = os.path.abspath(os.path.dirname(__file__)) -# -# -# def get_data(path): -# # return os.path.join(_ROOT, 'data', path) -# foo = os.path.join(_ROOT, 'data', path) -# print "path to " + path + " is " + foo -# return foo +""" +This is an Astropy affiliated package. +""" + +# Affiliated packages may add whatever they like to this file, but +# should keep this content at the top. +# ---------------------------------------------------------------------------- +from ._astropy_init import * +# ---------------------------------------------------------------------------- -# import artifact as artifact -# import caom_object as caom_object -# import chunk as chunk -# import observation as observation -# import part as part -# import plane as plane -# import caom_util as caom_util -# import wcs as wcs +# For egg_info test builds to pass, put package imports here. +if not _ASTROPY_SETUP_: +# from .caom2tools import * + pass diff --git a/caom2tools/_astropy_init.py b/caom2/caom2/_astropy_init.py similarity index 100% rename from caom2tools/_astropy_init.py rename to caom2/caom2/_astropy_init.py diff --git a/caom2tools/caom2/artifact.py b/caom2/caom2/artifact.py similarity index 100% rename from caom2tools/caom2/artifact.py rename to caom2/caom2/artifact.py diff --git a/caom2tools/caom2/caom_object.py b/caom2/caom2/caom_object.py similarity index 100% rename from caom2tools/caom2/caom_object.py rename to caom2/caom2/caom_object.py diff --git a/caom2tools/caom2/caom_util.py b/caom2/caom2/caom_util.py similarity index 100% rename from caom2tools/caom2/caom_util.py rename to caom2/caom2/caom_util.py diff --git a/caom2tools/caom2/chunk.py b/caom2/caom2/chunk.py similarity index 100% rename from caom2tools/caom2/chunk.py rename to caom2/caom2/chunk.py diff --git a/caom2tools/conftest.py b/caom2/caom2/conftest.py similarity index 100% rename from caom2tools/conftest.py rename to caom2/caom2/conftest.py diff --git a/caom2tools/data/CAOM-2.0.xsd b/caom2/caom2/data/CAOM-2.0.xsd similarity index 100% rename from caom2tools/data/CAOM-2.0.xsd rename to caom2/caom2/data/CAOM-2.0.xsd diff --git a/caom2tools/data/CAOM-2.1.xsd b/caom2/caom2/data/CAOM-2.1.xsd similarity index 100% rename from caom2tools/data/CAOM-2.1.xsd rename to caom2/caom2/data/CAOM-2.1.xsd diff --git a/caom2tools/data/CAOM-2.2.xsd b/caom2/caom2/data/CAOM-2.2.xsd similarity index 100% rename from caom2tools/data/CAOM-2.2.xsd rename to caom2/caom2/data/CAOM-2.2.xsd diff --git a/caom2tools/caom2/test/__init__.py b/caom2/caom2/data/__init__.py similarity index 100% rename from caom2tools/caom2/test/__init__.py rename to caom2/caom2/data/__init__.py diff --git a/caom2tools/caom2/enum.py b/caom2/caom2/enum.py similarity index 100% rename from caom2tools/caom2/enum.py rename to caom2/caom2/enum.py diff --git a/caom2tools/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py similarity index 99% rename from caom2tools/caom2/obs_reader_writer.py rename to caom2/caom2/obs_reader_writer.py index d5e50445..ca8ea212 100644 --- a/caom2tools/caom2/obs_reader_writer.py +++ b/caom2/caom2/obs_reader_writer.py @@ -84,7 +84,7 @@ import shape import wcs -DATA_PKG = 'caom2tools.data' +DATA_PKG = 'caom2.data' CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' diff --git a/caom2tools/caom2/observation.py b/caom2/caom2/observation.py similarity index 100% rename from caom2tools/caom2/observation.py rename to caom2/caom2/observation.py diff --git a/caom2tools/caom2/part.py b/caom2/caom2/part.py similarity index 100% rename from caom2tools/caom2/part.py rename to caom2/caom2/part.py diff --git a/caom2tools/caom2/plane.py b/caom2/caom2/plane.py similarity index 100% rename from caom2tools/caom2/plane.py rename to caom2/caom2/plane.py diff --git a/caom2tools/caom2/shape.py b/caom2/caom2/shape.py similarity index 100% rename from caom2tools/caom2/shape.py rename to caom2/caom2/shape.py diff --git a/caom2tools/caom2/test/data/__init__.py b/caom2/caom2/test/__init__.py similarity index 100% rename from caom2tools/caom2/test/data/__init__.py rename to caom2/caom2/test/__init__.py diff --git a/caom2tools/caom2/test/caom_test_instances.py b/caom2/caom2/test/caom_test_instances.py similarity index 98% rename from caom2tools/caom2/test/caom_test_instances.py rename to caom2/caom2/test/caom_test_instances.py index 19411740..2020cfbb 100644 --- a/caom2tools/caom2/test/caom_test_instances.py +++ b/caom2/caom2/test/caom_test_instances.py @@ -72,14 +72,14 @@ import collections from datetime import datetime -from caom2tools.caom2 import artifact -from caom2tools.caom2 import caom_util -from caom2tools.caom2 import chunk -from caom2tools.caom2 import observation -from caom2tools.caom2 import part -from caom2tools.caom2 import plane -from caom2tools.caom2 import shape -from caom2tools.caom2 import wcs +from caom2 import artifact +from caom2 import caom_util +from caom2 import chunk +from caom2 import observation +from caom2 import part +from caom2 import plane +from caom2 import shape +from caom2 import wcs class Caom2TestInstances(object): diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/CompleteCompositeCircle.xml b/caom2/caom2/test/data/CompleteCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositeCircle.xml rename to caom2/caom2/test/data/CompleteCompositeCircle.xml diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/CompleteCompositePolygon.xml b/caom2/caom2/test/data/CompleteCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteCompositePolygon.xml rename to caom2/caom2/test/data/CompleteCompositePolygon.xml diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/CompleteSimpleCircle.xml b/caom2/caom2/test/data/CompleteSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimpleCircle.xml rename to caom2/caom2/test/data/CompleteSimpleCircle.xml diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/CompleteSimplePolygon.xml b/caom2/caom2/test/data/CompleteSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/test/data/CompleteSimplePolygon.xml rename to caom2/caom2/test/data/CompleteSimplePolygon.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositeCircle.xml b/caom2/caom2/test/data/MinimalCompositeCircle.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositeCircle.xml rename to caom2/caom2/test/data/MinimalCompositeCircle.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/MinimalCompositePolygon.xml b/caom2/caom2/test/data/MinimalCompositePolygon.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalCompositePolygon.xml rename to caom2/caom2/test/data/MinimalCompositePolygon.xml diff --git a/caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/MinimalSimpleCircle.xml b/caom2/caom2/test/data/MinimalSimpleCircle.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimpleCircle.xml rename to caom2/caom2/test/data/MinimalSimpleCircle.xml diff --git a/caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/caom2tools/caom2/test/data/MinimalSimplePolygon.xml b/caom2/caom2/test/data/MinimalSimplePolygon.xml similarity index 100% rename from caom2tools/caom2/test/data/MinimalSimplePolygon.xml rename to caom2/caom2/test/data/MinimalSimplePolygon.xml diff --git a/caom2tools/data/__init__.py b/caom2/caom2/test/data/__init__.py similarity index 100% rename from caom2tools/data/__init__.py rename to caom2/caom2/test/data/__init__.py diff --git a/caom2tools/caom2/test/test_artifact.py b/caom2/caom2/test/test_artifact.py similarity index 100% rename from caom2tools/caom2/test/test_artifact.py rename to caom2/caom2/test/test_artifact.py diff --git a/caom2tools/caom2/test/test_caom_object.py b/caom2/caom2/test/test_caom_object.py similarity index 100% rename from caom2tools/caom2/test/test_caom_object.py rename to caom2/caom2/test/test_caom_object.py diff --git a/caom2tools/caom2/test/test_caom_util.py b/caom2/caom2/test/test_caom_util.py similarity index 100% rename from caom2tools/caom2/test/test_caom_util.py rename to caom2/caom2/test/test_caom_util.py diff --git a/caom2tools/caom2/test/test_chunk.py b/caom2/caom2/test/test_chunk.py similarity index 100% rename from caom2tools/caom2/test/test_chunk.py rename to caom2/caom2/test/test_chunk.py diff --git a/caom2tools/caom2/test/test_obs_reader_writer.py b/caom2/caom2/test/test_obs_reader_writer.py similarity index 99% rename from caom2tools/caom2/test/test_obs_reader_writer.py rename to caom2/caom2/test/test_obs_reader_writer.py index 3ac60c3e..00e486f7 100644 --- a/caom2tools/caom2/test/test_obs_reader_writer.py +++ b/caom2/caom2/test/test_obs_reader_writer.py @@ -827,8 +827,8 @@ def compare_point(self, expected, actual): class TestRoundTrip(unittest.TestCase): - TEST_PACKAGE = 'caom2tools.caom2.test' - TEST_DATA_PACKAGE = 'caom2tools.caom2.test.data' + TEST_PACKAGE = 'caom2.test' + TEST_DATA_PACKAGE = 'caom2.test.data' TEST_DATA_DIR = 'data' # XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' # XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/caom2' @@ -841,10 +841,10 @@ class TestRoundTrip(unittest.TestCase): # raise # # def copy_files(self): - # file_list = pkg_resources.resource_listdir("caom2tools.caom2.test", "data") + # file_list = pkg_resources.resource_listdir("caom2.test", "data") # for filename in file_list: # if filename.endswith(".xml"): - # the_file = pkg_resources.resource_stream("caom2tools.caom2.test.data", filename) + # the_file = pkg_resources.resource_stream("caom2.test.data", filename) # shutil.copy(the_file.name, TestRoundTrip.XML_FILE_SOURCE_DIR) def init(self): @@ -853,6 +853,8 @@ def init(self): def get_file_list(self): file_list = pkg_resources.resource_listdir(TestRoundTrip.TEST_PACKAGE, TestRoundTrip.TEST_DATA_DIR) + with open('/tmp/dbg.txt', 'w') as f: + f.write(str(file_list)) return [f for f in file_list if f.endswith('.xml')] def do_test(self, reader, writer, filename): diff --git a/caom2tools/caom2/test/test_observation.py b/caom2/caom2/test/test_observation.py similarity index 100% rename from caom2tools/caom2/test/test_observation.py rename to caom2/caom2/test/test_observation.py diff --git a/caom2tools/caom2/test/test_part.py b/caom2/caom2/test/test_part.py similarity index 100% rename from caom2tools/caom2/test/test_part.py rename to caom2/caom2/test/test_part.py diff --git a/caom2tools/caom2/test/test_plane.py b/caom2/caom2/test/test_plane.py similarity index 100% rename from caom2tools/caom2/test/test_plane.py rename to caom2/caom2/test/test_plane.py diff --git a/caom2tools/caom2/test/test_shape.py b/caom2/caom2/test/test_shape.py similarity index 100% rename from caom2tools/caom2/test/test_shape.py rename to caom2/caom2/test/test_shape.py diff --git a/caom2tools/caom2/test/test_wcs.py b/caom2/caom2/test/test_wcs.py similarity index 100% rename from caom2tools/caom2/test/test_wcs.py rename to caom2/caom2/test/test_wcs.py diff --git a/caom2tools/caom2/wcs.py b/caom2/caom2/wcs.py similarity index 100% rename from caom2tools/caom2/wcs.py rename to caom2/caom2/wcs.py diff --git a/dev_requirements.txt b/caom2/dev_requirements.txt similarity index 100% rename from dev_requirements.txt rename to caom2/dev_requirements.txt diff --git a/docs/Makefile b/caom2/docs/Makefile similarity index 100% rename from docs/Makefile rename to caom2/docs/Makefile diff --git a/docs/_templates/autosummary/base.rst b/caom2/docs/_templates/autosummary/base.rst similarity index 100% rename from docs/_templates/autosummary/base.rst rename to caom2/docs/_templates/autosummary/base.rst diff --git a/docs/_templates/autosummary/class.rst b/caom2/docs/_templates/autosummary/class.rst similarity index 100% rename from docs/_templates/autosummary/class.rst rename to caom2/docs/_templates/autosummary/class.rst diff --git a/docs/_templates/autosummary/module.rst b/caom2/docs/_templates/autosummary/module.rst similarity index 100% rename from docs/_templates/autosummary/module.rst rename to caom2/docs/_templates/autosummary/module.rst diff --git a/docs/conf.py b/caom2/docs/conf.py similarity index 100% rename from docs/conf.py rename to caom2/docs/conf.py diff --git a/docs/index.rst b/caom2/docs/index.rst similarity index 100% rename from docs/index.rst rename to caom2/docs/index.rst diff --git a/docs/make.bat b/caom2/docs/make.bat similarity index 100% rename from docs/make.bat rename to caom2/docs/make.bat diff --git a/ez_setup.py b/caom2/ez_setup.py similarity index 100% rename from ez_setup.py rename to caom2/ez_setup.py diff --git a/setup.cfg b/caom2/setup.cfg similarity index 86% rename from setup.cfg rename to caom2/setup.cfg index 40887f0f..c3ce8310 100644 --- a/setup.cfg +++ b/caom2/setup.cfg @@ -21,7 +21,7 @@ doctest_plus = enabled auto_use = True [metadata] -package_name = caom2tools +package_name = caom2 description = CAOM-2.2 library long_description = Python library for the CAOM-2.2 data model author = Canadian Astronomy Data Centre @@ -29,9 +29,8 @@ author_email = cadc@nrc-cnrc.gc.ca license = AGPLv3 url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 edit_on_github = False -github_project = opencadc/caom2tools +github_project = opencadc/caom2tools # version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) version = 2.2.2 [entry_points] -caom2-client = caom2tools.util.caom2repo:main diff --git a/caom2/setup.py b/caom2/setup.py new file mode 100755 index 00000000..41fef7a6 --- /dev/null +++ b/caom2/setup.py @@ -0,0 +1,121 @@ +#!/usr/bin/env python +# Licensed under a 3-clause BSD style license - see LICENSE.rst + +import glob +import os +import sys + +import ah_bootstrap +from setuptools import setup + +# A dirty hack to get around some early import/configurations ambiguities +if sys.version_info[0] >= 3: + import builtins +else: + import __builtin__ as builtins +builtins._ASTROPY_SETUP_ = True + +from astropy_helpers.setup_helpers import (register_commands, get_debug_option, + get_package_info) +from astropy_helpers.git_helpers import get_git_devstr +from astropy_helpers.version_helpers import generate_version_py + +# Get some values from the setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser + +conf = ConfigParser() +conf.read(['setup.cfg']) +metadata = dict(conf.items('metadata')) + +PACKAGENAME = metadata.get('package_name', 'packagename') +DESCRIPTION = metadata.get('description', 'Astropy affiliated package') +AUTHOR = metadata.get('author', '') +AUTHOR_EMAIL = metadata.get('author_email', '') +LICENSE = metadata.get('license', 'unknown') +URL = metadata.get('url', 'http://astropy.org') + +# Get the long description from the package's docstring +__import__(PACKAGENAME) +package = sys.modules[PACKAGENAME] +LONG_DESCRIPTION = package.__doc__ + +# Store the package name in a built-in variable so it's easy +# to get from other parts of the setup infrastructure +builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME + +# VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +VERSION = metadata.get('version', '2.2.2') + +# Indicates if this version is a release version +RELEASE = 'dev' not in VERSION + +if not RELEASE: + VERSION += get_git_devstr(False) + +# Populate the dict of setup command overrides; this should be done before +# invoking any other functionality from distutils since it can potentially +# modify distutils' behavior. +cmdclassd = register_commands(PACKAGENAME, VERSION, RELEASE) + +# Freeze build information in version.py +generate_version_py(PACKAGENAME, VERSION, RELEASE, + get_debug_option(PACKAGENAME)) + +# Treat everything in scripts except README.rst as a script to be installed +scripts = [fname for fname in glob.glob(os.path.join('scripts', '*')) + if os.path.basename(fname) != 'README.rst'] + + +# Get configuration information from all of the various subpackages. +# See the docstring for setup_helpers.update_package_files for more +# details. +package_info = get_package_info() + +# Add the project-global data +package_info['package_data'].setdefault(PACKAGENAME, []) +package_info['package_data'][PACKAGENAME].append('data/*') +package_info['package_data'][PACKAGENAME].append('test/data/*') + +# Define entry points for command-line scripts +entry_points = {'console_scripts': []} + +entry_point_list = conf.items('entry_points') +for entry_point in entry_point_list: + entry_points['console_scripts'].append('{0} = {1}'.format(entry_point[0], + entry_point[1])) + +# Include all .c files, recursively, including those generated by +# Cython, since we can not do this in MANIFEST.in with a "dynamic" +# directory name. +c_files = [] +for root, dirs, files in os.walk(PACKAGENAME): + for filename in files: + if filename.endswith('.c'): + c_files.append( + os.path.join( + os.path.relpath(root, PACKAGENAME), filename)) +package_info['package_data'][PACKAGENAME].extend(c_files) + +# Note that requires and provides should not be included in the call to +# ``setup``, since these are now deprecated. See this link for more details: +# https://groups.google.com/forum/#!topic/astropy-dev/urYO8ckB2uM + +setup(name=PACKAGENAME, + version=VERSION, + description=DESCRIPTION, + scripts=scripts, + install_requires=['lxml', 'requests'], + author=AUTHOR, + author_email=AUTHOR_EMAIL, + license=LICENSE, + url=URL, + long_description=LONG_DESCRIPTION, + cmdclass=cmdclassd, + zip_safe=False, + use_2to3=False, + entry_points=entry_points, + **package_info +) diff --git a/caom2repo/LICENSE b/caom2repo/LICENSE new file mode 100644 index 00000000..dbbe3558 --- /dev/null +++ b/caom2repo/LICENSE @@ -0,0 +1,661 @@ + GNU AFFERO GENERAL PUBLIC LICENSE + Version 3, 19 November 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU Affero General Public License is a free, copyleft license for +software and other kinds of works, specifically designed to ensure +cooperation with the community in the case of network server software. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +our General Public Licenses are intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + Developers that use our General Public Licenses protect your rights +with two steps: (1) assert copyright on the software, and (2) offer +you this License which gives you legal permission to copy, distribute +and/or modify the software. + + A secondary benefit of defending all users' freedom is that +improvements made in alternate versions of the program, if they +receive widespread use, become available for other developers to +incorporate. Many developers of free software are heartened and +encouraged by the resulting cooperation. However, in the case of +software used on network servers, this result may fail to come about. +The GNU General Public License permits making a modified version and +letting the public access it on a server without ever releasing its +source code to the public. + + The GNU Affero General Public License is designed specifically to +ensure that, in such cases, the modified source code becomes available +to the community. It requires the operator of a network server to +provide the source code of the modified version running there to the +users of that server. Therefore, public use of a modified version, on +a publicly accessible server, gives the public access to the source +code of the modified version. + + An older license, called the Affero General Public License and +published by Affero, was designed to accomplish similar goals. This is +a different license, not a version of the Affero GPL, but Affero has +released a new version of the Affero GPL which permits relicensing under +this license. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU Affero General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Remote Network Interaction; Use with the GNU General Public License. + + Notwithstanding any other provision of this License, if you modify the +Program, your modified version must prominently offer all users +interacting with it remotely through a computer network (if your version +supports such interaction) an opportunity to receive the Corresponding +Source of your version by providing access to the Corresponding Source +from a network server at no charge, through some standard or customary +means of facilitating copying of software. This Corresponding Source +shall include the Corresponding Source for any work covered by version 3 +of the GNU General Public License that is incorporated pursuant to the +following paragraph. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the work with which it is combined will remain governed by version +3 of the GNU General Public License. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU Affero General Public License from time to time. Such new versions +will be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU Affero General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU Affero General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU Affero General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU Affero General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If your software can interact with users remotely through a computer +network, you should also make sure that it provides a way for users to +get its source. For example, if your program is a web application, its +interface could display a "Source" link that leads users to an archive +of the code. There are many ways you could offer source, and different +solutions will be better for different programs; see section 13 for the +specific requirements. + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU AGPL, see +. diff --git a/caom2repo/MANIFEST.in b/caom2repo/MANIFEST.in new file mode 100644 index 00000000..c3bf88f0 --- /dev/null +++ b/caom2repo/MANIFEST.in @@ -0,0 +1,40 @@ +include README.rst +include CHANGES.rst + +include ez_setup.py +include ah_bootstrap.py +include setup.cfg + +recursive-include packagename *.pyx *.c *.pxd +recursive-include docs * +recursive-include licenses * +recursive-include cextern * +recursive-include scripts * + +prune build +prune docs/_build +prune docs/api + + +# the next few stanzas are for astropy_helpers. It's derived from the +# astropy_helpers/MANIFEST.in, but requires additional includes for the actual +# package directory and egg-info. + +include astropy_helpers/README.rst +include astropy_helpers/CHANGES.rst +include astropy_helpers/LICENSE.rst +recursive-include astropy_helpers/licenses * + +include astropy_helpers/ez_setup.py +include astropy_helpers/ah_bootstrap.py + +recursive-include astropy_helpers/astropy_helpers *.py *.pyx *.c *.h +recursive-include astropy_helpers/astropy_helpers.egg-info * +# include the sphinx stuff with "*" because there are css/html/rst/etc. +recursive-include astropy_helpers/astropy_helpers/sphinx * + +prune astropy_helpers/build +prune astropy_helpers/astropy_helpers/tests + + +global-exclude *.pyc *.o diff --git a/caom2repo/README.md b/caom2repo/README.md new file mode 100644 index 00000000..f276ac90 --- /dev/null +++ b/caom2repo/README.md @@ -0,0 +1,2 @@ +# caom2repo +Common Archive Observation Model - repo access library and client diff --git a/caom2repo/ah_bootstrap.py b/caom2repo/ah_bootstrap.py new file mode 100644 index 00000000..0dc50071 --- /dev/null +++ b/caom2repo/ah_bootstrap.py @@ -0,0 +1,987 @@ +""" +This bootstrap module contains code for ensuring that the astropy_helpers +package will be importable by the time the setup.py script runs. It also +includes some workarounds to ensure that a recent-enough version of setuptools +is being used for the installation. + +This module should be the first thing imported in the setup.py of distributions +that make use of the utilities in astropy_helpers. If the distribution ships +with its own copy of astropy_helpers, this module will first attempt to import +from the shipped copy. However, it will also check PyPI to see if there are +any bug-fix releases on top of the current version that may be useful to get +past platform-specific bugs that have been fixed. When running setup.py, use +the ``--offline`` command-line option to disable the auto-upgrade checks. + +When this module is imported or otherwise executed it automatically calls a +main function that attempts to read the project's setup.cfg file, which it +checks for a configuration section called ``[ah_bootstrap]`` the presences of +that section, and options therein, determine the next step taken: If it +contains an option called ``auto_use`` with a value of ``True``, it will +automatically call the main function of this module called +`use_astropy_helpers` (see that function's docstring for full details). +Otherwise no further action is taken (however, +``ah_bootstrap.use_astropy_helpers`` may be called manually from within the +setup.py script). + +Additional options in the ``[ah_boostrap]`` section of setup.cfg have the same +names as the arguments to `use_astropy_helpers`, and can be used to configure +the bootstrap script when ``auto_use = True``. + +See https://github.com/astropy/astropy-helpers for more details, and for the +latest version of this module. +""" + +import contextlib +import errno +import imp +import io +import locale +import os +import re +import subprocess as sp +import sys + +try: + from ConfigParser import ConfigParser, RawConfigParser +except ImportError: + from configparser import ConfigParser, RawConfigParser + + +if sys.version_info[0] < 3: + _str_types = (str, unicode) + _text_type = unicode + PY3 = False +else: + _str_types = (str, bytes) + _text_type = str + PY3 = True + + +# What follows are several import statements meant to deal with install-time +# issues with either missing or misbehaving pacakges (including making sure +# setuptools itself is installed): + + +# Some pre-setuptools checks to ensure that either distribute or setuptools >= +# 0.7 is used (over pre-distribute setuptools) if it is available on the path; +# otherwise the latest setuptools will be downloaded and bootstrapped with +# ``ez_setup.py``. This used to be included in a separate file called +# setuptools_bootstrap.py; but it was combined into ah_bootstrap.py +try: + import pkg_resources + _setuptools_req = pkg_resources.Requirement.parse('setuptools>=0.7') + # This may raise a DistributionNotFound in which case no version of + # setuptools or distribute is properly installed + _setuptools = pkg_resources.get_distribution('setuptools') + if _setuptools not in _setuptools_req: + # Older version of setuptools; check if we have distribute; again if + # this results in DistributionNotFound we want to give up + _distribute = pkg_resources.get_distribution('distribute') + if _setuptools != _distribute: + # It's possible on some pathological systems to have an old version + # of setuptools and distribute on sys.path simultaneously; make + # sure distribute is the one that's used + sys.path.insert(1, _distribute.location) + _distribute.activate() + imp.reload(pkg_resources) +except: + # There are several types of exceptions that can occur here; if all else + # fails bootstrap and use the bootstrapped version + from ez_setup import use_setuptools + use_setuptools() + + +# Note: The following import is required as a workaround to +# https://github.com/astropy/astropy-helpers/issues/89; if we don't import this +# module now, it will get cleaned up after `run_setup` is called, but that will +# later cause the TemporaryDirectory class defined in it to stop working when +# used later on by setuptools +try: + import setuptools.py31compat +except ImportError: + pass + + +# matplotlib can cause problems if it is imported from within a call of +# run_setup(), because in some circumstances it will try to write to the user's +# home directory, resulting in a SandboxViolation. See +# https://github.com/matplotlib/matplotlib/pull/4165 +# Making sure matplotlib, if it is available, is imported early in the setup +# process can mitigate this (note importing matplotlib.pyplot has the same +# issue) +try: + import matplotlib + matplotlib.use('Agg') + import matplotlib.pyplot +except: + # Ignore if this fails for *any* reason* + pass + + +# End compatibility imports... + + +# In case it didn't successfully import before the ez_setup checks +import pkg_resources + +from setuptools import Distribution +from setuptools.package_index import PackageIndex +from setuptools.sandbox import run_setup + +from distutils import log +from distutils.debug import DEBUG + + +# TODO: Maybe enable checking for a specific version of astropy_helpers? +DIST_NAME = 'astropy-helpers' +PACKAGE_NAME = 'astropy_helpers' + +# Defaults for other options +DOWNLOAD_IF_NEEDED = True +INDEX_URL = 'https://pypi.python.org/simple' +USE_GIT = True +OFFLINE = False +AUTO_UPGRADE = True + +# A list of all the configuration options and their required types +CFG_OPTIONS = [ + ('auto_use', bool), ('path', str), ('download_if_needed', bool), + ('index_url', str), ('use_git', bool), ('offline', bool), + ('auto_upgrade', bool) +] + + +class _Bootstrapper(object): + """ + Bootstrapper implementation. See ``use_astropy_helpers`` for parameter + documentation. + """ + + def __init__(self, path=None, index_url=None, use_git=None, offline=None, + download_if_needed=None, auto_upgrade=None): + + if path is None: + path = PACKAGE_NAME + + if not (isinstance(path, _str_types) or path is False): + raise TypeError('path must be a string or False') + + if PY3 and not isinstance(path, _text_type): + fs_encoding = sys.getfilesystemencoding() + path = path.decode(fs_encoding) # path to unicode + + self.path = path + + # Set other option attributes, using defaults where necessary + self.index_url = index_url if index_url is not None else INDEX_URL + self.offline = offline if offline is not None else OFFLINE + + # If offline=True, override download and auto-upgrade + if self.offline: + download_if_needed = False + auto_upgrade = False + + self.download = (download_if_needed + if download_if_needed is not None + else DOWNLOAD_IF_NEEDED) + self.auto_upgrade = (auto_upgrade + if auto_upgrade is not None else AUTO_UPGRADE) + + # If this is a release then the .git directory will not exist so we + # should not use git. + git_dir_exists = os.path.exists(os.path.join(os.path.dirname(__file__), '.git')) + if use_git is None and not git_dir_exists: + use_git = False + + self.use_git = use_git if use_git is not None else USE_GIT + # Declared as False by default--later we check if astropy-helpers can be + # upgraded from PyPI, but only if not using a source distribution (as in + # the case of import from a git submodule) + self.is_submodule = False + + @classmethod + def main(cls, argv=None): + if argv is None: + argv = sys.argv + + config = cls.parse_config() + config.update(cls.parse_command_line(argv)) + + auto_use = config.pop('auto_use', False) + bootstrapper = cls(**config) + + if auto_use: + # Run the bootstrapper, otherwise the setup.py is using the old + # use_astropy_helpers() interface, in which case it will run the + # bootstrapper manually after reconfiguring it. + bootstrapper.run() + + return bootstrapper + + @classmethod + def parse_config(cls): + if not os.path.exists('setup.cfg'): + return {} + + cfg = ConfigParser() + + try: + cfg.read('setup.cfg') + except Exception as e: + if DEBUG: + raise + + log.error( + "Error reading setup.cfg: {0!r}\n{1} will not be " + "automatically bootstrapped and package installation may fail." + "\n{2}".format(e, PACKAGE_NAME, _err_help_msg)) + return {} + + if not cfg.has_section('ah_bootstrap'): + return {} + + config = {} + + for option, type_ in CFG_OPTIONS: + if not cfg.has_option('ah_bootstrap', option): + continue + + if type_ is bool: + value = cfg.getboolean('ah_bootstrap', option) + else: + value = cfg.get('ah_bootstrap', option) + + config[option] = value + + return config + + @classmethod + def parse_command_line(cls, argv=None): + if argv is None: + argv = sys.argv + + config = {} + + # For now we just pop recognized ah_bootstrap options out of the + # arg list. This is imperfect; in the unlikely case that a setup.py + # custom command or even custom Distribution class defines an argument + # of the same name then we will break that. However there's a catch22 + # here that we can't just do full argument parsing right here, because + # we don't yet know *how* to parse all possible command-line arguments. + if '--no-git' in argv: + config['use_git'] = False + argv.remove('--no-git') + + if '--offline' in argv: + config['offline'] = True + argv.remove('--offline') + + return config + + def run(self): + strategies = ['local_directory', 'local_file', 'index'] + dist = None + + # First, remove any previously imported versions of astropy_helpers; + # this is necessary for nested installs where one package's installer + # is installing another package via setuptools.sandbox.run_setup, as in + # the case of setup_requires + for key in list(sys.modules): + try: + if key == PACKAGE_NAME or key.startswith(PACKAGE_NAME + '.'): + del sys.modules[key] + except AttributeError: + # Sometimes mysterious non-string things can turn up in + # sys.modules + continue + + # Check to see if the path is a submodule + self.is_submodule = self._check_submodule() + + for strategy in strategies: + method = getattr(self, 'get_{0}_dist'.format(strategy)) + dist = method() + if dist is not None: + break + else: + raise _AHBootstrapSystemExit( + "No source found for the {0!r} package; {0} must be " + "available and importable as a prerequisite to building " + "or installing this package.".format(PACKAGE_NAME)) + + # This is a bit hacky, but if astropy_helpers was loaded from a + # directory/submodule its Distribution object gets a "precedence" of + # "DEVELOP_DIST". However, in other cases it gets a precedence of + # "EGG_DIST". However, when activing the distribution it will only be + # placed early on sys.path if it is treated as an EGG_DIST, so always + # do that + dist = dist.clone(precedence=pkg_resources.EGG_DIST) + + # Otherwise we found a version of astropy-helpers, so we're done + # Just active the found distribution on sys.path--if we did a + # download this usually happens automatically but it doesn't hurt to + # do it again + # Note: Adding the dist to the global working set also activates it + # (makes it importable on sys.path) by default. + + try: + pkg_resources.working_set.add(dist, replace=True) + except TypeError: + # Some (much) older versions of setuptools do not have the + # replace=True option here. These versions are old enough that all + # bets may be off anyways, but it's easy enough to work around just + # in case... + if dist.key in pkg_resources.working_set.by_key: + del pkg_resources.working_set.by_key[dist.key] + pkg_resources.working_set.add(dist) + + @property + def config(self): + """ + A `dict` containing the options this `_Bootstrapper` was configured + with. + """ + + return dict((optname, getattr(self, optname)) + for optname, _ in CFG_OPTIONS if hasattr(self, optname)) + + def get_local_directory_dist(self): + """ + Handle importing a vendored package from a subdirectory of the source + distribution. + """ + + if not os.path.isdir(self.path): + return + + log.info('Attempting to import astropy_helpers from {0} {1!r}'.format( + 'submodule' if self.is_submodule else 'directory', + self.path)) + + dist = self._directory_import() + + if dist is None: + log.warn( + 'The requested path {0!r} for importing {1} does not ' + 'exist, or does not contain a copy of the {1} ' + 'package.'.format(self.path, PACKAGE_NAME)) + elif self.auto_upgrade and not self.is_submodule: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_local_file_dist(self): + """ + Handle importing from a source archive; this also uses setup_requires + but points easy_install directly to the source archive. + """ + + if not os.path.isfile(self.path): + return + + log.info('Attempting to unpack and import astropy_helpers from ' + '{0!r}'.format(self.path)) + + try: + dist = self._do_download(find_links=[self.path]) + except Exception as e: + if DEBUG: + raise + + log.warn( + 'Failed to import {0} from the specified archive {1!r}: ' + '{2}'.format(PACKAGE_NAME, self.path, str(e))) + dist = None + + if dist is not None and self.auto_upgrade: + # A version of astropy-helpers was found on the available path, but + # check to see if a bugfix release is available on PyPI + upgrade = self._do_upgrade(dist) + if upgrade is not None: + dist = upgrade + + return dist + + def get_index_dist(self): + if not self.download: + log.warn('Downloading {0!r} disabled.'.format(DIST_NAME)) + return None + + log.warn( + "Downloading {0!r}; run setup.py with the --offline option to " + "force offline installation.".format(DIST_NAME)) + + try: + dist = self._do_download() + except Exception as e: + if DEBUG: + raise + log.warn( + 'Failed to download and/or install {0!r} from {1!r}:\n' + '{2}'.format(DIST_NAME, self.index_url, str(e))) + dist = None + + # No need to run auto-upgrade here since we've already presumably + # gotten the most up-to-date version from the package index + return dist + + def _directory_import(self): + """ + Import astropy_helpers from the given path, which will be added to + sys.path. + + Must return True if the import succeeded, and False otherwise. + """ + + # Return True on success, False on failure but download is allowed, and + # otherwise raise SystemExit + path = os.path.abspath(self.path) + + # Use an empty WorkingSet rather than the man + # pkg_resources.working_set, since on older versions of setuptools this + # will invoke a VersionConflict when trying to install an upgrade + ws = pkg_resources.WorkingSet([]) + ws.add_entry(path) + dist = ws.by_key.get(DIST_NAME) + + if dist is None: + # We didn't find an egg-info/dist-info in the given path, but if a + # setup.py exists we can generate it + setup_py = os.path.join(path, 'setup.py') + if os.path.isfile(setup_py): + with _silence(): + run_setup(os.path.join(path, 'setup.py'), + ['egg_info']) + + for dist in pkg_resources.find_distributions(path, True): + # There should be only one... + return dist + + return dist + + def _do_download(self, version='', find_links=None): + if find_links: + allow_hosts = '' + index_url = None + else: + allow_hosts = None + index_url = self.index_url + + # Annoyingly, setuptools will not handle other arguments to + # Distribution (such as options) before handling setup_requires, so it + # is not straightforward to programmatically augment the arguments which + # are passed to easy_install + class _Distribution(Distribution): + def get_option_dict(self, command_name): + opts = Distribution.get_option_dict(self, command_name) + if command_name == 'easy_install': + if find_links is not None: + opts['find_links'] = ('setup script', find_links) + if index_url is not None: + opts['index_url'] = ('setup script', index_url) + if allow_hosts is not None: + opts['allow_hosts'] = ('setup script', allow_hosts) + return opts + + if version: + req = '{0}=={1}'.format(DIST_NAME, version) + else: + req = DIST_NAME + + attrs = {'setup_requires': [req]} + + try: + if DEBUG: + _Distribution(attrs=attrs) + else: + with _silence(): + _Distribution(attrs=attrs) + + # If the setup_requires succeeded it will have added the new dist to + # the main working_set + return pkg_resources.working_set.by_key.get(DIST_NAME) + except Exception as e: + if DEBUG: + raise + + msg = 'Error retrieving {0} from {1}:\n{2}' + if find_links: + source = find_links[0] + elif index_url != INDEX_URL: + source = index_url + else: + source = 'PyPI' + + raise Exception(msg.format(DIST_NAME, source, repr(e))) + + def _do_upgrade(self, dist): + # Build up a requirement for a higher bugfix release but a lower minor + # release (so API compatibility is guaranteed) + next_version = _next_version(dist.parsed_version) + + req = pkg_resources.Requirement.parse( + '{0}>{1},<{2}'.format(DIST_NAME, dist.version, next_version)) + + package_index = PackageIndex(index_url=self.index_url) + + upgrade = package_index.obtain(req) + + if upgrade is not None: + return self._do_download(version=upgrade.version) + + def _check_submodule(self): + """ + Check if the given path is a git submodule. + + See the docstrings for ``_check_submodule_using_git`` and + ``_check_submodule_no_git`` for further details. + """ + + if (self.path is None or + (os.path.exists(self.path) and not os.path.isdir(self.path))): + return False + + if self.use_git: + return self._check_submodule_using_git() + else: + return self._check_submodule_no_git() + + def _check_submodule_using_git(self): + """ + Check if the given path is a git submodule. If so, attempt to initialize + and/or update the submodule if needed. + + This function makes calls to the ``git`` command in subprocesses. The + ``_check_submodule_no_git`` option uses pure Python to check if the given + path looks like a git submodule, but it cannot perform updates. + """ + + cmd = ['git', 'submodule', 'status', '--', self.path] + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except _CommandNotFound: + # The git command simply wasn't found; this is most likely the + # case on user systems that don't have git and are simply + # trying to install the package from PyPI or a source + # distribution. Silently ignore this case and simply don't try + # to use submodules + return False + + stderr = stderr.strip() + + if returncode != 0 and stderr: + # Unfortunately the return code alone cannot be relied on, as + # earlier versions of git returned 0 even if the requested submodule + # does not exist + + # This is a warning that occurs in perl (from running git submodule) + # which only occurs with a malformatted locale setting which can + # happen sometimes on OSX. See again + # https://github.com/astropy/astropy/issues/2749 + perl_warning = ('perl: warning: Falling back to the standard locale ' + '("C").') + if not stderr.strip().endswith(perl_warning): + # Some other unknown error condition occurred + log.warn('git submodule command failed ' + 'unexpectedly:\n{0}'.format(stderr)) + return False + + # Output of `git submodule status` is as follows: + # + # 1: Status indicator: '-' for submodule is uninitialized, '+' if + # submodule is initialized but is not at the commit currently indicated + # in .gitmodules (and thus needs to be updated), or 'U' if the + # submodule is in an unstable state (i.e. has merge conflicts) + # + # 2. SHA-1 hash of the current commit of the submodule (we don't really + # need this information but it's useful for checking that the output is + # correct) + # + # 3. The output of `git describe` for the submodule's current commit + # hash (this includes for example what branches the commit is on) but + # only if the submodule is initialized. We ignore this information for + # now + _git_submodule_status_re = re.compile( + '^(?P[+-U ])(?P[0-9a-f]{40}) ' + '(?P\S+)( .*)?$') + + # The stdout should only contain one line--the status of the + # requested submodule + m = _git_submodule_status_re.match(stdout) + if m: + # Yes, the path *is* a git submodule + self._update_submodule(m.group('submodule'), m.group('status')) + return True + else: + log.warn( + 'Unexpected output from `git submodule status`:\n{0}\n' + 'Will attempt import from {1!r} regardless.'.format( + stdout, self.path)) + return False + + def _check_submodule_no_git(self): + """ + Like ``_check_submodule_using_git``, but simply parses the .gitmodules file + to determine if the supplied path is a git submodule, and does not exec any + subprocesses. + + This can only determine if a path is a submodule--it does not perform + updates, etc. This function may need to be updated if the format of the + .gitmodules file is changed between git versions. + """ + + gitmodules_path = os.path.abspath('.gitmodules') + + if not os.path.isfile(gitmodules_path): + return False + + # This is a minimal reader for gitconfig-style files. It handles a few of + # the quirks that make gitconfig files incompatible with ConfigParser-style + # files, but does not support the full gitconfig syntax (just enough + # needed to read a .gitmodules file). + gitmodules_fileobj = io.StringIO() + + # Must use io.open for cross-Python-compatible behavior wrt unicode + with io.open(gitmodules_path) as f: + for line in f: + # gitconfig files are more flexible with leading whitespace; just + # go ahead and remove it + line = line.lstrip() + + # comments can start with either # or ; + if line and line[0] in (':', ';'): + continue + + gitmodules_fileobj.write(line) + + gitmodules_fileobj.seek(0) + + cfg = RawConfigParser() + + try: + cfg.readfp(gitmodules_fileobj) + except Exception as exc: + log.warn('Malformatted .gitmodules file: {0}\n' + '{1} cannot be assumed to be a git submodule.'.format( + exc, self.path)) + return False + + for section in cfg.sections(): + if not cfg.has_option(section, 'path'): + continue + + submodule_path = cfg.get(section, 'path').rstrip(os.sep) + + if submodule_path == self.path.rstrip(os.sep): + return True + + return False + + def _update_submodule(self, submodule, status): + if status == ' ': + # The submodule is up to date; no action necessary + return + elif status == '-': + if self.offline: + raise _AHBootstrapSystemExit( + "Cannot initialize the {0} submodule in --offline mode; " + "this requires being able to clone the submodule from an " + "online repository.".format(submodule)) + cmd = ['update', '--init'] + action = 'Initializing' + elif status == '+': + cmd = ['update'] + action = 'Updating' + if self.offline: + cmd.append('--no-fetch') + elif status == 'U': + raise _AHBoostrapSystemExit( + 'Error: Submodule {0} contains unresolved merge conflicts. ' + 'Please complete or abandon any changes in the submodule so that ' + 'it is in a usable state, then try again.'.format(submodule)) + else: + log.warn('Unknown status {0!r} for git submodule {1!r}. Will ' + 'attempt to use the submodule as-is, but try to ensure ' + 'that the submodule is in a clean state and contains no ' + 'conflicts or errors.\n{2}'.format(status, submodule, + _err_help_msg)) + return + + err_msg = None + cmd = ['git', 'submodule'] + cmd + ['--', submodule] + log.warn('{0} {1} submodule with: `{2}`'.format( + action, submodule, ' '.join(cmd))) + + try: + log.info('Running `{0}`; use the --no-git option to disable git ' + 'commands'.format(' '.join(cmd))) + returncode, stdout, stderr = run_cmd(cmd) + except OSError as e: + err_msg = str(e) + else: + if returncode != 0: + err_msg = stderr + + if err_msg is not None: + log.warn('An unexpected error occurred updating the git submodule ' + '{0!r}:\n{1}\n{2}'.format(submodule, err_msg, + _err_help_msg)) + +class _CommandNotFound(OSError): + """ + An exception raised when a command run with run_cmd is not found on the + system. + """ + + +def run_cmd(cmd): + """ + Run a command in a subprocess, given as a list of command-line + arguments. + + Returns a ``(returncode, stdout, stderr)`` tuple. + """ + + try: + p = sp.Popen(cmd, stdout=sp.PIPE, stderr=sp.PIPE) + # XXX: May block if either stdout or stderr fill their buffers; + # however for the commands this is currently used for that is + # unlikely (they should have very brief output) + stdout, stderr = p.communicate() + except OSError as e: + if DEBUG: + raise + + if e.errno == errno.ENOENT: + msg = 'Command not found: `{0}`'.format(' '.join(cmd)) + raise _CommandNotFound(msg, cmd) + else: + raise _AHBoostrapSystemExit( + 'An unexpected error occurred when running the ' + '`{0}` command:\n{1}'.format(' '.join(cmd), str(e))) + + + # Can fail of the default locale is not configured properly. See + # https://github.com/astropy/astropy/issues/2749. For the purposes under + # consideration 'latin1' is an acceptable fallback. + try: + stdio_encoding = locale.getdefaultlocale()[1] or 'latin1' + except ValueError: + # Due to an OSX oddity locale.getdefaultlocale() can also crash + # depending on the user's locale/language settings. See: + # http://bugs.python.org/issue18378 + stdio_encoding = 'latin1' + + # Unlikely to fail at this point but even then let's be flexible + if not isinstance(stdout, _text_type): + stdout = stdout.decode(stdio_encoding, 'replace') + if not isinstance(stderr, _text_type): + stderr = stderr.decode(stdio_encoding, 'replace') + + return (p.returncode, stdout, stderr) + + +def _next_version(version): + """ + Given a parsed version from pkg_resources.parse_version, returns a new + version string with the next minor version. + + Examples + ======== + >>> _next_version(pkg_resources.parse_version('1.2.3')) + '1.3.0' + """ + + if hasattr(version, 'base_version'): + # New version parsing from setuptools >= 8.0 + if version.base_version: + parts = version.base_version.split('.') + else: + parts = [] + else: + parts = [] + for part in version: + if part.startswith('*'): + break + parts.append(part) + + parts = [int(p) for p in parts] + + if len(parts) < 3: + parts += [0] * (3 - len(parts)) + + major, minor, micro = parts[:3] + + return '{0}.{1}.{2}'.format(major, minor + 1, 0) + + +class _DummyFile(object): + """A noop writeable object.""" + + errors = '' # Required for Python 3.x + encoding = 'utf-8' + + def write(self, s): + pass + + def flush(self): + pass + + +@contextlib.contextmanager +def _silence(): + """A context manager that silences sys.stdout and sys.stderr.""" + + old_stdout = sys.stdout + old_stderr = sys.stderr + sys.stdout = _DummyFile() + sys.stderr = _DummyFile() + exception_occurred = False + try: + yield + except: + exception_occurred = True + # Go ahead and clean up so that exception handling can work normally + sys.stdout = old_stdout + sys.stderr = old_stderr + raise + + if not exception_occurred: + sys.stdout = old_stdout + sys.stderr = old_stderr + + +_err_help_msg = """ +If the problem persists consider installing astropy_helpers manually using pip +(`pip install astropy_helpers`) or by manually downloading the source archive, +extracting it, and installing by running `python setup.py install` from the +root of the extracted source code. +""" + + +class _AHBootstrapSystemExit(SystemExit): + def __init__(self, *args): + if not args: + msg = 'An unknown problem occurred bootstrapping astropy_helpers.' + else: + msg = args[0] + + msg += '\n' + _err_help_msg + + super(_AHBootstrapSystemExit, self).__init__(msg, *args[1:]) + + +if sys.version_info[:2] < (2, 7): + # In Python 2.6 the distutils log does not log warnings, errors, etc. to + # stderr so we have to wrap it to ensure consistency at least in this + # module + import distutils + + class log(object): + def __getattr__(self, attr): + return getattr(distutils.log, attr) + + def warn(self, msg, *args): + self._log_to_stderr(distutils.log.WARN, msg, *args) + + def error(self, msg): + self._log_to_stderr(distutils.log.ERROR, msg, *args) + + def fatal(self, msg): + self._log_to_stderr(distutils.log.FATAL, msg, *args) + + def log(self, level, msg, *args): + if level in (distutils.log.WARN, distutils.log.ERROR, + distutils.log.FATAL): + self._log_to_stderr(level, msg, *args) + else: + distutils.log.log(level, msg, *args) + + def _log_to_stderr(self, level, msg, *args): + # This is the only truly 'public' way to get the current threshold + # of the log + current_threshold = distutils.log.set_threshold(distutils.log.WARN) + distutils.log.set_threshold(current_threshold) + if level >= current_threshold: + if args: + msg = msg % args + sys.stderr.write('%s\n' % msg) + sys.stderr.flush() + + log = log() + + +BOOTSTRAPPER = _Bootstrapper.main() + + +def use_astropy_helpers(**kwargs): + """ + Ensure that the `astropy_helpers` module is available and is importable. + This supports automatic submodule initialization if astropy_helpers is + included in a project as a git submodule, or will download it from PyPI if + necessary. + + Parameters + ---------- + + path : str or None, optional + A filesystem path relative to the root of the project's source code + that should be added to `sys.path` so that `astropy_helpers` can be + imported from that path. + + If the path is a git submodule it will automatically be initialized + and/or updated. + + The path may also be to a ``.tar.gz`` archive of the astropy_helpers + source distribution. In this case the archive is automatically + unpacked and made temporarily available on `sys.path` as a ``.egg`` + archive. + + If `None` skip straight to downloading. + + download_if_needed : bool, optional + If the provided filesystem path is not found an attempt will be made to + download astropy_helpers from PyPI. It will then be made temporarily + available on `sys.path` as a ``.egg`` archive (using the + ``setup_requires`` feature of setuptools. If the ``--offline`` option + is given at the command line the value of this argument is overridden + to `False`. + + index_url : str, optional + If provided, use a different URL for the Python package index than the + main PyPI server. + + use_git : bool, optional + If `False` no git commands will be used--this effectively disables + support for git submodules. If the ``--no-git`` option is given at the + command line the value of this argument is overridden to `False`. + + auto_upgrade : bool, optional + By default, when installing a package from a non-development source + distribution ah_boostrap will try to automatically check for patch + releases to astropy-helpers on PyPI and use the patched version over + any bundled versions. Setting this to `False` will disable that + functionality. If the ``--offline`` option is given at the command line + the value of this argument is overridden to `False`. + + offline : bool, optional + If `False` disable all actions that require an internet connection, + including downloading packages from the package index and fetching + updates to any git submodule. Defaults to `True`. + """ + + global BOOTSTRAPPER + + config = BOOTSTRAPPER.config + config.update(**kwargs) + + # Create a new bootstrapper with the updated configuration and run it + BOOTSTRAPPER = _Bootstrapper(**config) + BOOTSTRAPPER.run() diff --git a/caom2repo/astropy_helpers b/caom2repo/astropy_helpers new file mode 160000 index 00000000..2732e3a5 --- /dev/null +++ b/caom2repo/astropy_helpers @@ -0,0 +1 @@ +Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e diff --git a/caom2tools/__init__.py b/caom2repo/caom2repo/__init__.py old mode 100644 new mode 100755 similarity index 98% rename from caom2tools/__init__.py rename to caom2repo/caom2repo/__init__.py index e7359a5f..210f62b7 --- a/caom2tools/__init__.py +++ b/caom2repo/caom2repo/__init__.py @@ -1,3 +1,4 @@ + # Licensed under a 3-clause BSD style license - see LICENSE.rst """ @@ -13,4 +14,4 @@ # For egg_info test builds to pass, put package imports here. if not _ASTROPY_SETUP_: # from .caom2tools import * - pass + pass \ No newline at end of file diff --git a/caom2tools/util/_astropy_init.py b/caom2repo/caom2repo/_astropy_init.py similarity index 100% rename from caom2tools/util/_astropy_init.py rename to caom2repo/caom2repo/_astropy_init.py diff --git a/caom2repo/caom2repo/conftest.py b/caom2repo/caom2repo/conftest.py new file mode 100644 index 00000000..829ba1d7 --- /dev/null +++ b/caom2repo/caom2repo/conftest.py @@ -0,0 +1,38 @@ +# this contains imports plugins that configure py.test for astropy tests. +# by importing them here in conftest.py they are discoverable by py.test +# no matter how it is invoked within the source tree. + +from astropy.tests.pytest_plugins import * + +## Uncomment the following line to treat all DeprecationWarnings as +## exceptions +# enable_deprecations_as_exceptions() + +## Uncomment and customize the following lines to add/remove entries from +## the list of packages for which version numbers are displayed when running +## the tests. Making it pass for KeyError is essential in some cases when +## the package uses other astropy affiliated packages. +# try: +# PYTEST_HEADER_MODULES['Astropy'] = 'astropy' +# PYTEST_HEADER_MODULES['scikit-image'] = 'skimage' +# del PYTEST_HEADER_MODULES['h5py'] +# except (NameError, KeyError): # NameError is needed to support Astropy < 1.0 +# pass + +## Uncomment the following lines to display the version number of the +## package rather than the version number of Astropy in the top line when +## running the tests. +# import os +# +# # This is to figure out the affiliated package version, rather than +# # using Astropy's +# try: +# from .version import version +# except ImportError: +# version = 'dev' +# +# try: +# packagename = os.path.basename(os.path.dirname(__file__)) +# TESTED_VERSIONS[packagename] = version +# except NameError: # Needed to support Astropy <= 1.0.0 +# pass diff --git a/caom2tools/util/caom2repo.py b/caom2repo/caom2repo/core.py similarity index 99% rename from caom2tools/util/caom2repo.py rename to caom2repo/caom2repo/core.py index ad0d93a5..332395cb 100755 --- a/caom2tools/util/caom2repo.py +++ b/caom2repo/caom2repo/core.py @@ -78,7 +78,7 @@ from cadctools.net import ws from cadctools.util import util -from ..caom2.obs_reader_writer import ObservationReader, ObservationWriter +from caom2.obs_reader_writer import ObservationReader, ObservationWriter BATCH_SIZE = int(10000) SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it diff --git a/caom2tools/util/test/__init__.py b/caom2repo/caom2repo/test/__init__.py similarity index 100% rename from caom2tools/util/test/__init__.py rename to caom2repo/caom2repo/test/__init__.py diff --git a/caom2tools/util/test/addplaneplugin.py b/caom2repo/caom2repo/test/addplaneplugin.py similarity index 98% rename from caom2tools/util/test/addplaneplugin.py rename to caom2repo/caom2repo/test/addplaneplugin.py index 3bacc25d..20e52a4f 100755 --- a/caom2tools/util/test/addplaneplugin.py +++ b/caom2repo/caom2repo/test/addplaneplugin.py @@ -67,8 +67,8 @@ #*********************************************************************** # -from caom2tools.caom2.observation import Observation -from caom2tools.caom2.plane import Plane +from caom2.observation import Observation +from caom2.plane import Plane class ObservationUpdater: diff --git a/caom2tools/util/test/passplugin.py b/caom2repo/caom2repo/test/passplugin.py similarity index 99% rename from caom2tools/util/test/passplugin.py rename to caom2repo/caom2repo/test/passplugin.py index cdd33143..9d5cfc75 100755 --- a/caom2tools/util/test/passplugin.py +++ b/caom2repo/caom2repo/test/passplugin.py @@ -67,7 +67,7 @@ #*********************************************************************** # -from caom2tools.caom2.observation import Observation +from caom2.observation import Observation class ObservationUpdater: diff --git a/caom2tools/util/test/test_caom2repo.py b/caom2repo/caom2repo/test/test_core.py similarity index 97% rename from caom2tools/util/test/test_caom2repo.py rename to caom2repo/caom2repo/test/test_core.py index ef1eb533..838a7548 100644 --- a/caom2tools/util/test/test_caom2repo.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -78,10 +78,10 @@ from datetime import datetime from cadctools import util -from caom2tools.util import caom2repo -from caom2tools.util.caom2repo import CAOM2RepoClient, DATE_FORMAT -from caom2tools.caom2.observation import SimpleObservation -from caom2tools.caom2.obs_reader_writer import ObservationReader, ObservationWriter +from caom2repo import core +from caom2repo.core import CAOM2RepoClient, DATE_FORMAT +from caom2.observation import SimpleObservation +from caom2.obs_reader_writer import ObservationReader, ObservationWriter THIS_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -175,7 +175,7 @@ def raise_error(): raise http_error # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.open', MagicMock(), create=True) - @patch('caom2tools.util.caom2repo.ws.BaseWsClient.get') + @patch('caom2repo.core.ws.BaseWsClient.get') def test_get_observations(self, mock_get): # This is almost similar to the previous test except that it gets # observations matching a collection and start/end criteria @@ -194,12 +194,12 @@ def test_get_observations(self, mock_get): expect_observations = ['700000o', '700001o'] self.assertEquals(expect_observations, visitor._get_observations('cfht')) self.assertEquals(end_date, visitor._start) - mock_get.assert_called_once_with('cfht', params={'MAXREC':caom2repo.BATCH_SIZE}) + mock_get.assert_called_once_with('cfht', params={'MAXREC':core.BATCH_SIZE}) mock_get.reset_mock() visitor._get_observations('cfht', end=datetime.strptime('2000-11-11', '%Y-%m-%d')) mock_get.assert_called_once_with('cfht', params={'END':'2000-11-11T00:00:00.000000', - 'MAXREC': caom2repo.BATCH_SIZE}) + 'MAXREC': core.BATCH_SIZE}) mock_get.reset_mock() visitor._get_observations('cfht', @@ -207,7 +207,7 @@ def test_get_observations(self, mock_get): end=datetime.strptime('2000-11-12', '%Y-%m-%d')) mock_get.assert_called_once_with('cfht', params={'START':'2000-11-11T00:00:00.000000', 'END': '2000-11-12T00:00:00.000000', - 'MAXREC': caom2repo.BATCH_SIZE}) + 'MAXREC': core.BATCH_SIZE}) # patch sleep to stop the test from sleeping and slowing down execution @@ -359,7 +359,7 @@ def raise_error(): raise http_error def test_process(self): - caom2repo.BATCH_SIZE = 3 # size of the batch is 3 + core.BATCH_SIZE = 3 # size of the batch is 3 obs = [['a', 'b', 'c'], ['d'], []] visitor = CAOM2RepoClient() visitor.get_observation = MagicMock(return_value=MagicMock(spec=SimpleObservation)) @@ -375,7 +375,7 @@ def test_process(self): THIS_DIR, 'passplugin.py'), 'cfht')) - @patch('caom2tools.util.caom2repo.CAOM2RepoClient') + @patch('caom2repo.core.CAOM2RepoClient') def test_main(self, client_mock): collection = 'cfht' observation_id = '7000000o' @@ -388,30 +388,30 @@ def test_main(self, client_mock): with open(ifile, 'w') as infile: ObservationWriter().write(obs, infile) sys.argv = ["caom2tools", "create", ifile] - caom2repo.main() + core.main() client_mock.return_value.put_observation.assert_called_with(obs) # test update sys.argv = ["caom2tools", "update", ifile] - caom2repo.main() + core.main() client_mock.return_value.post_observation.assert_called_with(obs) # test read sys.argv = ["caom2tools", "read", "--collection", collection, observation_id] client_mock.return_value.get_observation.return_value = obs - caom2repo.main() + core.main() client_mock.return_value.get_observation.assert_called_with(collection, observation_id) # repeat with outout argument sys.argv = ["caom2tools", "read", "--collection", collection, "--output", ifile, observation_id] client_mock.return_value.get_observation.return_value = obs - caom2repo.main() + core.main() client_mock.return_value.get_observation.assert_called_with(collection, observation_id) os.remove(ifile) # test delete sys.argv = ["caom2tools", "delete", "--collection", collection, observation_id] - caom2repo.main() + core.main() client_mock.return_value.delete_observation.assert_called_with(collection=collection, observation=observation_id) @@ -421,7 +421,7 @@ def test_main(self, client_mock): sys.argv = ["caom2tools", "visit", "--plugin", plugin_file, "--start", "2012-01-01T11:22:33.44", "--end", "2013-01-01T11:33:22.443", collection] with open(plugin_file, 'r') as infile: - caom2repo.main() + core.main() client_mock.return_value.visit.assert_called_with(ANY, collection, start=util.str2ivoa("2012-01-01T11:22:33.44"), end=util.str2ivoa("2013-01-01T11:33:22.443")) @@ -603,40 +603,40 @@ def update(self, observation): with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(usage, stdout_mock.getvalue()) # create --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "create", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(create_usage, stdout_mock.getvalue()) # read --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "read", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(read_usage, stdout_mock.getvalue()) # update --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "update", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(update_usage, stdout_mock.getvalue()) # delete --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "delete", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(delete_usage, stdout_mock.getvalue()) # visit --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: sys.argv = ["caom2-client", "visit", "--help"] with self.assertRaises(MyExitError): - caom2repo.main() + core.main() self.assertEqual(visit_usage, stdout_mock.getvalue()) \ No newline at end of file diff --git a/caom2repo/dev_requirements.txt b/caom2repo/dev_requirements.txt new file mode 100644 index 00000000..0d69562b --- /dev/null +++ b/caom2repo/dev_requirements.txt @@ -0,0 +1,7 @@ +numpy==1.12.0b1 +astropy==1.2.1 +cadctools==0.1.dev11 +-e . +funcsigs==1.0.2 +mock==2.0.0 +xml-compare==1.0.5 diff --git a/caom2repo/docs/Makefile b/caom2repo/docs/Makefile new file mode 100644 index 00000000..fb03f26e --- /dev/null +++ b/caom2repo/docs/Makefile @@ -0,0 +1,133 @@ +# Makefile for Sphinx documentation +# + +# You can set these variables from the command line. +SPHINXOPTS = +SPHINXBUILD = sphinx-build +PAPER = +BUILDDIR = _build + +# Internal variables. +PAPEROPT_a4 = -D latex_paper_size=a4 +PAPEROPT_letter = -D latex_paper_size=letter +ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) . + +.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest + +#This is needed with git because git doesn't create a dir if it's empty +$(shell [ -d "_static" ] || mkdir -p _static) + +help: + @echo "Please use \`make ' where is one of" + @echo " html to make standalone HTML files" + @echo " dirhtml to make HTML files named index.html in directories" + @echo " singlehtml to make a single large HTML file" + @echo " pickle to make pickle files" + @echo " json to make JSON files" + @echo " htmlhelp to make HTML files and a HTML help project" + @echo " qthelp to make HTML files and a qthelp project" + @echo " devhelp to make HTML files and a Devhelp project" + @echo " epub to make an epub" + @echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter" + @echo " latexpdf to make LaTeX files and run them through pdflatex" + @echo " text to make text files" + @echo " man to make manual pages" + @echo " changes to make an overview of all changed/added/deprecated items" + @echo " linkcheck to check all external links for integrity" + +clean: + -rm -rf $(BUILDDIR) + -rm -rf api + -rm -rf generated + +html: + $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/html." + +dirhtml: + $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml + @echo + @echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml." + +singlehtml: + $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml + @echo + @echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml." + +pickle: + $(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle + @echo + @echo "Build finished; now you can process the pickle files." + +json: + $(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json + @echo + @echo "Build finished; now you can process the JSON files." + +htmlhelp: + $(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp + @echo + @echo "Build finished; now you can run HTML Help Workshop with the" \ + ".hhp project file in $(BUILDDIR)/htmlhelp." + +qthelp: + $(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp + @echo + @echo "Build finished; now you can run "qcollectiongenerator" with the" \ + ".qhcp project file in $(BUILDDIR)/qthelp, like this:" + @echo "# qcollectiongenerator $(BUILDDIR)/qthelp/Astropy.qhcp" + @echo "To view the help file:" + @echo "# assistant -collectionFile $(BUILDDIR)/qthelp/Astropy.qhc" + +devhelp: + $(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp + @echo + @echo "Build finished." + @echo "To view the help file:" + @echo "# mkdir -p $$HOME/.local/share/devhelp/Astropy" + @echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/Astropy" + @echo "# devhelp" + +epub: + $(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub + @echo + @echo "Build finished. The epub file is in $(BUILDDIR)/epub." + +latex: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo + @echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex." + @echo "Run \`make' in that directory to run these through (pdf)latex" \ + "(use \`make latexpdf' here to do that automatically)." + +latexpdf: + $(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex + @echo "Running LaTeX files through pdflatex..." + make -C $(BUILDDIR)/latex all-pdf + @echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex." + +text: + $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text + @echo + @echo "Build finished. The text files are in $(BUILDDIR)/text." + +man: + $(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man + @echo + @echo "Build finished. The manual pages are in $(BUILDDIR)/man." + +changes: + $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes + @echo + @echo "The overview file is in $(BUILDDIR)/changes." + +linkcheck: + $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck + @echo + @echo "Link check complete; look for any errors in the above output " \ + "or in $(BUILDDIR)/linkcheck/output.txt." + +doctest: + @echo "Run 'python setup.py test' in the root directory to run doctests " \ + @echo "in the documentation." diff --git a/caom2repo/docs/_templates/autosummary/base.rst b/caom2repo/docs/_templates/autosummary/base.rst new file mode 100644 index 00000000..9cabaf52 --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/base.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/base.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/_templates/autosummary/class.rst b/caom2repo/docs/_templates/autosummary/class.rst new file mode 100644 index 00000000..6b214a5c --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/class.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/class.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/_templates/autosummary/module.rst b/caom2repo/docs/_templates/autosummary/module.rst new file mode 100644 index 00000000..f38315b2 --- /dev/null +++ b/caom2repo/docs/_templates/autosummary/module.rst @@ -0,0 +1,2 @@ +{% extends "autosummary_core/module.rst" %} +{# The template this is inherited from is in astropy/sphinx/ext/templates/autosummary_core. If you want to modify this template, it is strongly recommended that you still inherit from the astropy template. #} \ No newline at end of file diff --git a/caom2repo/docs/conf.py b/caom2repo/docs/conf.py new file mode 100644 index 00000000..78d20fd8 --- /dev/null +++ b/caom2repo/docs/conf.py @@ -0,0 +1,172 @@ +# -*- coding: utf-8 -*- +# Licensed under a 3-clause BSD style license - see LICENSE.rst +# +# Astropy documentation build configuration file. +# +# This file is execfile()d with the current directory set to its containing dir. +# +# Note that not all possible configuration values are present in this file. +# +# All configuration values have a default. Some values are defined in +# the global Astropy configuration which is loaded here before anything else. +# See astropy.sphinx.conf for which values are set there. + +# If extensions (or modules to document with autodoc) are in another directory, +# add these directories to sys.path here. If the directory is relative to the +# documentation root, use os.path.abspath to make it absolute, like shown here. +# sys.path.insert(0, os.path.abspath('..')) +# IMPORTANT: the above commented section was generated by sphinx-quickstart, but +# is *NOT* appropriate for astropy or Astropy affiliated packages. It is left +# commented out with this explanation to make it clear why this should not be +# done. If the sys.path entry above is added, when the astropy.sphinx.conf +# import occurs, it will import the *source* version of astropy instead of the +# version installed (if invoked as "make html" or directly with sphinx), or the +# version in the build directory (if "python setup.py build_sphinx" is used). +# Thus, any C-extensions that are needed to build the documentation will *not* +# be accessible, and the documentation will not build correctly. + +import datetime +import os +import sys + +try: + import astropy_helpers +except ImportError: + # Building from inside the docs/ directory? + if os.path.basename(os.getcwd()) == 'docs': + a_h_path = os.path.abspath(os.path.join('..', 'astropy_helpers')) + if os.path.isdir(a_h_path): + sys.path.insert(1, a_h_path) + +# Load all of the global Astropy configuration +from astropy_helpers.sphinx.conf import * + +# Get configuration information from setup.cfg +try: + from ConfigParser import ConfigParser +except ImportError: + from configparser import ConfigParser +conf = ConfigParser() + +conf.read([os.path.join(os.path.dirname(__file__), '..', 'setup.cfg')]) +setup_cfg = dict(conf.items('metadata')) + +# -- General configuration ---------------------------------------------------- + +# If your documentation needs a minimal Sphinx version, state it here. +#needs_sphinx = '1.2' + +# To perform a Sphinx version check that needs to be more specific than +# major.minor, call `check_sphinx_version("x.y.z")` here. +# check_sphinx_version("1.2.1") + +# List of patterns, relative to source directory, that match files and +# directories to ignore when looking for source files. +exclude_patterns.append('_templates') + +# This is added to the end of RST files - a good place to put substitutions to +# be used globally. +rst_epilog += """ +""" + +# -- Project information ------------------------------------------------------ + +# This does not *have* to match the package name, but typically does +project = setup_cfg['package_name'] +author = setup_cfg['author'] +copyright = '{0}, {1}'.format( + datetime.datetime.now().year, setup_cfg['author']) + +# The version info for the project you're documenting, acts as replacement for +# |version| and |release|, also used in various other places throughout the +# built documents. + +__import__(setup_cfg['package_name']) +package = sys.modules[setup_cfg['package_name']] + +# The short X.Y version. +version = package.__version__.split('-', 1)[0] +# The full version, including alpha/beta/rc tags. +release = package.__version__ + + +# -- Options for HTML output -------------------------------------------------- + +# A NOTE ON HTML THEMES +# The global astropy configuration uses a custom theme, 'bootstrap-astropy', +# which is installed along with astropy. A different theme can be used or +# the options for this theme can be modified by overriding some of the +# variables set in the global configuration. The variables set in the +# global configuration are listed below, commented out. + + +# Please update these texts to match the name of your package. +html_theme_options = { + 'logotext1': 'package', # white, semi-bold + 'logotext2': '-template', # orange, light + 'logotext3': ':docs' # white, light + } + +# Add any paths that contain custom themes here, relative to this directory. +# To use a different custom theme, add the directory containing the theme. +#html_theme_path = [] + +# The theme to use for HTML and HTML Help pages. See the documentation for +# a list of builtin themes. To override the custom theme, set this to the +# name of a builtin theme or the name of a custom theme in html_theme_path. +#html_theme = None + +# Custom sidebar templates, maps document names to template names. +#html_sidebars = {} + +# The name of an image file (within the static path) to use as favicon of the +# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 +# pixels large. +#html_favicon = '' + +# If not '', a 'Last updated on:' timestamp is inserted at every page bottom, +# using the given strftime format. +#html_last_updated_fmt = '' + +# The name for this set of Sphinx documents. If None, it defaults to +# " v documentation". +html_title = '{0} v{1}'.format(project, release) + +# Output file base name for HTML help builder. +htmlhelp_basename = project + 'doc' + + +# -- Options for LaTeX output ------------------------------------------------- + +# Grouping the document tree into LaTeX files. List of tuples +# (source start file, target name, title, author, documentclass [howto/manual]). +latex_documents = [('index', project + '.tex', project + u' Documentation', + author, 'manual')] + + +# -- Options for manual page output ------------------------------------------- + +# One entry per manual page. List of tuples +# (source start file, name, description, authors, manual section). +man_pages = [('index', project.lower(), project + u' Documentation', + [author], 1)] + + +# -- Options for the edit_on_github extension --------------------------------- + +if eval(setup_cfg.get('edit_on_github')): + extensions += ['astropy_helpers.sphinx.ext.edit_on_github'] + + versionmod = __import__(setup_cfg['package_name'] + '.version') + edit_on_github_project = setup_cfg['github_project'] + if versionmod.version.release: + edit_on_github_branch = "v" + versionmod.version.version + else: + edit_on_github_branch = "master" + + edit_on_github_source_root = "" + edit_on_github_doc_root = "docs" + +# -- Resolving issue number to links in changelog ----------------------------- +github_issues_url = 'https://github.com/{0}/issues/'.format(setup_cfg['github_project']) + diff --git a/caom2tools/util/__init__.py b/caom2repo/docs/index.rst old mode 100755 new mode 100644 similarity index 100% rename from caom2tools/util/__init__.py rename to caom2repo/docs/index.rst diff --git a/caom2repo/docs/make.bat b/caom2repo/docs/make.bat new file mode 100644 index 00000000..93dfe92b --- /dev/null +++ b/caom2repo/docs/make.bat @@ -0,0 +1,170 @@ +@ECHO OFF + +REM Command file for Sphinx documentation + +if "%SPHINXBUILD%" == "" ( + set SPHINXBUILD=sphinx-build +) +set BUILDDIR=_build +set ALLSPHINXOPTS=-d %BUILDDIR%/doctrees %SPHINXOPTS% . +if NOT "%PAPER%" == "" ( + set ALLSPHINXOPTS=-D latex_paper_size=%PAPER% %ALLSPHINXOPTS% +) + +if "%1" == "" goto help + +if "%1" == "help" ( + :help + echo.Please use `make ^` where ^ is one of + echo. html to make standalone HTML files + echo. dirhtml to make HTML files named index.html in directories + echo. singlehtml to make a single large HTML file + echo. pickle to make pickle files + echo. json to make JSON files + echo. htmlhelp to make HTML files and a HTML help project + echo. qthelp to make HTML files and a qthelp project + echo. devhelp to make HTML files and a Devhelp project + echo. epub to make an epub + echo. latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter + echo. text to make text files + echo. man to make manual pages + echo. changes to make an overview over all changed/added/deprecated items + echo. linkcheck to check all external links for integrity + echo. doctest to run all doctests embedded in the documentation if enabled + goto end +) + +if "%1" == "clean" ( + for /d %%i in (%BUILDDIR%\*) do rmdir /q /s %%i + del /q /s %BUILDDIR%\* + goto end +) + +if "%1" == "html" ( + %SPHINXBUILD% -b html %ALLSPHINXOPTS% %BUILDDIR%/html + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/html. + goto end +) + +if "%1" == "dirhtml" ( + %SPHINXBUILD% -b dirhtml %ALLSPHINXOPTS% %BUILDDIR%/dirhtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/dirhtml. + goto end +) + +if "%1" == "singlehtml" ( + %SPHINXBUILD% -b singlehtml %ALLSPHINXOPTS% %BUILDDIR%/singlehtml + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The HTML pages are in %BUILDDIR%/singlehtml. + goto end +) + +if "%1" == "pickle" ( + %SPHINXBUILD% -b pickle %ALLSPHINXOPTS% %BUILDDIR%/pickle + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the pickle files. + goto end +) + +if "%1" == "json" ( + %SPHINXBUILD% -b json %ALLSPHINXOPTS% %BUILDDIR%/json + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can process the JSON files. + goto end +) + +if "%1" == "htmlhelp" ( + %SPHINXBUILD% -b htmlhelp %ALLSPHINXOPTS% %BUILDDIR%/htmlhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run HTML Help Workshop with the ^ +.hhp project file in %BUILDDIR%/htmlhelp. + goto end +) + +if "%1" == "qthelp" ( + %SPHINXBUILD% -b qthelp %ALLSPHINXOPTS% %BUILDDIR%/qthelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; now you can run "qcollectiongenerator" with the ^ +.qhcp project file in %BUILDDIR%/qthelp, like this: + echo.^> qcollectiongenerator %BUILDDIR%\qthelp\Astropy.qhcp + echo.To view the help file: + echo.^> assistant -collectionFile %BUILDDIR%\qthelp\Astropy.ghc + goto end +) + +if "%1" == "devhelp" ( + %SPHINXBUILD% -b devhelp %ALLSPHINXOPTS% %BUILDDIR%/devhelp + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. + goto end +) + +if "%1" == "epub" ( + %SPHINXBUILD% -b epub %ALLSPHINXOPTS% %BUILDDIR%/epub + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The epub file is in %BUILDDIR%/epub. + goto end +) + +if "%1" == "latex" ( + %SPHINXBUILD% -b latex %ALLSPHINXOPTS% %BUILDDIR%/latex + if errorlevel 1 exit /b 1 + echo. + echo.Build finished; the LaTeX files are in %BUILDDIR%/latex. + goto end +) + +if "%1" == "text" ( + %SPHINXBUILD% -b text %ALLSPHINXOPTS% %BUILDDIR%/text + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The text files are in %BUILDDIR%/text. + goto end +) + +if "%1" == "man" ( + %SPHINXBUILD% -b man %ALLSPHINXOPTS% %BUILDDIR%/man + if errorlevel 1 exit /b 1 + echo. + echo.Build finished. The manual pages are in %BUILDDIR%/man. + goto end +) + +if "%1" == "changes" ( + %SPHINXBUILD% -b changes %ALLSPHINXOPTS% %BUILDDIR%/changes + if errorlevel 1 exit /b 1 + echo. + echo.The overview file is in %BUILDDIR%/changes. + goto end +) + +if "%1" == "linkcheck" ( + %SPHINXBUILD% -b linkcheck %ALLSPHINXOPTS% %BUILDDIR%/linkcheck + if errorlevel 1 exit /b 1 + echo. + echo.Link check complete; look for any errors in the above output ^ +or in %BUILDDIR%/linkcheck/output.txt. + goto end +) + +if "%1" == "doctest" ( + %SPHINXBUILD% -b doctest %ALLSPHINXOPTS% %BUILDDIR%/doctest + if errorlevel 1 exit /b 1 + echo. + echo.Testing of doctests in the sources finished, look at the ^ +results in %BUILDDIR%/doctest/output.txt. + goto end +) + +:end diff --git a/caom2repo/ez_setup.py b/caom2repo/ez_setup.py new file mode 100644 index 00000000..fc22046b --- /dev/null +++ b/caom2repo/ez_setup.py @@ -0,0 +1,425 @@ +#!/usr/bin/env python + +""" +Setuptools bootstrapping installer. + +Maintained at https://github.com/pypa/setuptools/tree/bootstrap. + +Run this script to install or upgrade setuptools. +""" + +import os +import shutil +import sys +import tempfile +import zipfile +import optparse +import subprocess +import platform +import textwrap +import contextlib +import json +import codecs + +from distutils import log + +try: + from urllib.request import urlopen + from urllib.parse import urljoin +except ImportError: + from urllib2 import urlopen + from urlparse import urljoin + +try: + from site import USER_SITE +except ImportError: + USER_SITE = None + +LATEST = object() +DEFAULT_VERSION = LATEST +DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" +DEFAULT_SAVE_DIR = os.curdir + + +def _python_cmd(*args): + """ + Execute a command. + + Return True if the command succeeded. + """ + args = (sys.executable,) + args + return subprocess.call(args) == 0 + + +def _install(archive_filename, install_args=()): + """Install Setuptools.""" + with archive_context(archive_filename): + # installing + log.warn('Installing Setuptools') + if not _python_cmd('setup.py', 'install', *install_args): + log.warn('Something went wrong during the installation.') + log.warn('See the error message above.') + # exitcode will be 2 + return 2 + + +def _build_egg(egg, archive_filename, to_dir): + """Build Setuptools egg.""" + with archive_context(archive_filename): + # building an egg + log.warn('Building a Setuptools egg in %s', to_dir) + _python_cmd('setup.py', '-q', 'bdist_egg', '--dist-dir', to_dir) + # returning the result + log.warn(egg) + if not os.path.exists(egg): + raise IOError('Could not build the egg.') + + +class ContextualZipFile(zipfile.ZipFile): + + """Supplement ZipFile class to support context manager for Python 2.6.""" + + def __enter__(self): + return self + + def __exit__(self, type, value, traceback): + self.close() + + def __new__(cls, *args, **kwargs): + """Construct a ZipFile or ContextualZipFile as appropriate.""" + if hasattr(zipfile.ZipFile, '__exit__'): + return zipfile.ZipFile(*args, **kwargs) + return super(ContextualZipFile, cls).__new__(cls) + + +@contextlib.contextmanager +def archive_context(filename): + """ + Unzip filename to a temporary directory, set to the cwd. + + The unzipped target is cleaned up after. + """ + tmpdir = tempfile.mkdtemp() + log.warn('Extracting in %s', tmpdir) + old_wd = os.getcwd() + try: + os.chdir(tmpdir) + with ContextualZipFile(filename) as archive: + archive.extractall() + + # going in the directory + subdir = os.path.join(tmpdir, os.listdir(tmpdir)[0]) + os.chdir(subdir) + log.warn('Now working in %s', subdir) + yield + + finally: + os.chdir(old_wd) + shutil.rmtree(tmpdir) + + +def _do_download(version, download_base, to_dir, download_delay): + """Download Setuptools.""" + egg = os.path.join(to_dir, 'setuptools-%s-py%d.%d.egg' + % (version, sys.version_info[0], sys.version_info[1])) + if not os.path.exists(egg): + archive = download_setuptools(version, download_base, + to_dir, download_delay) + _build_egg(egg, archive, to_dir) + sys.path.insert(0, egg) + + # Remove previously-imported pkg_resources if present (see + # https://bitbucket.org/pypa/setuptools/pull-request/7/ for details). + if 'pkg_resources' in sys.modules: + _unload_pkg_resources() + + import setuptools + setuptools.bootstrap_install_from = egg + + +def use_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, download_delay=15): + """ + Ensure that a setuptools version is installed. + + Return None. Raise SystemExit if the requested version + or later cannot be installed. + """ + version = _resolve_version(version) + to_dir = os.path.abspath(to_dir) + + # prior to importing, capture the module state for + # representative modules. + rep_modules = 'pkg_resources', 'setuptools' + imported = set(sys.modules).intersection(rep_modules) + + try: + import pkg_resources + pkg_resources.require("setuptools>=" + version) + # a suitable version is already installed + return + except ImportError: + # pkg_resources not available; setuptools is not installed; download + pass + except pkg_resources.DistributionNotFound: + # no version of setuptools was found; allow download + pass + except pkg_resources.VersionConflict as VC_err: + if imported: + _conflict_bail(VC_err, version) + + # otherwise, unload pkg_resources to allow the downloaded version to + # take precedence. + del pkg_resources + _unload_pkg_resources() + + return _do_download(version, download_base, to_dir, download_delay) + + +def _conflict_bail(VC_err, version): + """ + Setuptools was imported prior to invocation, so it is + unsafe to unload it. Bail out. + """ + conflict_tmpl = textwrap.dedent(""" + The required version of setuptools (>={version}) is not available, + and can't be installed while this script is running. Please + install a more recent version first, using + 'easy_install -U setuptools'. + + (Currently using {VC_err.args[0]!r}) + """) + msg = conflict_tmpl.format(**locals()) + sys.stderr.write(msg) + sys.exit(2) + + +def _unload_pkg_resources(): + sys.meta_path = [ + importer + for importer in sys.meta_path + if importer.__class__.__module__ != 'pkg_resources.extern' + ] + del_modules = [ + name for name in sys.modules + if name.startswith('pkg_resources') + ] + for mod_name in del_modules: + del sys.modules[mod_name] + + +def _clean_check(cmd, target): + """ + Run the command to download target. + + If the command fails, clean up before re-raising the error. + """ + try: + subprocess.check_call(cmd) + except subprocess.CalledProcessError: + if os.access(target, os.F_OK): + os.unlink(target) + raise + + +def download_file_powershell(url, target): + """ + Download the file at url to target using Powershell. + + Powershell will validate trust. + Raise an exception if the command cannot complete. + """ + target = os.path.abspath(target) + ps_cmd = ( + "[System.Net.WebRequest]::DefaultWebProxy.Credentials = " + "[System.Net.CredentialCache]::DefaultCredentials; " + '(new-object System.Net.WebClient).DownloadFile("%(url)s", "%(target)s")' + % locals() + ) + cmd = [ + 'powershell', + '-Command', + ps_cmd, + ] + _clean_check(cmd, target) + + +def has_powershell(): + """Determine if Powershell is available.""" + if platform.system() != 'Windows': + return False + cmd = ['powershell', '-Command', 'echo test'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_powershell.viable = has_powershell + + +def download_file_curl(url, target): + cmd = ['curl', url, '--location', '--silent', '--output', target] + _clean_check(cmd, target) + + +def has_curl(): + cmd = ['curl', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_curl.viable = has_curl + + +def download_file_wget(url, target): + cmd = ['wget', url, '--quiet', '--output-document', target] + _clean_check(cmd, target) + + +def has_wget(): + cmd = ['wget', '--version'] + with open(os.path.devnull, 'wb') as devnull: + try: + subprocess.check_call(cmd, stdout=devnull, stderr=devnull) + except Exception: + return False + return True +download_file_wget.viable = has_wget + + +def download_file_insecure(url, target): + """Use Python to download the file, without connection authentication.""" + src = urlopen(url) + try: + # Read all the data in one block. + data = src.read() + finally: + src.close() + + # Write all the data in one block to avoid creating a partial file. + with open(target, "wb") as dst: + dst.write(data) +download_file_insecure.viable = lambda: True + + +def get_best_downloader(): + downloaders = ( + download_file_powershell, + download_file_curl, + download_file_wget, + download_file_insecure, + ) + viable_downloaders = (dl for dl in downloaders if dl.viable()) + return next(viable_downloaders, None) + + +def download_setuptools( + version=DEFAULT_VERSION, download_base=DEFAULT_URL, + to_dir=DEFAULT_SAVE_DIR, delay=15, + downloader_factory=get_best_downloader): + """ + Download setuptools from a specified location and return its filename. + + `version` should be a valid setuptools version number that is available + as an sdist for download under the `download_base` URL (which should end + with a '/'). `to_dir` is the directory where the egg will be downloaded. + `delay` is the number of seconds to pause before an actual download + attempt. + + ``downloader_factory`` should be a function taking no arguments and + returning a function for downloading a URL to a target. + """ + version = _resolve_version(version) + # making sure we use the absolute path + to_dir = os.path.abspath(to_dir) + zip_name = "setuptools-%s.zip" % version + url = download_base + zip_name + saveto = os.path.join(to_dir, zip_name) + if not os.path.exists(saveto): # Avoid repeated downloads + log.warn("Downloading %s", url) + downloader = downloader_factory() + downloader(url, saveto) + return os.path.realpath(saveto) + + +def _resolve_version(version): + """ + Resolve LATEST version + """ + if version is not LATEST: + return version + + meta_url = urljoin(DEFAULT_URL, '/pypi/setuptools/json') + resp = urlopen(meta_url) + with contextlib.closing(resp): + try: + charset = resp.info().get_content_charset() + except Exception: + # Python 2 compat; assume UTF-8 + charset = 'UTF-8' + reader = codecs.getreader(charset) + doc = json.load(reader(resp)) + + return str(doc['info']['version']) + + +def _build_install_args(options): + """ + Build the arguments to 'python setup.py install' on the setuptools package. + + Returns list of command line arguments. + """ + return ['--user'] if options.user_install else [] + + +def _parse_args(): + """Parse the command line for options.""" + parser = optparse.OptionParser() + parser.add_option( + '--user', dest='user_install', action='store_true', default=False, + help='install in user site package') + parser.add_option( + '--download-base', dest='download_base', metavar="URL", + default=DEFAULT_URL, + help='alternative URL from where to download the setuptools package') + parser.add_option( + '--insecure', dest='downloader_factory', action='store_const', + const=lambda: download_file_insecure, default=get_best_downloader, + help='Use internal, non-validating downloader' + ) + parser.add_option( + '--version', help="Specify which version to download", + default=DEFAULT_VERSION, + ) + parser.add_option( + '--to-dir', + help="Directory to save (and re-use) package", + default=DEFAULT_SAVE_DIR, + ) + options, args = parser.parse_args() + # positional arguments are ignored + return options + + +def _download_args(options): + """Return args for download_setuptools function from cmdline args.""" + return dict( + version=options.version, + download_base=options.download_base, + downloader_factory=options.downloader_factory, + to_dir=options.to_dir, + ) + + +def main(): + """Install or upgrade setuptools and EasyInstall.""" + options = _parse_args() + archive = download_setuptools(**_download_args(options)) + return _install(archive, _build_install_args(options)) + +if __name__ == '__main__': + sys.exit(main()) diff --git a/caom2repo/setup.cfg b/caom2repo/setup.cfg new file mode 100644 index 00000000..462e1320 --- /dev/null +++ b/caom2repo/setup.cfg @@ -0,0 +1,37 @@ +[build_sphinx] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[build_docs] +source-dir = docs +build-dir = docs/_build +all_files = 1 + +[upload_docs] +upload-dir = docs/_build/html +show-response = 1 + +[pytest] +minversion = 2.2 +norecursedirs = build docs/_build +doctest_plus = enabled + +[ah_bootstrap] +auto_use = True + +[metadata] +package_name = caom2repo +description = CAOM-2.2 repo access and tools +long_description = Tools for accessing a repo for the CAOM-2.2 data model +author = Canadian Astronomy Data Centre +author_email = cadc@nrc-cnrc.gc.ca +license = AGPLv3 +url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 +edit_on_github = False +github_project = opencadc/caom2tools +# version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) +version = 2.2.2 + +[entry_points] +caom2-client = caom2repo.core:main diff --git a/setup.py b/caom2repo/setup.py similarity index 98% rename from setup.py rename to caom2repo/setup.py index dc1730db..1b40d4a1 100755 --- a/setup.py +++ b/caom2repo/setup.py @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['lxml', 'requests'], + install_requires=['cadctools'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, diff --git a/caom2tools/test/__init__.py b/caom2tools/test/__init__.py deleted file mode 100644 index 2ff7e2a6..00000000 --- a/caom2tools/test/__init__.py +++ /dev/null @@ -1,4 +0,0 @@ -# Licensed under a 3-clause BSD style license - see LICENSE.rst -""" -This packages contains affiliated package tests. -""" diff --git a/caom2tools/test/coveragerc b/caom2tools/test/coveragerc deleted file mode 100644 index bec7c291..00000000 --- a/caom2tools/test/coveragerc +++ /dev/null @@ -1,31 +0,0 @@ -[run] -source = {packagename} -omit = - {packagename}/_astropy_init* - {packagename}/conftest* - {packagename}/cython_version* - {packagename}/setup_package* - {packagename}/*/setup_package* - {packagename}/*/*/setup_package* - {packagename}/tests/* - {packagename}/*/tests/* - {packagename}/*/*/tests/* - {packagename}/version* - -[report] -exclude_lines = - # Have to re-enable the standard pragma - pragma: no cover - - # Don't complain about packages we have installed - except ImportError - - # Don't complain if tests don't hit assertions - raise AssertionError - raise NotImplementedError - - # Don't complain about script hooks - def main\(.*\): - - # Ignore branches that don't pertain to this version of Python - pragma: py{ignore_python_version} \ No newline at end of file diff --git a/caom2tools/test/setup_package.py b/caom2tools/test/setup_package.py deleted file mode 100644 index f2fd9ed4..00000000 --- a/caom2tools/test/setup_package.py +++ /dev/null @@ -1,3 +0,0 @@ -def get_package_data(): - return { - _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} From 5c5d25ef9b7ed2f46902cc8142652a0f41393be1 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 23 Nov 2016 16:16:32 -0800 Subject: [PATCH 30/54] Major re-arrangement of the packages --- caom2/caom2/test/test_obs_reader_writer.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/caom2/caom2/test/test_obs_reader_writer.py b/caom2/caom2/test/test_obs_reader_writer.py index 00e486f7..82385f46 100644 --- a/caom2/caom2/test/test_obs_reader_writer.py +++ b/caom2/caom2/test/test_obs_reader_writer.py @@ -853,8 +853,6 @@ def init(self): def get_file_list(self): file_list = pkg_resources.resource_listdir(TestRoundTrip.TEST_PACKAGE, TestRoundTrip.TEST_DATA_DIR) - with open('/tmp/dbg.txt', 'w') as f: - f.write(str(file_list)) return [f for f in file_list if f.endswith('.xml')] def do_test(self, reader, writer, filename): From eaa5d8bf1a4bc68d74cabe52b11b689e9e7ab4c4 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 24 Nov 2016 10:13:28 -0800 Subject: [PATCH 31/54] Made astropy_helpers git submodules --- .gitmodules | 6 ++++++ caom2/astropy_helpers | 2 +- caom2/caom2/__init__.py | 5 ++--- caom2repo/astropy_helpers | 2 +- caom2repo/caom2repo/__init__.py | 5 ++--- 5 files changed, 12 insertions(+), 8 deletions(-) diff --git a/.gitmodules b/.gitmodules index 6a20fa6e..0273d302 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,9 @@ [submodule "astropy_helpers"] path = astropy_helpers url = https://github.com/astropy/astropy-helpers.git +[submodule "caom2/astropy_helpers"] + path = caom2/astropy_helpers + url = https://github.com/astropy/astropy-helpers.git +[submodule "caom2repo/astropy_helpers"] + path = caom2repo/astropy_helpers + url = https://github.com/astropy/astropy-helpers.git diff --git a/caom2/astropy_helpers b/caom2/astropy_helpers index 2732e3a5..23f3e832 160000 --- a/caom2/astropy_helpers +++ b/caom2/astropy_helpers @@ -1 +1 @@ -Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e +Subproject commit 23f3e832a69b97911ad24091197d2cac2aab9ffe diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index d06b3005..205ec5ce 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -81,6 +81,5 @@ # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -if not _ASTROPY_SETUP_: -# from .caom2tools import * - pass +#if not _ASTROPY_SETUP_: +# from .caom2 import * diff --git a/caom2repo/astropy_helpers b/caom2repo/astropy_helpers index 2732e3a5..23f3e832 160000 --- a/caom2repo/astropy_helpers +++ b/caom2repo/astropy_helpers @@ -1 +1 @@ -Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e +Subproject commit 23f3e832a69b97911ad24091197d2cac2aab9ffe diff --git a/caom2repo/caom2repo/__init__.py b/caom2repo/caom2repo/__init__.py index 210f62b7..e7095e0b 100755 --- a/caom2repo/caom2repo/__init__.py +++ b/caom2repo/caom2repo/__init__.py @@ -12,6 +12,5 @@ # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -if not _ASTROPY_SETUP_: -# from .caom2tools import * - pass \ No newline at end of file +#if not _ASTROPY_SETUP_: +# from .caom2repo import * \ No newline at end of file From f8a892b74fa8b850771b334a078998dff32ee1a8 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 24 Nov 2016 12:22:41 -0800 Subject: [PATCH 32/54] s1950: added __all__ list to modules --- caom2/README.md | 365 ++++++++++++++++++++++++++++++- caom2/caom2/__init__.py | 12 +- caom2/caom2/artifact.py | 21 +- caom2/caom2/caom_object.py | 12 +- caom2/caom2/caom_util.py | 72 +----- caom2/caom2/chunk.py | 57 +++-- caom2/caom2/obs_reader_writer.py | 15 +- caom2/caom2/observation.py | 37 ++-- caom2/caom2/part.py | 19 +- caom2/caom2/plane.py | 48 ++-- caom2/caom2/shape.py | 11 +- caom2/caom2/wcs.py | 49 +---- 12 files changed, 507 insertions(+), 211 deletions(-) diff --git a/caom2/README.md b/caom2/README.md index 9181d329..d3fc044c 100644 --- a/caom2/README.md +++ b/caom2/README.md @@ -1,2 +1,363 @@ -# caom2 -Common Archive Observation Model - data model library +# caom2tools +Common Archive Observation Model - data engineering tools + +caom2 module + +The caom2 module is a library implementing the Common Archive Observation Model (CAOM-2.2) for manipulating CAOM observations and reading and writing XML documents. + + + + +## To create a minimal Simple Observation +```python + observation = SimpleObservation('collection', 'observationID') + + observation.planes = TypedOrderedDict(Plane) + plane = Plane('productID') + observation.planes['productID'] = plane + + plane.artifacts = TypedOrderedDict(Artifact) + artifact = Artifact('uri:foo/bar', ProductType.SCIENCE, ReleaseType.META) + plane.artifacts['uri:foo/bar'] = artifact + + artifact.parts = TypedOrderedDict(Part) + part = Part('name') + artifact.parts['name'] = part + + part.chunks = TypedList(Chunk) + chunk = Chunk() + part.chunks.append(chunk) + + writer = ObservationWriter() + writer.write(observation, sys.stdout) +``` +```xml + + + collection + observationID + + exposure + + + + productID + + + uri:foo/bar + science + meta + + + name + + + + + + + + + + +``` +## To create a complete SimpleObservation + +```python + observation = SimpleObservation('collection', 'observationID') + observation.obs_type = 'flat' + observation.intent = ObservationIntentType.SCIENCE + observation.meta_release = datetime(2016, 11, 22, 11, 53, 44, 0) + + observation.proposal = Proposal('proposal id') + observation.proposal.pi_name = 'pi name' + observation.proposal.project = 'proposal project' + observation.proposal.title = 'proposal title' + observation.proposal.keywords.update({'proposal', 'key', 'words'}) + + observation.target = Target('target name') + observation.target.target_type = TargetType.OBJECT + observation.target.standard = False + observation.target.redshift = 1.5 + observation.target.keywords.update({'target', 'key', 'words'}) + + point = Point(1.0, 2.0) + observation.target_position = TargetPosition(point, 'coordsys') + observation.target_position.equinox = 3.0 + + observation.telescope = Telescope('telescope name') + observation.telescope.geo_location_x = 1.0 + observation.telescope.geo_location_y = 2.0 + observation.telescope.geo_location_z = 3.0 + observation.telescope.keywords.update({'telescope', 'key', 'words'}) + + observation.instrument = Instrument('instrument name') + observation.instrument.keywords.update({'instrument', 'key', 'words'}) + + observation.env = Environment() + observation.env.seeing = 0.08 + observation.env.humidity = 0.35 + observation.env.elevation = 2.7 + observation.env.tau = 0.7 + observation.env.wavelength_tau = 450e-6 + observation.env.ambient_temp = 20.0 + observation.env.photometric = True + + observation.planes = TypedOrderedDict(Plane) + plane = Plane('productID') + observation.planes['productID'] = plane + + plane.meta_release = datetime(2016, 11, 22, 12, 26, 21, 0) + plane.data_release = datetime(2018, 01, 01, 00, 00, 00, 0) + plane.data_product_type = DataProductType.IMAGE + plane.calibration_level = CalibrationLevel.PRODUCT + + plane.provenance = provenance = Provenance('name') + plane.provenance.version = 'version' + plane.provenance.product = 'product' + plane.provenance.producer = 'producer' + plane.provenance.run_id = 'run_id' + plane.provenance.reference = 'http://foo/bar' + plane.provenance.last_executed = datetime(2016, 11, 22, 12, 28, 16, 0) + plane.provenance.keywords.update({'provenance', 'key', 'words'}) + + plane.metrics = Metrics() + plane.metrics.source_number_density = 1.0 + plane.metrics.background = 2.0 + plane.metrics.background_std_dev = 3.0 + plane.metrics.flux_density_limit = 4.0 + plane.metrics.mag_limit = 5.0 + + plane.artifacts = TypedOrderedDict(Artifact) + artifact = Artifact('uri:foo/bar', ProductType.SCIENCE, ReleaseType.META) + plane.artifacts['uri:foo/bar'] = artifact + + artifact.content_type = 'application/fits' + artifact.content_length = 12345L + + artifact.parts = TypedOrderedDict(Part) + part = Part('name') + artifact.parts['name'] = part + part.product_type = ProductType.SCIENCE + + part.chunks = TypedList(Chunk) + chunk = Chunk() + part.chunks.append(chunk) + + chunk.product_type = ProductType.SCIENCE + chunk.naxis = 5 + chunk.observable_axis = 1 + chunk.position_axis_1 = 1 + chunk.position_axis_2 = 2 + chunk.energy_axis = 3 + chunk.time_axis = 4 + chunk.polarization_axis = 5 + + observable_axis = Slice(Axis('observable_ctype', 'observable_cunit'), 1L) + chunk.observable = ObservableAxis(observable_axis) + + position_axis = CoordAxis2D(Axis('position_ctype_1', 'position_cunit_1'), + Axis('position_ctype_2', 'position_cunit_2')) + chunk.position = SpatialWCS(position_axis) + chunk.position.coordsys = 'position coordsys' + chunk.position.equinox = 2000.0 + chunk.position.resolution = 0.5 + + energy_axis = CoordAxis1D(Axis('energy_ctype', 'energy_cunit')) + chunk.energy = SpectralWCS(energy_axis, 'specsys') + chunk.energy.ssysobs = 'ssysobs' + chunk.energy.ssyssrc = 'ssyssrc' + chunk.energy.restfrq = 1.0 + chunk.energy.restwav = 2.0 + chunk.energy.velosys = 3.0 + chunk.energy.zsource = 4.0 + chunk.energy.velang = 5.0 + chunk.energy.bandpassName = 'bandpass name' + chunk.energy.resolvingPower = 6.0 + chunk.energy.transition = EnergyTransition('H', '21cm') + + time_axis = CoordAxis1D(Axis('time_ctype', 'time_cunit')) + chunk.time = TemporalWCS(time_axis) + chunk.time.exposure = 1.0 + chunk.time.resolution = 2.0 + chunk.time.timesys = 'UTC' + chunk.time.trefpos = 'TOPOCENTER' + chunk.time.mjdref = 3.0 + + polarization_axis = CoordAxis1D(Axis('STOKES')) + polarization_axis.function = CoordFunction1D(4L, 1.0, RefCoord(1.0, 1.0)) + chunk.polarization = PolarizationWCS(polarization_axis) + + writer = ObservationWriter() + writer.write(observation, sys.stdout) +``` +```xml + + + collection + observationID + 2016-11-22T11:53:44.000 + + exposure + + flat + science + + proposal id + pi name + proposal project + proposal title + proposal words key + + + target name + object + false + 1.5 + words key target + + + coordsys + 3.0 + + 1.0 + 2.0 + + + + telescope name + 1.0 + 2.0 + 3.0 + words key telescope + + + instrument name + instrument words key + + + + productID + 2016-11-22T12:26:21.000 + 2018-01-01T00:00:00.000 + image + 3 + + name + version + producer + run_id + http://foo/bar + 2016-11-22T12:28:16.000 + provenance words key + + + 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + + + + uri:foo/bar + science + meta + application/fits + 12345 + + + name + science + + + science + 5 + 1 + 1 + 2 + 3 + 4 + 5 + + + + observable_ctype + observable_cunit + + 1 + + + + + + position_ctype_1 + position_cunit_1 + + + position_ctype_2 + position_cunit_2 + + + position coordsys + 2000.0 + 0.5 + + + + + energy_ctype + energy_cunit + + + specsys + ssysobs + ssyssrc + 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + + H + 21cm + + + + + + time_ctype + time_cunit + + + UTC + TOPOCENTER + 3.0 + 1.0 + 2.0 + + + + + STOKES + + + 4 + 1.0 + + 1.0 + 1.0 + + + + + + + + + + + + + +``` \ No newline at end of file diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index d06b3005..5440e932 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -82,5 +82,15 @@ # For egg_info test builds to pass, put package imports here. if not _ASTROPY_SETUP_: -# from .caom2tools import * pass + +from artifact import * +from caom_object import * +from caom_util import * +from chunk import * +from obs_reader_writer import * +from observation import * +from part import * +from plane import * +from shape import * +from wcs import * diff --git a/caom2/caom2/artifact.py b/caom2/caom2/artifact.py index 3a9536e2..4ad75b29 100644 --- a/caom2/caom2/artifact.py +++ b/caom2/caom2/artifact.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """Defines the caom2.Artifact class. @@ -94,6 +93,8 @@ DATA="data", META="meta") +__all__ = ['Artifact'] + class Artifact(caom_object.AbstractCaomEntity): """Contains the meta data assocaited with a file. @@ -131,11 +132,11 @@ def __init__(self, self.content_type = content_type self.content_length = content_length if parts is None: - parts = caom_util.TypedOrderedDict((part.Part),) + parts = caom_util.TypedOrderedDict(part.Part,) self.parts = parts def _key(self): - return (self.uri) + return self.uri def __hash__(self): return hash(self._key()) @@ -252,8 +253,6 @@ def parts(self): @parts.setter def parts(self, value): - caom_util.type_check(value, - caom_util.TypedOrderedDict, - 'parts', - override=False) + caom_util.type_check(value, caom_util.TypedOrderedDict, 'parts', + override=False) self._parts = value diff --git a/caom2/caom2/caom_object.py b/caom2/caom2/caom_object.py index d89b5e74..eda025f0 100644 --- a/caom2/caom2/caom_object.py +++ b/caom2/caom2/caom_object.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,9 +64,10 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # + import inspect import random import time @@ -76,6 +76,8 @@ import caom_util +__all__ = ['CaomObject', 'AbstractCaomEntity'] + class CaomObject(object): """ diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index 7df14a7a..eb0a7c23 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """ @@ -83,11 +82,7 @@ import uuid from datetime import datetime -# import artifact -# import chunk -# import observation -# import part -# import plane +__all__ = ['TypedList', 'ProducTypedSettType', 'TypedOrderedDict', 'ClassProperty'] # TODO both these are very bad, implement more sensibly @@ -235,8 +230,8 @@ def __str__(self): return "\n".join(["{}".format(v) for v in self]) def __repr__(self): - return "TypedList((%r))," % (self._oktypes) + ( - "(".join(["(%r)" % (v) for v in self]) + ")") + return "TypedList((%r))," % self._oktypes + ( + "(".join(["(%r)" % v for v in self]) + ")") def check(self, v): assert isinstance(v, self._oktypes), ( @@ -336,7 +331,7 @@ class TypedOrderedDict(collections.OrderedDict): with the wrong type. """ - def __init__(self, keyType, *args): + def __init__(self, key_type, *args): """ Initializes a TypedOrderedDict. @@ -349,7 +344,7 @@ def __init__(self, keyType, *args): is not the same as keyType. """ super(TypedOrderedDict, self).__init__(self) - self._keyType = keyType + self._keyType = key_type for arg in args: self.__setitem__(arg[0], arg[1]) @@ -358,7 +353,7 @@ def __str__(self): for k, v in self.iteritems()]) def __repr__(self): - return "TypeOrderedDict((%r))," % (self._keyType) + ( + return "TypeOrderedDict((%r))," % self._keyType + ( "(".join(["(%r,%r)" % (k, v) for k, v in self.iteritems()]) + ")") def check(self, key, value): @@ -389,50 +384,3 @@ class ClassProperty(property): """ """ def __get__(self, cls, owner): return self.fget.__get__(None, owner)() - - -# class Validator(object): -# -# def __init__(self): -# self.errors = {} -# -# def validate(self, obs): -# if not isinstance(obs, observation.Observation): -# self.errors['observation'] = 'not an Observation instance' -# return -# self._validate_planes(obs.planes) -# if len(self.errors) > 0: -# return False -# return True -# -# def _validate_planes(self, planes): -# for product_id, _plane in planes.iteritems(): -# if not isinstance(_plane, plane.Plane): -# self.errors['plane'].append("not a Plane instance") -# continue -# if product_id != _plane.product_id: -# self.errors['plane'].append("plane productIDs do not match") -# self._validate_artifacts(_plane.artifacts) -# -# def _validate_artifacts(self, artifacts): -# for uri, _artifact in artifacts.iteritems(): -# if not isinstance(_artifact, artifact.Artifact): -# self.errors['artifact'].append("not an Artifact instance") -# continue -# if uri != _artifact.uri: -# self.errors['artifact'].append("artifact uris do not match") -# self._validate_parts(_artifact.parts) -# -# def _validate_parts(self, parts): -# for name, _part in parts.iteritems(): -# if not isinstance(_part, part.Part): -# self.errors['part'].append("not a Part instance") -# continue -# if name != _part.name: -# self.errors['part'].append("part names do not match") -# self._validate_chunks(_part.chunks) -# -# def _validate_chunks(self, chunks): -# for _chunk in chunks: -# if not isinstance(_chunk, chunk.Chunk): -# self.errors['chunk'].append("not a chunk instance") diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py index 5ca4a125..51296f4e 100644 --- a/caom2/caom2/chunk.py +++ b/caom2/caom2/chunk.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,18 +64,20 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """Defines caom2.Chunk class. """ -import artifact import caom_object import caom_util -import plane import wcs +from artifact import ProductType +from plane import EnergyTransition + +__all__ = ['Chunk', 'ObservableAxis', 'SpatialWCS', 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] class Chunk(caom_object.AbstractCaomEntity): @@ -101,19 +102,19 @@ class Chunk(caom_object.AbstractCaomEntity): """ def __init__(self, product_type=None, - naxis=None, - position_axis_1=None, - position_axis_2=None, - position=None, - energy_axis=None, - energy=None, - time_axis=None, - time=None, - polarization_axis=None, - polarization=None, - observable_axis=None, - observable=None, - ): + naxis=None, + position_axis_1=None, + position_axis_2=None, + position=None, + energy_axis=None, + energy=None, + time_axis=None, + time=None, + polarization_axis=None, + polarization=None, + observable_axis=None, + observable=None, + ): super(Chunk, self).__init__() self.product_type = product_type @@ -137,7 +138,7 @@ def product_type(self): eg. Chunk.product_type = ProductType('SCIENCE') Allowed values: - """ + str(artifact.ProductType.names()) + """ + """ + str(ProductType.names()) + """ """ @@ -145,10 +146,10 @@ def product_type(self): @product_type.setter def product_type(self, value): - if isinstance(value, str) and value in artifact.ProductType.names(): - ## be helpful - value = artifact.ProductType('value') - caom_util.type_check(value, artifact.ProductType, 'product_type') + if isinstance(value, str) and value in ProductType.names(): + # be helpful + value = ProductType('value') + caom_util.type_check(value, ProductType, 'product_type') self._product_type = value @property @@ -730,7 +731,7 @@ def transition(self): @transition.setter def transition(self, value): - caom_util.type_check(value, plane.EnergyTransition, "transition") + caom_util.type_check(value, EnergyTransition, "transition") self._transition = value @property @@ -835,7 +836,7 @@ def mjdref(self): @mjdref.setter def mjdref(self, value): caom_util.type_check(value, float, 'mjdref') - ### set the limits to be after 1800 but before year 2050 + # set the limits to be after 1800 but before year 2050 caom_util.value_check(value, -22000, 70000, 'mjdref') self._mjdref = value @@ -909,5 +910,3 @@ def axis(self, value): if value.axis.ctype != 'STOKES': raise ValueError('CTYPE must be STOKES') self._axis = value - - diff --git a/caom2/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py index ca8ea212..60955c35 100644 --- a/caom2/caom2/obs_reader_writer.py +++ b/caom2/caom2/obs_reader_writer.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """ Defines ObservationReader class """ @@ -101,6 +100,8 @@ XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" XSI = "{%s}" % XSI_NAMESPACE +__all__ = ['ObservationReader', 'ObservationWriter', 'ObservationParsingException'] + class ObservationReader(object): """ObservationReader """ @@ -583,7 +584,7 @@ def _get_axis(self, element_tag, parent, ns, required): return None else: return wcs.Axis(self._get_child_text("ctype", el, ns, True), - self._get_child_text("cunit", el, ns, False)) + self._get_child_text("cunit", el, ns, False)) def _get_slice(self, element_tag, parent, ns, required): """Build a Slice object from an XML representation of a Slice element. @@ -602,7 +603,7 @@ def _get_slice(self, element_tag, parent, ns, required): return None else: return wcs.Slice(self._get_axis("axis", el, ns, True), - self._get_child_text_as_long("bin", el, ns, True)) + self._get_child_text_as_long("bin", el, ns, True)) def _get_observable_axis(self, element_tag, parent, ns, required): """Build an ObservableAxis object from an XML representation of an diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py index 3281b459..be614f82 100644 --- a/caom2/caom2/observation.py +++ b/caom2/caom2/observation.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """definition of the caom2.Observation object.""" @@ -76,9 +75,9 @@ import caom_object import caom_util -import plane -import shape from enum import Enum +from plane import Plane +from shape import Point ObservationIntentType = Enum('ObservationIntentType', CALIBRATION="calibration", @@ -91,6 +90,10 @@ FIELD="field", OBJECT="object") +__all__ = ['Observation', 'ObservationURI', 'Algorithm', 'SimpleObservation', + 'CompositeObservation', 'Environment', 'Instrument', 'Proposal', + 'Requirements', 'Target', 'TargetPosition', 'Telescope'] + class Observation(caom_object.AbstractCaomEntity): """ @@ -188,7 +191,7 @@ def __init__(self, self.requirements = requirements self.meta_release = meta_release if planes is None: - planes = caom_util.TypedOrderedDict((plane.Plane),) + planes = caom_util.TypedOrderedDict(Plane,) self.planes = planes # Properties @@ -463,7 +466,7 @@ def __init__(self, uri): self._uri = tmp.geturl() (collection, observation_id) = tmp.path.split("/") - if collection is None: + if collection is None: raise ValueError( "uri did not contain a collection part. received: {}" .format(uri)) @@ -511,8 +514,8 @@ def get_observation_uri(cls, collection, observation_id): @property @classmethod - def SCHEME(cls): - """The SCHEME defines where this Observation can be looked up. + def scheme(cls): + """The scheme defines where this Observation can be looked up. Only 'caom' is currently supported.""" return cls._SCHEME @@ -554,7 +557,7 @@ def __init__(self, name): self._name = name def _key(self): - return (self._name) + return self._name def __ne__(self, y): return not self.__eq__(y) @@ -647,9 +650,7 @@ def algorithm(self, value=_ALGORITHM): if isinstance(value, str): value = Algorithm(value) caom_util.type_check(value, Algorithm, 'algorithm', override=False) - caom_util.value_check(value, None, None, - 'algorithm', - override=self._ALGORITHM) + caom_util.value_check(value, None, None, 'algorithm', override=self._ALGORITHM) self._algorithm = value @@ -917,14 +918,14 @@ def __init__(self, # Properties @property - def id(self): + def proposal_id(self): """The proposal ID. Sometimes also called a RUNID. type: str """ return self._proposal_id - @id.setter + @proposal_id.setter def proposal_id(self, value): caom_util.type_check(value, str, 'id') self._proposal_id = value @@ -1159,7 +1160,7 @@ def coordinates(self): @coordinates.setter def coordinates(self, value): - caom_util.type_check(value, shape.Point, "coordinates") + caom_util.type_check(value, Point, "coordinates") self._coordinates = value @property diff --git a/caom2/caom2/part.py b/caom2/caom2/part.py index 740cc587..4050605d 100644 --- a/caom2/caom2/part.py +++ b/caom2/caom2/part.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,16 +64,18 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """Defines the caom2.Part class which describes the caom2_Observation_Plane_Artifact_Part object.""" -import artifact import caom_object import caom_util -import chunk +from artifact import ProductType +from chunk import Chunk + +__all__ = ['Part'] class Part(caom_object.AbstractCaomEntity): @@ -91,7 +92,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = caom_util.TypedList((chunk.Chunk), ) + chunks = caom_util.TypedList(Chunk, ) self.chunks = chunks def _key(self): @@ -115,7 +116,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - caom_util.type_check(value, artifact.ProductType, "product_type") + caom_util.type_check(value, ProductType, "product_type") self._product_type = value @property diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py index 959bffa3..1d1edf8f 100644 --- a/caom2/caom2/plane.py +++ b/caom2/caom2/plane.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # """defines the caom2.Plane class""" @@ -74,13 +73,13 @@ from urlparse import SplitResult from urlparse import urlsplit -import artifact import caom_object import caom_util -import observation import shape import wcs +from artifact import Artifact from enum import Enum +from observation import ObservationURI CalibrationLevel = Enum('CalibrationLevel', RAW_INSTRUMENT=0, @@ -124,6 +123,9 @@ Quality = Enum('Quality', JUNK="junk") +__all__ = ['Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', + 'Position', 'Energy', 'EnergyTransition', 'Polarization', 'Time'] + class Plane(caom_object.AbstractCaomEntity): """ Plane class """ @@ -146,7 +148,7 @@ def __init__(self, product_id, super(Plane, self).__init__() self.product_id = product_id if artifacts is None: - artifacts = caom_util.TypedOrderedDict((artifact.Artifact), ) + artifacts = caom_util.TypedOrderedDict(Artifact, ) self.artifacts = artifacts self.meta_release = meta_release @@ -227,9 +229,9 @@ def meta_release(self): def meta_release(self, value): caom_util.type_check(value, datetime, 'meta_release') caom_util.value_check(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'meta_release') + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'meta_release') self._meta_release = value @property @@ -251,9 +253,9 @@ def data_release(self): def data_release(self, value): caom_util.type_check(value, datetime, 'data_release') caom_util.value_check(value, - datetime(1800, 1, 1, 0, 0, 0), - datetime(2050, 1, 1, 0, 0, 0), - 'data_release') + datetime(1800, 1, 1, 0, 0, 0), + datetime(2050, 1, 1, 0, 0, 0), + 'data_release') self._data_release = value @property @@ -331,8 +333,8 @@ def quality(self, value): caom_util.type_check(value, DataQuality, 'quality') self._quality = value - #@property - #def observable(self): + # @property + # def observable(self): # """ """ # return self._observable @@ -436,13 +438,13 @@ def get_plane_uri(cls, observation_uri, product_id): observation_uri : the uri of the observation product_id : ID of the product """ - caom_util.type_check(observation_uri, observation.ObservationURI, "observation_uri", - override=False) + caom_util.type_check(observation_uri, ObservationURI, "observation_uri", + override=False) caom_util.type_check(product_id, str, "observation_uri", override=False) caom_util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path - uri = SplitResult(observation.ObservationURI._SCHEME, "", path + "/" + + uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + product_id, "", "").geturl() return cls(uri) @@ -458,7 +460,7 @@ def uri(self, value): caom_util.type_check(value, str, "uri", override=False) tmp = urlsplit(value) - if tmp.scheme != observation.ObservationURI._SCHEME: + if tmp.scheme != ObservationURI._SCHEME: raise ValueError("{} doesn't have an allowed scheme".format(value)) if tmp.geturl() != value: raise ValueError("Failed to parse uri correctly: {}".format(value)) @@ -471,8 +473,7 @@ def uri(self, value): self._product_id = product_id self._observation_uri = \ - observation.ObservationURI.get_observation_uri(collection, - observation_id) + ObservationURI.get_observation_uri(collection, observation_id) self._uri = value @property @@ -637,7 +638,7 @@ def __init__(self, name, self.last_executed = last_executed self._keywords = set() - self._inputs = caom_util.TypedSet((PlaneURI), ) + self._inputs = caom_util.TypedSet(PlaneURI, ) # Properties @@ -1094,4 +1095,3 @@ def exposure(self): def exposure(self, value): caom_util.type_check(value, float, 'exposure') self._exposure = value - diff --git a/caom2/caom2/shape.py b/caom2/caom2/shape.py index 2f39fedf..13d225eb 100644 --- a/caom2/caom2/shape.py +++ b/caom2/caom2/shape.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,7 +64,7 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # import caom_object @@ -77,6 +76,8 @@ LINE=1, MOVE=2) +__all__ = ['Box', 'Circle', 'Interval', 'Point', 'Polygon', 'Vertex'] + class Box(caom_object.CaomObject): diff --git a/caom2/caom2/wcs.py b/caom2/caom2/wcs.py index 23aa7b75..d731cee5 100644 --- a/caom2/caom2/wcs.py +++ b/caom2/caom2/wcs.py @@ -1,8 +1,7 @@ -#!/usr/bin/env python2.7 # -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2010. (c) 2010. # Government of Canada Gouvernement du Canada @@ -65,13 +64,17 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # import caom_object import caom_util +__all__ = ['Axis', 'Coord2D', 'CoordAxis1D', 'CoordAxis2D', 'CoordBounds1D', 'CoordBounds2D', 'CoordCircle2D', + 'CoordError', 'CoordFunction1D', 'CoordFunction2D', 'CoordPolygon2D', 'CoordRange1D', 'CoordRange2D', + 'Dimension2D', 'RefCoord', 'Slice', 'ValueCoord2D'] + class Axis(caom_object.CaomObject): """the Axis class holds the definition of the axis type and units""" @@ -374,7 +377,7 @@ class CoordBounds1D(caom_object.CaomObject): def __init__(self, samples=None): if samples is None: - samples = caom_util.TypedList((CoordRange1D),) + samples = caom_util.TypedList(CoordRange1D,) self.samples = samples @property @@ -392,10 +395,7 @@ def samples(self): @samples.setter def samples(self, value): - caom_util.type_check(value, - caom_util.TypedList, - 'samples', - override=False) + caom_util.type_check(value, caom_util.TypedList, 'samples', override=False) self._samples = value @@ -706,7 +706,7 @@ class CoordPolygon2D(caom_object.CaomObject): def __init__(self, vertices=None): if vertices is None: - vertices = caom_util.TypedList((ValueCoord2D),) + vertices = caom_util.TypedList(ValueCoord2D,) self.vertices = vertices @property @@ -970,30 +970,3 @@ def coord2(self): def coord2(self, value): caom_util.type_check(value, float, 'coord2', override=False) self._coord2 = value - - -class EnergyTransition(caom_object.CaomObject): - """ EnergyTransition """ - - def __init__(self, species, transition): - """ - Construct an EnergyTransition instance - - Arguments: - species - transition - """ - caom_util.type_check(species, str, "species", override=False) - caom_util.type_check(transition, str, "transition", override=False) - self._species = species - self._transition = transition - - @property - def species(self): - """ Species """ - return self._species - - @property - def transition(self): - """ Transition """ - return self._transition From 50c52df1929503e505b6ed9d9f054bc7286def0f Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 24 Nov 2016 12:54:45 -0800 Subject: [PATCH 33/54] =?UTF-8?q?s1950:=20merge=20in=20Adrian=E2=80=99s=20?= =?UTF-8?q?s1950=20changes?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- caom2/astropy_helpers | 1 - caom2/caom2/__init__.py | 4 ++-- caom2repo/astropy_helpers | 1 - caom2repo/caom2repo/__init__.py | 5 ++--- 4 files changed, 4 insertions(+), 7 deletions(-) delete mode 160000 caom2/astropy_helpers delete mode 160000 caom2repo/astropy_helpers diff --git a/caom2/astropy_helpers b/caom2/astropy_helpers deleted file mode 160000 index 2732e3a5..00000000 --- a/caom2/astropy_helpers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 5440e932..8198aaa4 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -81,8 +81,8 @@ # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -if not _ASTROPY_SETUP_: - pass +# if not _ASTROPY_SETUP_: +# from .caom2 import * from artifact import * from caom_object import * diff --git a/caom2repo/astropy_helpers b/caom2repo/astropy_helpers deleted file mode 160000 index 2732e3a5..00000000 --- a/caom2repo/astropy_helpers +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 2732e3a5dadc60169aef90ac887e5726526e253e diff --git a/caom2repo/caom2repo/__init__.py b/caom2repo/caom2repo/__init__.py index 210f62b7..e7095e0b 100755 --- a/caom2repo/caom2repo/__init__.py +++ b/caom2repo/caom2repo/__init__.py @@ -12,6 +12,5 @@ # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -if not _ASTROPY_SETUP_: -# from .caom2tools import * - pass \ No newline at end of file +#if not _ASTROPY_SETUP_: +# from .caom2repo import * \ No newline at end of file From 9160a1bd95b93a9235630f354e4e4ba3ac163ffb Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 24 Nov 2016 14:25:45 -0800 Subject: [PATCH 34/54] S1950: fixing unit tests --- caom2/caom2/__init__.py | 20 +++++------ caom2/caom2/caom_util.py | 2 +- caom2/caom2/chunk.py | 13 ++++--- caom2/caom2/data/__init__.py | 0 caom2/caom2/observation.py | 8 ++--- caom2/caom2/part.py | 8 ++--- caom2/caom2/plane.py | 45 +++++-------------------- caom2/caom2/test/caom_test_instances.py | 2 +- caom2/caom2/test/test_chunk.py | 2 +- caom2/caom2/test/test_plane.py | 15 +++++---- caom2/caom2/wcs.py | 29 +++++++++++++++- 11 files changed, 72 insertions(+), 72 deletions(-) delete mode 100644 caom2/caom2/data/__init__.py diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 8198aaa4..8825a50f 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -84,13 +84,13 @@ # if not _ASTROPY_SETUP_: # from .caom2 import * -from artifact import * -from caom_object import * -from caom_util import * -from chunk import * -from obs_reader_writer import * -from observation import * -from part import * -from plane import * -from shape import * -from wcs import * +# from artifact import * +# from caom_object import * +# from caom_util import * +# from chunk import * +# from obs_reader_writer import * +# from observation import * +# from part import * +# from plane import * +# from shape import * +# from wcs import * diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index eb0a7c23..c93936bd 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -82,7 +82,7 @@ import uuid from datetime import datetime -__all__ = ['TypedList', 'ProducTypedSettType', 'TypedOrderedDict', 'ClassProperty'] +__all__ = ['TypedList', 'TypedSet', 'TypedOrderedDict', 'ClassProperty'] # TODO both these are very bad, implement more sensibly diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py index 51296f4e..b0e5de83 100644 --- a/caom2/caom2/chunk.py +++ b/caom2/caom2/chunk.py @@ -71,11 +71,10 @@ """ +import artifact import caom_object import caom_util import wcs -from artifact import ProductType -from plane import EnergyTransition __all__ = ['Chunk', 'ObservableAxis', 'SpatialWCS', 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] @@ -138,7 +137,7 @@ def product_type(self): eg. Chunk.product_type = ProductType('SCIENCE') Allowed values: - """ + str(ProductType.names()) + """ + """ + str(artifact.ProductType.names()) + """ """ @@ -146,10 +145,10 @@ def product_type(self): @product_type.setter def product_type(self, value): - if isinstance(value, str) and value in ProductType.names(): + if isinstance(value, str) and value in artifact.ProductType.names(): # be helpful - value = ProductType('value') - caom_util.type_check(value, ProductType, 'product_type') + value = artifact.ProductType('value') + caom_util.type_check(value, artifact.ProductType, 'product_type') self._product_type = value @property @@ -731,7 +730,7 @@ def transition(self): @transition.setter def transition(self, value): - caom_util.type_check(value, EnergyTransition, "transition") + caom_util.type_check(value, wcs.EnergyTransition, "transition") self._transition = value @property diff --git a/caom2/caom2/data/__init__.py b/caom2/caom2/data/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py index be614f82..3ab5c9dd 100644 --- a/caom2/caom2/observation.py +++ b/caom2/caom2/observation.py @@ -76,8 +76,8 @@ import caom_object import caom_util from enum import Enum -from plane import Plane -from shape import Point +import plane +import shape ObservationIntentType = Enum('ObservationIntentType', CALIBRATION="calibration", @@ -191,7 +191,7 @@ def __init__(self, self.requirements = requirements self.meta_release = meta_release if planes is None: - planes = caom_util.TypedOrderedDict(Plane,) + planes = caom_util.TypedOrderedDict(plane.Plane,) self.planes = planes # Properties @@ -1160,7 +1160,7 @@ def coordinates(self): @coordinates.setter def coordinates(self, value): - caom_util.type_check(value, Point, "coordinates") + caom_util.type_check(value, shape.Point, "coordinates") self._coordinates = value @property diff --git a/caom2/caom2/part.py b/caom2/caom2/part.py index 4050605d..b1f8fd1e 100644 --- a/caom2/caom2/part.py +++ b/caom2/caom2/part.py @@ -70,10 +70,10 @@ """Defines the caom2.Part class which describes the caom2_Observation_Plane_Artifact_Part object.""" +import artifact import caom_object import caom_util -from artifact import ProductType -from chunk import Chunk +import chunk __all__ = ['Part'] @@ -92,7 +92,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = caom_util.TypedList(Chunk, ) + chunks = caom_util.TypedList(chunk.Chunk, ) self.chunks = chunks def _key(self): @@ -116,7 +116,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - caom_util.type_check(value, ProductType, "product_type") + caom_util.type_check(value, artifact.ProductType, "product_type") self._product_type = value @property diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py index 1d1edf8f..1356ca57 100644 --- a/caom2/caom2/plane.py +++ b/caom2/caom2/plane.py @@ -73,13 +73,13 @@ from urlparse import SplitResult from urlparse import urlsplit +import artifact import caom_object import caom_util +import observation import shape import wcs -from artifact import Artifact from enum import Enum -from observation import ObservationURI CalibrationLevel = Enum('CalibrationLevel', RAW_INSTRUMENT=0, @@ -124,7 +124,7 @@ JUNK="junk") __all__ = ['Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', - 'Position', 'Energy', 'EnergyTransition', 'Polarization', 'Time'] + 'Position', 'Energy', 'Polarization', 'Time'] class Plane(caom_object.AbstractCaomEntity): @@ -148,7 +148,7 @@ def __init__(self, product_id, super(Plane, self).__init__() self.product_id = product_id if artifacts is None: - artifacts = caom_util.TypedOrderedDict(Artifact, ) + artifacts = caom_util.TypedOrderedDict(artifact.Artifact, ) self.artifacts = artifacts self.meta_release = meta_release @@ -438,13 +438,13 @@ def get_plane_uri(cls, observation_uri, product_id): observation_uri : the uri of the observation product_id : ID of the product """ - caom_util.type_check(observation_uri, ObservationURI, "observation_uri", + caom_util.type_check(observation_uri, observation.ObservationURI, "observation_uri", override=False) caom_util.type_check(product_id, str, "observation_uri", override=False) caom_util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path - uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + + uri = SplitResult(observation.ObservationURI._SCHEME, "", path + "/" + product_id, "", "").geturl() return cls(uri) @@ -460,7 +460,7 @@ def uri(self, value): caom_util.type_check(value, str, "uri", override=False) tmp = urlsplit(value) - if tmp.scheme != ObservationURI._SCHEME: + if tmp.scheme != observation.ObservationURI._SCHEME: raise ValueError("{} doesn't have an allowed scheme".format(value)) if tmp.geturl() != value: raise ValueError("Failed to parse uri correctly: {}".format(value)) @@ -473,7 +473,7 @@ def uri(self, value): self._product_id = product_id self._observation_uri = \ - ObservationURI.get_observation_uri(collection, observation_id) + observation.ObservationURI.get_observation_uri(collection, observation_id) self._uri = value @property @@ -917,38 +917,11 @@ def transition(self): @transition.setter def transition(self, value): if value is not None: - assert isinstance(value, EnergyTransition), ( + assert isinstance(value, wcs.EnergyTransition), ( "transition is not an EnergyTransition: {0}".format(value)) self._transition = value -class EnergyTransition(caom_object.CaomObject): - """ EnergyTransition """ - - def __init__(self, species, transition): - """ - Construct an EnergyTransition instance - - Arguments: - species - transition - """ - caom_util.type_check(species, str, "species", override=False) - caom_util.type_check(transition, str, "transition", override=False) - self._species = species - self._transition = transition - - @property - def species(self): - """ Species """ - return self._species - - @property - def transition(self): - """ Transition """ - return self._transition - - class Polarization(caom_object.CaomObject): """ Polarization """ diff --git a/caom2/caom2/test/caom_test_instances.py b/caom2/caom2/test/caom_test_instances.py index 2020cfbb..949f1bb5 100644 --- a/caom2/caom2/test/caom_test_instances.py +++ b/caom2/caom2/test/caom_test_instances.py @@ -350,7 +350,7 @@ def get_spectral_wcs(self): energy.velang = 5.0 energy.bandpassName = "energy bandpassName" energy.resolvingPower = 6.0 - energy.transition = plane.EnergyTransition("H", "21cm") + energy.transition = wcs.EnergyTransition("H", "21cm") return energy def get_temporal_wcs(self): diff --git a/caom2/caom2/test/test_chunk.py b/caom2/caom2/test/test_chunk.py index e311ff3a..78ccc796 100644 --- a/caom2/caom2/test/test_chunk.py +++ b/caom2/caom2/test/test_chunk.py @@ -264,7 +264,7 @@ def test_init(self): energy.bandpass_name = "bandpass_name" self.assertEqual(energy.bandpass_name, "bandpass_name") - transition = plane.EnergyTransition("species", "transition") + transition = wcs.EnergyTransition("species", "transition") energy.transition = transition self.assertEqual(energy.transition, transition) diff --git a/caom2/caom2/test/test_plane.py b/caom2/caom2/test/test_plane.py index 7c46c71a..e79739a9 100644 --- a/caom2/caom2/test/test_plane.py +++ b/caom2/caom2/test/test_plane.py @@ -75,6 +75,7 @@ from .. import artifact from .. import observation from .. import plane +from .. import wcs class TestEnums(unittest.TestCase): @@ -483,19 +484,19 @@ class TestEnergyTransition(unittest.TestCase): def test__init__(self): # test for invalid values - self.assertRaises(TypeError, plane.EnergyTransition, None, None) - self.assertRaises(TypeError, plane.EnergyTransition, 'aString', None) - self.assertRaises(TypeError, plane.EnergyTransition, None, 'aString') - self.assertRaises(TypeError, plane.EnergyTransition, 1, 'aString') - self.assertRaises(TypeError, plane.EnergyTransition, 'aString', 2) + self.assertRaises(TypeError, wcs.EnergyTransition, None, None) + self.assertRaises(TypeError, wcs.EnergyTransition, 'aString', None) + self.assertRaises(TypeError, wcs.EnergyTransition, None, 'aString') + self.assertRaises(TypeError, wcs.EnergyTransition, 1, 'aString') + self.assertRaises(TypeError, wcs.EnergyTransition, 'aString', 2) # test for happy path - transition = plane.EnergyTransition("aSpecies", "aTransition") + transition = wcs.EnergyTransition("aSpecies", "aTransition") self.assertEqual(transition._species, "aSpecies") self.assertEqual(transition._transition, "aTransition") def test_setters(self): # test that we cannot change the attribute values - transition = plane.EnergyTransition("aSpecies", "aTransition") + transition = wcs.EnergyTransition("aSpecies", "aTransition") try: transition.species = "newSpecies" transition.transition = "newTransition" diff --git a/caom2/caom2/wcs.py b/caom2/caom2/wcs.py index d731cee5..dd0b690c 100644 --- a/caom2/caom2/wcs.py +++ b/caom2/caom2/wcs.py @@ -73,7 +73,7 @@ __all__ = ['Axis', 'Coord2D', 'CoordAxis1D', 'CoordAxis2D', 'CoordBounds1D', 'CoordBounds2D', 'CoordCircle2D', 'CoordError', 'CoordFunction1D', 'CoordFunction2D', 'CoordPolygon2D', 'CoordRange1D', 'CoordRange2D', - 'Dimension2D', 'RefCoord', 'Slice', 'ValueCoord2D'] + 'Dimension2D', 'EnergyTransition', 'RefCoord', 'Slice', 'ValueCoord2D'] class Axis(caom_object.CaomObject): @@ -856,6 +856,33 @@ def naxis2(self, value): self._naxis2 = value +class EnergyTransition(caom_object.CaomObject): + """ EnergyTransition """ + + def __init__(self, species, transition): + """ + Construct an EnergyTransition instance + + Arguments: + species + transition + """ + caom_util.type_check(species, str, "species", override=False) + caom_util.type_check(transition, str, "transition", override=False) + self._species = species + self._transition = transition + + @property + def species(self): + """ Species """ + return self._species + + @property + def transition(self): + """ Transition """ + return self._transition + + class RefCoord(caom_object.CaomObject): """A refernce coordinate object, maps pixel value to wcs value From f77232e9416e1bb50f5079aaef910d622afbf77d Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Thu, 24 Nov 2016 14:28:13 -0800 Subject: [PATCH 35/54] s1950: added imports to init.py --- caom2/caom2/__init__.py | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 8825a50f..8198aaa4 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -84,13 +84,13 @@ # if not _ASTROPY_SETUP_: # from .caom2 import * -# from artifact import * -# from caom_object import * -# from caom_util import * -# from chunk import * -# from obs_reader_writer import * -# from observation import * -# from part import * -# from plane import * -# from shape import * -# from wcs import * +from artifact import * +from caom_object import * +from caom_util import * +from chunk import * +from obs_reader_writer import * +from observation import * +from part import * +from plane import * +from shape import * +from wcs import * From 8aa9faabedf9ca639327162ccef0f30761a1810a Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Fri, 25 Nov 2016 09:29:29 -0800 Subject: [PATCH 36/54] s1950: fix xml reader/writer tests --- caom2/caom2/obs_reader_writer.py | 20 ++++++++----- caom2/caom2/test/test_obs_reader_writer.py | 35 +++++----------------- 2 files changed, 21 insertions(+), 34 deletions(-) diff --git a/caom2/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py index 60955c35..05ab397d 100644 --- a/caom2/caom2/obs_reader_writer.py +++ b/caom2/caom2/obs_reader_writer.py @@ -69,9 +69,9 @@ """ Defines ObservationReader class """ +import os import uuid -import pkg_resources from lxml import etree import artifact @@ -83,7 +83,7 @@ import shape import wcs -DATA_PKG = 'caom2.data' +DATA_PKG = 'data' CAOM20_SCHEMA_FILE = 'CAOM-2.0.xsd' CAOM21_SCHEMA_FILE = 'CAOM-2.1.xsd' @@ -100,6 +100,8 @@ XSI_NAMESPACE = "http://www.w3.org/2001/XMLSchema-instance" XSI = "{%s}" % XSI_NAMESPACE +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + __all__ = ['ObservationReader', 'ObservationWriter', 'ObservationParsingException'] @@ -117,8 +119,10 @@ def __init__(self, valididate=False): self._validate = valididate if self._validate: - caom20_schema_path = pkg_resources.resource_filename( - DATA_PKG, CAOM20_SCHEMA_FILE) + # caom20_schema_path = pkg_resources.resource_filename( + # DATA_PKG, CAOM20_SCHEMA_FILE) + caom20_schema_path = os.path.join(THIS_DIR + '/' + DATA_PKG, + CAOM20_SCHEMA_FILE) parser = etree.XMLParser(remove_blank_text=True) xsd = etree.parse(caom20_schema_path, parser) @@ -1039,7 +1043,7 @@ def _get_transition(self, element_tag, parent, ns, required): if el is None: return None else: - return plane.EnergyTransition( + return wcs.EnergyTransition( self._get_child_text("species", el, ns, True), self._get_child_text("transition", el, ns, True)) @@ -1399,8 +1403,10 @@ def __init__(self, validate=False, write_empty_collections=False, schema_file = CAOM21_SCHEMA_FILE else: schema_file = CAOM22_SCHEMA_FILE - schema_path = pkg_resources.resource_filename( - DATA_PKG, schema_file) + schema_path = os.path.join(THIS_DIR + '/' + DATA_PKG, + schema_file) + # schema_path = pkg_resources.resource_filename( + # DATA_PKG, schema_file) xmlschema_doc = etree.parse(schema_path) self._xmlschema = etree.XMLSchema(xmlschema_doc) diff --git a/caom2/caom2/test/test_obs_reader_writer.py b/caom2/caom2/test/test_obs_reader_writer.py index 82385f46..c9d5563c 100644 --- a/caom2/caom2/test/test_obs_reader_writer.py +++ b/caom2/caom2/test/test_obs_reader_writer.py @@ -73,7 +73,6 @@ import os import unittest -import pkg_resources from lxml import etree from xml_compare import xml_compare @@ -82,6 +81,8 @@ from .. import observation from .. import wcs +THIS_DIR = os.path.dirname(os.path.realpath(__file__)) + def minimal_simple(depth, bounds_is_circle, version): instances = caom_test_instances.Caom2TestInstances() @@ -827,38 +828,18 @@ def compare_point(self, expected, actual): class TestRoundTrip(unittest.TestCase): - TEST_PACKAGE = 'caom2.test' - TEST_DATA_PACKAGE = 'caom2.test.data' - TEST_DATA_DIR = 'data' - # XML_FILE_SOURCE_DIR = '/tmp/caom2-round-trip-test' - # XML_FILE_DEST_DIR = '/tmp/caom2-round-trip-test/caom2' - - # def make_test_dir(self): - # try: - # os.makedirs(TestRoundTrip.XML_FILE_SOURCE_DIR) - # except OSError as exception: - # if exception.errno != errno.EEXIST: - # raise - # - # def copy_files(self): - # file_list = pkg_resources.resource_listdir("caom2.test", "data") - # for filename in file_list: - # if filename.endswith(".xml"): - # the_file = pkg_resources.resource_stream("caom2.test.data", filename) - # shutil.copy(the_file.name, TestRoundTrip.XML_FILE_SOURCE_DIR) + TEST_DATA = 'data' def init(self): pass def get_file_list(self): - file_list = pkg_resources.resource_listdir(TestRoundTrip.TEST_PACKAGE, - TestRoundTrip.TEST_DATA_DIR) - return [f for f in file_list if f.endswith('.xml')] + return [f for f in os.listdir(THIS_DIR + "/" + TestRoundTrip.TEST_DATA) + if f.endswith('.xml')] def do_test(self, reader, writer, filename): - source_file = pkg_resources.resource_stream(TestRoundTrip.TEST_DATA_PACKAGE, filename) - source_file_path = os.path.abspath(source_file.name) - print "test file: " + source_file_path + source_file_path = os.path.join(THIS_DIR + "/" + + TestRoundTrip.TEST_DATA + "/" + filename) source_xml_fp = open(source_file_path, 'r') obs = reader.read(source_file_path) source_xml_fp.close() @@ -898,5 +879,5 @@ def test_round_trip(self): else: self.do_test(reader, writer20, filename) - except Exception as e: + except Exception: raise From 9ac8c974096d4bb1ce04326358214b4316b0f91e Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Fri, 25 Nov 2016 13:25:40 -0800 Subject: [PATCH 37/54] s1950: changed test directory to tests, added Python 3 checking, switched to using standard Enum class --- caom2/caom2/__init__.py | 31 +- caom2/caom2/artifact.py | 34 ++- caom2/caom2/caom_object.py | 5 +- caom2/caom2/caom_util.py | 3 + caom2/caom2/chunk.py | 54 +++- caom2/caom2/enum.py | 267 ------------------ caom2/caom2/obs_reader_writer.py | 39 +-- caom2/caom2/observation.py | 58 +++- caom2/caom2/part.py | 12 +- caom2/caom2/plane.py | 201 +++++++++---- caom2/caom2/shape.py | 23 +- caom2/caom2/test/data/__init__.py | 0 caom2/caom2/{test => tests}/__init__.py | 0 .../{test => tests}/caom_test_instances.py | 9 +- caom2/caom2/tests/coveragerc | 31 ++ .../data/CompleteCompositeCircle-CAOM-2.1.xml | 0 .../data/CompleteCompositeCircle-CAOM-2.2.xml | 0 .../data/CompleteCompositeCircle.xml | 0 .../CompleteCompositePolygon-CAOM-2.1.xml | 0 .../CompleteCompositePolygon-CAOM-2.2.xml | 0 .../data/CompleteCompositePolygon.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.1.xml | 0 .../data/CompleteSimpleCircle-CAOM-2.2.xml | 0 .../data/CompleteSimpleCircle.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.1.xml | 0 .../data/CompleteSimplePolygon-CAOM-2.2.xml | 0 .../data/CompleteSimplePolygon.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.1.xml | 0 .../data/MinimalCompositeCircle-CAOM-2.2.xml | 0 .../data/MinimalCompositeCircle.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.1.xml | 0 .../data/MinimalCompositePolygon-CAOM-2.2.xml | 0 .../data/MinimalCompositePolygon.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.1.xml | 0 .../data/MinimalSimpleCircle-CAOM-2.2.xml | 0 .../data/MinimalSimpleCircle.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.1.xml | 0 .../data/MinimalSimplePolygon-CAOM-2.2.xml | 0 .../data/MinimalSimplePolygon.xml | 0 caom2/caom2/tests/setup_package.py | 7 + caom2/caom2/{test => tests}/test_artifact.py | 35 +-- .../caom2/{test => tests}/test_caom_object.py | 23 +- caom2/caom2/{test => tests}/test_caom_util.py | 10 +- caom2/caom2/{test => tests}/test_chunk.py | 40 ++- .../{test => tests}/test_obs_reader_writer.py | 15 +- .../caom2/{test => tests}/test_observation.py | 3 + caom2/caom2/{test => tests}/test_part.py | 8 +- caom2/caom2/{test => tests}/test_plane.py | 10 +- caom2/caom2/{test => tests}/test_shape.py | 3 + caom2/caom2/{test => tests}/test_wcs.py | 4 +- caom2/caom2/wcs.py | 6 +- caom2/setup.py | 2 +- 52 files changed, 461 insertions(+), 472 deletions(-) delete mode 100644 caom2/caom2/enum.py delete mode 100644 caom2/caom2/test/data/__init__.py rename caom2/caom2/{test => tests}/__init__.py (100%) rename caom2/caom2/{test => tests}/caom_test_instances.py (98%) create mode 100644 caom2/caom2/tests/coveragerc rename caom2/caom2/{test => tests}/data/CompleteCompositeCircle-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteCompositeCircle-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteCompositeCircle.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteCompositePolygon-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteCompositePolygon-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteCompositePolygon.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimpleCircle-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimpleCircle-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimpleCircle.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimplePolygon-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimplePolygon-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/CompleteSimplePolygon.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositeCircle-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositeCircle-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositeCircle.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositePolygon-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositePolygon-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalCompositePolygon.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimpleCircle-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimpleCircle-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimpleCircle.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimplePolygon-CAOM-2.1.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimplePolygon-CAOM-2.2.xml (100%) rename caom2/caom2/{test => tests}/data/MinimalSimplePolygon.xml (100%) create mode 100644 caom2/caom2/tests/setup_package.py rename caom2/caom2/{test => tests}/test_artifact.py (81%) rename caom2/caom2/{test => tests}/test_caom_object.py (88%) rename caom2/caom2/{test => tests}/test_caom_util.py (98%) rename caom2/caom2/{test => tests}/test_chunk.py (87%) rename caom2/caom2/{test => tests}/test_obs_reader_writer.py (98%) rename caom2/caom2/{test => tests}/test_observation.py (99%) rename caom2/caom2/{test => tests}/test_part.py (94%) rename caom2/caom2/{test => tests}/test_plane.py (98%) rename caom2/caom2/{test => tests}/test_shape.py (97%) rename caom2/caom2/{test => tests}/test_wcs.py (99%) diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 8198aaa4..58c1bfe9 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -84,13 +84,24 @@ # if not _ASTROPY_SETUP_: # from .caom2 import * -from artifact import * -from caom_object import * -from caom_util import * -from chunk import * -from obs_reader_writer import * -from observation import * -from part import * -from plane import * -from shape import * -from wcs import * +# from caom_util import * +# from caom_object import * +# from wcs import * +# from shape import * +# from chunk import * +# from part import * +# from artifact import * +# from plane import * +# from observation import * +# from obs_reader_writer import * + +# from obs_reader_writer import * +# from observation import * +# from plane import * +# from artifact import * +# from part import * +# from chunk import * +# from shape import * +# from wcs import * +# from caom_object import * +# from caom_util import * diff --git a/caom2/caom2/artifact.py b/caom2/caom2/artifact.py index 4ad75b29..bbd9d84a 100644 --- a/caom2/caom2/artifact.py +++ b/caom2/caom2/artifact.py @@ -71,29 +71,27 @@ """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + from urlparse import urlparse -import caom_object -import caom_util -import part from enum import Enum +from . import caom_object +from . import caom_util +from . import chunk +from . import part -ProductType = Enum('ProductType', - SCIENCE="science", - CALIBRATION="calibration", - PREVIEW="preview", - INFO="info", - NOISE="noise", - WEIGHT="weight", - AUXILIARY="auxiliary", - THUMBNAIL="thumbnail", - ) +__all__ = ['ReleaseType', 'Artifact'] -ReleaseType = Enum('ReleaseType', - DATA="data", - META="meta") -__all__ = ['Artifact'] +class ReleaseType(Enum): + """" + DATA: "data" + META: "meta" + """ + DATA = "data" + META = "meta" class Artifact(caom_object.AbstractCaomEntity): @@ -181,7 +179,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - caom_util.type_check(value, ProductType, "product_type", False) + caom_util.type_check(value, chunk.ProductType, "product_type", False) self._product_type = value @property diff --git a/caom2/caom2/caom_object.py b/caom2/caom2/caom_object.py index eda025f0..24f0a4b3 100644 --- a/caom2/caom2/caom_object.py +++ b/caom2/caom2/caom_object.py @@ -67,6 +67,8 @@ # *********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) import inspect import random @@ -74,7 +76,8 @@ import uuid from datetime import datetime -import caom_util +from . import caom_util + __all__ = ['CaomObject', 'AbstractCaomEntity'] diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index c93936bd..600ae7f9 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -76,6 +76,9 @@ engineer get the correct meta data more quickly. """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import collections import struct import sys diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py index b0e5de83..5d8e877e 100644 --- a/caom2/caom2/chunk.py +++ b/caom2/caom2/chunk.py @@ -71,12 +71,48 @@ """ -import artifact -import caom_object -import caom_util -import wcs +from __future__ import (absolute_import, division, print_function, + unicode_literals) -__all__ = ['Chunk', 'ObservableAxis', 'SpatialWCS', 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] +from enum import Enum +from . import caom_object +from . import caom_util +from . import wcs + + +class ProductType(Enum): + """ + SCIENCE: "science" + CALIBRATION: "calibration" + PREVIEW: "preview" + INFO: "info" + NOISE: "noise" + WEIGHT: "weight" + AUXILIARY: "auxiliary" + THUMBNAIL: "thumbnail" + """ + SCIENCE = "science" + CALIBRATION = "calibration" + PREVIEW = "preview" + INFO = "info" + NOISE = "noise" + WEIGHT = "weight" + AUXILIARY = "auxiliary" + THUMBNAIL = "thumbnail" + +# ProductType = Enum('ProductType', +# SCIENCE="science", +# CALIBRATION="calibration", +# PREVIEW="preview", +# INFO="info", +# NOISE="noise", +# WEIGHT="weight", +# AUXILIARY="auxiliary", +# THUMBNAIL="thumbnail", +# ) + +__all__ = ['ProductType', 'Chunk', 'ObservableAxis', 'SpatialWCS', + 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] class Chunk(caom_object.AbstractCaomEntity): @@ -137,7 +173,7 @@ def product_type(self): eg. Chunk.product_type = ProductType('SCIENCE') Allowed values: - """ + str(artifact.ProductType.names()) + """ + """ + str(ProductType.names()) + """ """ @@ -145,10 +181,10 @@ def product_type(self): @product_type.setter def product_type(self, value): - if isinstance(value, str) and value in artifact.ProductType.names(): + if isinstance(value, str) and value in ProductType.names(): # be helpful - value = artifact.ProductType('value') - caom_util.type_check(value, artifact.ProductType, 'product_type') + value = ProductType('value') + caom_util.type_check(value, ProductType, 'product_type') self._product_type = value @property diff --git a/caom2/caom2/enum.py b/caom2/caom2/enum.py deleted file mode 100644 index 652c700d..00000000 --- a/caom2/caom2/enum.py +++ /dev/null @@ -1,267 +0,0 @@ -#!/usr/bin/env python - -""" -Copyright (C) 2011 Cameron Hayne (macdev@hayne.net) -This is published under the MIT Licence: ----------------------------------------- -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. -""" - -from operator import attrgetter - - -class EnumClass(object): - """ - EnumClass is the superclass of all enum classes created by - the 'Enum' function below. - Each such subclass represents a set of named values. - """ - - def __new__(cls, name, value=None): - # I presume that 'value' is an immutable object - # but not sure how to enforce this - existingObj = cls.get(name) - if existingObj: - if value is None or value == existingObj.value: - return existingObj - else: - raise TypeError("can't overwrite an existing enum") - else: - if value is None: # e.g. MyEnumType('foo') - existingNames = cls.names() - if existingNames: - # probably trying to refer to an existing enum object - # but got the name wrong - raise ValueError(("'%s' is not a valid enum name" - + " (Must be one of: %s)") - % (name, str(existingNames))) - else: - # probably trying to create an enum object - # without specifying a value, just a name - raise ValueError("must supply value for enum") - # create a new instance of 'cls' - obj = super(EnumClass, cls).__new__(cls) - # and assign 'name' & 'value' (via the superclass) - super(EnumClass, obj).__setattr__('name', name) - super(EnumClass, obj).__setattr__('value', value) - # assign 'obj' as a class attribute for 'name' in 'cls' - setattr(cls, name, obj) - return obj - - def __copy__(self): - return self - - def __deepcopy__(self, memo): - # I presume that the 'value' is not a mutable object - return self - - def __setattr__(self, name, value): - raise TypeError("can't modify an enum") - - def __delattr__(self, name): - raise TypeError("can't modify an enum") - - # no need for __cmp__ or __hash__ since above methods ensure immutability - - def __str__(self): - return self.name - - def __list__(self): - return self.names() - - @classmethod - def addAlias(cls, name, existingName): - """ - Add 'name' as an alias for 'existingName'. - 'name' is a string. - 'existingName' is the name of one of the existing enum objects. - This is intended as a way to maintain backward compatibility - when the enum names get changed. - Example of use: - Vehicles.addAlias('horselessCarriage', 'car') - # Now old code referring to Vehicles.horselessCarriage - # will get the same object as Vehicles.car - # i.e. Vehicles.horselessCarriage.name is 'car' - # But Vehicles.names() does not include 'horselessCarriage' - """ - existingNames = cls.names() - if name in existingNames: - raise ValueError("The name '%s' is already in use." % name) - if existingName not in existingNames: - raise ValueError(("'%s' is not one of the existing enum names." - + " (Must be one of: %s)") - % (existingName, str(existingNames))) - existingObj = cls.get(existingName) - setattr(cls, name, existingObj) - - @classmethod - def get(cls, name): - """ - Return the enum instance with the specified name. - Return None if there is no such instance. - """ - return getattr(cls, name.strip(), None) - - @classmethod - def getByValue(cls, value): - """ - Return an enum instance that has the specified value. - Return None if there is no such instance. - Note that there may be more than one enum instance with the same value - and in that case this method returns whichever one it finds first. - """ - for obj in cls.objects(): - if obj.value == value: - return obj - return None - - @classmethod - def listOfNamesToListOfEnums(cls, listOfNames): - """ - Convert a list of strings (names of enums of this class) - into a list of enum instances. - Example of use: - listOfNames = ['red', 'blue'] - listOfEnums = Colours.listOfNamesToListOfEnums(listOfNames) - # would give [Colours.red, Colours.blue] - """ - listOfEnums = [cls(name) for name in listOfNames] - return listOfEnums - - @classmethod - def commaSepStrToEnumList(cls, commaSepNamesStr): - enumList = list() - commaSepNamesStr = commaSepNamesStr.lstrip('[ ') - commaSepNamesStr = commaSepNamesStr.rstrip(' ]') - names = commaSepNamesStr.split(',') - for name in names: - name = name.strip() - enumObj = cls.get(name) - if enumObj is not None: - enumList.append(enumObj) - return enumList - - @classmethod - def objects(cls): - objs = set() # need to use set since might have aliases - for obj in cls.__dict__.values(): - if isinstance(obj, cls): - objs.add(obj) - objList = sorted(objs, key=attrgetter('value')) - return objList - - @classmethod - def names(cls): - objList = cls.objects() - nameList = [obj.name for obj in objList] - return nameList -# ----------------------------------------------------------------------------- - - -def Enum(classname, **kargs): - """ - Create a new class named as specifed in the first argument, - and then create instances of this class with the name/value pairs of - the subsequent (keyword) arguments. - Return the newly created class object. - The values can be anything (not necessarily integers) - but should be immutable objects (e.g. shouldn't be a list). - Examples of use: - >>> Colours = Enum('Colours', red=1, green=2, blue=3) - >>> Colours.green.name - 'green' - - >>> print Colours.green - green - - >>> Colours.green.value - 2 - - >>> Colours.names() - ['red', 'green', 'blue'] - - >>> Colours.get('blue').value - 3 - - >>> Colours.getByValue(3).name - 'blue' - - >>> Colours('blue').value - 3 - - >>> Colours.addAlias('bleu', 'blue') - >>> Colours.names() - ['red', 'green', 'blue'] - - >>> Colours.bleu.value - 3 - - >>> [x.name for x in Colours.objects()] - ['red', 'green', 'blue'] - - >>> listOfNames = ['red', 'blue'] - >>> [x.name for x in Colours.listOfNamesToListOfEnums(listOfNames)] - ['red', 'blue'] - - >>> commaSepStr = "red, blue" - >>> [x.name for x in Colours.commaSepStrToEnumList(commaSepStr)] - ['red', 'blue'] - - - >>> Numbers = Enum('Numbers', pi=3.1415926, e=2.71828) - >>> isinstance(Numbers, type) - True - - >>> Numbers.names() - ['e', 'pi'] - - >>> round(Numbers.e.value, 3) - 2.718 - - >>> x = Numbers.pi - >>> x is Numbers('pi') - True - - >>> Numbers('phi') - Traceback (most recent call last): - ... - ValueError: 'phi' is not a valid enum name \ - (Must be one of: ['e', 'pi']) - - - >>> Numbers.e.value = 42 - Traceback (most recent call last): - ... - TypeError: can't modify an enum - """ - - # create a new class derived from EnumClass - cls = type(classname, (EnumClass,), dict()) - for name in kargs.keys(): - # create an instance of 'cls' for each keyword arg - obj = cls(name, kargs[name]) - # return the newly created class to the caller - return cls - -# ----------------------------------------------------------------------------- -# ----------------------------------------------------------------------------- - -if __name__ == "__main__": - import doctest - doctest.testmod() diff --git a/caom2/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py index 05ab397d..e056f926 100644 --- a/caom2/caom2/obs_reader_writer.py +++ b/caom2/caom2/obs_reader_writer.py @@ -69,19 +69,22 @@ """ Defines ObservationReader class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import os import uuid from lxml import etree -import artifact -import caom_util -import chunk -import observation -import part -import plane -import shape -import wcs +from . import artifact +from . import caom_util +from . import chunk +from . import observation +from . import part +from . import plane +from . import shape +from . import wcs DATA_PKG = 'data' @@ -1160,7 +1163,7 @@ def _add_chunks(self, chunks, parent, ns): self._get_child_text("productType", chunk_element, ns, False) if product_type: _chunk.product_type = \ - artifact.ProductType.getByValue(product_type) + chunk.ProductType.getByValue(product_type) _chunk.naxis = \ self._get_child_text_as_int("naxis", chunk_element, ns, False) _chunk.observable_axis = \ @@ -1214,7 +1217,7 @@ def _add_parts(self, parts, parent, ns): self._get_child_text("productType", part_element, ns, False) if product_type: _part.product_type = \ - artifact.ProductType.getByValue(product_type) + chunk.ProductType.getByValue(product_type) self._add_chunks(_part.chunks, part_element, ns) self._set_entity_attributes(part_element, ns, _part) parts[_part.name] = _part @@ -1238,15 +1241,15 @@ def _add_artifacts(self, artifacts, parent, ns): product_type = self._get_child_text("productType", artifact_element, ns, False) if product_type is None: - product_type = artifact.ProductType.SCIENCE - print "Using default Artifact.productType value {0}".format(str(artifact.ProductType.SCIENCE)) + product_type = chunk.ProductType.SCIENCE + print("Using default Artifact.productType value {0}".format(str(chunk.ProductType.SCIENCE))) else: - product_type = artifact.ProductType.getByValue(product_type) + product_type = chunk.ProductType.getByValue(product_type) release_type = self._get_child_text("releaseType", artifact_element, ns, False) if release_type is None: release_type = artifact.ReleaseType.DATA - print "Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA)) + print("Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA))) else: release_type = artifact.ReleaseType.getByValue(release_type) @@ -1647,14 +1650,14 @@ def _add_artifacts_element(self, artifacts, parent): self._add_enity_attributes(_artifact, artifact_element) self._add_element("uri", _artifact.uri, artifact_element) if self._output_version > 21: - self._add_element("productType", artifact.ProductType.get( + self._add_element("productType", chunk.ProductType.get( str(_artifact.product_type)).value, artifact_element) self._add_element("releaseType", artifact.ReleaseType.get( str(_artifact.release_type)).value, artifact_element) self._add_element("contentType", _artifact.content_type, artifact_element) self._add_element("contentLength", _artifact.content_length, artifact_element) if self._output_version < 22: - self._add_element("productType", artifact.ProductType.get( + self._add_element("productType", chunk.ProductType.get( str(_artifact.product_type)).value, artifact_element) self._add_parts_element(_artifact.parts, artifact_element) @@ -1668,7 +1671,7 @@ def _add_parts_element(self, parts, parent): self._add_enity_attributes(_part, part_element) self._add_element("name", _part.name, part_element) if _part.product_type is not None: - self._add_element("productType", artifact.ProductType.get( + self._add_element("productType", chunk.ProductType.get( str(_part.product_type)).value, part_element) self._add_chunks_element(_part.chunks, part_element) @@ -1682,7 +1685,7 @@ def _add_chunks_element(self, chunks, parent): self._add_enity_attributes(_chunk, chunk_element) if _chunk.product_type is not None: self._add_element("productType", - artifact.ProductType.get(str(_chunk.product_type)).value, + chunk.ProductType.get(str(_chunk.product_type)).value, chunk_element) self._add_element("naxis", _chunk.naxis, chunk_element) self._add_element("observableAxis", _chunk.observable_axis, diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py index 3ab5c9dd..514839a8 100644 --- a/caom2/caom2/observation.py +++ b/caom2/caom2/observation.py @@ -69,32 +69,62 @@ """definition of the caom2.Observation object.""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + from datetime import datetime from urlparse import SplitResult from urlparse import urlsplit -import caom_object -import caom_util from enum import Enum -import plane -import shape +from . import caom_object +from . import caom_util +# from . import plane +from .plane import Plane +from . import shape -ObservationIntentType = Enum('ObservationIntentType', - CALIBRATION="calibration", - SCIENCE="science") +# ObservationIntentType = Enum('ObservationIntentType', +# CALIBRATION="calibration", +# SCIENCE="science") -Status = Enum('Status', - FAIL="fail") +# Status = Enum('Status', +# FAIL="fail") -TargetType = Enum('TargetType', - FIELD="field", - OBJECT="object") +# TargetType = Enum('TargetType', +# FIELD="field", +# OBJECT="object") -__all__ = ['Observation', 'ObservationURI', 'Algorithm', 'SimpleObservation', +__all__ = ['ObservationIntentType', 'Status', 'TargetType', + 'Observation', 'ObservationURI', 'Algorithm', 'SimpleObservation', 'CompositeObservation', 'Environment', 'Instrument', 'Proposal', 'Requirements', 'Target', 'TargetPosition', 'Telescope'] +class ObservationIntentType(Enum): + """ + CALIBRATION: "calibration" + SCIENCE: "science" + """ + CALIBRATION = "calibration" + SCIENCE = "science" + + +class Status(Enum): + """ + FAIL: "fail" + """ + FAIL = "fail" + + +class TargetType(Enum): + """ + FIELD: "field", + OBJECT: "object" + """ + FIELD = "field" + OBJECT = "object" + + class Observation(caom_object.AbstractCaomEntity): """ Observation @@ -191,7 +221,7 @@ def __init__(self, self.requirements = requirements self.meta_release = meta_release if planes is None: - planes = caom_util.TypedOrderedDict(plane.Plane,) + planes = caom_util.TypedOrderedDict(Plane,) self.planes = planes # Properties diff --git a/caom2/caom2/part.py b/caom2/caom2/part.py index b1f8fd1e..b5477755 100644 --- a/caom2/caom2/part.py +++ b/caom2/caom2/part.py @@ -70,10 +70,12 @@ """Defines the caom2.Part class which describes the caom2_Observation_Plane_Artifact_Part object.""" -import artifact -import caom_object -import caom_util -import chunk +from __future__ import (absolute_import, division, print_function, + unicode_literals) + +from . import caom_object +from . import caom_util +from . import chunk __all__ = ['Part'] @@ -116,7 +118,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - caom_util.type_check(value, artifact.ProductType, "product_type") + caom_util.type_check(value, chunk.ProductType, "product_type") self._product_type = value @property diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py index 1356ca57..c84577de 100644 --- a/caom2/caom2/plane.py +++ b/caom2/caom2/plane.py @@ -69,62 +69,155 @@ """defines the caom2.Plane class""" +from __future__ import (absolute_import, division, print_function, + unicode_literals) + from datetime import datetime from urlparse import SplitResult from urlparse import urlsplit -import artifact -import caom_object -import caom_util -import observation -import shape -import wcs from enum import Enum +from . import artifact +from . import caom_object +from . import caom_util +# from . import observation +from .observation import ObservationURI +from . import shape +from . import wcs + +# CalibrationLevel = Enum('CalibrationLevel', +# RAW_INSTRUMENT=0, +# RAW_STANDARD=1, +# CALIBRATED=2, +# PRODUCT=3) + +# DataProductType = Enum('DataProductType', +# IMAGE="image", +# CATALOG="catalog", +# CUBE="cube", +# EVENTLIST="eventlist", +# SPECTRUM="spectrum", +# TIMESERIES="timeseries", +# VISIBILITY="visibility") + +# EnergyBand = Enum('EnergyBand', +# EUV="EUV", +# GAMMARAY="Gamma-ray", +# INFRARED="Infrared", +# MILLIMETER="Millimeter", +# OPTICAL="Optical", +# RADIO="Radio", +# UV="UV", +# XRAY="X-ray") + +# PolarizationState = Enum('PolarizationState', +# I="I", +# Q="Q", +# U="U", +# V="V", +# LL="LL", +# LR="LR", +# RL="RL", +# RR="RR", +# XX="XX", +# XY="XY", +# YX="YX", +# YY="YY") + +# Quality = Enum('Quality', +# JUNK="junk") + +__all__ = ['CalibrationLevel', 'DataProductType', 'EnergyBand', "PolarizationState", "Quality", + 'Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', 'Position', 'Energy', + 'Polarization', 'Time'] + + +class CalibrationLevel(Enum): + """ + RAW_INSTRUMENT: 0 + RAW_STANDARD: 1 + CALIBRATED: 2 + PRODUCT: 3 + """ + RAW_INSTRUMENT = 0 + RAW_STANDARD = 1 + CALIBRATED = 2 + PRODUCT = 3 + + +class DataProductType(Enum): + """ + IMAGE: "image" + CATALOG: "catalog" + CUBE: "cube" + EVENTLIST: "eventlist" + SPECTRUM: "spectrum" + TIMESERIES: "timeseries" + VISIBILITY: "visibility" + """ + IMAGE = "image" + CATALOG = "catalog" + CUBE = "cube" + EVENTLIST = "eventlist" + SPECTRUM = "spectrum" + TIMESERIES = "timeseries" + VISIBILITY = "visibility" + -CalibrationLevel = Enum('CalibrationLevel', - RAW_INSTRUMENT=0, - RAW_STANDARD=1, - CALIBRATED=2, - PRODUCT=3) - -DataProductType = Enum('DataProductType', - IMAGE="image", - CATALOG="catalog", - CUBE="cube", - EVENTLIST="eventlist", - SPECTRUM="spectrum", - TIMESERIES="timeseries", - VISIBILITY="visibility") - -EnergyBand = Enum('EnergyBand', - EUV="EUV", - GAMMARAY="Gamma-ray", - INFRARED="Infrared", - MILLIMETER="Millimeter", - OPTICAL="Optical", - RADIO="Radio", - UV="UV", - XRAY="X-ray") - -PolarizationState = Enum('PolarizationState', - I="I", - Q="Q", - U="U", - V="V", - LL="LL", - LR="LR", - RL="RL", - RR="RR", - XX="XX", - XY="XY", - YX="YX", - YY="YY") - -Quality = Enum('Quality', - JUNK="junk") - -__all__ = ['Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', - 'Position', 'Energy', 'Polarization', 'Time'] +class EnergyBand(Enum): + """ + GAMMARAY: "Gamma-ray" + INFRARED: "Infrared" + MILLIMETER: "Millimeter" + OPTICAL: "Optical" + RADIO: "Radio" + UV: "UV" + XRAY: "X-ray" + """ + EUV = "EUV" + GAMMARAY = "Gamma-ray" + INFRARED = "Infrared" + MILLIMETER = "Millimeter" + OPTICAL = "Optical" + RADIO = "Radio" + UV = "UV" + XRAY = "X-ray" + + +class PolarizationState(Enum): + """ + I: "I" + Q: "Q" + U: "U" + V: "V" + LL: "LL" + LR: "LR" + RL: "RL" + RR: "RR" + XX: "XX" + XY: "XY" + YX: "YX" + YY: "YY" + """ + I = "I" + Q = "Q" + U = "U" + V = "V" + LL = "LL" + LR = "LR" + RL = "RL" + RR = "RR" + XX = "XX" + XY = "XY" + YX = "YX" + YY = "YY" + + +class Quality(Enum): + """ + JUNK: junk + """ + JUNK = "junk" class Plane(caom_object.AbstractCaomEntity): @@ -438,13 +531,13 @@ def get_plane_uri(cls, observation_uri, product_id): observation_uri : the uri of the observation product_id : ID of the product """ - caom_util.type_check(observation_uri, observation.ObservationURI, "observation_uri", + caom_util.type_check(observation_uri, ObservationURI, "observation_uri", override=False) caom_util.type_check(product_id, str, "observation_uri", override=False) caom_util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path - uri = SplitResult(observation.ObservationURI._SCHEME, "", path + "/" + + uri = SplitResult(ObservationURI._SCHEME, "", path + "/" + product_id, "", "").geturl() return cls(uri) @@ -460,7 +553,7 @@ def uri(self, value): caom_util.type_check(value, str, "uri", override=False) tmp = urlsplit(value) - if tmp.scheme != observation.ObservationURI._SCHEME: + if tmp.scheme != ObservationURI._SCHEME: raise ValueError("{} doesn't have an allowed scheme".format(value)) if tmp.geturl() != value: raise ValueError("Failed to parse uri correctly: {}".format(value)) @@ -473,7 +566,7 @@ def uri(self, value): self._product_id = product_id self._observation_uri = \ - observation.ObservationURI.get_observation_uri(collection, observation_id) + ObservationURI.get_observation_uri(collection, observation_id) self._uri = value @property diff --git a/caom2/caom2/shape.py b/caom2/caom2/shape.py index 13d225eb..b553cf44 100644 --- a/caom2/caom2/shape.py +++ b/caom2/caom2/shape.py @@ -67,16 +67,25 @@ # *********************************************************************** # -import caom_object -import caom_util +from __future__ import (absolute_import, division, print_function, + unicode_literals) + from enum import Enum +from . import caom_object +from . import caom_util + +__all__ = ['SegmentType', 'Box', 'Circle', 'Interval', 'Point', 'Polygon', 'Vertex'] -SegmentType = Enum('SegmentType', - CLOSE=0, - LINE=1, - MOVE=2) -__all__ = ['Box', 'Circle', 'Interval', 'Point', 'Polygon', 'Vertex'] +class SegmentType(Enum): + """ + CLOSE: 0 + LINE: 1 + MOVE: 2 + """ + CLOSE = 0 + LINE = 1 + MOVE = 2 class Box(caom_object.CaomObject): diff --git a/caom2/caom2/test/data/__init__.py b/caom2/caom2/test/data/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/caom2/caom2/test/__init__.py b/caom2/caom2/tests/__init__.py similarity index 100% rename from caom2/caom2/test/__init__.py rename to caom2/caom2/tests/__init__.py diff --git a/caom2/caom2/test/caom_test_instances.py b/caom2/caom2/tests/caom_test_instances.py similarity index 98% rename from caom2/caom2/test/caom_test_instances.py rename to caom2/caom2/tests/caom_test_instances.py index 949f1bb5..51220e2a 100644 --- a/caom2/caom2/test/caom_test_instances.py +++ b/caom2/caom2/tests/caom_test_instances.py @@ -69,6 +69,9 @@ """ Defines Caom2TestInstances class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import collections from datetime import datetime @@ -280,7 +283,7 @@ def get_quality(self): def get_artifacts(self): artifacts = collections.OrderedDict() _artifact = artifact.Artifact("ad:foo/bar1", - artifact.ProductType.SCIENCE, + chunk.ProductType.SCIENCE, artifact.ReleaseType.META) if self.complete: _artifact.content_type = "application/fits" @@ -295,7 +298,7 @@ def get_parts(self): parts = collections.OrderedDict() _part = part.Part("x") if self.complete: - _part.product_type = artifact.ProductType.SCIENCE + _part.product_type = chunk.ProductType.SCIENCE if self.depth > 4: for chunk in self.get_chunks(): _part.chunks.append(chunk) @@ -306,7 +309,7 @@ def get_chunks(self): chunks = caom_util.TypedList(chunk.Chunk, ) _chunk = chunk.Chunk() if self.complete: - _chunk.product_type = artifact.ProductType.SCIENCE + _chunk.product_type = chunk.ProductType.SCIENCE _chunk.naxis = 5 _chunk.observable_axis = 1 _chunk.position_axis_1 = 1 diff --git a/caom2/caom2/tests/coveragerc b/caom2/caom2/tests/coveragerc new file mode 100644 index 00000000..bec7c291 --- /dev/null +++ b/caom2/caom2/tests/coveragerc @@ -0,0 +1,31 @@ +[run] +source = {packagename} +omit = + {packagename}/_astropy_init* + {packagename}/conftest* + {packagename}/cython_version* + {packagename}/setup_package* + {packagename}/*/setup_package* + {packagename}/*/*/setup_package* + {packagename}/tests/* + {packagename}/*/tests/* + {packagename}/*/*/tests/* + {packagename}/version* + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about packages we have installed + except ImportError + + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + + # Don't complain about script hooks + def main\(.*\): + + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} \ No newline at end of file diff --git a/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/CompleteCompositeCircle.xml b/caom2/caom2/tests/data/CompleteCompositeCircle.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositeCircle.xml rename to caom2/caom2/tests/data/CompleteCompositeCircle.xml diff --git a/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/CompleteCompositePolygon.xml b/caom2/caom2/tests/data/CompleteCompositePolygon.xml similarity index 100% rename from caom2/caom2/test/data/CompleteCompositePolygon.xml rename to caom2/caom2/tests/data/CompleteCompositePolygon.xml diff --git a/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/CompleteSimpleCircle.xml b/caom2/caom2/tests/data/CompleteSimpleCircle.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimpleCircle.xml rename to caom2/caom2/tests/data/CompleteSimpleCircle.xml diff --git a/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/CompleteSimplePolygon.xml b/caom2/caom2/tests/data/CompleteSimplePolygon.xml similarity index 100% rename from caom2/caom2/test/data/CompleteSimplePolygon.xml rename to caom2/caom2/tests/data/CompleteSimplePolygon.xml diff --git a/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositeCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/MinimalCompositeCircle.xml b/caom2/caom2/tests/data/MinimalCompositeCircle.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositeCircle.xml rename to caom2/caom2/tests/data/MinimalCompositeCircle.xml diff --git a/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/MinimalCompositePolygon.xml b/caom2/caom2/tests/data/MinimalCompositePolygon.xml similarity index 100% rename from caom2/caom2/test/data/MinimalCompositePolygon.xml rename to caom2/caom2/tests/data/MinimalCompositePolygon.xml diff --git a/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimpleCircle-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/MinimalSimpleCircle.xml b/caom2/caom2/tests/data/MinimalSimpleCircle.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimpleCircle.xml rename to caom2/caom2/tests/data/MinimalSimpleCircle.xml diff --git a/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml b/caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.1.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.1.xml diff --git a/caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml b/caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimplePolygon-CAOM-2.2.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon-CAOM-2.2.xml diff --git a/caom2/caom2/test/data/MinimalSimplePolygon.xml b/caom2/caom2/tests/data/MinimalSimplePolygon.xml similarity index 100% rename from caom2/caom2/test/data/MinimalSimplePolygon.xml rename to caom2/caom2/tests/data/MinimalSimplePolygon.xml diff --git a/caom2/caom2/tests/setup_package.py b/caom2/caom2/tests/setup_package.py new file mode 100644 index 00000000..6e4be679 --- /dev/null +++ b/caom2/caom2/tests/setup_package.py @@ -0,0 +1,7 @@ +def get_package_data(): + return { + _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} + + +def requires_2to3(): + return False diff --git a/caom2/caom2/test/test_artifact.py b/caom2/caom2/tests/test_artifact.py similarity index 81% rename from caom2/caom2/test/test_artifact.py rename to caom2/caom2/tests/test_artifact.py index 785b0778..592f37e2 100644 --- a/caom2/caom2/test/test_artifact.py +++ b/caom2/caom2/tests/test_artifact.py @@ -69,6 +69,9 @@ """ Defines TestArtifact class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from urlparse import urlparse @@ -79,37 +82,6 @@ class TestEnums(unittest.TestCase): def test_all(self): - # test for invalid value - self.assertEqual(artifact.ProductType.get("no_such_string"), None) - self.assertRaises(AttributeError, artifact.ProductType.get, None) - self.assertRaises(AttributeError, artifact.ProductType.get, 1) - - self.assertEqual(artifact.ReleaseType.get("no_such_string"), None) - self.assertRaises(AttributeError, artifact.ReleaseType.get, None) - self.assertRaises(AttributeError, artifact.ReleaseType.get, 1) - - # test that we can get the object for each enum by name - self.assertEqual(artifact.ProductType.SCIENCE.name, "SCIENCE") - self.assertEqual(artifact.ProductType.get( - artifact.ProductType.SCIENCE.name).name, "SCIENCE") - self.assertEqual(artifact.ProductType.get( - 'SCIENCE').value, "science") - self.assertEqual(artifact.ProductType.get( - artifact.ProductType.SCIENCE.name).value, "science") - self.assertEqual(artifact.ProductType.getByValue( - artifact.ProductType.SCIENCE.value).value, "science") - self.assertEqual(artifact.ProductType.getByValue( - artifact.ProductType.SCIENCE.value).name, "SCIENCE") - - self.assertEqual(artifact.ProductType.SCIENCE.value, "science") - self.assertEqual(artifact.ProductType.CALIBRATION.value, "calibration") - self.assertEqual(artifact.ProductType.PREVIEW.value, "preview") - self.assertEqual(artifact.ProductType.INFO.value, "info") - self.assertEqual(artifact.ProductType.NOISE.value, "noise") - self.assertEqual(artifact.ProductType.WEIGHT.value, "weight") - self.assertEqual(artifact.ProductType.AUXILIARY.value, "auxiliary") - self.assertEqual(artifact.ProductType.THUMBNAIL.value, "thumbnail") - self.assertEqual(artifact.ReleaseType.DATA.value, "data") self.assertEqual(artifact.ReleaseType.META.value, "meta") @@ -189,7 +161,6 @@ def test_all(self): "caom://#observation://? something#//", artifact.ReleaseType('META'), artifact.ProductType('THUMBNAIL')) - print artifact.uri except ValueError: exception = True self.assertTrue(exception, "Missing exception") diff --git a/caom2/caom2/test/test_caom_object.py b/caom2/caom2/tests/test_caom_object.py similarity index 88% rename from caom2/caom2/test/test_caom_object.py rename to caom2/caom2/tests/test_caom_object.py index 81249c89..a4f3c474 100644 --- a/caom2/caom2/test/test_caom_object.py +++ b/caom2/caom2/tests/test_caom_object.py @@ -69,14 +69,17 @@ """ Defines TestCaom2IdGenerator class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest -from .. import artifact from .. import caom_object from .. import chunk -from .. import observation from .. import part from .. import plane +from .. import artifact +from .. import observation class TestCaom2IdGenerator(unittest.TestCase): @@ -84,21 +87,21 @@ class TestCaom2IdGenerator(unittest.TestCase): def test_all(self): #Not much for now. Just to make sure that all the clients work test_entity = caom_object.AbstractCaomEntity() - print test_entity._id, test_entity._last_modified + print(test_entity._id, test_entity._last_modified) test_artifact = artifact.Artifact("caom2:/blah/blah", - artifact.ProductType.SCIENCE, - artifact.ReleaseType.DATA) - print test_artifact._id, test_artifact._last_modified + chunk.ProductType.SCIENCE, + chunk.ReleaseType.DATA) + print(test_artifact._id, test_artifact._last_modified) test_chunk = chunk.Chunk() - print test_chunk._id, test_chunk._last_modified + print(test_chunk._id, test_chunk._last_modified) algorithm = observation.Algorithm("myAlg") test_observation = observation.Observation("colect", "obs", algorithm) - print test_observation._id, test_observation._last_modified + print(test_observation._id, test_observation._last_modified) test_part = part.Part("part") - print test_part._id, test_part._last_modified + print(test_part._id, test_part._last_modified) test_plane = plane.Plane("prodid") - print test_plane._id, test_plane._last_modified + print(test_plane._id, test_plane._last_modified) diff --git a/caom2/caom2/test/test_caom_util.py b/caom2/caom2/tests/test_caom_util.py similarity index 98% rename from caom2/caom2/test/test_caom_util.py rename to caom2/caom2/tests/test_caom_util.py index eac58ae7..d26a53ef 100644 --- a/caom2/caom2/test/test_caom_util.py +++ b/caom2/caom2/tests/test_caom_util.py @@ -67,13 +67,17 @@ #*********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest import uuid from .. import artifact +from .. import caom_util +from .. import chunk from .. import part from .. import plane -from .. import caom_util class TestCaomUtil(unittest.TestCase): @@ -213,8 +217,8 @@ def test_typed_ordered_dict(self): # test validation and constructor with an empty dictionary test_plane10 = plane.Plane('key10') test_artifact66 = artifact.Artifact('caom:CFHT/55/66', - artifact.ProductType.SCIENCE, - artifact.ReleaseType.DATA) + chunk.ProductType.SCIENCE, + chunk.ReleaseType.DATA) test_part10 = part.Part("10") test_plane_uri = plane.PlaneURI('caom:CFHT/55/66') my_dict_plane = caom_util.TypedOrderedDict(plane.Plane,) diff --git a/caom2/caom2/test/test_chunk.py b/caom2/caom2/tests/test_chunk.py similarity index 87% rename from caom2/caom2/test/test_chunk.py rename to caom2/caom2/tests/test_chunk.py index 78ccc796..c60772e4 100644 --- a/caom2/caom2/test/test_chunk.py +++ b/caom2/caom2/tests/test_chunk.py @@ -69,14 +69,46 @@ """ Defines TestChunk class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest -from .. import artifact from .. import chunk -from .. import plane from .. import wcs +class TestEnums(unittest.TestCase): + + def test_all(self): + # test for invalid value + self.assertEqual(chunk.ProductType.get("no_such_string"), None) + self.assertRaises(AttributeError, chunk.ProductType.get, None) + self.assertRaises(AttributeError, chunk.ProductType.get, 1) + + # test that we can get the object for each enum by name + self.assertEqual(chunk.ProductType.SCIENCE.name, "SCIENCE") + self.assertEqual(chunk.ProductType.get( + chunk.ProductType.SCIENCE.name).name, "SCIENCE") + self.assertEqual(chunk.ProductType.get( + 'SCIENCE').value, "science") + self.assertEqual(chunk.ProductType.get( + chunk.ProductType.SCIENCE.name).value, "science") + self.assertEqual(chunk.ProductType.getByValue( + chunk.ProductType.SCIENCE.value).value, "science") + self.assertEqual(chunk.ProductType.getByValue( + chunk.ProductType.SCIENCE.value).name, "SCIENCE") + + self.assertEqual(chunk.ProductType.SCIENCE.value, "science") + self.assertEqual(chunk.ProductType.CALIBRATION.value, "calibration") + self.assertEqual(chunk.ProductType.PREVIEW.value, "preview") + self.assertEqual(chunk.ProductType.INFO.value, "info") + self.assertEqual(chunk.ProductType.NOISE.value, "noise") + self.assertEqual(chunk.ProductType.WEIGHT.value, "weight") + self.assertEqual(chunk.ProductType.AUXILIARY.value, "auxiliary") + self.assertEqual(chunk.ProductType.THUMBNAIL.value, "thumbnail") + + class TestChunk(unittest.TestCase): def test_init(self): @@ -112,8 +144,8 @@ def test_attributes(self): test_chunk.time = float(1.0) test_chunk.polarization = float(1.0) - test_chunk.product_type = artifact.ProductType.SCIENCE - self.assertEqual(artifact.ProductType.SCIENCE, test_chunk.product_type) + test_chunk.product_type = chunk.ProductType.SCIENCE + self.assertEqual(chunk.ProductType.SCIENCE, test_chunk.product_type) test_chunk.naxis = int(5) self.assertEqual(int(5), test_chunk.naxis) diff --git a/caom2/caom2/test/test_obs_reader_writer.py b/caom2/caom2/tests/test_obs_reader_writer.py similarity index 98% rename from caom2/caom2/test/test_obs_reader_writer.py rename to caom2/caom2/tests/test_obs_reader_writer.py index c9d5563c..15b30678 100644 --- a/caom2/caom2/test/test_obs_reader_writer.py +++ b/caom2/caom2/tests/test_obs_reader_writer.py @@ -69,6 +69,9 @@ """ Defines TestObservationReaderWriter class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import StringIO import os import unittest @@ -123,7 +126,6 @@ def complete_composite(depth, bounds_is_circle, version): class TestObservationReaderWriter(unittest.TestCase): def test_invalid_long_id(self): - print "Test Invalid long id " simple_observation = minimal_simple(1, False, 20) writer = obs_reader_writer.ObservationWriter( False, False, "caom2", obs_reader_writer.CAOM20_NAMESPACE) @@ -143,7 +145,6 @@ def test_invalid_long_id(self): pass def test_invalid_uuid(self): - print "Test Invalid UUID id" simple_observation = minimal_simple(1, False, 21) writer = obs_reader_writer.ObservationWriter(False, False) # default writer is 2.1 output = StringIO.StringIO() @@ -164,7 +165,7 @@ def test_invalid_uuid(self): def test_minimal_simple(self): for version in (20, 21): for i in range(1, 6): - print "Test Minimal Simple {} version {}".format(i, version) + print("Test Minimal Simple {} version {}".format(i, version)) # CoordBounds2D as CoordCircle2D simple_observation = minimal_simple(i, True, version) # write empty elements @@ -181,7 +182,7 @@ def test_minimal_simple(self): def test_complete_simple(self): for version in (20, 21, 22): for i in range(1, 6): - print "Test Complete Simple {} version {}".format(i, version) + print("Test Complete Simple {} version {}".format(i, version)) # CoordBounds2D as CoordCircle2D simple_observation = complete_simple(i, True, version) # write empty elements @@ -198,7 +199,7 @@ def test_complete_simple(self): def test_minimal_composite(self): for version in (20, 21, 22): for i in range(1, 6): - print "Test Minimal Composite {} version {}".format(i, version) + print("Test Minimal Composite {} version {}".format(i, version)) # CoordBounds2D as CoordCircle2D composite_observation = minimal_composite(i, True, version) # write empty elements @@ -215,7 +216,7 @@ def test_minimal_composite(self): def test_complete_composite(self): for version in (20, 21, 22): for i in range(1, 6): - print "Test Complete Composite {} version {}".format(i, version) + print("Test Complete Composite {} version {}".format(i, version)) # CoordBounds2D as CoordCircle2D composite_observation = complete_composite(i, True, version) # write empty elements @@ -858,7 +859,7 @@ def do_test(self, reader, writer, filename): # test/data/*.xml files can be used in this test. def test_round_trip(self): - print "Test Round Trip" + print("Test Round Trip") try: self.init() diff --git a/caom2/caom2/test/test_observation.py b/caom2/caom2/tests/test_observation.py similarity index 99% rename from caom2/caom2/test/test_observation.py rename to caom2/caom2/tests/test_observation.py index 7724c274..34dd7f34 100644 --- a/caom2/caom2/test/test_observation.py +++ b/caom2/caom2/tests/test_observation.py @@ -69,6 +69,9 @@ """ Defines TestObservation class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from datetime import datetime diff --git a/caom2/caom2/test/test_part.py b/caom2/caom2/tests/test_part.py similarity index 94% rename from caom2/caom2/test/test_part.py rename to caom2/caom2/tests/test_part.py index 026c9bef..edad821f 100644 --- a/caom2/caom2/test/test_part.py +++ b/caom2/caom2/tests/test_part.py @@ -69,9 +69,11 @@ """ Defines TestPart class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest -from .. import artifact from .. import chunk from .. import part @@ -87,8 +89,8 @@ def test_init(self): self.assertIsNone(test_part.product_type) self.assertTrue(len(test_part.chunks) == 0) - test_part.product_type = artifact.ProductType.SCIENCE - self.assertEqual(artifact.ProductType.SCIENCE, test_part.product_type) + test_part.product_type = chunk.ProductType.SCIENCE + self.assertEqual(chunk.ProductType.SCIENCE, test_part.product_type) test_chunk = chunk.Chunk() test_chunk.naxis = 5 diff --git a/caom2/caom2/test/test_plane.py b/caom2/caom2/tests/test_plane.py similarity index 98% rename from caom2/caom2/test/test_plane.py rename to caom2/caom2/tests/test_plane.py index e79739a9..1e097156 100644 --- a/caom2/caom2/test/test_plane.py +++ b/caom2/caom2/tests/test_plane.py @@ -69,12 +69,16 @@ """ Defines TestPlane class """ +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from datetime import datetime from .. import artifact from .. import observation from .. import plane +from .. import chunk from .. import wcs @@ -186,14 +190,14 @@ def test_all(self): self.assertIsNone(test_plane.polarization, "Default polarization") test_artifact1 = artifact.Artifact("caom:GEMINI/222/333", - artifact.ProductType.SCIENCE, + chunk.ProductType.SCIENCE, artifact.ReleaseType.DATA) test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact1 self.assertEquals(1, len(test_plane.artifacts), "Artifacts") self.assertTrue("caom:GEMINI/222/333" in test_plane.artifacts.keys()) test_artifact2 = artifact.Artifact("caom:CFHT/55/66", - artifact.ProductType.SCIENCE, + chunk.ProductType.SCIENCE, artifact.ReleaseType.DATA) test_plane.artifacts["caom:CFHT/55/66"] = test_artifact2 self.assertEquals(2, len(test_plane.artifacts), "Artifacts") @@ -202,7 +206,7 @@ def test_all(self): #try to append a duplicate artifact test_artifact3 = artifact.Artifact("caom:GEMINI/222/333", - artifact.ProductType.SCIENCE, + chunk.ProductType.SCIENCE, artifact.ReleaseType.DATA) test_plane.artifacts["caom:GEMINI/222/333"] = test_artifact3 self.assertEquals(2, len(test_plane.artifacts), "Artifacts") diff --git a/caom2/caom2/test/test_shape.py b/caom2/caom2/tests/test_shape.py similarity index 97% rename from caom2/caom2/test/test_shape.py rename to caom2/caom2/tests/test_shape.py index 39fbbb51..da1f8177 100644 --- a/caom2/caom2/test/test_shape.py +++ b/caom2/caom2/tests/test_shape.py @@ -67,6 +67,9 @@ #*********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from .. import shape diff --git a/caom2/caom2/test/test_wcs.py b/caom2/caom2/tests/test_wcs.py similarity index 99% rename from caom2/caom2/test/test_wcs.py rename to caom2/caom2/tests/test_wcs.py index 19ef2132..105aeacc 100644 --- a/caom2/caom2/test/test_wcs.py +++ b/caom2/caom2/tests/test_wcs.py @@ -67,6 +67,9 @@ #*********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) + import unittest from .. import wcs @@ -267,7 +270,6 @@ def test_init(self): self.assertRaises(TypeError, wcs.CoordError, float(1.0), int(1)) error = wcs.CoordError(float(1), float(2)) - print error.rnder self.assertIsNotNone(error) self.assertEqual(error.syser, float(1)) self.assertEqual(error.rnder, float(2)) diff --git a/caom2/caom2/wcs.py b/caom2/caom2/wcs.py index dd0b690c..d944e23c 100644 --- a/caom2/caom2/wcs.py +++ b/caom2/caom2/wcs.py @@ -67,9 +67,11 @@ # *********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) -import caom_object -import caom_util +from . import caom_object +from . import caom_util __all__ = ['Axis', 'Coord2D', 'CoordAxis1D', 'CoordAxis2D', 'CoordBounds1D', 'CoordBounds2D', 'CoordCircle2D', 'CoordError', 'CoordFunction1D', 'CoordFunction2D', 'CoordPolygon2D', 'CoordRange1D', 'CoordRange2D', diff --git a/caom2/setup.py b/caom2/setup.py index 41fef7a6..d9b51bd9 100755 --- a/caom2/setup.py +++ b/caom2/setup.py @@ -77,7 +77,7 @@ # Add the project-global data package_info['package_data'].setdefault(PACKAGENAME, []) package_info['package_data'][PACKAGENAME].append('data/*') -package_info['package_data'][PACKAGENAME].append('test/data/*') +package_info['package_data'][PACKAGENAME].append('tests/data/*') # Define entry points for command-line scripts entry_points = {'console_scripts': []} From f074b398ccfafe2a8cb994061d32909e969257d0 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Mon, 28 Nov 2016 14:55:11 -0800 Subject: [PATCH 38/54] s1950: renamed caom_object.py common.py and moved in ObservationURI from observation.py, unit tests fixes for futures imports. --- caom2/caom2/__init__.py | 20 +- caom2/caom2/artifact.py | 17 +- caom2/caom2/caom_util.py | 3 +- caom2/caom2/chunk.py | 53 ++--- caom2/caom2/{caom_object.py => common.py} | 117 +++++++++- caom2/caom2/obs_reader_writer.py | 56 +++-- caom2/caom2/observation.py | 209 +++++------------- caom2/caom2/part.py | 15 +- caom2/caom2/plane.py | 57 ++--- caom2/caom2/shape.py | 14 +- caom2/caom2/tests/caom_test_instances.py | 4 +- caom2/caom2/tests/test_artifact.py | 16 +- caom2/caom2/tests/test_caom_util.py | 20 +- caom2/caom2/tests/test_chunk.py | 30 ++- .../{test_caom_object.py => test_common.py} | 36 ++- caom2/caom2/tests/test_obs_reader_writer.py | 2 +- caom2/caom2/tests/test_observation.py | 75 +++---- caom2/caom2/tests/test_plane.py | 99 +++++---- caom2/caom2/tests/test_shape.py | 15 +- caom2/caom2/wcs.py | 50 ++--- 20 files changed, 466 insertions(+), 442 deletions(-) rename caom2/caom2/{caom_object.py => common.py} (63%) rename caom2/caom2/tests/{test_caom_object.py => test_common.py} (79%) diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 58c1bfe9..6d236e51 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -84,16 +84,16 @@ # if not _ASTROPY_SETUP_: # from .caom2 import * -# from caom_util import * -# from caom_object import * -# from wcs import * -# from shape import * -# from chunk import * -# from part import * -# from artifact import * -# from plane import * -# from observation import * -# from obs_reader_writer import * +from caom_util import * +from common import * +from wcs import * +from shape import * +from chunk import * +from part import * +from artifact import * +from plane import * +from observation import * +from obs_reader_writer import * # from obs_reader_writer import * # from observation import * diff --git a/caom2/caom2/artifact.py b/caom2/caom2/artifact.py index bbd9d84a..961a9004 100644 --- a/caom2/caom2/artifact.py +++ b/caom2/caom2/artifact.py @@ -77,10 +77,11 @@ from urlparse import urlparse from enum import Enum -from . import caom_object + from . import caom_util -from . import chunk -from . import part +from .chunk import ProductType +from .common import AbstractCaomEntity +from .part import Part __all__ = ['ReleaseType', 'Artifact'] @@ -94,7 +95,7 @@ class ReleaseType(Enum): META = "meta" -class Artifact(caom_object.AbstractCaomEntity): +class Artifact(AbstractCaomEntity): """Contains the meta data assocaited with a file. - location of the file (uri) @@ -130,7 +131,7 @@ def __init__(self, self.content_type = content_type self.content_length = content_length if parts is None: - parts = caom_util.TypedOrderedDict(part.Part,) + parts = caom_util.TypedOrderedDict(Part,) self.parts = parts def _key(self): @@ -161,7 +162,7 @@ def uri(self): @uri.setter def uri(self, value): - caom_util.type_check(value, str, 'uri') + caom_util.type_check(value, unicode, 'uri') uri = urlparse(value).geturl() caom_util.value_check(value, None, None, 'uri', override=uri) self._uri = uri @@ -179,7 +180,7 @@ def product_type(self): @product_type.setter def product_type(self, value): - caom_util.type_check(value, chunk.ProductType, "product_type", False) + caom_util.type_check(value, ProductType, "product_type", False) self._product_type = value @property @@ -208,7 +209,7 @@ def content_type(self): @content_type.setter def content_type(self, value): - caom_util.type_check(value, str, "content_type") + caom_util.type_check(value, unicode, "content_type") self._content_type = value @property diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index 600ae7f9..1a5b28b2 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -160,9 +160,10 @@ def long2uuid(l): Takes a long and creates a UUID using the 16 byte long as the least significant bytes in the 32 byte UUID. """ + foo = l.bit_length() if l.bit_length() > 63: raise ValueError("expected 64 bit long {}".format(l)) - return uuid.UUID(bytes='\x00'*8 + str(struct.pack(">q", l))) + return uuid.UUID(int=l) def type_check(value, value_type, variable, override=None): diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py index 5d8e877e..a56f7983 100644 --- a/caom2/caom2/chunk.py +++ b/caom2/caom2/chunk.py @@ -75,7 +75,8 @@ unicode_literals) from enum import Enum -from . import caom_object +from .common import AbstractCaomEntity +from .common import CaomObject from . import caom_util from . import wcs @@ -115,7 +116,7 @@ class ProductType(Enum): 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] -class Chunk(caom_object.AbstractCaomEntity): +class Chunk(AbstractCaomEntity): """A caom2.Chunk object. A chunk is a peice of file part. eg. a column in a Table extension of a FITS file. @@ -170,18 +171,18 @@ def __init__(self, product_type=None, def product_type(self): """A word that describes the content of the chunk. - eg. Chunk.product_type = ProductType('SCIENCE') - - Allowed values: - """ + str(ProductType.names()) + """ - + eg. Chunk.product_type = ProductType.SCIENCE """ + # Allowed values: + # """ + str(ProductType.names()) + """ + # + # """ return self._product_type @product_type.setter def product_type(self, value): - if isinstance(value, str) and value in ProductType.names(): + if isinstance(value, unicode) and value in ProductType.names(): # be helpful value = ProductType('value') caom_util.type_check(value, ProductType, 'product_type') @@ -394,7 +395,7 @@ def polarization(self, value): self._polarization = value -class ObservableAxis(caom_object.CaomObject): +class ObservableAxis(CaomObject): """The slice through the data structure that provides the thing being described by this Axis. @@ -468,7 +469,7 @@ def independent(self, value): self._independent = value -class SpatialWCS(caom_object.CaomObject): +class SpatialWCS(CaomObject): """this object contains the WCS information needed to convert an astronomical spatial location (ie. RA/DEC) into a pixel location in the image. @@ -509,14 +510,14 @@ def coordsys(self): eg. SpatialWCS.coordsys="ICRS" - type: str + type: unicode """ return self._coordsys @coordsys.setter def coordsys(self, value): - caom_util.type_check(value, str, 'coordsys') + caom_util.type_check(value, unicode, 'coordsys') self._coordsys = value @property @@ -554,7 +555,7 @@ def resolution(self, value): self._resolution = value -class SpectralWCS(caom_object.CaomObject): +class SpectralWCS(CaomObject): """A transformation that maps pixel coordinates to spectral ones. Note that a 2D image has implicit 'spectral' (and temporal) @@ -623,13 +624,13 @@ def specsys(self): eg. BARYCENT - type: str + type: unicode """ return self._specsys @specsys.setter def specsys(self, value): - caom_util.type_check(value, str, 'specsys', override=False) + caom_util.type_check(value, unicode, 'specsys', override=False) self._specsys = value @property @@ -643,13 +644,13 @@ def ssysobs(self): Nominally 'TOPOCENT' - type: str + type: unicode """ return self._ssysobs @ssysobs.setter def ssysobs(self, value): - caom_util.type_check(value, str, 'ssysobs') + caom_util.type_check(value, unicode, 'ssysobs') self._ssysobs = value @property @@ -663,7 +664,7 @@ def ssyssrc(self): @ssyssrc.setter def ssyssrc(self, value): - caom_util.type_check(value, str, 'ssyssrc') + caom_util.type_check(value, unicode, 'ssyssrc') self._ssyssrc = value @property @@ -747,13 +748,13 @@ def bandpass_name(self): """string the represent the bandpass of the observation. eg. r' - type: str + type: unicode """ return self._bandpass_name @bandpass_name.setter def bandpass_name(self, value): - caom_util.type_check(value, str, 'bandpass_name') + caom_util.type_check(value, unicode, 'bandpass_name') self._bandpass_name = value @property @@ -787,7 +788,7 @@ def resolving_power(self, value): self._resolving_power = value -class TemporalWCS(caom_object.CaomObject): +class TemporalWCS(CaomObject): """Describes the Time variation within the data. In the case of a single exposure, define the center of the first @@ -827,13 +828,13 @@ def timesys(self): """The time scale that you are using, almost alwasy UTC. eg. timesys = "UTC" - type: str + type: unicode """ return self._timesys @timesys.setter def timesys(self, value): - caom_util.type_check(value, str, 'timesys') + caom_util.type_check(value, unicode, 'timesys') self._timesys = value @property @@ -843,13 +844,13 @@ def trefpos(self): light-time corrections have been applied. eg. trefpos = "TOPOCENTER" - type: str + type: unicode """ return self._trefpos @trefpos.setter def trefpos(self, value): - caom_util.type_check(value, str, 'trefpos') + caom_util.type_check(value, unicode, 'trefpos') self._trefpos = value @property @@ -916,7 +917,7 @@ def resolution(self, value): self._resolution = value -class PolarizationWCS(caom_object.CaomObject): +class PolarizationWCS(CaomObject): """A WCS structure that describes the relation ship between a pixel location and the polarization value. diff --git a/caom2/caom2/caom_object.py b/caom2/caom2/common.py similarity index 63% rename from caom2/caom2/caom_object.py rename to caom2/caom2/common.py index 24f0a4b3..2dab521e 100644 --- a/caom2/caom2/caom_object.py +++ b/caom2/caom2/common.py @@ -75,11 +75,13 @@ import time import uuid from datetime import datetime +from urlparse import SplitResult +from urlparse import urlsplit from . import caom_util -__all__ = ['CaomObject', 'AbstractCaomEntity'] +__all__ = ['CaomObject', 'AbstractCaomEntity', 'ObservationURI'] class CaomObject(object): @@ -134,16 +136,19 @@ def _gen_id(cls, fulluuid=False): return: UUID """ + gen_id = uuid.uuid4() if fulluuid: - return uuid.uuid4() + return gen_id else: - vmrandom = random.randint(-int(0x7fff), int(0x7fff)) << 8 * 6 - randtime = int(round(time.time() * 1000000)) - randtime = randtime & 0xffffffffffff - rand = vmrandom | randtime - if rand & 0x8000000000000000: - rand = 0x1000000000000000 + rand - return caom_util.long2uuid(rand) + return uuid.UUID(fields=(0x00000000, 0x0000, 0x0000, + gen_id.clock_seq_hi_variant, gen_id.clock_seq_low, gen_id.node)) + # vmrandom = random.randint(-int(0x7fff), int(0x7fff)) << 8 * 6 + # randtime = int(round(time.time() * 1000000)) + # randtime = randtime & 0xffffffffffff + # rand = vmrandom | randtime + # if rand & 0x8000000000000000: + # rand = 0x1000000000000000 + rand + # return caom_util.long2uuid(rand) @classmethod def _gen_last_modified(cls): @@ -155,3 +160,97 @@ def _gen_last_modified(cls): now = datetime.now() return datetime(now.year, now.month, now.day, now.hour, now.minute, \ now.second, long(str(now.microsecond)[:-3] + '000')) + + +class ObservationURI(CaomObject): + """ Observation URI """ + + _SCHEME = str("caom") + + def __init__(self, uri): + """ + Initializes an Observation instance + + Arguments: + uri : URI corresponding to observation + """ + tmp = urlsplit(uri) + + if tmp.scheme != ObservationURI._SCHEME: + raise ValueError( + "uri must be have scheme of {}. received: {}" + .format(ObservationURI._SCHEME, uri)) + if tmp.geturl() != uri: + raise ValueError( + "uri parsing failure. received: {}".format(uri)) + + self._uri = tmp.geturl() + (collection, observation_id) = tmp.path.split("/") + if collection is None: + raise ValueError( + "uri did not contain a collection part. received: {}" + .format(uri)) + caom_util.validate_path_component(self, "collection", collection) + if observation_id is None: + raise ValueError( + "uri did not contain an observation_id part. received: {}" + .format(uri)) + caom_util.validate_path_component(self, "observation_id", observation_id) + (self._collection, self._observation_id) = (collection, observation_id) + self._print_attributes = ['uri', 'collection', 'observation_id'] + + def _key(self): + return self.uri + + def __eq__(self, y): + if isinstance(y, ObservationURI): + return self._key() == y._key() + return False + + def __hash__(self): + return hash(self._key()) + + @classmethod + def get_observation_uri(cls, collection, observation_id): + """ + Initializes an Observation URI instance + + Arguments: + collection : collection + observation_id : ID of the observation + """ + + caom_util.type_check(collection, unicode, "collection", override=False) + caom_util.type_check(observation_id, unicode, "observation_id", override=False) + + caom_util.validate_path_component(cls, "collection", collection) + caom_util.validate_path_component(cls, "observation_id", observation_id) + + uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + observation_id, + "", "").geturl() + return cls(uri) + + # Properties + + @property + @classmethod + def scheme(cls): + """The scheme defines where this Observation can be looked up. + + Only 'caom' is currently supported.""" + return cls._SCHEME + + @property + def uri(self): + """The uri that the caom service can use to find the observation""" + return self._uri + + @property + def collection(self): + """The collection part of this Observations uri""" + return self._collection + + @property + def observation_id(self): + """The observation_id of this Observations uri""" + return self._observation_id diff --git a/caom2/caom2/obs_reader_writer.py b/caom2/caom2/obs_reader_writer.py index e056f926..7c3e59f4 100644 --- a/caom2/caom2/obs_reader_writer.py +++ b/caom2/caom2/obs_reader_writer.py @@ -182,7 +182,7 @@ def _get_child_text(self, element_tag, parent, ns, required): if child_element is None: return None else: - return child_element.text + return unicode(child_element.text) def _get_child_text_as_int(self, element_tag, parent, ns, required): child_element = self._get_child_element(element_tag, parent, ns, required) @@ -288,7 +288,7 @@ def _get_target(self, element_tag, parent, ns, required): target = observation.Target(self._get_child_text("name", el, ns, True)) target_type = self._get_child_text("type", el, ns, False) if target_type: - target.target_type = observation.TargetType.getByValue(target_type) + target.target_type = observation.TargetType(target_type) target.standard = ("true" == self._get_child_text("standard", el, ns, False)) target.redshift = ( @@ -341,7 +341,7 @@ def _get_requirements(self, element_tag, parent, ns, required): return None else: flag = self._get_child_text("flag", el, ns, True) - requirements = observation.Requirements(observation.Status.getByValue(flag)) + requirements = observation.Requirements(observation.Status(flag)) return requirements def _get_telescope(self, element_tag, parent, ns, required): @@ -464,7 +464,7 @@ def _add_inputs(self, inputs, parent, ns): el = self._get_child_element("inputs", parent, ns, False) if el is not None: for uri_element in el.iterchildren("{" + ns + "}planeURI"): - inputs.add(plane.PlaneURI(uri_element.text)) + inputs.add(plane.PlaneURI(unicode(uri_element.text))) if not inputs: error = "No planeURI element found in members" @@ -551,7 +551,7 @@ def _get_quality(self, element_tag, parent, ns, required): return None else: flag = self._get_child_text("flag", el, ns, True) - data_quality = plane.DataQuality(plane.Quality.getByValue(flag)) + data_quality = plane.DataQuality(plane.Quality(flag)) return data_quality def _get_point(self, element_tag, parent, ns, required): @@ -1163,7 +1163,7 @@ def _add_chunks(self, chunks, parent, ns): self._get_child_text("productType", chunk_element, ns, False) if product_type: _chunk.product_type = \ - chunk.ProductType.getByValue(product_type) + chunk.ProductType(product_type) _chunk.naxis = \ self._get_child_text_as_int("naxis", chunk_element, ns, False) _chunk.observable_axis = \ @@ -1217,7 +1217,7 @@ def _add_parts(self, parts, parent, ns): self._get_child_text("productType", part_element, ns, False) if product_type: _part.product_type = \ - chunk.ProductType.getByValue(product_type) + chunk.ProductType(product_type) self._add_chunks(_part.chunks, part_element, ns) self._set_entity_attributes(part_element, ns, _part) parts[_part.name] = _part @@ -1244,14 +1244,14 @@ def _add_artifacts(self, artifacts, parent, ns): product_type = chunk.ProductType.SCIENCE print("Using default Artifact.productType value {0}".format(str(chunk.ProductType.SCIENCE))) else: - product_type = chunk.ProductType.getByValue(product_type) + product_type = chunk.ProductType(product_type) release_type = self._get_child_text("releaseType", artifact_element, ns, False) if release_type is None: release_type = artifact.ReleaseType.DATA print("Using default Artifact.releaseType value {0}".format(str(artifact.ReleaseType.DATA))) else: - release_type = artifact.ReleaseType.getByValue(release_type) + release_type = artifact.ReleaseType(release_type) _artifact = artifact.Artifact(uri, product_type, release_type) _artifact.content_type = self._get_child_text("contentType", artifact_element, ns, False) @@ -1286,12 +1286,12 @@ def _add_planes(self, planes, parent, ns): self._get_child_text("dataProductType", plane_element, ns, False) if data_product_type: _plane.data_product_type = \ - plane.DataProductType.getByValue(data_product_type) + plane.DataProductType(data_product_type) calibration_level = \ self._get_child_text("calibrationLevel", plane_element, ns, False) if calibration_level: _plane.calibration_level = \ - plane.CalibrationLevel.getByValue(int(calibration_level)) + plane.CalibrationLevel(int(calibration_level)) _plane.provenance = \ self._get_provenance("provenance", plane_element, ns, False) _plane.metrics = \ @@ -1321,9 +1321,9 @@ def read(self, source): self._xmlschema.assertValid(doc) root = doc.getroot() ns = root.nsmap["caom2"] - collection = self._get_child_element("collection", root, ns, True).text + collection = unicode(self._get_child_element("collection", root, ns, True).text) observation_id = \ - self._get_child_element("observationID", root, ns, True).text + unicode(self._get_child_element("observationID", root, ns, True).text) # Instantiate Algorithm algorithm = self._get_algorithm("algorithm", root, ns, True) # Instantiate Observation @@ -1341,7 +1341,7 @@ def read(self, source): self._get_child_text("type", root, ns, False) intent = self._get_child_text("intent", root, ns, False) if intent: - obs.intent = observation.ObservationIntentType.getByValue(intent) + obs.intent = observation.ObservationIntentType(intent) obs.meta_release = \ self._get_meta_release("metaRelease", root, ns, False) obs.proposal = \ @@ -1435,7 +1435,7 @@ def write(self, obs, out): self._add_element("type", obs.obs_type, obs_element) if obs.intent is not None: self._add_element( - "intent", observation.ObservationIntentType.get(str(obs.intent)).value, obs_element) + "intent",obs.intent.value, obs_element) self._add_proposal_element(obs.proposal, obs_element) self._add_target_element(obs.target, obs_element) @@ -1491,8 +1491,7 @@ def _add_target_element(self, target, parent): element = self._get_caom_element("target", parent) self._add_element("name", target.name, element) if target.target_type is not None: - self._add_element( - "type", observation.TargetType.get(str(target.target_type)).value, element) + self._add_element("type", target.target_type.value, element) if target.standard is not None: self._add_element("standard", str(target.standard).lower(), element) self._add_element("redshift", target.redshift, element) @@ -1519,7 +1518,7 @@ def _add_requirements_element(self, requirements, parent): element = self._get_caom_element("requirements", parent) self._add_element( - "flag", observation.Status.get(str(requirements.flag)).value, element) + "flag", requirements.flag.value, element) def _add_telescope_element(self, telescope, parent): if telescope is None: @@ -1581,11 +1580,11 @@ def _add_planes_element(self, planes, parent): plane_element) if _plane.data_product_type is not None: self._add_element("dataProductType", - plane.DataProductType.get(str(_plane.data_product_type)).value, + _plane.data_product_type.value, plane_element) if _plane.calibration_level is not None: self._add_element("calibrationLevel", - plane.CalibrationLevel(str(_plane.calibration_level)).value, + _plane.calibration_level.value, plane_element) self._add_provenance_element(_plane.provenance, plane_element) self._add_metrics_element(_plane.metrics, plane_element) @@ -1629,8 +1628,7 @@ def _add_quality_element(self, quality, parent): return element = self._get_caom_element("quality", parent) - self._add_element( - "flag", plane.Quality.get(str(quality.flag)).value, element) + self._add_element("flag", quality.flag.value, element) def _add_transition_element(self, transition, parent): if transition is None: @@ -1650,15 +1648,12 @@ def _add_artifacts_element(self, artifacts, parent): self._add_enity_attributes(_artifact, artifact_element) self._add_element("uri", _artifact.uri, artifact_element) if self._output_version > 21: - self._add_element("productType", chunk.ProductType.get( - str(_artifact.product_type)).value, artifact_element) - self._add_element("releaseType", artifact.ReleaseType.get( - str(_artifact.release_type)).value, artifact_element) + self._add_element("productType", _artifact.product_type.value, artifact_element) + self._add_element("releaseType", _artifact.release_type.value, artifact_element) self._add_element("contentType", _artifact.content_type, artifact_element) self._add_element("contentLength", _artifact.content_length, artifact_element) if self._output_version < 22: - self._add_element("productType", chunk.ProductType.get( - str(_artifact.product_type)).value, artifact_element) + self._add_element("productType", _artifact.product_type.value, artifact_element) self._add_parts_element(_artifact.parts, artifact_element) def _add_parts_element(self, parts, parent): @@ -1671,8 +1666,7 @@ def _add_parts_element(self, parts, parent): self._add_enity_attributes(_part, part_element) self._add_element("name", _part.name, part_element) if _part.product_type is not None: - self._add_element("productType", chunk.ProductType.get( - str(_part.product_type)).value, part_element) + self._add_element("productType", _part.product_type.value, part_element) self._add_chunks_element(_part.chunks, part_element) def _add_chunks_element(self, chunks, parent): @@ -1685,7 +1679,7 @@ def _add_chunks_element(self, chunks, parent): self._add_enity_attributes(_chunk, chunk_element) if _chunk.product_type is not None: self._add_element("productType", - chunk.ProductType.get(str(_chunk.product_type)).value, + _chunk.product_type.value, chunk_element) self._add_element("naxis", _chunk.naxis, chunk_element) self._add_element("observableAxis", _chunk.observable_axis, diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py index 514839a8..8da2c3c6 100644 --- a/caom2/caom2/observation.py +++ b/caom2/caom2/observation.py @@ -73,26 +73,15 @@ unicode_literals) from datetime import datetime -from urlparse import SplitResult -from urlparse import urlsplit from enum import Enum -from . import caom_object + from . import caom_util -# from . import plane +from .common import AbstractCaomEntity +from .common import CaomObject +from .common import ObservationURI from .plane import Plane -from . import shape - -# ObservationIntentType = Enum('ObservationIntentType', -# CALIBRATION="calibration", -# SCIENCE="science") - -# Status = Enum('Status', -# FAIL="fail") - -# TargetType = Enum('TargetType', -# FIELD="field", -# OBJECT="object") +from .shape import Point __all__ = ['ObservationIntentType', 'Status', 'TargetType', 'Observation', 'ObservationURI', 'Algorithm', 'SimpleObservation', @@ -125,7 +114,7 @@ class TargetType(Enum): OBJECT = "object" -class Observation(caom_object.AbstractCaomEntity): +class Observation(AbstractCaomEntity): """ Observation @@ -230,13 +219,13 @@ def collection(self): """The name of the collection of observations, normally a telescope name. - type: str + type: unicode """ return self._collection @collection.setter def collection(self, value): - caom_util.type_check(value, str, 'collection', override=False) + caom_util.type_check(value, unicode, 'collection', override=False) self._collection = value @property @@ -244,13 +233,13 @@ def observation_id(self): """A string that uniquely identifies this obseravtion within the given collection. - type: str + type: unicode """ return self._observation_id @observation_id.setter def observation_id(self, value): - caom_util.type_check(value, str, 'observation_id', override=False) + caom_util.type_check(value, unicode, 'observation_id', override=False) self._observation_id = value @property @@ -258,7 +247,7 @@ def uri(self): """A URI for this observation referenced in the caom system. This attribute is auto geneqrated from the other metadata. - type: str + type: unicode """ return self._uri @@ -295,7 +284,7 @@ def algorithm(self): @algorithm.setter def algorithm(self, value): - if isinstance(value, str): + if isinstance(value, unicode): value = Algorithm(value) caom_util.type_check(value, Algorithm, 'algorithm') self._algorithm = value @@ -313,7 +302,7 @@ def intent(self): @intent.setter def intent(self, value): - if isinstance(value, str): + if isinstance(value, unicode): value = ObservationIntentType(value) caom_util.type_check(value, ObservationIntentType, 'intent') self._intent = value @@ -335,13 +324,13 @@ def obs_type(self): """The OBSTYPE of the observation being recorded. eg. OBJECT, FLAT, BIAS - type: str + type: unicode """ return self._obs_type @obs_type.setter def obs_type(self, value): - caom_util.type_check(value, str, 'obs_type') + caom_util.type_check(value, unicode, 'obs_type') self._obs_type = value @property @@ -385,8 +374,8 @@ def instrument(self): @instrument.setter def instrument(self, value): - if isinstance(value, str): - value = Instrument(str) + if isinstance(value, unicode): + value = Instrument(value) caom_util.type_check(value, Instrument, "instrument") self._instrument = value @@ -401,8 +390,8 @@ def target(self): @target.setter def target(self, value): - if isinstance(value, str): - value = Target(str) + if isinstance(value, unicode): + value = Target(value) caom_util.type_check(value, Target, 'target') self._target = value @@ -472,101 +461,7 @@ def meta_release(self, value): self._meta_release = value -class ObservationURI(caom_object.CaomObject): - """ Observation URI """ - - _SCHEME = str("caom") - - def __init__(self, uri): - """ - Initializes an Observation instance - - Arguments: - uri : URI corresponding to observation - """ - tmp = urlsplit(uri) - - if tmp.scheme != ObservationURI._SCHEME: - raise ValueError( - "uri must be have scheme of {}. received: {}" - .format(ObservationURI._SCHEME, uri)) - if tmp.geturl() != uri: - raise ValueError( - "uri parsing failure. received: {}".format(uri)) - - self._uri = tmp.geturl() - (collection, observation_id) = tmp.path.split("/") - if collection is None: - raise ValueError( - "uri did not contain a collection part. received: {}" - .format(uri)) - caom_util.validate_path_component(self, "collection", collection) - if observation_id is None: - raise ValueError( - "uri did not contain an observation_id part. received: {}" - .format(uri)) - caom_util.validate_path_component(self, "observation_id", observation_id) - (self._collection, self._observation_id) = (collection, observation_id) - self._print_attributes = ['uri', 'collection', 'observation_id'] - - def _key(self): - return self.uri - - def __eq__(self, y): - if isinstance(y, ObservationURI): - return self._key() == y._key() - return False - - def __hash__(self): - return hash(self._key()) - - @classmethod - def get_observation_uri(cls, collection, observation_id): - """ - Initializes an Observation URI instance - - Arguments: - collection : collection - observation_id : ID of the observation - """ - - caom_util.type_check(collection, str, "collection", override=False) - caom_util.type_check(observation_id, str, "observation_id", override=False) - - caom_util.validate_path_component(cls, "collection", collection) - caom_util.validate_path_component(cls, "observation_id", observation_id) - - uri = SplitResult(ObservationURI._SCHEME, "", collection + "/" + observation_id, - "", "").geturl() - return cls(uri) - - # Properties - - @property - @classmethod - def scheme(cls): - """The scheme defines where this Observation can be looked up. - - Only 'caom' is currently supported.""" - return cls._SCHEME - - @property - def uri(self): - """The uri that the caom service can use to find the observation""" - return self._uri - - @property - def collection(self): - """The collection part of this Observations uri""" - return self._collection - - @property - def observation_id(self): - """The observation_id of this Observations uri""" - return self._observation_id - - -class Algorithm(caom_object.CaomObject): +class Algorithm(CaomObject): """ The concept of Algorithm is to provide a way for users to find all composite observation sets that have been built using a particular @@ -583,7 +478,7 @@ def __init__(self, name): simple observation, otherwise name of algorithm that selected composite members or just 'composite' works too. """ - caom_util.type_check(name, str, "name", override=False) + caom_util.type_check(name, unicode, 'name', override=False) self._name = name def _key(self): @@ -677,7 +572,7 @@ def algorithm(self): @algorithm.setter def algorithm(self, value=_ALGORITHM): # build an Algorithm type if passed a string... - if isinstance(value, str): + if isinstance(value, unicode): value = Algorithm(value) caom_util.type_check(value, Algorithm, 'algorithm', override=False) caom_util.value_check(value, None, None, 'algorithm', override=self._ALGORITHM) @@ -747,7 +642,7 @@ def members(self): return self._members -class Environment(caom_object.CaomObject): +class Environment(CaomObject): """A CAOM2 Environment Object. This object contains the various values that can be set in the environment @@ -870,7 +765,7 @@ def photometric(self, value): self._photometric = value -class Instrument(caom_object.CaomObject): +class Instrument(CaomObject): """The telescopic instrument that recorded a given observation. Each observation should have an associated instrument. @@ -890,7 +785,7 @@ def __init__(self, name): Arguments: name - name of the instrument """ - caom_util.type_check(name, str, 'name', override='none') + caom_util.type_check(name, unicode, 'name', override='none') self._name = name self._keywords = set() @@ -899,7 +794,7 @@ def __init__(self, name): def name(self): """The name of the instrument. - type: str + type: unicode """ return self._name @@ -923,7 +818,7 @@ def keywords(self): return self._keywords -class Proposal(caom_object.CaomObject): +class Proposal(CaomObject): """ Proposal """ def __init__(self, @@ -951,13 +846,13 @@ def __init__(self, def proposal_id(self): """The proposal ID. Sometimes also called a RUNID. - type: str + type: unicode """ return self._proposal_id @proposal_id.setter def proposal_id(self, value): - caom_util.type_check(value, str, 'id') + caom_util.type_check(value, unicode, 'id') self._proposal_id = value @property @@ -983,43 +878,43 @@ def pi_name(self): """The name (First Last) of the Principle Investigator of the Proposal. - type: str + type: unicode """ return self._pi_name @pi_name.setter def pi_name(self, value): - caom_util.type_check(value, str, 'pi_name') + caom_util.type_check(value, unicode, 'pi_name') self._pi_name = value @property def project(self): """The name of a project associated with this proposal. - type: str + type: unicode """ return self._project @project.setter def project(self, value): - caom_util.type_check(value, str, 'project') + caom_util.type_check(value, unicode, 'project') self._project = value @property def title(self): """The title of the proposal. - type: str + type: unicode """ return self._title @title.setter def title(self, value): - caom_util.type_check(value, str, 'title') + caom_util.type_check(value, unicode, 'title') self._title = value -class Requirements(caom_object.CaomObject): +class Requirements(CaomObject): """ Requirements """ def __init__(self, flag): @@ -1042,7 +937,7 @@ def flag(self, value): self._flag = value -class Target(caom_object.CaomObject): +class Target(CaomObject): """ Target """ def __init__(self, name, @@ -1075,30 +970,30 @@ def name(self): """A name for the target eg 'NGC 3115' - type: str + type: unicode """ return self._name @name.setter def name(self, value): - caom_util.type_check(value, str, "name", override=False) + caom_util.type_check(value, unicode, "name", override=False) self._name = value @property def target_type(self): """A keyword describing the type of target. - - must be from the list - """ + ",".join(TargetType.names()) + """ - type: TargetType - """ + # must be from the list + # """ + ",".join(TargetType.names()) + """ + # type: TargetType + # + # """ return self._type @target_type.setter def target_type(self, value): - if isinstance(value, str): + if isinstance(value, unicode): value = TargetType(value) caom_util.type_check(value, TargetType, "target_type") self._type = value @@ -1165,7 +1060,7 @@ def moving(self, value): self._moving = value -class TargetPosition(caom_object.CaomObject): +class TargetPosition(CaomObject): """ TargetPosition """ def __init__(self, coordinates, coordsys, equinox=None): @@ -1190,7 +1085,7 @@ def coordinates(self): @coordinates.setter def coordinates(self, value): - caom_util.type_check(value, shape.Point, "coordinates") + caom_util.type_check(value, Point, "coordinates") self._coordinates = value @property @@ -1200,7 +1095,7 @@ def coordsys(self): @coordsys.setter def coordsys(self, value): - caom_util.type_check(value, str, "coordsys") + caom_util.type_check(value, unicode, "coordsys") self._coordsys = value @property @@ -1214,7 +1109,7 @@ def equinox(self, value): self._equinox = value -class Telescope(caom_object.CaomObject): +class Telescope(CaomObject): """ Telescope """ def __init__(self, name, @@ -1231,7 +1126,7 @@ def __init__(self, name, """ assert name is not None, "No telescope name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) + assert isinstance(name, unicode), "name is not a str: {0}".format(name) self.name = name self.geo_location_x = geo_location_x self.geo_location_y = geo_location_y @@ -1247,14 +1142,14 @@ def name(self): """a name for this facility. eg. CFHT - type: str + type: unicode """ return self._name @name.setter def name(self, value): - caom_util.type_check(value, str, 'name', override=False) + caom_util.type_check(value, unicode, 'name', override=False) self._name = value @property diff --git a/caom2/caom2/part.py b/caom2/caom2/part.py index b5477755..8f594088 100644 --- a/caom2/caom2/part.py +++ b/caom2/caom2/part.py @@ -73,14 +73,15 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -from . import caom_object from . import caom_util -from . import chunk +from .chunk import Chunk +from .chunk import ProductType +from .common import AbstractCaomEntity __all__ = ['Part'] -class Part(caom_object.AbstractCaomEntity): +class Part(AbstractCaomEntity): """A qualitative subsection of an artifact. eg: a extension of a FITS file. @@ -94,7 +95,7 @@ def __init__(self, name, product_type=None, chunks=None): self.name = name self.product_type = product_type if chunks is None: - chunks = caom_util.TypedList(chunk.Chunk, ) + chunks = caom_util.TypedList(Chunk, ) self.chunks = chunks def _key(self): @@ -113,12 +114,12 @@ def product_type(self): """The type of data product referred to by this part. Must be one of the allowed data product types: - str(ProductType.names())""" + unicode(ProductType.names())""" return self._product_type @product_type.setter def product_type(self, value): - caom_util.type_check(value, chunk.ProductType, "product_type") + caom_util.type_check(value, ProductType, "product_type") self._product_type = value @property @@ -131,7 +132,7 @@ def name(self): @name.setter def name(self, value): - caom_util.type_check(value, str, 'name', override=False) + caom_util.type_check(value, unicode, 'name', override=False) self._name = value @property diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py index c84577de..47214cb5 100644 --- a/caom2/caom2/plane.py +++ b/caom2/caom2/plane.py @@ -77,13 +77,14 @@ from urlparse import urlsplit from enum import Enum -from . import artifact -from . import caom_object + from . import caom_util -# from . import observation -from .observation import ObservationURI from . import shape from . import wcs +from .artifact import Artifact +from .common import AbstractCaomEntity +from .common import CaomObject +from .common import ObservationURI # CalibrationLevel = Enum('CalibrationLevel', # RAW_INSTRUMENT=0, @@ -220,7 +221,7 @@ class Quality(Enum): JUNK = "junk" -class Plane(caom_object.AbstractCaomEntity): +class Plane(AbstractCaomEntity): """ Plane class """ def __init__(self, product_id, @@ -241,7 +242,7 @@ def __init__(self, product_id, super(Plane, self).__init__() self.product_id = product_id if artifacts is None: - artifacts = caom_util.TypedOrderedDict(artifact.Artifact, ) + artifacts = caom_util.TypedOrderedDict(Artifact, ) self.artifacts = artifacts self.meta_release = meta_release @@ -272,13 +273,13 @@ def product_id(self): observation, that is stored in this plane. eg: '1234567p' - type: str + type: unicode """ return self._product_id @product_id.setter def product_id(self, value): - caom_util.type_check(value, str, 'product_id', override=False) + caom_util.type_check(value, unicode, 'product_id', override=False) self._product_id = value @property @@ -375,7 +376,7 @@ def calibration_level(self): is converted to an integer during storage. eg. Plane.calibration_level = "RAW_STANDARD" - type: str + type: unicode Must be one of CalibrationLevel.names() @@ -497,7 +498,7 @@ def compute_polarization(self): "has not been implemented in this module") -class PlaneURI(caom_object.CaomObject): +class PlaneURI(CaomObject): """ Plane URI """ def __init__(self, uri): @@ -533,7 +534,7 @@ def get_plane_uri(cls, observation_uri, product_id): """ caom_util.type_check(observation_uri, ObservationURI, "observation_uri", override=False) - caom_util.type_check(product_id, str, "observation_uri", override=False) + caom_util.type_check(product_id, unicode, "observation_uri", override=False) caom_util.validate_path_component(cls, "product_id", product_id) path = urlsplit(observation_uri.uri).path @@ -550,7 +551,7 @@ def uri(self): @uri.setter def uri(self, value): - caom_util.type_check(value, str, "uri", override=False) + caom_util.type_check(value, unicode, "uri", override=False) tmp = urlsplit(value) if tmp.scheme != ObservationURI._SCHEME: @@ -581,7 +582,7 @@ def observation_uri(self): return self._observation_uri -class DataQuality(caom_object.CaomObject): +class DataQuality(CaomObject): """ DataQuality """ def __init__(self, flag): @@ -604,7 +605,7 @@ def flag(self, value): self._flag = value -class Metrics(caom_object.CaomObject): +class Metrics(CaomObject): """ Metrics """ def __init__(self): @@ -702,7 +703,7 @@ def mag_limit(self, value): self._mag_limit = value -class Provenance(caom_object.CaomObject): +class Provenance(CaomObject): """ Provenance """ def __init__(self, name, @@ -720,7 +721,7 @@ def __init__(self, name, """ assert name is not None, "No name provided" - assert isinstance(name, str), "name is not a str: {0}".format(name) + assert isinstance(name, unicode), "name is not a unicode: {0}".format(name) self._name = name self.version = version @@ -747,7 +748,7 @@ def version(self): @version.setter def version(self, value): - caom_util.type_check(value, str, 'version') + caom_util.type_check(value, unicode, 'version') self._version = value @property @@ -757,7 +758,7 @@ def project(self): @project.setter def project(self, value): - caom_util.type_check(value, str, 'project') + caom_util.type_check(value, unicode, 'project') self._project = value @property @@ -767,7 +768,7 @@ def producer(self): @producer.setter def producer(self, value): - caom_util.type_check(value, str, 'producer') + caom_util.type_check(value, unicode, 'producer') self._producer = value @property @@ -777,7 +778,7 @@ def run_id(self): @run_id.setter def run_id(self, value): - caom_util.type_check(value, str, 'run_id') + caom_util.type_check(value, unicode, 'run_id') self._run_id = value @property @@ -787,7 +788,7 @@ def reference(self): @reference.setter def reference(self, value): - caom_util.type_check(value, str, 'version') + caom_util.type_check(value, unicode, 'version') if value is not None: tmp = urlsplit(value) assert tmp.geturl() == value, "Invalid URI: " + value @@ -805,7 +806,7 @@ def last_executed(self, value): @property def keywords(self): - """ Set of keywords as str""" + """ Set of keywords as unicode""" return self._keywords @property @@ -814,7 +815,7 @@ def inputs(self): return self._inputs -class Position(caom_object.CaomObject): +class Position(CaomObject): """ Position """ def __init__(self, bounds=None, @@ -898,7 +899,7 @@ def time_dependent(self, value): self._time_dependent = value -class Energy(caom_object.CaomObject): +class Energy(CaomObject): """ Energy """ def __init__(self): @@ -986,8 +987,8 @@ def bandpass_name(self): @bandpass_name.setter def bandpass_name(self, value): if value is not None: - assert isinstance(value, str), ( - "bandpass name is not str: {0}".format(value)) + assert isinstance(value, unicode), ( + "bandpass name is not unicode: {0}".format(value)) self._bandpass_name = value @property @@ -1015,7 +1016,7 @@ def transition(self, value): self._transition = value -class Polarization(caom_object.CaomObject): +class Polarization(CaomObject): """ Polarization """ def __init__(self, @@ -1047,7 +1048,7 @@ def dimension(self, value): self._dimension = value -class Time(caom_object.CaomObject): +class Time(CaomObject): """ Time """ def __init__(self, diff --git a/caom2/caom2/shape.py b/caom2/caom2/shape.py index b553cf44..c5520a49 100644 --- a/caom2/caom2/shape.py +++ b/caom2/caom2/shape.py @@ -71,7 +71,7 @@ unicode_literals) from enum import Enum -from . import caom_object +from . import common from . import caom_util __all__ = ['SegmentType', 'Box', 'Circle', 'Interval', 'Point', 'Polygon', 'Vertex'] @@ -88,25 +88,25 @@ class SegmentType(Enum): MOVE = 2 -class Box(caom_object.CaomObject): +class Box(common.CaomObject): def __init__(self): pass -class Circle(caom_object.CaomObject): +class Circle(common.CaomObject): def __init__(self): pass -class Interval(caom_object.CaomObject): +class Interval(common.CaomObject): def __init__(self): pass -class Point(caom_object.CaomObject): +class Point(common.CaomObject): def __init__(self, cval1, cval2): @@ -138,13 +138,13 @@ def cval2(self, value): self._cval2 = value -class Polygon(caom_object.CaomObject): +class Polygon(common.CaomObject): def __init__(self): pass -class Vertex(caom_object.CaomObject): +class Vertex(common.CaomObject): def __init__(self): pass diff --git a/caom2/caom2/tests/caom_test_instances.py b/caom2/caom2/tests/caom_test_instances.py index 51220e2a..3a6a4a84 100644 --- a/caom2/caom2/tests/caom_test_instances.py +++ b/caom2/caom2/tests/caom_test_instances.py @@ -300,8 +300,8 @@ def get_parts(self): if self.complete: _part.product_type = chunk.ProductType.SCIENCE if self.depth > 4: - for chunk in self.get_chunks(): - _part.chunks.append(chunk) + for _chunk in self.get_chunks(): + _part.chunks.append(_chunk) parts["x"] = _part return parts diff --git a/caom2/caom2/tests/test_artifact.py b/caom2/caom2/tests/test_artifact.py index 592f37e2..d2d82b4d 100644 --- a/caom2/caom2/tests/test_artifact.py +++ b/caom2/caom2/tests/test_artifact.py @@ -93,28 +93,28 @@ def test_all(self): test_artifact = artifact.Artifact("caom:GEMINI/12345") with self.assertRaises(TypeError): test_artifact = artifact.Artifact("caom:GEMINI/12345", - artifact.ReleaseType('META'), - artifact.ProductType('THUMBNAIL')) + artifact.ReleaseType.META, + artifact.ProductType.THUMBNAIL) with self.assertRaises(TypeError): test_artifact = artifact.Artifact("caom:GEMINI/12345", - artifact.ProductType('THUMBNAIL'), + artifact.ProductType.THUMBNAIL, None) with self.assertRaises(TypeError): test_artifact = artifact.Artifact("caom:GEMINI/12345", None, - artifact.ReleaseType('META')) + artifact.ReleaseType.META) test_artifact = artifact.Artifact("caom:GEMINI/12345", - artifact.ProductType('THUMBNAIL'), - artifact.ReleaseType('META')) + artifact.ProductType.THUMBNAIL, + artifact.ReleaseType.META) urlparse("caom:GEMINI/12345") self.assertEqual("caom:GEMINI/12345", test_artifact.uri, "Artifact URI") - self.assertEqual(artifact.ProductType('THUMBNAIL'), + self.assertEqual(artifact.ProductType.THUMBNAIL, test_artifact.product_type, "Artifact ProductType") - self.assertEqual(artifact.ReleaseType('META'), + self.assertEqual(artifact.ReleaseType.META, test_artifact.release_type, "Artifact ReleaseType") diff --git a/caom2/caom2/tests/test_caom_util.py b/caom2/caom2/tests/test_caom_util.py index d26a53ef..5f32ee68 100644 --- a/caom2/caom2/tests/test_caom_util.py +++ b/caom2/caom2/tests/test_caom_util.py @@ -83,7 +83,7 @@ class TestCaomUtil(unittest.TestCase): def test_typed_list(self): - my_list1 = caom_util.TypedList(str, "Test1") + my_list1 = caom_util.TypedList(unicode, "Test1") self.assertEquals(1, len(my_list1), "list1 length") self.assertEqual("Test1", my_list1[0], "Non matching elements") @@ -124,7 +124,7 @@ def test_typed_list(self): exception = False try: - my_list2 = caom_util.TypedList(str, 1, 3) + my_list2 = caom_util.TypedList(unicode, 1, 3) except AssertionError: exception = True self.assertTrue(exception, "Exception thrown") @@ -133,7 +133,7 @@ def test_typed_list(self): self.assertEqual("Test1", my_list1[0], "Non matching elements") self.assertEqual("Test2", my_list1[1], "Non matching elements") - my_list2 = caom_util.TypedList(str, "Test3", "Test4") + my_list2 = caom_util.TypedList(unicode, "Test3", "Test4") my_list1.extend(my_list2) self.assertEquals(4, len(my_list1), "list1 length") self.assertEqual("Test1", my_list1[0], "Non matching elements") @@ -186,15 +186,15 @@ def test_validate_path_component(self): def test_typed_set(self): - my_set = caom_util.TypedSet(str,) + my_set = caom_util.TypedSet(unicode,) with self.assertRaises(AssertionError): my_set.add(float(1.0)) my_set.add(long(1)) my_set.add(bool(1)) - self.assertRaises(AssertionError, caom_util.TypedSet, str, float(1.0)) + self.assertRaises(AssertionError, caom_util.TypedSet, unicode, float(1.0)) - my_set = caom_util.TypedSet(str, "Test1") + my_set = caom_util.TypedSet(unicode, "Test1") self.assertEquals(1, len(my_set)) self.assertEqual("Test1", my_set.pop()) @@ -207,7 +207,7 @@ def test_typed_set(self): my_set.add(bool(1)) my_set.add("Test1") - my_set = caom_util.TypedSet(str,) + my_set = caom_util.TypedSet(unicode,) my_set.add("Test1") my_set.add("Test1") self.assertTrue(len(my_set) == 1) @@ -216,9 +216,9 @@ def test_typed_ordered_dict(self): # test validation and constructor with an empty dictionary test_plane10 = plane.Plane('key10') - test_artifact66 = artifact.Artifact('caom:CFHT/55/66', + test_artifact66 = artifact.Artifact("caom:CFHT/55/66", chunk.ProductType.SCIENCE, - chunk.ReleaseType.DATA) + artifact.ReleaseType.DATA) test_part10 = part.Part("10") test_plane_uri = plane.PlaneURI('caom:CFHT/55/66') my_dict_plane = caom_util.TypedOrderedDict(plane.Plane,) @@ -257,7 +257,7 @@ def test_typed_ordered_dict(self): test_plane1 = plane.Plane('key1') test_plane2 = plane.Plane('key2') my_dict1 = caom_util.TypedOrderedDict(plane.Plane, ('key1', test_plane1), - ('key2', test_plane2)) + ('key2', test_plane2)) self.assertEqual(2, len(my_dict1), 'mismatch in the number of entries in dictionary.') # test assignment via setdefault diff --git a/caom2/caom2/tests/test_chunk.py b/caom2/caom2/tests/test_chunk.py index c60772e4..ccc91c50 100644 --- a/caom2/caom2/tests/test_chunk.py +++ b/caom2/caom2/tests/test_chunk.py @@ -82,22 +82,20 @@ class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(chunk.ProductType.get("no_such_string"), None) - self.assertRaises(AttributeError, chunk.ProductType.get, None) - self.assertRaises(AttributeError, chunk.ProductType.get, 1) + with self.assertRaises(ValueError): + chunk.ProductType("no_such_string") + with self.assertRaises(ValueError): + chunk.ProductType(None) + with self.assertRaises(ValueError): + chunk.ProductType(1) # test that we can get the object for each enum by name self.assertEqual(chunk.ProductType.SCIENCE.name, "SCIENCE") - self.assertEqual(chunk.ProductType.get( - chunk.ProductType.SCIENCE.name).name, "SCIENCE") - self.assertEqual(chunk.ProductType.get( - 'SCIENCE').value, "science") - self.assertEqual(chunk.ProductType.get( - chunk.ProductType.SCIENCE.name).value, "science") - self.assertEqual(chunk.ProductType.getByValue( - chunk.ProductType.SCIENCE.value).value, "science") - self.assertEqual(chunk.ProductType.getByValue( - chunk.ProductType.SCIENCE.value).name, "SCIENCE") + self.assertEqual(chunk.ProductType[ + chunk.ProductType.SCIENCE.name].name, "SCIENCE") + self.assertEqual(chunk.ProductType['SCIENCE'].value, "science") + self.assertEqual(chunk.ProductType[ + chunk.ProductType.SCIENCE.name].value, "science") self.assertEqual(chunk.ProductType.SCIENCE.value, "science") self.assertEqual(chunk.ProductType.CALIBRATION.value, "calibration") @@ -145,7 +143,7 @@ def test_attributes(self): test_chunk.polarization = float(1.0) test_chunk.product_type = chunk.ProductType.SCIENCE - self.assertEqual(chunk.ProductType.SCIENCE, test_chunk.product_type) + self.assertEqual(chunk.ProductType.SCIENCE.name, test_chunk.product_type.name) test_chunk.naxis = int(5) self.assertEqual(int(5), test_chunk.naxis) @@ -325,10 +323,10 @@ def test_init(self): time.resolution = float(2.0) self.assertEqual(time.resolution, float(2.0)) - time.timesys = str("timesys") + time.timesys = "timesys" self.assertEqual(time.timesys, "timesys") - time.trefpos = str("trefpos") + time.trefpos = "trefpos" self.assertEqual(time.trefpos, "trefpos") time.mjdref = float(3.0) diff --git a/caom2/caom2/tests/test_caom_object.py b/caom2/caom2/tests/test_common.py similarity index 79% rename from caom2/caom2/tests/test_caom_object.py rename to caom2/caom2/tests/test_common.py index a4f3c474..6bed5256 100644 --- a/caom2/caom2/tests/test_caom_object.py +++ b/caom2/caom2/tests/test_common.py @@ -74,7 +74,7 @@ import unittest -from .. import caom_object +from .. import common from .. import chunk from .. import part from .. import plane @@ -85,12 +85,12 @@ class TestCaom2IdGenerator(unittest.TestCase): def test_all(self): - #Not much for now. Just to make sure that all the clients work - test_entity = caom_object.AbstractCaomEntity() + # Not much for now. Just to make sure that all the clients work + test_entity = common.AbstractCaomEntity() print(test_entity._id, test_entity._last_modified) test_artifact = artifact.Artifact("caom2:/blah/blah", chunk.ProductType.SCIENCE, - chunk.ReleaseType.DATA) + artifact.ReleaseType.DATA) print(test_artifact._id, test_artifact._last_modified) test_chunk = chunk.Chunk() @@ -105,3 +105,31 @@ def test_all(self): test_plane = plane.Plane("prodid") print(test_plane._id, test_plane._last_modified) + + +class TestObservationURI(unittest.TestCase): + + def test_all(self): + obs_uri = observation.ObservationURI("caom:GEMINI/12345") + self.assertEqual("caom:GEMINI/12345", obs_uri.uri, "Observation URI") + self.assertEqual("GEMINI", obs_uri.collection, "Collection") + self.assertEqual("12345", obs_uri.observation_id, "Observation ID") + + obs_uri = observation.ObservationURI.get_observation_uri("CFHT", "654321") + self.assertEqual("caom:CFHT/654321", obs_uri.uri, "Observation URI") + self.assertEqual("CFHT", obs_uri.collection, "Collection") + self.assertEqual("654321", obs_uri.observation_id, "Observation ID") + + exception = False + try: + obs_uri = observation.ObservationURI.get_observation_uri(None, "123") + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") + + exception = False + try: + obs_uri = observation.ObservationURI.get_observation_uri("GEMINI", None) + except TypeError: + exception = True + self.assertTrue(exception, "Missing exception") diff --git a/caom2/caom2/tests/test_obs_reader_writer.py b/caom2/caom2/tests/test_obs_reader_writer.py index 15b30678..e2973ec9 100644 --- a/caom2/caom2/tests/test_obs_reader_writer.py +++ b/caom2/caom2/tests/test_obs_reader_writer.py @@ -79,7 +79,7 @@ from lxml import etree from xml_compare import xml_compare -import caom_test_instances +from . import caom_test_instances from .. import obs_reader_writer from .. import observation from .. import wcs diff --git a/caom2/caom2/tests/test_observation.py b/caom2/caom2/tests/test_observation.py index 34dd7f34..f6b5dae1 100644 --- a/caom2/caom2/tests/test_observation.py +++ b/caom2/caom2/tests/test_observation.py @@ -85,17 +85,26 @@ class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(observation.ObservationIntentType.get("no_such_string"), None) - self.assertRaises(AttributeError, observation.ObservationIntentType.get, None) - self.assertRaises(AttributeError, observation.ObservationIntentType.get, 1) - - self.assertEqual(observation.Status.get("no_such_string"), None) - self.assertRaises(AttributeError, observation.Status.get, None) - self.assertRaises(AttributeError, observation.Status.get, 1) - - self.assertEqual(observation.TargetType.get("no_such_string"), None) - self.assertRaises(AttributeError, observation.TargetType.get, None) - self.assertRaises(AttributeError, observation.TargetType.get, 1) + with self.assertRaises(KeyError): + observation.ObservationIntentType["no_such_string"] + with self.assertRaises(ValueError): + observation.ObservationIntentType(None) + with self.assertRaises(ValueError): + observation.ObservationIntentType(1) + + with self.assertRaises(KeyError): + observation.Status["no_such_string"] + with self.assertRaises(ValueError): + observation.Status(None) + with self.assertRaises(ValueError): + observation.Status(1) + + with self.assertRaises(KeyError): + observation.TargetType["no_such_string"] + with self.assertRaises(ValueError): + observation.TargetType(None) + with self.assertRaises(ValueError): + observation.TargetType(1) # test that we can get the object for each enum by name self.assertEqual(observation.ObservationIntentType.CALIBRATION.value, "calibration") @@ -211,34 +220,6 @@ def test_all(self): target_position=obs.target_position) -class TestObservationURI(unittest.TestCase): - - def test_all(self): - obs_uri = observation.ObservationURI("caom:GEMINI/12345") - self.assertEqual("caom:GEMINI/12345", obs_uri.uri, "Observation URI") - self.assertEqual("GEMINI", obs_uri.collection, "Collection") - self.assertEqual("12345", obs_uri.observation_id, "Observation ID") - - obs_uri = observation.ObservationURI.get_observation_uri("CFHT", "654321") - self.assertEqual("caom:CFHT/654321", obs_uri.uri, "Observation URI") - self.assertEqual("CFHT", obs_uri.collection, "Collection") - self.assertEqual("654321", obs_uri.observation_id, "Observation ID") - - exception = False - try: - obs_uri = observation.ObservationURI.get_observation_uri(None, "123") - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - exception = False - try: - obs_uri = observation.ObservationURI.get_observation_uri("GEMINI", None) - except TypeError: - exception = True - self.assertTrue(exception, "Missing exception") - - class TestSimpleObservation(unittest.TestCase): def test_all(self): @@ -319,12 +300,12 @@ def test_all(self): # Test the complete constructor def test_complete_init(self): - collection = str("CFHT") - observation_id = str("543210") + collection = "CFHT" + observation_id = "543210" algorithm = observation.SimpleObservation._ALGORITHM sequence_number = int(3) intent = observation.ObservationIntentType.SCIENCE - obs_type = str("foo") + obs_type = "foo" proposal = observation.Proposal("123") telescope = observation.Telescope("TEL") instrument = observation.Instrument("INST") @@ -491,12 +472,12 @@ def test_all(self): # Test the complete constructor def test_complete_init(self): - collection = str("CFHT") - observation_id = str("543210") - algorithm = str("algo") + collection = "CFHT" + observation_id = "543210" + algorithm = "algo" sequence_number = int(3) intent = observation.ObservationIntentType.SCIENCE - obs_type = str("foo") + obs_type = "foo" proposal = observation.Proposal("123") telescope = observation.Telescope("TEL") instrument = observation.Instrument("INST") @@ -659,7 +640,7 @@ def test_all(self): self.assertEqual("myTarget", target.name, "target name") target.target_type = observation.TargetType.FIELD - self.assertEqual(observation.TargetType.FIELD, target.target_type, "target type") + self.assertEqual(observation.TargetType.FIELD.name, target.target_type.name, "target type") self.assertEqual(0, len(target.keywords), "Default number of keywords") target.keywords.add("optical") diff --git a/caom2/caom2/tests/test_plane.py b/caom2/caom2/tests/test_plane.py index 1e097156..98983c58 100644 --- a/caom2/caom2/tests/test_plane.py +++ b/caom2/caom2/tests/test_plane.py @@ -86,25 +86,40 @@ class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(plane.CalibrationLevel.get("no_such_string"), None) - self.assertRaises(AttributeError, plane.CalibrationLevel.get, None) - self.assertRaises(AttributeError, plane.CalibrationLevel.get, 999) - - self.assertEqual(plane.DataProductType.get("no_such_string"), None) - self.assertRaises(AttributeError, plane.DataProductType.get, None) - self.assertRaises(AttributeError, plane.DataProductType.get, 1) - - self.assertEqual(plane.EnergyBand.get("no_such_string"), None) - self.assertRaises(AttributeError, plane.EnergyBand.get, None) - self.assertRaises(AttributeError, plane.EnergyBand.get, 1) - - self.assertEqual(plane.PolarizationState.get("no_such_string"), None) - self.assertRaises(AttributeError, plane.PolarizationState.get, None) - self.assertRaises(AttributeError, plane.PolarizationState.get, 1) - - self.assertEqual(plane.Quality.get("no_such_string"), None) - self.assertRaises(AttributeError, plane.Quality.get, None) - self.assertRaises(AttributeError, plane.Quality.get, 1) + with self.assertRaises(ValueError): + plane.CalibrationLevel("no_such_string") + with self.assertRaises(ValueError): + plane.CalibrationLevel(None) + with self.assertRaises(ValueError): + plane.CalibrationLevel(999) + + with self.assertRaises(ValueError): + plane.DataProductType("no_such_string") + with self.assertRaises(ValueError): + plane.DataProductType(None) + with self.assertRaises(ValueError): + plane.DataProductType(1) + + with self.assertRaises(ValueError): + plane.EnergyBand("no_such_string") + with self.assertRaises(ValueError): + plane.EnergyBand(None) + with self.assertRaises(ValueError): + plane.EnergyBand(1) + + with self.assertRaises(ValueError): + plane.PolarizationState("no_such_string") + with self.assertRaises(ValueError): + plane.PolarizationState(None) + with self.assertRaises(ValueError): + plane.PolarizationState(1) + + with self.assertRaises(ValueError): + plane.Quality("no_such_string") + with self.assertRaises(ValueError): + plane.Quality(None) + with self.assertRaises(ValueError): + plane.Quality(1) # test that we can get the object for each enum by name self.assertEqual(plane.CalibrationLevel.RAW_INSTRUMENT.value, 0) @@ -120,29 +135,29 @@ def test_all(self): self.assertEqual(plane.DataProductType.TIMESERIES.value, "timeseries") self.assertEqual(plane.DataProductType.VISIBILITY.value, "visibility") - self.assertEqual(plane.EnergyBand.get('RADIO').value, "Radio") - self.assertEqual(plane.EnergyBand.get('MILLIMETER').value, "Millimeter") - self.assertEqual(plane.EnergyBand.get('INFRARED').value, "Infrared") - self.assertEqual(plane.EnergyBand.get('OPTICAL').value, "Optical") - self.assertEqual(plane.EnergyBand.get('UV').value, "UV") - self.assertEqual(plane.EnergyBand.get('EUV').value, "EUV") - self.assertEqual(plane.EnergyBand.get('XRAY').value, "X-ray") - self.assertEqual(plane.EnergyBand.get('GAMMARAY').value, "Gamma-ray") - - self.assertEqual(plane.PolarizationState.get('I').value, "I") - self.assertEqual(plane.PolarizationState.get('Q').value, "Q") - self.assertEqual(plane.PolarizationState.get('U').value, "U") - self.assertEqual(plane.PolarizationState.get('V').value, "V") - self.assertEqual(plane.PolarizationState.get('LL').value, "LL") - self.assertEqual(plane.PolarizationState.get('LR').value, "LR") - self.assertEqual(plane.PolarizationState.get('RL').value, "RL") - self.assertEqual(plane.PolarizationState.get('RR').value, "RR") - self.assertEqual(plane.PolarizationState.get('XX').value, "XX") - self.assertEqual(plane.PolarizationState.get('XY').value, "XY") - self.assertEqual(plane.PolarizationState.get('YX').value, "YX") - self.assertEqual(plane.PolarizationState.get('YY').value, "YY") - - self.assertEqual(plane.Quality.get('JUNK').value, "junk") + self.assertEqual(plane.EnergyBand['RADIO'].value, "Radio") + self.assertEqual(plane.EnergyBand['MILLIMETER'].value, "Millimeter") + self.assertEqual(plane.EnergyBand['INFRARED'].value, "Infrared") + self.assertEqual(plane.EnergyBand['OPTICAL'].value, "Optical") + self.assertEqual(plane.EnergyBand['UV'].value, "UV") + self.assertEqual(plane.EnergyBand['EUV'].value, "EUV") + self.assertEqual(plane.EnergyBand['XRAY'].value, "X-ray") + self.assertEqual(plane.EnergyBand['GAMMARAY'].value, "Gamma-ray") + + self.assertEqual(plane.PolarizationState['I'].value, "I") + self.assertEqual(plane.PolarizationState['Q'].value, "Q") + self.assertEqual(plane.PolarizationState['U'].value, "U") + self.assertEqual(plane.PolarizationState['V'].value, "V") + self.assertEqual(plane.PolarizationState['LL'].value, "LL") + self.assertEqual(plane.PolarizationState['LR'].value, "LR") + self.assertEqual(plane.PolarizationState['RL'].value, "RL") + self.assertEqual(plane.PolarizationState['RR'].value, "RR") + self.assertEqual(plane.PolarizationState['XX'].value, "XX") + self.assertEqual(plane.PolarizationState['XY'].value, "XY") + self.assertEqual(plane.PolarizationState['YX'].value, "YX") + self.assertEqual(plane.PolarizationState['YY'].value, "YY") + + self.assertEqual(plane.Quality['JUNK'].value, "junk") class TestPlane(unittest.TestCase): diff --git a/caom2/caom2/tests/test_shape.py b/caom2/caom2/tests/test_shape.py index da1f8177..2e9d0e6d 100644 --- a/caom2/caom2/tests/test_shape.py +++ b/caom2/caom2/tests/test_shape.py @@ -79,10 +79,19 @@ class TestEnums(unittest.TestCase): def test_all(self): # test for invalid value - self.assertEqual(shape.SegmentType.get("foo"), None) - self.assertRaises(AttributeError, shape.SegmentType.get, None) - self.assertRaises(AttributeError, shape.SegmentType.get, 999) + with self.assertRaises(KeyError): + shape.SegmentType["foo"] + with self.assertRaises(KeyError): + shape.SegmentType[None] + with self.assertRaises(KeyError): + shape.SegmentType[999] + with self.assertRaises(ValueError): + shape.SegmentType("foo") + with self.assertRaises(ValueError): + shape.SegmentType(None) + with self.assertRaises(ValueError): + shape.SegmentType(4) self.assertEqual(shape.SegmentType.CLOSE.value, 0) self.assertEqual(shape.SegmentType.LINE.value, 1) self.assertEqual(shape.SegmentType.MOVE.value, 2) diff --git a/caom2/caom2/wcs.py b/caom2/caom2/wcs.py index d944e23c..70e8e4bc 100644 --- a/caom2/caom2/wcs.py +++ b/caom2/caom2/wcs.py @@ -70,7 +70,7 @@ from __future__ import (absolute_import, division, print_function, unicode_literals) -from . import caom_object +from . import common from . import caom_util __all__ = ['Axis', 'Coord2D', 'CoordAxis1D', 'CoordAxis2D', 'CoordBounds1D', 'CoordBounds2D', 'CoordCircle2D', @@ -78,7 +78,7 @@ 'Dimension2D', 'EnergyTransition', 'RefCoord', 'Slice', 'ValueCoord2D'] -class Axis(caom_object.CaomObject): +class Axis(common.CaomObject): """the Axis class holds the definition of the axis type and units""" def __init__(self, ctype, cunit=None): @@ -91,14 +91,14 @@ def ctype(self): """The Coordinate Type value for this axis. eg. DEC - type: str + type: unicode """ return self._ctype @ctype.setter def ctype(self, value): - caom_util.type_check(value, str, 'ctype', override=False) + caom_util.type_check(value, unicode, 'ctype', override=False) self._ctype = value @property @@ -106,18 +106,18 @@ def cunit(self): """The unit of the coordinate that results after transform. eg. deg - type: str + type: unicode """ return self._cunit @cunit.setter def cunit(self, value): - caom_util.type_check(value, str, 'cunit') + caom_util.type_check(value, unicode, 'cunit') self._cunit = value -class Coord2D(caom_object.CaomObject): +class Coord2D(common.CaomObject): """Represents the reference point. eg: Coord2D(RefCoord(crpix1,crval1),RefCoord(crpix2,crval2)) @@ -154,7 +154,7 @@ def coord2(self, value): self._coord2 = value -class CoordAxis1D(caom_object.CaomObject): +class CoordAxis1D(common.CaomObject): """Holds the metadata needed to transform a 1D pixel value into a World Coordinate value. @@ -249,7 +249,7 @@ def function(self, value): self._function = value -class CoordAxis2D(caom_object.CaomObject): +class CoordAxis2D(common.CaomObject): """This object hold the metadata need to transform a 2D pixel array (say an image) into a World position, say RA/DEC @@ -371,7 +371,7 @@ def function(self, value): self._function = value -class CoordBounds1D(caom_object.CaomObject): +class CoordBounds1D(common.CaomObject): """Contains the bounds for a 1D axis, a list of ranges """ @@ -401,7 +401,7 @@ def samples(self, value): self._samples = value -class CoordBounds2D(caom_object.CaomObject): +class CoordBounds2D(common.CaomObject): """Contains the bounds for a 2D axis """ @@ -429,7 +429,7 @@ def bounds(self, value): self._bounds = value -class CoordCircle2D(caom_object.CaomObject): +class CoordCircle2D(common.CaomObject): """A circle expressed in both pixel and WCS value coordinates. These objects are used to map out the bounds of spatial WCS. @@ -474,7 +474,7 @@ def radius(self, value): self._radius = value -class CoordError(caom_object.CaomObject): +class CoordError(common.CaomObject): """Holds the systematic (syser) and random (rnder) error on a coordinate. @@ -523,7 +523,7 @@ def rnder(self, value): self._rnder = value -class CoordFunction1D(caom_object.CaomObject): +class CoordFunction1D(common.CaomObject): """Defines a linear function that transforms from pixel to WCS values. @@ -587,7 +587,7 @@ def ref_coord(self, value): self._ref_coord = value -class CoordFunction2D(caom_object.CaomObject): +class CoordFunction2D(common.CaomObject): """Describes the parameters needed for the standard CD matrix. defines a linear translation between pixel and WCS. @@ -697,7 +697,7 @@ def cd22(self, value): self._cd22 = value -class CoordPolygon2D(caom_object.CaomObject): +class CoordPolygon2D(common.CaomObject): """A object to contain a TypeList ValueCoord2D vertices that are a polygon. The vertices are given as ValueCoord2D objects, which are coordinate pairs. @@ -733,7 +733,7 @@ def vertices(self, value): self._vertices = value -class CoordRange1D(caom_object.CaomObject): +class CoordRange1D(common.CaomObject): """a CoordRange1D object contains the start and end of a range of values, expressed in both pixel and WCS units. @@ -774,7 +774,7 @@ def end(self, value): self._end = value -class CoordRange2D(caom_object.CaomObject): +class CoordRange2D(common.CaomObject): """A range (x1,y1) to (x2,y2) in two dimenstions. The range object should know the coordinate in both @@ -813,7 +813,7 @@ def end(self, value): self._end = value -class Dimension2D(caom_object.CaomObject): +class Dimension2D(common.CaomObject): """Hey, how big is this thing? What are its dimensions. That's what Dimension2D will tell you. @@ -858,7 +858,7 @@ def naxis2(self, value): self._naxis2 = value -class EnergyTransition(caom_object.CaomObject): +class EnergyTransition(common.CaomObject): """ EnergyTransition """ def __init__(self, species, transition): @@ -869,8 +869,8 @@ def __init__(self, species, transition): species transition """ - caom_util.type_check(species, str, "species", override=False) - caom_util.type_check(transition, str, "transition", override=False) + caom_util.type_check(species, unicode, "species", override=False) + caom_util.type_check(transition, unicode, "transition", override=False) self._species = species self._transition = transition @@ -885,7 +885,7 @@ def transition(self): return self._transition -class RefCoord(caom_object.CaomObject): +class RefCoord(common.CaomObject): """A refernce coordinate object, maps pixel value to wcs value """ @@ -930,7 +930,7 @@ def val(self, value): self._val = value -class Slice(caom_object.CaomObject): +class Slice(common.CaomObject): """defines a slice in a set of data contains values. The slice keeps track of the type/unit and values. @@ -973,7 +973,7 @@ def bin(self, value): self._bin = value -class ValueCoord2D(caom_object.CaomObject): +class ValueCoord2D(common.CaomObject): """Represents the reference point.""" def __init__(self, coord1, coord2): From 480e28827bfe65536814c996c55aa4a28dd14546 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Mon, 28 Nov 2016 15:14:23 -0800 Subject: [PATCH 39/54] Removed dependency on requests --- caom2/setup.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/caom2/setup.py b/caom2/setup.py index d9b51bd9..e4589445 100755 --- a/caom2/setup.py +++ b/caom2/setup.py @@ -47,7 +47,7 @@ builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME # VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -VERSION = metadata.get('version', '2.2.2') +VERSION = metadata.get('version', '0.dev') # Indicates if this version is a release version RELEASE = 'dev' not in VERSION @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['lxml', 'requests'], + install_requires=['lxml'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, From ba896fd46446167255f6e9759b7ebf8ff612f320 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Mon, 28 Nov 2016 21:59:37 -0800 Subject: [PATCH 40/54] Fixed the observation reader-writer tests --- caom2/caom2/caom_util.py | 4 +++- caom2/caom2/tests/test_caom_util.py | 2 +- caom2repo/caom2repo/core.py | 6 +++--- caom2repo/caom2repo/test/test_core.py | 4 ++-- 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index 1a5b28b2..da9e8ed5 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -149,7 +149,7 @@ def uuid2long(uid): return the UUID least significant bytes as a long. """ - longs = struct.unpack('>qq', str(uid.bytes)) + longs = struct.unpack(str('>qq'), str(uid.bytes)) if longs[0] != 0: raise ValueError("lossy conversion from UUID to long: {}".format(uid)) return longs[1] @@ -163,6 +163,8 @@ def long2uuid(l): foo = l.bit_length() if l.bit_length() > 63: raise ValueError("expected 64 bit long {}".format(l)) + if l < 0: + l = (1<<64L) + l return uuid.UUID(int=l) diff --git a/caom2/caom2/tests/test_caom_util.py b/caom2/caom2/tests/test_caom_util.py index 5f32ee68..728bd88d 100644 --- a/caom2/caom2/tests/test_caom_util.py +++ b/caom2/caom2/tests/test_caom_util.py @@ -296,7 +296,7 @@ def test_typed_ordered_dict(self): def test_uuid2long(self): # > 64 bit uuid - u = uuid.UUID('3d26e30b-10cc-4301-8193-f2e0c6b63302') + u = uuid.UUID('{3d26e30b-10cc-4301-8193-f2e0c6b63302}') try: caom_util.uuid2long(u) self.fail("> 64 uuid should raise ValueError") diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index 332395cb..9911db98 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -75,8 +75,8 @@ import os.path #TODO to be changed to io.StringIO when caom2 is prepared for python3 from StringIO import StringIO -from cadctools.net import ws -from cadctools.util import util +from cadctools import net +from cadctools import util from caom2.obs_reader_writer import ObservationReader, ObservationWriter @@ -101,7 +101,7 @@ def __init__(self, anon=True, cert_file=None, server=None): if server is not None: s = server agent = 'CAOM2RepoClient' #TODO add version - self._repo_client = ws.BaseWsClient(s, anon=anon, cert_file=cert_file, agent=agent, retry=True) + self._repo_client = net.BaseWsClient(s, anon=anon, cert_file=cert_file, agent=agent, retry=True) logging.info('Service URL: {}'.format(self._repo_client.base_url)) diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/test/test_core.py index 838a7548..54ba7cf6 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -175,7 +175,7 @@ def raise_error(): raise http_error # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.open', MagicMock(), create=True) - @patch('caom2repo.core.ws.BaseWsClient.get') + @patch('caom2repo.core.net.BaseWsClient.get') def test_get_observations(self, mock_get): # This is almost similar to the previous test except that it gets # observations matching a collection and start/end criteria @@ -402,7 +402,7 @@ def test_main(self, client_mock): client_mock.return_value.get_observation.return_value = obs core.main() client_mock.return_value.get_observation.assert_called_with(collection, observation_id) - # repeat with outout argument + # repeat with output argument sys.argv = ["caom2tools", "read", "--collection", collection, "--output", ifile, observation_id] client_mock.return_value.get_observation.return_value = obs core.main() From 3bf2f0526abb72a7c60b41cb33669487a7700f56 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 29 Nov 2016 10:30:11 -0800 Subject: [PATCH 41/54] s1950: cleanup --- caom2/caom2/__init__.py | 11 --------- caom2/caom2/artifact.py | 8 +++--- caom2/caom2/caom_util.py | 1 - caom2/caom2/chunk.py | 21 ++++------------ caom2/caom2/common.py | 10 -------- caom2/caom2/observation.py | 16 ++++++------ caom2/caom2/part.py | 2 +- caom2/caom2/plane.py | 50 +++----------------------------------- caom2/dev_requirements.txt | 1 + caom2/setup.py | 2 +- 10 files changed, 24 insertions(+), 98 deletions(-) diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 6d236e51..72729425 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -94,14 +94,3 @@ from plane import * from observation import * from obs_reader_writer import * - -# from obs_reader_writer import * -# from observation import * -# from plane import * -# from artifact import * -# from part import * -# from chunk import * -# from shape import * -# from wcs import * -# from caom_object import * -# from caom_util import * diff --git a/caom2/caom2/artifact.py b/caom2/caom2/artifact.py index 961a9004..446654fe 100644 --- a/caom2/caom2/artifact.py +++ b/caom2/caom2/artifact.py @@ -172,9 +172,9 @@ def product_type(self): """The product type associated with the Artifact. type: caom2.ProductType - restricted to caom2.ProductType.names() + restricted to caom2.ProductType - eg. Artifact.product_type = caom2.ProductType('SCIENCE') + eg. Artifact.product_type = caom2.ProductType['SCIENCE'] """ return self._product_type @@ -188,9 +188,9 @@ def release_type(self): """The release type associated with the Artifact. type: caom2.ReleaseType - restricted to caom2.ReleaseType.names() + restricted to caom2.ReleaseType - eg. Artifact.release = caom2.ReleaseType('META') + eg. Artifact.release = caom2.ReleaseType['META'] """ return self._release_type diff --git a/caom2/caom2/caom_util.py b/caom2/caom2/caom_util.py index da9e8ed5..3f4c3c7b 100644 --- a/caom2/caom2/caom_util.py +++ b/caom2/caom2/caom_util.py @@ -160,7 +160,6 @@ def long2uuid(l): Takes a long and creates a UUID using the 16 byte long as the least significant bytes in the 32 byte UUID. """ - foo = l.bit_length() if l.bit_length() > 63: raise ValueError("expected 64 bit long {}".format(l)) if l < 0: diff --git a/caom2/caom2/chunk.py b/caom2/caom2/chunk.py index a56f7983..9482c7ae 100644 --- a/caom2/caom2/chunk.py +++ b/caom2/caom2/chunk.py @@ -101,17 +101,6 @@ class ProductType(Enum): AUXILIARY = "auxiliary" THUMBNAIL = "thumbnail" -# ProductType = Enum('ProductType', -# SCIENCE="science", -# CALIBRATION="calibration", -# PREVIEW="preview", -# INFO="info", -# NOISE="noise", -# WEIGHT="weight", -# AUXILIARY="auxiliary", -# THUMBNAIL="thumbnail", -# ) - __all__ = ['ProductType', 'Chunk', 'ObservableAxis', 'SpatialWCS', 'SpectralWCS', 'TemporalWCS', 'PolarizationWCS'] @@ -172,11 +161,11 @@ def product_type(self): """A word that describes the content of the chunk. eg. Chunk.product_type = ProductType.SCIENCE + + Allowed values: + """ + str(list(ProductType)) + """ + """ - # Allowed values: - # """ + str(ProductType.names()) + """ - # - # """ return self._product_type @@ -639,7 +628,7 @@ def ssysobs(self): range of the non-spectral world coordinates For example, for a large image the the wavelength at the edges - is different from the centres. This refernce frame is one where they + is different from the centres. This reference frame is one where they are not different. Nominally 'TOPOCENT' diff --git a/caom2/caom2/common.py b/caom2/caom2/common.py index 2dab521e..f3e7fb15 100644 --- a/caom2/caom2/common.py +++ b/caom2/caom2/common.py @@ -71,8 +71,6 @@ unicode_literals) import inspect -import random -import time import uuid from datetime import datetime from urlparse import SplitResult @@ -80,7 +78,6 @@ from . import caom_util - __all__ = ['CaomObject', 'AbstractCaomEntity', 'ObservationURI'] @@ -142,13 +139,6 @@ def _gen_id(cls, fulluuid=False): else: return uuid.UUID(fields=(0x00000000, 0x0000, 0x0000, gen_id.clock_seq_hi_variant, gen_id.clock_seq_low, gen_id.node)) - # vmrandom = random.randint(-int(0x7fff), int(0x7fff)) << 8 * 6 - # randtime = int(round(time.time() * 1000000)) - # randtime = randtime & 0xffffffffffff - # rand = vmrandom | randtime - # if rand & 0x8000000000000000: - # rand = 0x1000000000000000 + rand - # return caom_util.long2uuid(rand) @classmethod def _gen_last_modified(cls): diff --git a/caom2/caom2/observation.py b/caom2/caom2/observation.py index 8da2c3c6..ad997a02 100644 --- a/caom2/caom2/observation.py +++ b/caom2/caom2/observation.py @@ -263,7 +263,7 @@ def planes(self): see caom2.Plane for details about a creating a plane. - type: TypedOrderDict((Plane),) + type: TypedOrderDict(Plane,) eg. Observation.planes.add(Plane("SCIENCE")) """ @@ -295,7 +295,7 @@ def intent(self): type: ObservationIntentType - see ObservationIntentType.names() for allowed values + see ObservationIntentType for allowed values """ return self._intent @@ -381,7 +381,7 @@ def instrument(self, value): @property def target(self): - """Reference to a Target object associted with this observation. + """Reference to a Target object associated with this observation. can be None type: caom2.Target @@ -983,12 +983,12 @@ def name(self, value): @property def target_type(self): """A keyword describing the type of target. + + must be from the list + """ + str(list(TargetType)) + """ + type: TargetType + """ - # must be from the list - # """ + ",".join(TargetType.names()) + """ - # type: TargetType - # - # """ return self._type @target_type.setter diff --git a/caom2/caom2/part.py b/caom2/caom2/part.py index 8f594088..6ae23b9f 100644 --- a/caom2/caom2/part.py +++ b/caom2/caom2/part.py @@ -114,7 +114,7 @@ def product_type(self): """The type of data product referred to by this part. Must be one of the allowed data product types: - unicode(ProductType.names())""" + caom2.ProductType""" return self._product_type @product_type.setter diff --git a/caom2/caom2/plane.py b/caom2/caom2/plane.py index 47214cb5..db693fc3 100644 --- a/caom2/caom2/plane.py +++ b/caom2/caom2/plane.py @@ -86,48 +86,6 @@ from .common import CaomObject from .common import ObservationURI -# CalibrationLevel = Enum('CalibrationLevel', -# RAW_INSTRUMENT=0, -# RAW_STANDARD=1, -# CALIBRATED=2, -# PRODUCT=3) - -# DataProductType = Enum('DataProductType', -# IMAGE="image", -# CATALOG="catalog", -# CUBE="cube", -# EVENTLIST="eventlist", -# SPECTRUM="spectrum", -# TIMESERIES="timeseries", -# VISIBILITY="visibility") - -# EnergyBand = Enum('EnergyBand', -# EUV="EUV", -# GAMMARAY="Gamma-ray", -# INFRARED="Infrared", -# MILLIMETER="Millimeter", -# OPTICAL="Optical", -# RADIO="Radio", -# UV="UV", -# XRAY="X-ray") - -# PolarizationState = Enum('PolarizationState', -# I="I", -# Q="Q", -# U="U", -# V="V", -# LL="LL", -# LR="LR", -# RL="RL", -# RR="RR", -# XX="XX", -# XY="XY", -# YX="YX", -# YY="YY") - -# Quality = Enum('Quality', -# JUNK="junk") - __all__ = ['CalibrationLevel', 'DataProductType', 'EnergyBand', "PolarizationState", "Quality", 'Plane', 'PlaneURI', 'DataQuality', 'Metrics', 'Provenance', 'Position', 'Energy', 'Polarization', 'Time'] @@ -357,9 +315,9 @@ def data_product_type(self): """The type of file structure that this plane contains. eg. - Plane.data_product_type = 'EVENTLIST' + Plane.data_product_type = DataProductType['EVENTLIST'] - see DataProductType.names() for allowed values + see DataProductType for allowed values """ return self._data_product_type @@ -375,10 +333,10 @@ def calibration_level(self): the data contained in this plane have received. The string is converted to an integer during storage. - eg. Plane.calibration_level = "RAW_STANDARD" + eg. Plane.calibration_level = CalibrationLevel['RAW_STANDARD'] type: unicode - Must be one of CalibrationLevel.names() + Must be one of CalibrationLevel """ return self._calibration_level diff --git a/caom2/dev_requirements.txt b/caom2/dev_requirements.txt index 0d69562b..8d9e99ca 100644 --- a/caom2/dev_requirements.txt +++ b/caom2/dev_requirements.txt @@ -5,3 +5,4 @@ cadctools==0.1.dev11 funcsigs==1.0.2 mock==2.0.0 xml-compare==1.0.5 +enum34==1.1.6 diff --git a/caom2/setup.py b/caom2/setup.py index e4589445..aa4ee731 100755 --- a/caom2/setup.py +++ b/caom2/setup.py @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['lxml'], + install_requires=['lxml', 'enum34'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, From 9b3aeb71e215d7643df1c5e4c7c2ff1d13be3281 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 29 Nov 2016 12:11:17 -0800 Subject: [PATCH 42/54] Updates after caom2 changes --- caom2/caom2/__init__.py | 24 ++++++++++------------ caom2/setup.py | 2 +- caom2repo/caom2repo/core.py | 4 ++++ caom2repo/caom2repo/test/addplaneplugin.py | 3 ++- caom2repo/caom2repo/test/test_core.py | 3 ++- 5 files changed, 20 insertions(+), 16 deletions(-) diff --git a/caom2/caom2/__init__.py b/caom2/caom2/__init__.py index 6d236e51..0c9fe5c1 100644 --- a/caom2/caom2/__init__.py +++ b/caom2/caom2/__init__.py @@ -81,19 +81,17 @@ # ---------------------------------------------------------------------------- # For egg_info test builds to pass, put package imports here. -# if not _ASTROPY_SETUP_: -# from .caom2 import * - -from caom_util import * -from common import * -from wcs import * -from shape import * -from chunk import * -from part import * -from artifact import * -from plane import * -from observation import * -from obs_reader_writer import * +if not _ASTROPY_SETUP_: + from caom_util import * + from common import * + from wcs import * + from shape import * + from chunk import * + from part import * + from artifact import * + from plane import * + from observation import * + from obs_reader_writer import * # from obs_reader_writer import * # from observation import * diff --git a/caom2/setup.py b/caom2/setup.py index e4589445..aa4ee731 100755 --- a/caom2/setup.py +++ b/caom2/setup.py @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['lxml'], + install_requires=['lxml', 'enum34'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index 9911db98..4b2fb217 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -66,6 +66,8 @@ # #*********************************************************************** # +from __future__ import (absolute_import, division, print_function, + unicode_literals) from datetime import datetime import logging import argparse @@ -80,6 +82,8 @@ from caom2.obs_reader_writer import ObservationReader, ObservationWriter +__all__ = ['CAOM2RepoClient'] + BATCH_SIZE = int(10000) SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat diff --git a/caom2repo/caom2repo/test/addplaneplugin.py b/caom2repo/caom2repo/test/addplaneplugin.py index 20e52a4f..c2cfd5a7 100755 --- a/caom2repo/caom2repo/test/addplaneplugin.py +++ b/caom2repo/caom2repo/test/addplaneplugin.py @@ -66,7 +66,8 @@ # #*********************************************************************** # - +from __future__ import (absolute_import, division, print_function, + unicode_literals) from caom2.observation import Observation from caom2.plane import Plane diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/test/test_core.py index 54ba7cf6..eae869c2 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -66,7 +66,8 @@ # #*********************************************************************** # - +from __future__ import (absolute_import, division, print_function, + unicode_literals) import unittest import copy import sys From 7be031fb28dfcc6cafaa1c7139a5c84888578c33 Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 29 Nov 2016 12:15:43 -0800 Subject: [PATCH 43/54] s1950: syntax cleanup --- caom2repo/caom2repo/core.py | 118 ++++++++++----------- caom2repo/caom2repo/test/addplaneplugin.py | 14 ++- caom2repo/caom2repo/test/passplugin.py | 11 +- caom2repo/caom2repo/test/test_core.py | 34 +++--- 4 files changed, 82 insertions(+), 95 deletions(-) diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index 9911db98..7206a91b 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -1,7 +1,7 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2016. (c) 2016. # Government of Canada Gouvernement du Canada @@ -64,25 +64,27 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -from datetime import datetime -import logging import argparse import imp +import logging import os -import sys import os.path -#TODO to be changed to io.StringIO when caom2 is prepared for python3 +import sys from StringIO import StringIO +from datetime import datetime + from cadctools import net from cadctools import util - from caom2.obs_reader_writer import ObservationReader, ObservationWriter BATCH_SIZE = int(10000) -SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it -DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat +# TODO replace with SERVICE_URI when server supports it +SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' +# IVOA dateformat +DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" + class CAOM2RepoClient: @@ -100,11 +102,11 @@ def __init__(self, anon=True, cert_file=None, server=None): s = SERVICE_URL if server is not None: s = server - agent = 'CAOM2RepoClient' #TODO add version + agent = 'CAOM2RepoClient' + # TODO add version self._repo_client = net.BaseWsClient(s, anon=anon, cert_file=cert_file, agent=agent, retry=True) logging.info('Service URL: {}'.format(self._repo_client.base_url)) - def visit(self, plugin, collection, start=None, end=None): """ Main processing function that iterates through the observations of @@ -152,7 +154,7 @@ def _get_observations(self, collection, start=None, end=None): """ assert collection is not None observations = [] - params = {'MAXREC':BATCH_SIZE} + params = {'MAXREC': BATCH_SIZE} if start is not None: params['START'] = start.strftime(DATE_FORMAT) if end is not None: @@ -166,8 +168,7 @@ def _get_observations(self, collection, start=None, end=None): if last_datetime is not None: self._start = datetime.strptime(last_datetime, DATE_FORMAT) return observations - - + def _load_plugin_class(self, filepath): """ Loads the plugin method and sets the self.plugin to refer to it. @@ -175,7 +176,7 @@ def _load_plugin_class(self, filepath): """ expected_class = 'ObservationUpdater' - mod_name,file_ext = os.path.splitext(os.path.split(filepath)[-1]) + mod_name, file_ext = os.path.splitext(os.path.split(filepath)[-1]) if file_ext.lower() == '.pyc': py_mod = imp.load_compiled(mod_name, filepath) @@ -189,20 +190,18 @@ def _load_plugin_class(self, filepath): 'Cannot find ObservationUpdater class in pluging file ' + filepath) if not hasattr(self.plugin, 'update'): - raise Exception('Cannot find update method in plugin class ' +\ - filepath) - - - def get_observation(self, collection, observationID): + raise Exception('Cannot find update method in plugin class ' + filepath) + + def get_observation(self, collection, observation_id): """ Get an observation from the CAOM2 repo :param collection: name of the collection - :param observationID: the ID of the observation + :param observation_id: the ID of the observation :return: the caom2.observation.Observation object """ assert collection is not None - assert observationID is not None - resource = '/{}/{}'.format(collection, observationID) + assert observation_id is not None + resource = '/{}/{}'.format(collection, observation_id) logging.debug('GET '.format(resource)) response = self._repo_client.get(resource) @@ -214,7 +213,6 @@ def get_observation(self, collection, observationID): raise Exception('Got empty response for resource: {}'.format(resource)) return obs_reader.read(StringIO(content)) - def post_observation(self, observation): """ Updates an observation in the CAOM2 repo @@ -241,7 +239,6 @@ def post_observation(self, observation): raise Exception('Got empty response for resource: {}'.format(resource)) return obs_reader.read(StringIO(content)) - def put_observation(self, observation): """ Add an observation to the CAOM2 repo @@ -267,15 +264,14 @@ def put_observation(self, observation): raise Exception('Got empty response for resource: {}'.format(resource)) return obs_reader.read(StringIO(content)) - - def delete_observation(self, collection, observationID): + def delete_observation(self, collection, observation_id): """ Delete an observation from the CAOM2 repo :param collection: Name of the collection - :param observationID: ID of the observation + :param observation_id: ID of the observation """ - assert observationID is not None - resource = '/{}/{}'.format(collection, observationID) + assert observation_id is not None + resource = '/{}/{}'.format(collection, observation_id) logging.debug('DELETE {}'.format(resource)) response = self._repo_client.delete(resource) logging.debug('Successfully deleted Observation\n') @@ -310,38 +306,37 @@ def main(): visit_parser = subparsers.add_parser('visit', formatter_class=argparse.RawTextHelpFormatter, description='Visit observations in a collection') visit_parser.add_argument('--plugin', required=True, type=file, - metavar=(''), - help='Pluging class to update each observation') + metavar='', + help='Pluging class to update each observation') visit_parser.add_argument('--start', metavar='', - type=util.str2ivoa, - help='oldest dataset to visit (UTC %%Y-%%m-%%d format)') + type=util.str2ivoa, + help='oldest dataset to visit (UTC %%Y-%%m-%%d format)') visit_parser.add_argument('--end', metavar='', - type=util.str2ivoa, - help='earliest dataset to visit (UTC %%Y-%%m-%%d format)') + type=util.str2ivoa, + help='earliest dataset to visit (UTC %%Y-%%m-%%d format)') visit_parser.add_argument('--retries', metavar='', - type=int, - help='number of tries with transient server errors') - visit_parser.add_argument("-s", "--server", metavar=(''), - help="URL of the CAOM2 repo server") + type=int, + help='number of tries with transient server errors') + visit_parser.add_argument("-s", "--server", metavar='', + help="URL of the CAOM2 repo server") visit_parser.add_argument('collection', metavar='', type=str, - help='data collection in CAOM2 repo') + help='data collection in CAOM2 repo') visit_parser.epilog =\ -""" -Minimum plugin file format: ----- - from caom2.caom2_observation import Observation - - class ObservationUpdater: - - def update(self, observation): - assert isinstance(observation, Observation), ( - 'observation {} is not an Observation'.format(observation)) - # custom code to update the observation ----- -""" - args = parser.parse_args() + """ + Minimum plugin file format: + ---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation + ---- + """ + args = parser.parse_args() if args.verbose: logging.basicConfig(level=logging.INFO) @@ -359,7 +354,7 @@ def update(self, observation): retries = args.retries collection = args.collection logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". - format(plugin, start, end, collection, retries)) + format(plugin, start, end, collection, retries)) client.visit(plugin, collection, start=start, end=end) elif args.cmd == 'create': @@ -378,11 +373,10 @@ def update(self, observation): elif args.cmd == 'update': print("Update") obs_reader = ObservationReader() - client.post_observation(obs_reader.read(args.observation)) #TODO not sure if need to read in string first + # TODO not sure if need to read in string first + client.post_observation(obs_reader.read(args.observation)) else: print("Delete") client.delete_observation(collection=args.collection, observation=args.observationID) print("DONE") - - diff --git a/caom2repo/caom2repo/test/addplaneplugin.py b/caom2repo/caom2repo/test/addplaneplugin.py index 20e52a4f..88cfa5d5 100755 --- a/caom2repo/caom2repo/test/addplaneplugin.py +++ b/caom2repo/caom2repo/test/addplaneplugin.py @@ -1,7 +1,7 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2016. (c) 2016. # Government of Canada Gouvernement du Canada @@ -64,12 +64,13 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # from caom2.observation import Observation from caom2.plane import Plane + class ObservationUpdater: """ObservationUpdater that adds a plane to the observation.""" @@ -81,6 +82,3 @@ def update(self, observation): assert isinstance(observation, Observation), ( "observation %s is not an Observation".format(observation)) observation.planes.add(Plane('PREVIEW')) - - - diff --git a/caom2repo/caom2repo/test/passplugin.py b/caom2repo/caom2repo/test/passplugin.py index 9d5cfc75..a7b11f48 100755 --- a/caom2repo/caom2repo/test/passplugin.py +++ b/caom2repo/caom2repo/test/passplugin.py @@ -1,7 +1,7 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2016. (c) 2016. # Government of Canada Gouvernement du Canada @@ -64,11 +64,12 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # from caom2.observation import Observation + class ObservationUpdater: """Plugin that does not update the observation""" diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/test/test_core.py index 54ba7cf6..ecc70b64 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -1,7 +1,7 @@ -## -*- coding: utf-8 -*- -#*********************************************************************** -#****************** CANADIAN ASTRONOMY DATA CENTRE ******************* -#************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** +# # -*- coding: utf-8 -*- +# *********************************************************************** +# ****************** CANADIAN ASTRONOMY DATA CENTRE ******************* +# ************* CENTRE CANADIEN DE DONNÉES ASTRONOMIQUES ************** # # (c) 2016. (c) 2016. # Government of Canada Gouvernement du Canada @@ -64,24 +64,24 @@ # # $Revision: 4 $ # -#*********************************************************************** +# *********************************************************************** # -import unittest import copy -import sys import os -import requests -from mock import Mock, patch, MagicMock, ANY -#TODO to be changed to io.StringIO when caom2 is prepared for python3 +import sys +import unittest from StringIO import StringIO from datetime import datetime +import requests from cadctools import util +from caom2.obs_reader_writer import ObservationWriter +from caom2.observation import SimpleObservation +from mock import Mock, patch, MagicMock, ANY + from caom2repo import core from caom2repo.core import CAOM2RepoClient, DATE_FORMAT -from caom2.observation import SimpleObservation -from caom2.obs_reader_writer import ObservationReader, ObservationWriter THIS_DIR = os.path.dirname(os.path.realpath(__file__)) @@ -89,11 +89,11 @@ class MyExitError(Exception): pass + class TestCAOM2Repo(unittest.TestCase): """Test the Caom2Visitor class""" - def test_plugin_class(self): # plugin class does not change the observation collection = 'cfht' @@ -125,8 +125,7 @@ def test_plugin_class(self): # non-existent update method in ObservationUpdater class with self.assertRaises(Exception): visitor._load_plugin_class(os.path.join(THIS_DIR, 'noupdateplugin.py')) - - + # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.open', MagicMock(), create=True) @@ -171,7 +170,6 @@ def raise_error(): raise http_error with self.assertRaises(requests.HTTPError): visitor.get_observation(collection, observation_id) - # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.open', MagicMock(), create=True) @@ -209,7 +207,6 @@ def test_get_observations(self, mock_get): 'END': '2000-11-12T00:00:00.000000', 'MAXREC': core.BATCH_SIZE}) - # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.auth.get_user_password', Mock(return_value=('usr', 'passwd'))) @@ -261,7 +258,6 @@ def raise_error(): raise http_error with self.assertRaises(requests.HTTPError): visitor.post_observation(obs) - # patch sleep to stop the test from sleeping and slowing down execution @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) @patch('cadctools.net.ws.Session.send') @@ -357,7 +353,6 @@ def raise_error(): raise http_error with self.assertRaises(requests.HTTPError): visitor.delete_observation(collection, observation_id) - def test_process(self): core.BATCH_SIZE = 3 # size of the batch is 3 obs = [['a', 'b', 'c'], ['d'], []] @@ -374,7 +369,6 @@ def test_process(self): self.assertEquals(6, visitor.visit(os.path.join( THIS_DIR, 'passplugin.py'), 'cfht')) - @patch('caom2repo.core.CAOM2RepoClient') def test_main(self, client_mock): collection = 'cfht' From 2de4bd24542d34bc334b0a7a64dc895669a83e6a Mon Sep 17 00:00:00 2001 From: Jeff Burke Date: Tue, 29 Nov 2016 12:30:48 -0800 Subject: [PATCH 44/54] s1950: restored formatting for expected test strings. --- caom2repo/caom2repo/test/test_core.py | 309 +++++++++++++------------- 1 file changed, 153 insertions(+), 156 deletions(-) diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/test/test_core.py index 64480b4d..43228624 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -432,172 +432,169 @@ def test_help(self): # expected helper messages usage =\ - """usage: caom2-client [-h] [--certfile CERTFILE] [--anonymous] [--host HOST] - [--verbose] [--debug] [--quiet] - {create,read,update,delete,visit} ... - - Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) operations it also \ - implements a visitor operation that allows for updating multiple observations in a collection - - positional arguments: - {create,read,update,delete,visit} - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, \ - otherwise uses $HOME/.netrc for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - """ +"""usage: caom2-client [-h] [--certfile CERTFILE] [--anonymous] [--host HOST] + [--verbose] [--debug] [--quiet] + {create,read,update,delete,visit} ... + +Client for a CAOM2 repo. In addition to CRUD (Create, Read, Update and Delete) operations it also implements a visitor operation that allows for updating multiple observations in a collection + +positional arguments: + {create,read,update,delete,visit} + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" create_usage =\ - """usage: caom2-client create [-h] [--certfile CERTFILE] [--anonymous] - [--host HOST] [--verbose] [--debug] [--quiet] - - - Create a new observation - - positional arguments: - - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: - $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc - for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia- - iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - """ +"""usage: caom2-client create [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Create a new observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" read_usage =\ - """usage: caom2-client read [-h] [--certfile CERTFILE] [--anonymous] - [--host HOST] [--verbose] [--debug] [--quiet] - --collection - [--output ] - - - Read an existing observation - - positional arguments: - - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: - $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc - for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia- - iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - --collection - --output , -o - """ +"""usage: caom2-client read [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --collection + [--output ] + + +Read an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --collection + --output , -o +""" update_usage =\ - """usage: caom2-client update [-h] [--certfile CERTFILE] [--anonymous] - [--host HOST] [--verbose] [--debug] [--quiet] - - - Update an existing observation - - positional arguments: - - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: - $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc - for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia- - iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - """ +"""usage: caom2-client update [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + + +Update an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly +""" delete_usage =\ - """usage: caom2-client delete [-h] [--certfile CERTFILE] [--anonymous] - [--host HOST] [--verbose] [--debug] [--quiet] - --collection - - - Delete an existing observation - - positional arguments: - - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: - $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc - for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia- - iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - --collection - """ +"""usage: caom2-client delete [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --collection + + +Delete an existing observation + +positional arguments: + + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: + $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc + for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia- + iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --collection +""" visit_usage =\ - """usage: caom2-client visit [-h] [--certfile CERTFILE] [--anonymous] - [--host HOST] [--verbose] [--debug] [--quiet] - --plugin - [--start ] - [--end ] - [--retries ] - [-s ] - - - Visit observations in a collection - - positional arguments: - data collection in CAOM2 repo - - optional arguments: - -h, --help show this help message and exit - --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, \ - otherwise uses $HOME/.netrc for name/password) - --anonymous Force anonymous connection - --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) - --verbose verbose messages - --debug debug messages - --quiet run quietly - --plugin - Pluging class to update each observation - --start - oldest dataset to visit (UTC %Y-%m-%d format) - --end - earliest dataset to visit (UTC %Y-%m-%d format) - --retries - number of tries with transient server errors - -s , --server - URL of the CAOM2 repo server - - Minimum plugin file format: - ---- - from caom2.caom2_observation import Observation - - class ObservationUpdater: - - def update(self, observation): - assert isinstance(observation, Observation), ( - 'observation {} is not an Observation'.format(observation)) - # custom code to update the observation - ---- - """ +"""usage: caom2-client visit [-h] [--certfile CERTFILE] [--anonymous] + [--host HOST] [--verbose] [--debug] [--quiet] + --plugin + [--start ] + [--end ] + [--retries ] + [-s ] + + +Visit observations in a collection + +positional arguments: + data collection in CAOM2 repo + +optional arguments: + -h, --help show this help message and exit + --certfile CERTFILE location of your CADC certificate file (default: $HOME/.ssl/cadcproxy.pem, otherwise uses $HOME/.netrc for name/password) + --anonymous Force anonymous connection + --host HOST Base hostname for services(default: www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca) + --verbose verbose messages + --debug debug messages + --quiet run quietly + --plugin + Pluging class to update each observation + --start + oldest dataset to visit (UTC %Y-%m-%d format) + --end + earliest dataset to visit (UTC %Y-%m-%d format) + --retries + number of tries with transient server errors + -s , --server + URL of the CAOM2 repo server + +Minimum plugin file format: +---- + from caom2.caom2_observation import Observation + + class ObservationUpdater: + + def update(self, observation): + assert isinstance(observation, Observation), ( + 'observation {} is not an Observation'.format(observation)) + # custom code to update the observation +---- +""" # --help with patch('sys.stdout', new_callable=StringIO) as stdout_mock: From 5bf430f89ef1fa39598b47e05ba3cd01e803108a Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 29 Nov 2016 13:17:12 -0800 Subject: [PATCH 45/54] Fixed problem in service client --- caom2repo/caom2repo/core.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index 4b2fb217..5786c034 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -85,8 +85,9 @@ __all__ = ['CAOM2RepoClient'] BATCH_SIZE = int(10000) -SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2repo' #TODO replace with SERVICE_URI when server supports it +SERVICE_URL = 'www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/' #TODO replace with SERVICE_URI when server supports it DATE_FORMAT = "%Y-%m-%dT%H:%M:%S.%f" #IVOA dateformat +SERVICE = 'caom2repo' class CAOM2RepoClient: @@ -104,8 +105,10 @@ def __init__(self, anon=True, cert_file=None, server=None): s = SERVICE_URL if server is not None: s = server + if not s.endswith('/'): + s = s + "/" agent = 'CAOM2RepoClient' #TODO add version - self._repo_client = net.BaseWsClient(s, anon=anon, cert_file=cert_file, agent=agent, retry=True) + self._repo_client = net.BaseWsClient(s + SERVICE, anon=anon, cert_file=cert_file, agent=agent, retry=True) logging.info('Service URL: {}'.format(self._repo_client.base_url)) From 929285fd9bc2651ddd6c2053df22ea44a8221566 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Tue, 29 Nov 2016 14:28:52 -0800 Subject: [PATCH 46/54] Fixed service url --- caom2repo/caom2repo/core.py | 27 +++++++-------------------- caom2repo/caom2repo/test/test_core.py | 10 +++++----- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index 5786c034..d16d090b 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -216,7 +216,7 @@ def get_observation(self, collection, observationID): obs_reader = ObservationReader() content = response.content if len(content) == 0: - logging.error(response.status) + logging.error(response.status_code) response.close() raise Exception('Got empty response for resource: {}'.format(resource)) return obs_reader.read(StringIO(content)) @@ -240,13 +240,6 @@ def post_observation(self, observation): response = self._repo_client.post( resource, headers=headers, data=obs_xml) logging.debug('Successfully updated Observation\n') - obs_reader = ObservationReader() - content = response.content - if len(content) == 0: - logging.error(response.status) - response.close() - raise Exception('Got empty response for resource: {}'.format(resource)) - return obs_reader.read(StringIO(content)) def put_observation(self, observation): @@ -266,13 +259,6 @@ def put_observation(self, observation): response = self._repo_client.put( resource, headers=headers, data=obs_xml) logging.debug('Successfully put Observation\n') - obs_reader = ObservationReader() - content = response.content - if len(content) == 0: - logging.error(response.status) - response.close() - raise Exception('Got empty response for resource: {}'.format(resource)) - return obs_reader.read(StringIO(content)) def delete_observation(self, collection, observationID): @@ -285,7 +271,7 @@ def delete_observation(self, collection, observationID): resource = '/{}/{}'.format(collection, observationID) logging.debug('DELETE {}'.format(resource)) response = self._repo_client.delete(resource) - logging.debug('Successfully deleted Observation\n') + logging.info('Successfully deleted Observation {}\n') def main(): @@ -355,11 +341,12 @@ def update(self, observation): if args.debug: logging.basicConfig(level=logging.DEBUG) - - client = CAOM2RepoClient(anon=args.anonymous, cert_file=args.certfile, server=args.host) + certfile = None + if os.path.isfile(args.certfile): + certfile = args.certfile + client = CAOM2RepoClient(anon=args.anonymous, cert_file=certfile, server=args.host) if args.cmd == 'visit': print ("Visit") - plugin = args.plugin start = args.start end = args.end @@ -367,7 +354,7 @@ def update(self, observation): collection = args.collection logging.debug("Call visitor with plugin={}, start={}, end={}, dataset={}". format(plugin, start, end, collection, retries)) - client.visit(plugin, collection, start=start, end=end) + client.visit(plugin.name, collection, start=start, end=end) elif args.cmd == 'create': print("Create") diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/test/test_core.py index eae869c2..0cc02de5 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/test/test_core.py @@ -219,7 +219,7 @@ def test_post_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' service = 'caom2repo' - service_url = 'www.cadc.nrc.ca/{}'.format(service) + service_url = 'www.cadc.nrc.ca' obs = SimpleObservation(collection, observation_id) visitor = CAOM2RepoClient(anon=False, server=service_url) @@ -230,8 +230,8 @@ def test_post_observation(self, mock_conn): ObservationWriter().write(obs, iobuffer) obsxml = iobuffer.getvalue() response.content = obsxml - - self.assertEqual(obs, visitor.post_observation(obs)) + + visitor.post_observation(obs) self.assertEqual('POST', mock_conn.call_args[0][0].method) self.assertEqual('/{}/auth/{}/{}'.format(service, collection, observation_id), mock_conn.call_args[0][0].path_url) @@ -270,7 +270,7 @@ def test_put_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' service = 'caom2repo' - service_url = 'www.cadc.nrc.ca/{}'.format(service) + service_url = 'www.cadc.nrc.ca/' obs = SimpleObservation(collection, observation_id) visitor = CAOM2RepoClient(cert_file='somefile.pem', server=service_url) @@ -282,7 +282,7 @@ def test_put_observation(self, mock_conn): obsxml = iobuffer.getvalue() response.content = obsxml - self.assertEqual(obs, visitor.put_observation(obs)) + visitor.put_observation(obs) self.assertEqual('PUT', mock_conn.call_args[0][0].method) self.assertEqual('/{}/{}'.format(service, collection), mock_conn.call_args[0][0].path_url) From 1ed1a6e011ad8cc09d70b42ec93d7dc74f13ed8b Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Wed, 30 Nov 2016 16:35:26 -0800 Subject: [PATCH 47/54] Propagated new name for cadctools package --- caom2/dev_requirements.txt | 1 - caom2repo/caom2repo/core.py | 4 +-- .../caom2repo/{test => tests}/__init__.py | 0 .../{test => tests}/addplaneplugin.py | 0 caom2repo/caom2repo/tests/coveragerc | 31 +++++++++++++++++++ .../caom2repo/{test => tests}/passplugin.py | 0 caom2repo/caom2repo/tests/setup_package.py | 7 +++++ .../caom2repo/{test => tests}/test_core.py | 26 ++++++++-------- caom2repo/setup.cfg | 2 +- caom2repo/setup.py | 4 +-- 10 files changed, 56 insertions(+), 19 deletions(-) rename caom2repo/caom2repo/{test => tests}/__init__.py (100%) rename caom2repo/caom2repo/{test => tests}/addplaneplugin.py (100%) create mode 100644 caom2repo/caom2repo/tests/coveragerc rename caom2repo/caom2repo/{test => tests}/passplugin.py (100%) create mode 100644 caom2repo/caom2repo/tests/setup_package.py rename caom2repo/caom2repo/{test => tests}/test_core.py (97%) diff --git a/caom2/dev_requirements.txt b/caom2/dev_requirements.txt index 8d9e99ca..b3caf8fd 100644 --- a/caom2/dev_requirements.txt +++ b/caom2/dev_requirements.txt @@ -1,6 +1,5 @@ numpy==1.12.0b1 astropy==1.2.1 -cadctools==0.1.dev11 -e . funcsigs==1.0.2 mock==2.0.0 diff --git a/caom2repo/caom2repo/core.py b/caom2repo/caom2repo/core.py index d16d090b..26b2679c 100755 --- a/caom2repo/caom2repo/core.py +++ b/caom2repo/caom2repo/core.py @@ -77,8 +77,8 @@ import os.path #TODO to be changed to io.StringIO when caom2 is prepared for python3 from StringIO import StringIO -from cadctools import net -from cadctools import util +from cadcutils import net +from cadcutils import util from caom2.obs_reader_writer import ObservationReader, ObservationWriter diff --git a/caom2repo/caom2repo/test/__init__.py b/caom2repo/caom2repo/tests/__init__.py similarity index 100% rename from caom2repo/caom2repo/test/__init__.py rename to caom2repo/caom2repo/tests/__init__.py diff --git a/caom2repo/caom2repo/test/addplaneplugin.py b/caom2repo/caom2repo/tests/addplaneplugin.py similarity index 100% rename from caom2repo/caom2repo/test/addplaneplugin.py rename to caom2repo/caom2repo/tests/addplaneplugin.py diff --git a/caom2repo/caom2repo/tests/coveragerc b/caom2repo/caom2repo/tests/coveragerc new file mode 100644 index 00000000..bec7c291 --- /dev/null +++ b/caom2repo/caom2repo/tests/coveragerc @@ -0,0 +1,31 @@ +[run] +source = {packagename} +omit = + {packagename}/_astropy_init* + {packagename}/conftest* + {packagename}/cython_version* + {packagename}/setup_package* + {packagename}/*/setup_package* + {packagename}/*/*/setup_package* + {packagename}/tests/* + {packagename}/*/tests/* + {packagename}/*/*/tests/* + {packagename}/version* + +[report] +exclude_lines = + # Have to re-enable the standard pragma + pragma: no cover + + # Don't complain about packages we have installed + except ImportError + + # Don't complain if tests don't hit assertions + raise AssertionError + raise NotImplementedError + + # Don't complain about script hooks + def main\(.*\): + + # Ignore branches that don't pertain to this version of Python + pragma: py{ignore_python_version} \ No newline at end of file diff --git a/caom2repo/caom2repo/test/passplugin.py b/caom2repo/caom2repo/tests/passplugin.py similarity index 100% rename from caom2repo/caom2repo/test/passplugin.py rename to caom2repo/caom2repo/tests/passplugin.py diff --git a/caom2repo/caom2repo/tests/setup_package.py b/caom2repo/caom2repo/tests/setup_package.py new file mode 100644 index 00000000..6e4be679 --- /dev/null +++ b/caom2repo/caom2repo/tests/setup_package.py @@ -0,0 +1,7 @@ +def get_package_data(): + return { + _ASTROPY_PACKAGE_NAME_ + '.tests': ['coveragerc']} + + +def requires_2to3(): + return False diff --git a/caom2repo/caom2repo/test/test_core.py b/caom2repo/caom2repo/tests/test_core.py similarity index 97% rename from caom2repo/caom2repo/test/test_core.py rename to caom2repo/caom2repo/tests/test_core.py index 44d6464b..785af5d9 100644 --- a/caom2repo/caom2repo/test/test_core.py +++ b/caom2repo/caom2repo/tests/test_core.py @@ -78,7 +78,7 @@ from datetime import datetime import requests -from cadctools import util +from cadcutils import util from caom2.obs_reader_writer import ObservationWriter from caom2.observation import SimpleObservation from mock import Mock, patch, MagicMock, ANY @@ -130,9 +130,9 @@ def test_plugin_class(self): visitor._load_plugin_class(os.path.join(THIS_DIR, 'noupdateplugin.py')) # patch sleep to stop the test from sleeping and slowing down execution - @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) - @patch('cadctools.net.ws.open', MagicMock(), create=True) - @patch('cadctools.net.ws.Session.send') + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.open', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') def test_get_observation(self, mock_get): collection = 'cfht' observation_id = '7000000o' @@ -175,8 +175,8 @@ def raise_error(): raise http_error visitor.get_observation(collection, observation_id) # patch sleep to stop the test from sleeping and slowing down execution - @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) - @patch('cadctools.net.ws.open', MagicMock(), create=True) + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.open', MagicMock(), create=True) @patch('caom2repo.core.net.BaseWsClient.get') def test_get_observations(self, mock_get): # This is almost similar to the previous test except that it gets @@ -212,9 +212,9 @@ def test_get_observations(self, mock_get): 'MAXREC': core.BATCH_SIZE}) # patch sleep to stop the test from sleeping and slowing down execution - @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) - @patch('cadctools.net.ws.auth.get_user_password', Mock(return_value=('usr', 'passwd'))) - @patch('cadctools.net.ws.Session.send') + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.auth.get_user_password', Mock(return_value=('usr', 'passwd'))) + @patch('cadcutils.net.ws.Session.send') def test_post_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' @@ -264,8 +264,8 @@ def raise_error(): raise http_error visitor.post_observation(obs) # patch sleep to stop the test from sleeping and slowing down execution - @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) - @patch('cadctools.net.ws.Session.send') + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') def test_put_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' @@ -316,8 +316,8 @@ def raise_error(): raise http_error visitor.put_observation(obs) # patch sleep to stop the test from sleeping and slowing down execution - @patch('cadctools.net.ws.time.sleep', MagicMock(), create=True) - @patch('cadctools.net.ws.Session.send') + @patch('cadcutils.net.ws.time.sleep', MagicMock(), create=True) + @patch('cadcutils.net.ws.Session.send') def test_delete_observation(self, mock_conn): collection = 'cfht' observation_id = '7000000o' diff --git a/caom2repo/setup.cfg b/caom2repo/setup.cfg index 462e1320..6f200251 100644 --- a/caom2repo/setup.cfg +++ b/caom2repo/setup.cfg @@ -31,7 +31,7 @@ url = http://www.cadc-ccda.hia-iha.nrc-cnrc.gc.ca/caom2 edit_on_github = False github_project = opencadc/caom2tools # version should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -version = 2.2.2 +version = 1.0 [entry_points] caom2-client = caom2repo.core:main diff --git a/caom2repo/setup.py b/caom2repo/setup.py index 1b40d4a1..85687d31 100755 --- a/caom2repo/setup.py +++ b/caom2repo/setup.py @@ -47,7 +47,7 @@ builtins._ASTROPY_PACKAGE_NAME_ = PACKAGENAME # VERSION should be PEP386 compatible (http://www.python.org/dev/peps/pep-0386) -VERSION = metadata.get('version', '2.2.2') +VERSION = metadata.get('version', '1.0.dev') # Indicates if this version is a release version RELEASE = 'dev' not in VERSION @@ -107,7 +107,7 @@ version=VERSION, description=DESCRIPTION, scripts=scripts, - install_requires=['cadctools'], + install_requires=['cadcutils'], author=AUTHOR, author_email=AUTHOR_EMAIL, license=LICENSE, From c3cb0a1c597cdf559d69b85e1a20e9216a32c1d9 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:07:12 -0800 Subject: [PATCH 48/54] Fixed travis --- .travis.yml | 58 ++++++++++++++++++++++++++--------------------------- 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/.travis.yml b/.travis.yml index 46d6bd26..9ef113f0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,8 +2,8 @@ language: python python: - 2.7 - - 3.4 - - 3.5 + # - 3.4 + #- 3.5 #TODO fix it # Setting sudo to false opts in to Travis-CI container-based builds. sudo: false @@ -29,12 +29,12 @@ env: - NUMPY_VERSION=stable - ASTROPY_VERSION=stable - SETUP_CMD='test' - - PIP_DEPENDENCIES='' + - PIP_DEPENDENCIES='requests mock coverage' # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include # Cython code, you can set CONDA_DEPENDENCIES='' - - CONDA_DEPENDENCIES='Cython' + - CONDA_DEPENDENCIES='' # Conda packages for affiliated packages are hosted in channel # "astropy" while builds for astropy LTS with recent numpy versions @@ -62,42 +62,42 @@ matrix: # Check for sphinx doc build warnings - we do this first because it # may run for a long time - - python: 2.7 - env: SETUP_CMD='build_sphinx -w' + #- python: 2.7 + # env: SETUP_CMD='build_sphinx -w' # Try Astropy development version - - python: 2.7 - env: ASTROPY_VERSION=development - - python: 3.5 - env: ASTROPY_VERSION=development - - python: 2.7 - env: ASTROPY_VERSION=lts - - python: 3.5 - env: ASTROPY_VERSION=lts + #- python: 2.7 + # env: ASTROPY_VERSION=development + #- python: 3.5 + # env: ASTROPY_VERSION=development + #- python: 2.7 + # env: ASTROPY_VERSION=lts + #- python: 3.5 + # env: ASTROPY_VERSION=lts # Python 3.3 doesn't have numpy 1.10 in conda, but can be put # back into the main matrix once the numpy build is available in the # astropy-ci-extras channel (or in the one provided in the # CONDA_CHANNELS environmental variable). - - python: 3.3 - env: SETUP_CMD='egg_info' - - python: 3.3 - env: SETUP_CMD='test' NUMPY_VERSION=1.9 + #- python: 3.3 + # env: SETUP_CMD='egg_info' + #- python: 3.3 + # env: SETUP_CMD='test' NUMPY_VERSION=1.9 # Try older numpy versions - - python: 2.7 - env: NUMPY_VERSION=1.10 - - python: 2.7 - env: NUMPY_VERSION=1.9 - - python: 2.7 - env: NUMPY_VERSION=1.8 - - python: 2.7 - env: NUMPY_VERSION=1.7 + #- python: 2.7 + # env: NUMPY_VERSION=1.10 + #- python: 2.7 + # env: NUMPY_VERSION=1.9 + #- python: 2.7 + # env: NUMPY_VERSION=1.8 + #- python: 2.7 + # env: NUMPY_VERSION=1.7 # Try numpy pre-release - - python: 3.5 - env: NUMPY_VERSION=prerelease + #- python: 3.5 + # env: NUMPY_VERSION=prerelease install: @@ -125,7 +125,7 @@ install: # other dependencies. script: - - python setup.py $SETUP_CMD + - for mod in caom2 caom2repo; do cd $mod; python setup.py $SETUP_CMD || break -1; cd ..; done after_success: # If coveralls.io is set up for this package, uncomment the line From 8c6b0159a79fd78b04d309fbdddc824ef17509ef Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:11:12 -0800 Subject: [PATCH 49/54] Fixed travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 9ef113f0..7ed01ecb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ env: - NUMPY_VERSION=stable - ASTROPY_VERSION=stable - SETUP_CMD='test' - - PIP_DEPENDENCIES='requests mock coverage' + - PIP_DEPENDENCIES='requests enum34 mock coverage' # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include From 4a466a77bca9a6a526369b253e76793981efb939 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:14:31 -0800 Subject: [PATCH 50/54] Fixed travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7ed01ecb..7f6e604f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ env: - NUMPY_VERSION=stable - ASTROPY_VERSION=stable - SETUP_CMD='test' - - PIP_DEPENDENCIES='requests enum34 mock coverage' + - PIP_DEPENDENCIES='cadcutils lxml xml-compare requests enum34 mock coverage' # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include From 8388807455de9447ef27c09febc0ae137e2b841c Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:24:54 -0800 Subject: [PATCH 51/54] Fixed travis --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 7f6e604f..c8598b07 100644 --- a/.travis.yml +++ b/.travis.yml @@ -125,7 +125,8 @@ install: # other dependencies. script: - - for mod in caom2 caom2repo; do cd $mod; python setup.py $SETUP_CMD || break -1; cd ..; done + - cd caom2; python setup.py $SETUP_CMD || break -1 + - cd caom2repo; pip install ../caom2; python setup.py $SETUP_CMD || break -1 after_success: # If coveralls.io is set up for this package, uncomment the line From ff8393ea51d2a6e4074a1da60e7547b9748e108c Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:28:44 -0800 Subject: [PATCH 52/54] Fixed travis --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c8598b07..70a10b1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -125,7 +125,7 @@ install: # other dependencies. script: - - cd caom2; python setup.py $SETUP_CMD || break -1 + - cd caom2; python setup.py $SETUP_CMD || break -1;cd .. - cd caom2repo; pip install ../caom2; python setup.py $SETUP_CMD || break -1 after_success: From bc841d81a3294734099c8056da4ce31ebbf30be1 Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 09:11:12 -0800 Subject: [PATCH 53/54] Fixed travis --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9ef113f0..70a10b1f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -29,7 +29,7 @@ env: - NUMPY_VERSION=stable - ASTROPY_VERSION=stable - SETUP_CMD='test' - - PIP_DEPENDENCIES='requests mock coverage' + - PIP_DEPENDENCIES='cadcutils lxml xml-compare requests enum34 mock coverage' # For this package-template, we include examples of Cython modules, # so Cython is required for testing. If your package does not include @@ -125,7 +125,8 @@ install: # other dependencies. script: - - for mod in caom2 caom2repo; do cd $mod; python setup.py $SETUP_CMD || break -1; cd ..; done + - cd caom2; python setup.py $SETUP_CMD || break -1;cd .. + - cd caom2repo; pip install ../caom2; python setup.py $SETUP_CMD || break -1 after_success: # If coveralls.io is set up for this package, uncomment the line From 0f5715f33cb155420cad8dbd033cbc326aad9beb Mon Sep 17 00:00:00 2001 From: Adrian Damian Date: Thu, 1 Dec 2016 10:39:08 -0800 Subject: [PATCH 54/54] Renamed application (entry point) --- caom2repo/setup.cfg | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/caom2repo/setup.cfg b/caom2repo/setup.cfg index 6f200251..9687baeb 100644 --- a/caom2repo/setup.cfg +++ b/caom2repo/setup.cfg @@ -34,4 +34,4 @@ github_project = opencadc/caom2tools version = 1.0 [entry_points] -caom2-client = caom2repo.core:main +caom2-repo-client = caom2repo.core:main