astroquery-0.3.7/0000755000077000000240000000000013232443301013753 5ustar adamstaff00000000000000astroquery-0.3.7/ah_bootstrap.py0000644000077000000240000010616213232251136017023 0ustar adamstaff00000000000000""" 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 and by default the system-installed version of astropy-helpers will be used (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). This behavior can also be controlled using the ``--auto-use`` and ``--no-auto-use`` command-line flags. For clarity, an alias for ``--no-auto-use`` is ``--use-system-astropy-helpers``, and we recommend using the latter if needed. 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() # typing as a dependency for 1.6.1+ Sphinx causes issues when imported after # initializing submodule with ah_boostrap.py # See discussion and references in # https://github.com/astropy/astropy-helpers/issues/302 try: import typing # noqa except ImportError: pass # 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 # noqa 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' if PY3: UPPER_VERSION_EXCLUSIVE = None else: UPPER_VERSION_EXCLUSIVE = '3' # 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') if '--auto-use' in argv: config['auto_use'] = True argv.remove('--auto-use') if '--no-auto-use' in argv: config['auto_use'] = False argv.remove('--no-auto-use') if '--use-system-astropy-helpers' in argv: config['auto_use'] = False argv.remove('--use-system-astropy-helpers') 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: if UPPER_VERSION_EXCLUSIVE is None: req = DIST_NAME else: req = '{0}<{1}'.format(DIST_NAME, UPPER_VERSION_EXCLUSIVE) 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 _AHBootstrapSystemExit( '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 _AHBootstrapSystemExit( '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:]) 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() astroquery-0.3.7/astropy_helpers/0000755000077000000240000000000013232443301017176 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/ah_bootstrap.py0000644000077000000240000010616213232205045022244 0ustar adamstaff00000000000000""" 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 and by default the system-installed version of astropy-helpers will be used (however, ``ah_bootstrap.use_astropy_helpers`` may be called manually from within the setup.py script). This behavior can also be controlled using the ``--auto-use`` and ``--no-auto-use`` command-line flags. For clarity, an alias for ``--no-auto-use`` is ``--use-system-astropy-helpers``, and we recommend using the latter if needed. 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() # typing as a dependency for 1.6.1+ Sphinx causes issues when imported after # initializing submodule with ah_boostrap.py # See discussion and references in # https://github.com/astropy/astropy-helpers/issues/302 try: import typing # noqa except ImportError: pass # 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 # noqa 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' if PY3: UPPER_VERSION_EXCLUSIVE = None else: UPPER_VERSION_EXCLUSIVE = '3' # 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') if '--auto-use' in argv: config['auto_use'] = True argv.remove('--auto-use') if '--no-auto-use' in argv: config['auto_use'] = False argv.remove('--no-auto-use') if '--use-system-astropy-helpers' in argv: config['auto_use'] = False argv.remove('--use-system-astropy-helpers') 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: if UPPER_VERSION_EXCLUSIVE is None: req = DIST_NAME else: req = '{0}<{1}'.format(DIST_NAME, UPPER_VERSION_EXCLUSIVE) 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 _AHBootstrapSystemExit( '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 _AHBootstrapSystemExit( '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:]) 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() astroquery-0.3.7/astropy_helpers/astropy_helpers/0000755000077000000240000000000013232443301022421 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/__init__.py0000644000077000000240000000345413007171661024547 0ustar adamstaff00000000000000try: from .version import version as __version__ from .version import githash as __githash__ except ImportError: __version__ = '' __githash__ = '' # If we've made it as far as importing astropy_helpers, we don't need # ah_bootstrap in sys.modules anymore. Getting rid of it is actually necessary # if the package we're installing has a setup_requires of another package that # uses astropy_helpers (and possibly a different version at that) # See https://github.com/astropy/astropy/issues/3541 import sys if 'ah_bootstrap' in sys.modules: del sys.modules['ah_bootstrap'] # Note, this is repeated from ah_bootstrap.py, but is here too in case this # astropy-helpers was upgraded to from an older version that did not have this # check in its ah_bootstrap. # 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 import os # Ensure that all module-level code in astropy or other packages know that # we're in setup mode: if ('__main__' in sys.modules and hasattr(sys.modules['__main__'], '__file__')): filename = os.path.basename(sys.modules['__main__'].__file__) if filename.rstrip('co') == 'setup.py': if sys.version_info[0] >= 3: import builtins else: import __builtin__ as builtins builtins._ASTROPY_SETUP_ = True del filename astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/0000755000077000000240000000000013232443301024222 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/__init__.py0000644000077000000240000000000012544425160026331 0ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/_dummy.py0000644000077000000240000000557413007171661026110 0ustar adamstaff00000000000000""" Provides a base class for a 'dummy' setup.py command that has no functionality (probably due to a missing requirement). This dummy command can raise an exception when it is run, explaining to the user what dependencies must be met to use this command. The reason this is at all tricky is that we want the command to be able to provide this message even when the user passes arguments to the command. If we don't know ahead of time what arguments the command can take, this is difficult, because distutils does not allow unknown arguments to be passed to a setup.py command. This hacks around that restriction to provide a useful error message even when a user passes arguments to the dummy implementation of a command. Use this like: try: from some_dependency import SetupCommand except ImportError: from ._dummy import _DummyCommand class SetupCommand(_DummyCommand): description = \ 'Implementation of SetupCommand from some_dependency; ' 'some_dependency must be installed to run this command' # This is the message that will be raised when a user tries to # run this command--define it as a class attribute. error_msg = \ "The 'setup_command' command requires the some_dependency " "package to be installed and importable." """ import sys from setuptools import Command from distutils.errors import DistutilsArgError from textwrap import dedent class _DummyCommandMeta(type): """ Causes an exception to be raised on accessing attributes of a command class so that if ``./setup.py command_name`` is run with additional command-line options we can provide a useful error message instead of the default that tells users the options are unrecognized. """ def __init__(cls, name, bases, members): if bases == (Command, object): # This is the _DummyCommand base class, presumably return if not hasattr(cls, 'description'): raise TypeError( "_DummyCommand subclass must have a 'description' " "attribute.") if not hasattr(cls, 'error_msg'): raise TypeError( "_DummyCommand subclass must have an 'error_msg' " "attribute.") def __getattribute__(cls, attr): if attr in ('description', 'error_msg'): # Allow cls.description to work so that `./setup.py # --help-commands` still works return super(_DummyCommandMeta, cls).__getattribute__(attr) raise DistutilsArgError(cls.error_msg) if sys.version_info[0] < 3: exec(dedent(""" class _DummyCommand(Command, object): __metaclass__ = _DummyCommandMeta """)) else: exec(dedent(""" class _DummyCommand(Command, object, metaclass=_DummyCommandMeta): pass """)) astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/_test_compat.py0000644000077000000240000002671213126316034027271 0ustar adamstaff00000000000000""" Old implementation of ``./setup.py test`` command. This has been moved to astropy.tests as of Astropy v1.1.0, but a copy of the implementation is kept here for backwards compatibility. """ from __future__ import absolute_import, unicode_literals import inspect import os import shutil import subprocess import sys import tempfile from setuptools import Command from ..compat import _fix_user_options PY3 = sys.version_info[0] == 3 class AstropyTest(Command, object): description = 'Run the tests for this package' user_options = [ ('package=', 'P', "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=', 't', 'Specify a test location by path. If a relative path to a .py file, ' 'it is relative to the built package, so e.g., a leading "astropy/" ' 'is necessary. If a relative path to a .rst file, it is relative to ' 'the directory *below* the --docs-path directory, so a leading ' '"docs/" is usually necessary. May also be an absolute path.'), ('verbose-results', 'V', 'Turn on verbose output from pytest.'), ('plugins=', 'p', 'Plugins to enable when running pytest.'), ('pastebin=', 'b', "Enable pytest pastebin output. Either 'all' or 'failed'."), ('args=', 'a', 'Additional arguments to be passed to pytest.'), ('remote-data', 'R', 'Run tests that download remote data.'), ('pep8', '8', 'Enable PEP8 checking and disable regular tests. ' 'Requires the pytest-pep8 plugin.'), ('pdb', 'd', 'Start the interactive Python debugger on errors.'), ('coverage', 'c', 'Create a coverage report. Requires the coverage package.'), ('open-files', 'o', 'Fail if any tests leave files open. Requires the ' 'psutil package.'), ('parallel=', 'j', 'Run the tests in parallel on the specified number of ' 'CPUs. If negative, all the cores on the machine will be ' 'used. Requires the pytest-xdist plugin.'), ('docs-path=', None, 'The path to the documentation .rst files. If not provided, and ' 'the current directory contains a directory called "docs", that ' 'will be used.'), ('skip-docs', None, "Don't test the documentation .rst files."), ('repeat=', None, 'How many times to repeat each test (can be used to check for ' 'sporadic failures).'), ('temp-root=', None, 'The root directory in which to create the temporary testing files. ' 'If unspecified the system default is used (e.g. /tmp) as explained ' 'in the documentation for tempfile.mkstemp.') ] user_options = _fix_user_options(user_options) package_name = '' def initialize_options(self): self.package = None self.test_path = None self.verbose_results = False self.plugins = None self.pastebin = None self.args = None self.remote_data = False self.pep8 = False self.pdb = False self.coverage = False self.open_files = False self.parallel = 0 self.docs_path = None self.skip_docs = False self.repeat = None self.temp_root = None def finalize_options(self): # Normally we would validate the options here, but that's handled in # run_tests pass # Most of the test runner arguments have the same name as attributes on # this command class, with one exception (for now) _test_runner_arg_attr_map = { 'verbose': 'verbose_results' } def generate_testing_command(self): """ Build a Python script to run the tests. """ cmd_pre = '' # Commands to run before the test function cmd_post = '' # Commands to run after the test function if self.coverage: pre, post = self._generate_coverage_commands() cmd_pre += pre cmd_post += post def get_attr(arg): attr = self._test_runner_arg_attr_map.get(arg, arg) return getattr(self, attr) test_args = filter(lambda arg: hasattr(self, arg), self._get_test_runner_args()) test_args = ', '.join('{0}={1!r}'.format(arg, get_attr(arg)) for arg in test_args) if PY3: set_flag = "import builtins; builtins._ASTROPY_TEST_ = True" else: set_flag = "import __builtin__; __builtin__._ASTROPY_TEST_ = True" cmd = ('{cmd_pre}{0}; import {1.package_name}, sys; result = ' '{1.package_name}.test({test_args}); {cmd_post}' 'sys.exit(result)') return cmd.format(set_flag, self, cmd_pre=cmd_pre, cmd_post=cmd_post, test_args=test_args) def _validate_required_deps(self): """ This method checks that any required modules are installed before running the tests. """ try: import astropy # noqa except ImportError: raise ImportError( "The 'test' command requires the astropy package to be " "installed and importable.") def run(self): """ Run the tests! """ # Ensure there is a doc path if self.docs_path is None: if os.path.exists('docs'): self.docs_path = os.path.abspath('docs') # Build a testing install of the package self._build_temp_install() # Ensure all required packages are installed self._validate_required_deps() # Run everything in a try: finally: so that the tmp dir gets deleted. try: # Construct this modules testing command cmd = self.generate_testing_command() # Run the tests in a subprocess--this is necessary since # new extension modules may have appeared, and this is the # easiest way to set up a new environment # On Python 3.x prior to 3.3, the creation of .pyc files # is not atomic. py.test jumps through some hoops to make # this work by parsing import statements and carefully # importing files atomically. However, it can't detect # when __import__ is used, so its carefulness still fails. # The solution here (admittedly a bit of a hack), is to # turn off the generation of .pyc files altogether by # passing the `-B` switch to `python`. This does mean # that each core will have to compile .py file to bytecode # itself, rather than getting lucky and borrowing the work # already done by another core. Compilation is an # insignificant fraction of total testing time, though, so # it's probably not worth worrying about. retcode = subprocess.call([sys.executable, '-B', '-c', cmd], cwd=self.testing_path, close_fds=False) finally: # Remove temporary directory shutil.rmtree(self.tmp_dir) raise SystemExit(retcode) def _build_temp_install(self): """ Build the package and copy the build to a temporary directory for the purposes of testing this avoids creating pyc and __pycache__ directories inside the build directory """ self.reinitialize_command('build', inplace=True) self.run_command('build') build_cmd = self.get_finalized_command('build') new_path = os.path.abspath(build_cmd.build_lib) # On OSX the default path for temp files is under /var, but in most # cases on OSX /var is actually a symlink to /private/var; ensure we # dereference that link, because py.test is very sensitive to relative # paths... tmp_dir = tempfile.mkdtemp(prefix=self.package_name + '-test-', dir=self.temp_root) self.tmp_dir = os.path.realpath(tmp_dir) self.testing_path = os.path.join(self.tmp_dir, os.path.basename(new_path)) shutil.copytree(new_path, self.testing_path) new_docs_path = os.path.join(self.tmp_dir, os.path.basename(self.docs_path)) shutil.copytree(self.docs_path, new_docs_path) self.docs_path = new_docs_path shutil.copy('setup.cfg', self.tmp_dir) def _generate_coverage_commands(self): """ This method creates the post and pre commands if coverage is to be generated """ if self.parallel != 0: raise ValueError( "--coverage can not be used with --parallel") try: import coverage # noqa except ImportError: raise ImportError( "--coverage requires that the coverage package is " "installed.") # Don't use get_pkg_data_filename here, because it # requires importing astropy.config and thus screwing # up coverage results for those packages. coveragerc = os.path.join( self.testing_path, self.package_name, 'tests', 'coveragerc') # We create a coveragerc that is specific to the version # of Python we're running, so that we can mark branches # as being specifically for Python 2 or Python 3 with open(coveragerc, 'r') as fd: coveragerc_content = fd.read() if PY3: ignore_python_version = '2' else: ignore_python_version = '3' coveragerc_content = coveragerc_content.replace( "{ignore_python_version}", ignore_python_version).replace( "{packagename}", self.package_name) tmp_coveragerc = os.path.join(self.tmp_dir, 'coveragerc') with open(tmp_coveragerc, 'wb') as tmp: tmp.write(coveragerc_content.encode('utf-8')) cmd_pre = ( 'import coverage; ' 'cov = coverage.coverage(data_file="{0}", config_file="{1}"); ' 'cov.start();'.format( os.path.abspath(".coverage"), tmp_coveragerc)) cmd_post = ( 'cov.stop(); ' 'from astropy.tests.helper import _save_coverage; ' '_save_coverage(cov, result, "{0}", "{1}");'.format( os.path.abspath('.'), self.testing_path)) return cmd_pre, cmd_post def _get_test_runner_args(self): """ A hack to determine what arguments are supported by the package's test() function. In the future there should be a more straightforward API to determine this (really it should be determined by the ``TestRunner`` class for whatever version of Astropy is in use). """ if PY3: import builtins builtins._ASTROPY_TEST_ = True else: import __builtin__ __builtin__._ASTROPY_TEST_ = True try: pkg = __import__(self.package_name) if not hasattr(pkg, 'test'): raise ImportError( 'package {0} does not have a {0}.test() function as ' 'required by the Astropy test runner'.format(self.package_name)) argspec = inspect.getargspec(pkg.test) return argspec.args finally: if PY3: del builtins._ASTROPY_TEST_ else: del __builtin__._ASTROPY_TEST_ astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/build_ext.py0000644000077000000240000004636413126316034026574 0ustar adamstaff00000000000000import errno import os import re import shlex import shutil import subprocess import sys import textwrap from distutils import log, ccompiler, sysconfig from distutils.core import Extension from distutils.ccompiler import get_default_compiler from setuptools.command.build_ext import build_ext as SetuptoolsBuildExt from ..utils import get_numpy_include_path, invalidate_caches, classproperty from ..version_helpers import get_pkg_version_module def should_build_with_cython(package, release=None): """Returns the previously used Cython version (or 'unknown' if not previously built) if Cython should be used to build extension modules from pyx files. If the ``release`` parameter is not specified an attempt is made to determine the release flag from `astropy.version`. """ try: version_module = __import__(package + '.cython_version', fromlist=['release', 'cython_version']) except ImportError: version_module = None if release is None and version_module is not None: try: release = version_module.release except AttributeError: pass try: cython_version = version_module.cython_version except AttributeError: cython_version = 'unknown' # Only build with Cython if, of course, Cython is installed, we're in a # development version (i.e. not release) or the Cython-generated source # files haven't been created yet (cython_version == 'unknown'). The latter # case can happen even when release is True if checking out a release tag # from the repository have_cython = False try: import Cython # noqa have_cython = True except ImportError: pass if have_cython and (not release or cython_version == 'unknown'): return cython_version else: return False _compiler_versions = {} def get_compiler_version(compiler): if compiler in _compiler_versions: return _compiler_versions[compiler] # Different flags to try to get the compiler version # TODO: It might be worth making this configurable to support # arbitrary odd compilers; though all bets may be off in such # cases anyway flags = ['--version', '--Version', '-version', '-Version', '-v', '-V'] def try_get_version(flag): process = subprocess.Popen( shlex.split(compiler, posix=('win' not in sys.platform)) + [flag], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = process.communicate() if process.returncode != 0: return 'unknown' output = stdout.strip().decode('latin-1') # Safest bet if not output: # Some compilers return their version info on stderr output = stderr.strip().decode('latin-1') if not output: output = 'unknown' return output for flag in flags: version = try_get_version(flag) if version != 'unknown': break # Cache results to speed up future calls _compiler_versions[compiler] = version return version # TODO: I think this can be reworked without having to create the class # programmatically. def generate_build_ext_command(packagename, release): """ Creates a custom 'build_ext' command that allows for manipulating some of the C extension options at build time. We use a function to build the class since the base class for build_ext may be different depending on certain build-time parameters (for example, we may use Cython's build_ext instead of the default version in distutils). Uses the default distutils.command.build_ext by default. """ class build_ext(SetuptoolsBuildExt, object): package_name = packagename is_release = release _user_options = SetuptoolsBuildExt.user_options[:] _boolean_options = SetuptoolsBuildExt.boolean_options[:] _help_options = SetuptoolsBuildExt.help_options[:] force_rebuild = False _broken_compiler_mapping = [ ('i686-apple-darwin[0-9]*-llvm-gcc-4.2', 'clang') ] # Warning: Spaghetti code ahead. # During setup.py, the setup_helpers module needs the ability to add # items to a command's user_options list. At this stage we don't know # whether or not we can build with Cython, and so don't know for sure # what base class will be used for build_ext; nevertheless we want to # be able to provide a list to add options into. # # Later, once setup() has been called we should have all build # dependencies included via setup_requires available. distutils needs # to be able to access the user_options as a *class* attribute before # the class has been initialized, but we do need to be able to # enumerate the options for the correct base class at that point @classproperty def user_options(cls): from distutils import core if core._setup_distribution is None: # We haven't gotten into setup() yet, and the Distribution has # not yet been initialized return cls._user_options return cls._final_class.user_options @classproperty def boolean_options(cls): # Similar to user_options above from distutils import core if core._setup_distribution is None: # We haven't gotten into setup() yet, and the Distribution has # not yet been initialized return cls._boolean_options return cls._final_class.boolean_options @classproperty def help_options(cls): # Similar to user_options above from distutils import core if core._setup_distribution is None: # We haven't gotten into setup() yet, and the Distribution has # not yet been initialized return cls._help_options return cls._final_class.help_options @classproperty(lazy=True) def _final_class(cls): """ Late determination of what the build_ext base class should be, depending on whether or not Cython is available. """ uses_cython = should_build_with_cython(cls.package_name, cls.is_release) if uses_cython: # We need to decide late on whether or not to use Cython's # build_ext (since Cython may not be available earlier in the # setup.py if it was brought in via setup_requires) try: from Cython.Distutils.old_build_ext import old_build_ext as base_cls except ImportError: from Cython.Distutils import build_ext as base_cls else: base_cls = SetuptoolsBuildExt # Create and return an instance of a new class based on this class # using one of the above possible base classes def merge_options(attr): base = getattr(base_cls, attr) ours = getattr(cls, '_' + attr) all_base = set(opt[0] for opt in base) return base + [opt for opt in ours if opt[0] not in all_base] boolean_options = (base_cls.boolean_options + [opt for opt in cls._boolean_options if opt not in base_cls.boolean_options]) members = dict(cls.__dict__) members.update({ 'user_options': merge_options('user_options'), 'help_options': merge_options('help_options'), 'boolean_options': boolean_options, 'uses_cython': uses_cython, }) # Update the base class for the original build_ext command build_ext.__bases__ = (base_cls, object) # Create a new class for the existing class, but now with the # appropriate base class depending on whether or not to use Cython. # Ensure that object is one of the bases to make a new-style class. return type(cls.__name__, (build_ext,), members) def __new__(cls, *args, **kwargs): # By the time the command is actually instantialized, the # Distribution instance for the build has been instantiated, which # means setup_requires has been processed--now we can determine # what base class we can use for the actual build, and return an # instance of a build_ext command that uses that base class (right # now the options being Cython.Distutils.build_ext, or the stock # setuptools build_ext) new_cls = super(build_ext, cls._final_class).__new__( cls._final_class) # Since the new cls is not a subclass of the original cls, we must # manually call its __init__ new_cls.__init__(*args, **kwargs) return new_cls def finalize_options(self): # Add a copy of the _compiler.so module as well, but only if there # are in fact C modules to compile (otherwise there's no reason to # include a record of the compiler used) # Note, self.extensions may not be set yet, but # self.distribution.ext_modules is where any extension modules # passed to setup() can be found self._adjust_compiler() extensions = self.distribution.ext_modules if extensions: build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(packagename) src_path = os.path.relpath( os.path.join(os.path.dirname(__file__), 'src')) shutil.copy(os.path.join(src_path, 'compiler.c'), os.path.join(package_dir, '_compiler.c')) ext = Extension(self.package_name + '._compiler', [os.path.join(package_dir, '_compiler.c')]) extensions.insert(0, ext) super(build_ext, self).finalize_options() # Generate if self.uses_cython: try: from Cython import __version__ as cython_version except ImportError: # This shouldn't happen if we made it this far cython_version = None if (cython_version is not None and cython_version != self.uses_cython): self.force_rebuild = True # Update the used cython version self.uses_cython = cython_version # Regardless of the value of the '--force' option, force a rebuild # if the debug flag changed from the last build if self.force_rebuild: self.force = True def run(self): # For extensions that require 'numpy' in their include dirs, # replace 'numpy' with the actual paths np_include = get_numpy_include_path() for extension in self.extensions: if 'numpy' in extension.include_dirs: idx = extension.include_dirs.index('numpy') extension.include_dirs.insert(idx, np_include) extension.include_dirs.remove('numpy') self._check_cython_sources(extension) super(build_ext, self).run() # Update cython_version.py if building with Cython try: cython_version = get_pkg_version_module( packagename, fromlist=['cython_version'])[0] except (AttributeError, ImportError): cython_version = 'unknown' if self.uses_cython and self.uses_cython != cython_version: build_py = self.get_finalized_command('build_py') package_dir = build_py.get_package_dir(packagename) cython_py = os.path.join(package_dir, 'cython_version.py') with open(cython_py, 'w') as f: f.write('# Generated file; do not modify\n') f.write('cython_version = {0!r}\n'.format(self.uses_cython)) if os.path.isdir(self.build_lib): # The build/lib directory may not exist if the build_py # command was not previously run, which may sometimes be # the case self.copy_file(cython_py, os.path.join(self.build_lib, cython_py), preserve_mode=False) invalidate_caches() def _adjust_compiler(self): """ This function detects broken compilers and switches to another. If the environment variable CC is explicitly set, or a compiler is specified on the commandline, no override is performed -- the purpose here is to only override a default compiler. The specific compilers with problems are: * The default compiler in XCode-4.2, llvm-gcc-4.2, segfaults when compiling wcslib. The set of broken compilers can be updated by changing the compiler_mapping variable. It is a list of 2-tuples where the first in the pair is a regular expression matching the version of the broken compiler, and the second is the compiler to change to. """ if 'CC' in os.environ: # Check that CC is not set to llvm-gcc-4.2 c_compiler = os.environ['CC'] try: version = get_compiler_version(c_compiler) except OSError: msg = textwrap.dedent( """ The C compiler set by the CC environment variable: {compiler:s} cannot be found or executed. """.format(compiler=c_compiler)) log.warn(msg) sys.exit(1) for broken, fixed in self._broken_compiler_mapping: if re.match(broken, version): msg = textwrap.dedent( """Compiler specified by CC environment variable ({compiler:s}:{version:s}) will fail to compile {pkg:s}. Please set CC={fixed:s} and try again. You can do this, for example, by running: CC={fixed:s} python setup.py where is the command you ran. """.format(compiler=c_compiler, version=version, pkg=self.package_name, fixed=fixed)) log.warn(msg) sys.exit(1) # If C compiler is set via CC, and isn't broken, we are good to go. We # should definitely not try accessing the compiler specified by # ``sysconfig.get_config_var('CC')`` lower down, because this may fail # if the compiler used to compile Python is missing (and maybe this is # why the user is setting CC). For example, the official Python 2.7.3 # MacOS X binary was compiled with gcc-4.2, which is no longer available # in XCode 4. return if self.compiler is not None: # At this point, self.compiler will be set only if a compiler # was specified in the command-line or via setup.cfg, in which # case we don't do anything return compiler_type = ccompiler.get_default_compiler() if compiler_type == 'unix': # We have to get the compiler this way, as this is the one that is # used if os.environ['CC'] is not set. It is actually read in from # the Python Makefile. Note that this is not necessarily the same # compiler as returned by ccompiler.new_compiler() c_compiler = sysconfig.get_config_var('CC') try: version = get_compiler_version(c_compiler) except OSError: msg = textwrap.dedent( """ The C compiler used to compile Python {compiler:s}, and which is normally used to compile C extensions, is not available. You can explicitly specify which compiler to use by setting the CC environment variable, for example: CC=gcc python setup.py or if you are using MacOS X, you can try: CC=clang python setup.py """.format(compiler=c_compiler)) log.warn(msg) sys.exit(1) for broken, fixed in self._broken_compiler_mapping: if re.match(broken, version): os.environ['CC'] = fixed break def _check_cython_sources(self, extension): """ Where relevant, make sure that the .c files associated with .pyx modules are present (if building without Cython installed). """ # Determine the compiler we'll be using if self.compiler is None: compiler = get_default_compiler() else: compiler = self.compiler # Replace .pyx with C-equivalents, unless c files are missing for jdx, src in enumerate(extension.sources): base, ext = os.path.splitext(src) pyxfn = base + '.pyx' cfn = base + '.c' cppfn = base + '.cpp' if not os.path.isfile(pyxfn): continue if self.uses_cython: extension.sources[jdx] = pyxfn else: if os.path.isfile(cfn): extension.sources[jdx] = cfn elif os.path.isfile(cppfn): extension.sources[jdx] = cppfn else: msg = ( 'Could not find C/C++ file {0}.(c/cpp) for Cython ' 'file {1} when building extension {2}. Cython ' 'must be installed to build from a git ' 'checkout.'.format(base, pyxfn, extension.name)) raise IOError(errno.ENOENT, msg, cfn) # Current versions of Cython use deprecated Numpy API features # the use of which produces a few warnings when compiling. # These additional flags should squelch those warnings. # TODO: Feel free to remove this if/when a Cython update # removes use of the deprecated Numpy API if compiler == 'unix': extension.extra_compile_args.extend([ '-Wp,-w', '-Wno-unused-function']) return build_ext astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/build_py.py0000644000077000000240000000265612544425160026424 0ustar adamstaff00000000000000from setuptools.command.build_py import build_py as SetuptoolsBuildPy from ..utils import _get_platlib_dir class AstropyBuildPy(SetuptoolsBuildPy): user_options = SetuptoolsBuildPy.user_options[:] boolean_options = SetuptoolsBuildPy.boolean_options[:] def finalize_options(self): # Update build_lib settings from the build command to always put # build files in platform-specific subdirectories of build/, even # for projects with only pure-Python source (this is desirable # specifically for support of multiple Python version). build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) build_cmd.build_purelib = platlib_dir build_cmd.build_lib = platlib_dir self.build_lib = platlib_dir SetuptoolsBuildPy.finalize_options(self) def run_2to3(self, files, doctests=False): # Filter the files to exclude things that shouldn't be 2to3'd skip_2to3 = self.distribution.skip_2to3 filtered_files = [] for filename in files: for package in skip_2to3: if filename[len(self.build_lib) + 1:].startswith(package): break else: filtered_files.append(filename) SetuptoolsBuildPy.run_2to3(self, filtered_files, doctests) def run(self): # first run the normal build_py SetuptoolsBuildPy.run(self) astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/build_sphinx.py0000644000077000000240000002427713154552267027317 0ustar adamstaff00000000000000from __future__ import print_function import inspect import os import pkgutil import re import shutil import subprocess import sys import textwrap import warnings from distutils import log from distutils.cmd import DistutilsOptionError import sphinx from sphinx.setup_command import BuildDoc as SphinxBuildDoc from ..utils import minversion, AstropyDeprecationWarning PY3 = sys.version_info[0] >= 3 class AstropyBuildDocs(SphinxBuildDoc): """ A version of the ``build_docs`` command that uses the version of Astropy that is built by the setup ``build`` command, rather than whatever is installed on the system. To build docs against the installed version, run ``make html`` in the ``astropy/docs`` directory. This also automatically creates the docs/_static directories--this is needed because GitHub won't create the _static dir because it has no tracked files. """ description = 'Build Sphinx documentation for Astropy environment' user_options = SphinxBuildDoc.user_options[:] user_options.append( ('warnings-returncode', 'w', 'Parses the sphinx output and sets the return code to 1 if there ' 'are any warnings. Note that this will cause the sphinx log to ' 'only update when it completes, rather than continuously as is ' 'normally the case.')) user_options.append( ('clean-docs', 'l', 'Completely clean previous builds, including ' 'automodapi-generated files before building new ones')) user_options.append( ('no-intersphinx', 'n', 'Skip intersphinx, even if conf.py says to use it')) user_options.append( ('open-docs-in-browser', 'o', 'Open the docs in a browser (using the webbrowser module) if the ' 'build finishes successfully.')) boolean_options = SphinxBuildDoc.boolean_options[:] boolean_options.append('warnings-returncode') boolean_options.append('clean-docs') boolean_options.append('no-intersphinx') boolean_options.append('open-docs-in-browser') _self_iden_rex = re.compile(r"self\.([^\d\W][\w]+)", re.UNICODE) def initialize_options(self): SphinxBuildDoc.initialize_options(self) self.clean_docs = False self.no_intersphinx = False self.open_docs_in_browser = False self.warnings_returncode = False def finalize_options(self): SphinxBuildDoc.finalize_options(self) # Clear out previous sphinx builds, if requested if self.clean_docs: dirstorm = [os.path.join(self.source_dir, 'api'), os.path.join(self.source_dir, 'generated')] if self.build_dir is None: dirstorm.append('docs/_build') else: dirstorm.append(self.build_dir) for d in dirstorm: if os.path.isdir(d): log.info('Cleaning directory ' + d) shutil.rmtree(d) else: log.info('Not cleaning directory ' + d + ' because ' 'not present or not a directory') def run(self): # TODO: Break this method up into a few more subroutines and # document them better import webbrowser if PY3: from urllib.request import pathname2url else: from urllib import pathname2url # This is used at the very end of `run` to decide if sys.exit should # be called. If it's None, it won't be. retcode = None # If possible, create the _static dir if self.build_dir is not None: # the _static dir should be in the same place as the _build dir # for Astropy basedir, subdir = os.path.split(self.build_dir) if subdir == '': # the path has a trailing /... basedir, subdir = os.path.split(basedir) staticdir = os.path.join(basedir, '_static') if os.path.isfile(staticdir): raise DistutilsOptionError( 'Attempted to build_docs in a location where' + staticdir + 'is a file. Must be a directory.') self.mkpath(staticdir) # Now make sure Astropy is built and determine where it was built build_cmd = self.reinitialize_command('build') build_cmd.inplace = 0 self.run_command('build') build_cmd = self.get_finalized_command('build') build_cmd_path = os.path.abspath(build_cmd.build_lib) ah_importer = pkgutil.get_importer('astropy_helpers') ah_path = os.path.abspath(ah_importer.path) # Now generate the source for and spawn a new process that runs the # command. This is needed to get the correct imports for the built # version runlines, runlineno = inspect.getsourcelines(SphinxBuildDoc.run) subproccode = textwrap.dedent(""" from sphinx.setup_command import * os.chdir({srcdir!r}) sys.path.insert(0, {build_cmd_path!r}) sys.path.insert(0, {ah_path!r}) """).format(build_cmd_path=build_cmd_path, ah_path=ah_path, srcdir=self.source_dir) # runlines[1:] removes 'def run(self)' on the first line subproccode += textwrap.dedent(''.join(runlines[1:])) # All "self.foo" in the subprocess code needs to be replaced by the # values taken from the current self in *this* process subproccode = self._self_iden_rex.split(subproccode) for i in range(1, len(subproccode), 2): iden = subproccode[i] val = getattr(self, iden) if iden.endswith('_dir'): # Directories should be absolute, because the `chdir` call # in the new process moves to a different directory subproccode[i] = repr(os.path.abspath(val)) else: subproccode[i] = repr(val) subproccode = ''.join(subproccode) optcode = textwrap.dedent(""" class Namespace(object): pass self = Namespace() self.pdb = {pdb!r} self.verbosity = {verbosity!r} self.traceback = {traceback!r} """).format(pdb=getattr(self, 'pdb', False), verbosity=getattr(self, 'verbosity', 0), traceback=getattr(self, 'traceback', False)) subproccode = optcode + subproccode # This is a quick gross hack, but it ensures that the code grabbed from # SphinxBuildDoc.run will work in Python 2 if it uses the print # function if minversion(sphinx, '1.3'): subproccode = 'from __future__ import print_function' + subproccode if self.no_intersphinx: # the confoverrides variable in sphinx.setup_command.BuildDoc can # be used to override the conf.py ... but this could well break # if future versions of sphinx change the internals of BuildDoc, # so remain vigilant! subproccode = subproccode.replace( 'confoverrides = {}', 'confoverrides = {\'intersphinx_mapping\':{}}') log.debug('Starting subprocess of {0} with python code:\n{1}\n' '[CODE END])'.format(sys.executable, subproccode)) # To return the number of warnings, we need to capture stdout. This # prevents a continuous updating at the terminal, but there's no # apparent way around this. if self.warnings_returncode: proc = subprocess.Popen([sys.executable, '-c', subproccode], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) retcode = 1 with proc.stdout: for line in iter(proc.stdout.readline, b''): line = line.strip(b'\r\n') print(line.decode('utf-8')) if 'build succeeded.' == line.decode('utf-8'): retcode = 0 # Poll to set proc.retcode proc.wait() if retcode != 0: if os.environ.get('TRAVIS', None) == 'true': # this means we are in the travis build, so customize # the message appropriately. msg = ('The build_docs travis build FAILED ' 'because sphinx issued documentation ' 'warnings (scroll up to see the warnings).') else: # standard failure message msg = ('build_docs returning a non-zero exit ' 'code because sphinx issued documentation ' 'warnings.') log.warn(msg) else: proc = subprocess.Popen([sys.executable], stdin=subprocess.PIPE) proc.communicate(subproccode.encode('utf-8')) if proc.returncode == 0: if self.open_docs_in_browser: if self.builder == 'html': absdir = os.path.abspath(self.builder_target_dir) index_path = os.path.join(absdir, 'index.html') fileurl = 'file://' + pathname2url(index_path) webbrowser.open(fileurl) else: log.warn('open-docs-in-browser option was given, but ' 'the builder is not html! Ignoring.') else: log.warn('Sphinx Documentation subprocess failed with return ' 'code ' + str(proc.returncode)) retcode = proc.returncode if retcode is not None: # this is potentially dangerous in that there might be something # after the call to `setup` in `setup.py`, and exiting here will # prevent that from running. But there's no other apparent way # to signal what the return code should be. sys.exit(retcode) class AstropyBuildSphinx(AstropyBuildDocs): # pragma: no cover description = 'deprecated alias to the build_docs command' def run(self): warnings.warn( 'The "build_sphinx" command is now deprecated. Use' '"build_docs" instead.', AstropyDeprecationWarning) AstropyBuildDocs.run(self) astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/install.py0000644000077000000240000000074612544425160026261 0ustar adamstaff00000000000000from setuptools.command.install import install as SetuptoolsInstall from ..utils import _get_platlib_dir class AstropyInstall(SetuptoolsInstall): user_options = SetuptoolsInstall.user_options[:] boolean_options = SetuptoolsInstall.boolean_options[:] def finalize_options(self): build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) self.build_lib = platlib_dir SetuptoolsInstall.finalize_options(self) astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/install_lib.py0000644000077000000240000000100012544425160027067 0ustar adamstaff00000000000000from setuptools.command.install_lib import install_lib as SetuptoolsInstallLib from ..utils import _get_platlib_dir class AstropyInstallLib(SetuptoolsInstallLib): user_options = SetuptoolsInstallLib.user_options[:] boolean_options = SetuptoolsInstallLib.boolean_options[:] def finalize_options(self): build_cmd = self.get_finalized_command('build') platlib_dir = _get_platlib_dir(build_cmd) self.build_dir = platlib_dir SetuptoolsInstallLib.finalize_options(self) astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/register.py0000644000077000000240000000454712544425160026442 0ustar adamstaff00000000000000from setuptools.command.register import register as SetuptoolsRegister class AstropyRegister(SetuptoolsRegister): """Extends the built in 'register' command to support a ``--hidden`` option to make the registered version hidden on PyPI by default. The result of this is that when a version is registered as "hidden" it can still be downloaded from PyPI, but it does not show up in the list of actively supported versions under http://pypi.python.org/pypi/astropy, and is not set as the most recent version. Although this can always be set through the web interface it may be more convenient to be able to specify via the 'register' command. Hidden may also be considered a safer default when running the 'register' command, though this command uses distutils' normal behavior if the ``--hidden`` option is omitted. """ user_options = SetuptoolsRegister.user_options + [ ('hidden', None, 'mark this release as hidden on PyPI by default') ] boolean_options = SetuptoolsRegister.boolean_options + ['hidden'] def initialize_options(self): SetuptoolsRegister.initialize_options(self) self.hidden = False def build_post_data(self, action): data = SetuptoolsRegister.build_post_data(self, action) if action == 'submit' and self.hidden: data['_pypi_hidden'] = '1' return data def _set_config(self): # The original register command is buggy--if you use .pypirc with a # server-login section *at all* the repository you specify with the -r # option will be overwritten with either the repository in .pypirc or # with the default, # If you do not have a .pypirc using the -r option will just crash. # Way to go distutils # If we don't set self.repository back to a default value _set_config # can crash if there was a user-supplied value for this option; don't # worry, we'll get the real value back afterwards self.repository = 'pypi' SetuptoolsRegister._set_config(self) options = self.distribution.get_option_dict('register') if 'repository' in options: source, value = options['repository'] # Really anything that came from setup.cfg or the command line # should override whatever was in .pypirc self.repository = value astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/setup_package.py0000644000077000000240000000017013007171661027414 0ustar adamstaff00000000000000from os.path import join def get_package_data(): return {'astropy_helpers.commands': [join('src', 'compiler.c')]} astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/src/0000755000077000000240000000000013232443301025011 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/src/compiler.c0000644000077000000240000000573112544425160027005 0ustar adamstaff00000000000000#include /*************************************************************************** * Macros for determining the compiler version. * * These are borrowed from boost, and majorly abridged to include only * the compilers we care about. ***************************************************************************/ #ifndef PY3K #if PY_MAJOR_VERSION >= 3 #define PY3K 1 #else #define PY3K 0 #endif #endif #define STRINGIZE(X) DO_STRINGIZE(X) #define DO_STRINGIZE(X) #X #if defined __clang__ /* Clang C++ emulates GCC, so it has to appear early. */ # define COMPILER "Clang version " __clang_version__ #elif defined(__INTEL_COMPILER) || defined(__ICL) || defined(__ICC) || defined(__ECC) /* Intel */ # if defined(__INTEL_COMPILER) # define INTEL_VERSION __INTEL_COMPILER # elif defined(__ICL) # define INTEL_VERSION __ICL # elif defined(__ICC) # define INTEL_VERSION __ICC # elif defined(__ECC) # define INTEL_VERSION __ECC # endif # define COMPILER "Intel C compiler version " STRINGIZE(INTEL_VERSION) #elif defined(__GNUC__) /* gcc */ # define COMPILER "GCC version " __VERSION__ #elif defined(__SUNPRO_CC) /* Sun Workshop Compiler */ # define COMPILER "Sun compiler version " STRINGIZE(__SUNPRO_CC) #elif defined(_MSC_VER) /* Microsoft Visual C/C++ Must be last since other compilers define _MSC_VER for compatibility as well */ # if _MSC_VER < 1200 # define COMPILER_VERSION 5.0 # elif _MSC_VER < 1300 # define COMPILER_VERSION 6.0 # elif _MSC_VER == 1300 # define COMPILER_VERSION 7.0 # elif _MSC_VER == 1310 # define COMPILER_VERSION 7.1 # elif _MSC_VER == 1400 # define COMPILER_VERSION 8.0 # elif _MSC_VER == 1500 # define COMPILER_VERSION 9.0 # elif _MSC_VER == 1600 # define COMPILER_VERSION 10.0 # else # define COMPILER_VERSION _MSC_VER # endif # define COMPILER "Microsoft Visual C++ version " STRINGIZE(COMPILER_VERSION) #else /* Fallback */ # define COMPILER "Unknown compiler" #endif /*************************************************************************** * Module-level ***************************************************************************/ struct module_state { /* The Sun compiler can't handle empty structs */ #if defined(__SUNPRO_C) || defined(_MSC_VER) int _dummy; #endif }; #if PY3K static struct PyModuleDef moduledef = { PyModuleDef_HEAD_INIT, "_compiler", NULL, sizeof(struct module_state), NULL, NULL, NULL, NULL, NULL }; #define INITERROR return NULL PyMODINIT_FUNC PyInit__compiler(void) #else #define INITERROR return PyMODINIT_FUNC init_compiler(void) #endif { PyObject* m; #if PY3K m = PyModule_Create(&moduledef); #else m = Py_InitModule3("_compiler", NULL, NULL); #endif if (m == NULL) INITERROR; PyModule_AddStringConstant(m, "compiler", COMPILER); #if PY3K return m; #endif } astroquery-0.3.7/astropy_helpers/astropy_helpers/commands/test.py0000644000077000000240000000252413126316034025562 0ustar adamstaff00000000000000""" Different implementations of the ``./setup.py test`` command depending on what's locally available. If Astropy v1.1.0.dev or later is available it should be possible to import AstropyTest from ``astropy.tests.command``. If ``astropy`` can be imported but not ``astropy.tests.command`` (i.e. an older version of Astropy), we can use the backwards-compat implementation of the command. If Astropy can't be imported at all then there is a skeleton implementation that allows users to at least discover the ``./setup.py test`` command and learn that they need Astropy to run it. """ # Previously these except statements caught only ImportErrors, but there are # some other obscure exceptional conditions that can occur when importing # astropy.tests (at least on older versions) that can cause these imports to # fail try: import astropy # noqa try: from astropy.tests.command import AstropyTest except Exception: from ._test_compat import AstropyTest except Exception: # No astropy at all--provide the dummy implementation from ._dummy import _DummyCommand class AstropyTest(_DummyCommand): command_name = 'test' description = 'Run the tests for this package' error_msg = ( "The 'test' command requires the astropy package to be " "installed and importable.") astroquery-0.3.7/astropy_helpers/astropy_helpers/compat/0000755000077000000240000000000013232443301023704 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/compat/__init__.py0000644000077000000240000000056012354456432026033 0ustar adamstaff00000000000000def _fix_user_options(options): """ This is for Python 2.x and 3.x compatibility. distutils expects Command options to all be byte strings on Python 2 and Unicode strings on Python 3. """ def to_str_or_none(x): if x is None: return None return str(x) return [tuple(to_str_or_none(x) for x in y) for y in options] astroquery-0.3.7/astropy_helpers/astropy_helpers/distutils_helpers.py0000644000077000000240000001736213126316034026556 0ustar adamstaff00000000000000""" This module contains various utilities for introspecting the distutils module and the setup process. Some of these utilities require the `astropy_helpers.setup_helpers.register_commands` function to be called first, as it will affect introspection of setuptools command-line arguments. Other utilities in this module do not have that restriction. """ import os import sys from distutils import ccompiler, log from distutils.dist import Distribution from distutils.errors import DistutilsError from .utils import silence # This function, and any functions that call it, require the setup in # `astropy_helpers.setup_helpers.register_commands` to be run first. def get_dummy_distribution(): """ Returns a distutils Distribution object used to instrument the setup environment before calling the actual setup() function. """ from .setup_helpers import _module_state if _module_state['registered_commands'] is None: raise RuntimeError( 'astropy_helpers.setup_helpers.register_commands() must be ' 'called before using ' 'astropy_helpers.setup_helpers.get_dummy_distribution()') # Pre-parse the Distutils command-line options and config files to if # the option is set. dist = Distribution({'script_name': os.path.basename(sys.argv[0]), 'script_args': sys.argv[1:]}) dist.cmdclass.update(_module_state['registered_commands']) with silence(): try: dist.parse_config_files() dist.parse_command_line() except (DistutilsError, AttributeError, SystemExit): # Let distutils handle DistutilsErrors itself AttributeErrors can # get raise for ./setup.py --help SystemExit can be raised if a # display option was used, for example pass return dist def get_distutils_option(option, commands): """ Returns the value of the given distutils option. Parameters ---------- option : str The name of the option commands : list of str The list of commands on which this option is available Returns ------- val : str or None the value of the given distutils option. If the option is not set, returns None. """ dist = get_dummy_distribution() for cmd in commands: cmd_opts = dist.command_options.get(cmd) if cmd_opts is not None and option in cmd_opts: return cmd_opts[option][1] else: return None def get_distutils_build_option(option): """ Returns the value of the given distutils build option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build option. If the option is not set, returns None. """ return get_distutils_option(option, ['build', 'build_ext', 'build_clib']) def get_distutils_install_option(option): """ Returns the value of the given distutils install option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build option. If the option is not set, returns None. """ return get_distutils_option(option, ['install']) def get_distutils_build_or_install_option(option): """ Returns the value of the given distutils build or install option. Parameters ---------- option : str The name of the option Returns ------- val : str or None The value of the given distutils build or install option. If the option is not set, returns None. """ return get_distutils_option(option, ['build', 'build_ext', 'build_clib', 'install']) def get_compiler_option(): """ Determines the compiler that will be used to build extension modules. Returns ------- compiler : str The compiler option specified for the build, build_ext, or build_clib command; or the default compiler for the platform if none was specified. """ compiler = get_distutils_build_option('compiler') if compiler is None: return ccompiler.get_default_compiler() return compiler def add_command_option(command, name, doc, is_bool=False): """ Add a custom option to a setup command. Issues a warning if the option already exists on that command. Parameters ---------- command : str The name of the command as given on the command line name : str The name of the build option doc : str A short description of the option, for the `--help` message is_bool : bool, optional When `True`, the option is a boolean option and doesn't require an associated value. """ dist = get_dummy_distribution() cmdcls = dist.get_command_class(command) if (hasattr(cmdcls, '_astropy_helpers_options') and name in cmdcls._astropy_helpers_options): return attr = name.replace('-', '_') if hasattr(cmdcls, attr): raise RuntimeError( '{0!r} already has a {1!r} class attribute, barring {2!r} from ' 'being usable as a custom option name.'.format(cmdcls, attr, name)) for idx, cmd in enumerate(cmdcls.user_options): if cmd[0] == name: log.warn('Overriding existing {0!r} option ' '{1!r}'.format(command, name)) del cmdcls.user_options[idx] if name in cmdcls.boolean_options: cmdcls.boolean_options.remove(name) break cmdcls.user_options.append((name, None, doc)) if is_bool: cmdcls.boolean_options.append(name) # Distutils' command parsing requires that a command object have an # attribute with the same name as the option (with '-' replaced with '_') # in order for that option to be recognized as valid setattr(cmdcls, attr, None) # This caches the options added through add_command_option so that if it is # run multiple times in the same interpreter repeated adds are ignored # (this way we can still raise a RuntimeError if a custom option overrides # a built-in option) if not hasattr(cmdcls, '_astropy_helpers_options'): cmdcls._astropy_helpers_options = set([name]) else: cmdcls._astropy_helpers_options.add(name) def get_distutils_display_options(): """ Returns a set of all the distutils display options in their long and short forms. These are the setup.py arguments such as --name or --version which print the project's metadata and then exit. Returns ------- opts : set The long and short form display option arguments, including the - or -- """ short_display_opts = set('-' + o[1] for o in Distribution.display_options if o[1]) long_display_opts = set('--' + o[0] for o in Distribution.display_options) # Include -h and --help which are not explicitly listed in # Distribution.display_options (as they are handled by optparse) short_display_opts.add('-h') long_display_opts.add('--help') # This isn't the greatest approach to hardcode these commands. # However, there doesn't seem to be a good way to determine # whether build *will be* run as part of the command at this # phase. display_commands = set([ 'clean', 'register', 'setopt', 'saveopts', 'egg_info', 'alias']) return short_display_opts.union(long_display_opts.union(display_commands)) def is_distutils_display_option(): """ Returns True if sys.argv contains any of the distutils display options such as --version or --name. """ display_options = get_distutils_display_options() return bool(set(sys.argv[1:]).intersection(display_options)) astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/0000755000077000000240000000000013232443301023726 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/__init__.py0000644000077000000240000000111513126316034026041 0ustar adamstaff00000000000000# The ``astropy_helpers.extern`` sub-module includes modules developed elsewhere # that are bundled here for convenience. At the moment, this consists of the # following two sphinx extensions: # # * `numpydoc `_, a Sphinx extension # developed as part of the Numpy project. This is used to parse docstrings # in Numpy format # # * `sphinx-automodapi `_, a Sphinx # developed as part of the Astropy project. This used to be developed directly # in ``astropy-helpers`` but is now a standalone package. astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/0000755000077000000240000000000013232443301026070 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/__init__.py0000644000077000000240000000002413232205045030176 0ustar adamstaff00000000000000__version__ = '0.7' astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/autodoc_enhancements.py0000644000077000000240000001230413126316034032634 0ustar adamstaff00000000000000""" Miscellaneous enhancements to help autodoc along. """ import inspect import sys import types import sphinx from distutils.version import LooseVersion from sphinx.ext.autodoc import AttributeDocumenter, ModuleDocumenter from sphinx.util.inspect import isdescriptor if sys.version_info[0] == 3: class_types = (type,) else: class_types = (type, types.ClassType) SPHINX_LT_15 = (LooseVersion(sphinx.__version__) < LooseVersion('1.5')) MethodDescriptorType = type(type.__subclasses__) # See # https://github.com/astropy/astropy-helpers/issues/116#issuecomment-71254836 # for further background on this. def type_object_attrgetter(obj, attr, *defargs): """ This implements an improved attrgetter for type objects (i.e. classes) that can handle class attributes that are implemented as properties on a metaclass. Normally `getattr` on a class with a `property` (say, "foo"), would return the `property` object itself. However, if the class has a metaclass which *also* defines a `property` named "foo", ``getattr(cls, 'foo')`` will find the "foo" property on the metaclass and resolve it. For the purposes of autodoc we just want to document the "foo" property defined on the class, not on the metaclass. For example:: >>> class Meta(type): ... @property ... def foo(cls): ... return 'foo' ... >>> class MyClass(metaclass=Meta): ... @property ... def foo(self): ... \"\"\"Docstring for MyClass.foo property.\"\"\" ... return 'myfoo' ... >>> getattr(MyClass, 'foo') 'foo' >>> type_object_attrgetter(MyClass, 'foo') >>> type_object_attrgetter(MyClass, 'foo').__doc__ 'Docstring for MyClass.foo property.' The last line of the example shows the desired behavior for the purposes of autodoc. """ for base in obj.__mro__: if attr in base.__dict__: if isinstance(base.__dict__[attr], property): # Note, this should only be used for properties--for any other # type of descriptor (classmethod, for example) this can mess # up existing expectations of what getattr(cls, ...) returns return base.__dict__[attr] break return getattr(obj, attr, *defargs) if SPHINX_LT_15: # Provided to work around a bug in Sphinx # See https://github.com/sphinx-doc/sphinx/pull/1843 class AttributeDocumenter(AttributeDocumenter): @classmethod def can_document_member(cls, member, membername, isattr, parent): non_attr_types = cls.method_types + class_types + \ (MethodDescriptorType,) isdatadesc = isdescriptor(member) and not \ isinstance(member, non_attr_types) and not \ type(member).__name__ == "instancemethod" # That last condition addresses an obscure case of C-defined # methods using a deprecated type in Python 3, that is not # otherwise exported anywhere by Python return isdatadesc or (not isinstance(parent, ModuleDocumenter) and not inspect.isroutine(member) and not isinstance(member, class_types)) def setup(app): # Must have the autodoc extension set up first so we can override it app.setup_extension('sphinx.ext.autodoc') # Need to import this too since it re-registers all the documenter types # =_= import sphinx.ext.autosummary.generate app.add_autodoc_attrgetter(type, type_object_attrgetter) if sphinx.version_info < (1, 4, 2): # this is a really ugly hack to supress a warning that sphinx 1.4 # generates when overriding an existing directive (which is *desired* # behavior here). As of sphinx v1.4.2, this has been fixed: # https://github.com/sphinx-doc/sphinx/issues/2451 # But we leave it in for 1.4.0/1.4.1 . But if the "needs_sphinx" is # eventually updated to >= 1.4.2, this should be removed entirely (in # favor of the line in the "else" clause) _oldwarn = app._warning _oldwarncount = app._warncount try: try: # *this* is in a try/finally because we don't want to force six as # a real dependency. In sphinx 1.4, six is a prerequisite, so # there's no issue. But in older sphinxes this may not be true... # but the inderlying warning is absent anyway so we let it slide. from six import StringIO app._warning = StringIO() except ImportError: pass app.add_autodocumenter(AttributeDocumenter) finally: app._warning = _oldwarn app._warncount = _oldwarncount else: suppress_warnigns_orig = app.config.suppress_warnings[:] if 'app.add_directive' not in app.config.suppress_warnings: app.config.suppress_warnings.append('app.add_directive') try: app.add_autodocumenter(AttributeDocumenter) finally: app.config.suppress_warnings = suppress_warnigns_orig astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/automodapi.py0000644000077000000240000003665113126316034030623 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This directive takes a single argument that must be a module or package. It will produce a block of documentation that includes the docstring for the package, an :ref:`automodsumm` directive, and an :ref:`automod-diagram` if there are any classes in the module. If only the main docstring of the module/package is desired in the documentation, use `automodule`_ instead of `automodapi`_. It accepts the following options: * ``:include-all-objects:`` If present, include not just functions and classes, but all objects. This includes variables, for which a possible docstring after the variable definition will be shown. * ``:no-inheritance-diagram:`` If present, the inheritance diagram will not be shown even if the module/package has classes. * ``:skip: str`` This option results in the specified object being skipped, that is the object will *not* be included in the generated documentation. This option may appear any number of times to skip multiple objects. * ``:no-main-docstr:`` If present, the docstring for the module/package will not be generated. The function and class tables will still be used, however. * ``:headings: str`` Specifies the characters (in one string) used as the heading levels used for the generated section. This must have at least 2 characters (any after 2 will be ignored). This also *must* match the rest of the documentation on this page for sphinx to be happy. Defaults to "-^", which matches the convention used for Python's documentation, assuming the automodapi call is inside a top-level section (which usually uses '='). * ``:no-heading:`` If specified do not create a top level heading for the section. That is, do not create a title heading with text like "packagename Package". The actual docstring for the package/module will still be shown, though, unless ``:no-main-docstr:`` is given. * ``:allowed-package-names: str`` Specifies the packages that functions/classes documented here are allowed to be from, as comma-separated list of package names. If not given, only objects that are actually in a subpackage of the package currently being documented are included. * ``:inherited-members:`` / ``:no-inherited-members:`` The global sphinx configuration option ``automodsumm_inherited_members`` decides if members that a class inherits from a base class are included in the generated documentation. The option ``:inherited-members:`` or ``:no-inherited-members:`` allows the user to overrride the global setting. This extension also adds three sphinx configuration options: * ``automodapi_toctreedirnm`` This must be a string that specifies the name of the directory the automodsumm generated documentation ends up in. This directory path should be relative to the documentation root (e.g., same place as ``index.rst``). Defaults to ``'api'``. * ``automodapi_writereprocessed`` Should be a bool, and if `True`, will cause `automodapi`_ to write files with any `automodapi`_ sections replaced with the content Sphinx processes after `automodapi`_ has run. The output files are not actually used by sphinx, so this option is only for figuring out the cause of sphinx warnings or other debugging. Defaults to `False`. * ``automodsumm_inherited_members`` Should be a bool and if ``True`` members that a class inherits from a base class are included in the generated documentation. Defaults to ``False``. .. _automodule: http://sphinx-doc.org/latest/ext/autodoc.html?highlight=automodule#directive-automodule """ # Implementation note: # The 'automodapi' directive is not actually implemented as a docutils # directive. Instead, this extension searches for the 'automodapi' text in # all sphinx documents, and replaces it where necessary from a template built # into this extension. This is necessary because automodsumm (and autosummary) # use the "builder-inited" event, which comes before the directives are # actually built. import inspect import io import os import re import sys from .utils import find_mod_objs if sys.version_info[0] == 3: text_type = str else: text_type = unicode automod_templ_modheader = """ {modname} {pkgormod} {modhds}{pkgormodhds} {automoduleline} """ automod_templ_classes = """ Classes {clshds} .. automodsumm:: {modname} :classes-only: {clsfuncoptions} """ automod_templ_funcs = """ Functions {funchds} .. automodsumm:: {modname} :functions-only: {clsfuncoptions} """ automod_templ_vars = """ Variables {otherhds} .. automodsumm:: {modname} :variables-only: {clsfuncoptions} """ automod_templ_inh = """ Class Inheritance Diagram {clsinhsechds} .. automod-diagram:: {modname} :private-bases: :parts: 1 {allowedpkgnms} {skip} """ _automodapirex = re.compile(r'^(?:\.\.\s+automodapi::\s*)([A-Za-z0-9_.]+)' r'\s*$((?:\n\s+:[a-zA-Z_\-]+:.*$)*)', flags=re.MULTILINE) # the last group of the above regex is intended to go into finall with the below _automodapiargsrex = re.compile(r':([a-zA-Z_\-]+):(.*)$', flags=re.MULTILINE) def automodapi_replace(sourcestr, app, dotoctree=True, docname=None, warnings=True): """ Replaces `sourcestr`'s entries of ".. automdapi::" with the automodapi template form based on provided options. This is used with the sphinx event 'source-read' to replace `automodapi`_ entries before sphinx actually processes them, as automodsumm needs the code to be present to generate stub documentation. Parameters ---------- sourcestr : str The string with sphinx source to be checked for automodapi replacement. app : `sphinx.application.Application` The sphinx application. dotoctree : bool If `True`, a ":toctree:" option will be added in the ".. automodsumm::" sections of the template, pointing to the appropriate "generated" directory based on the Astropy convention (e.g. in ``docs/api``) docname : str The name of the file for this `sourcestr` (if known - if not, it can be `None`). If not provided and `dotoctree` is `True`, the generated files may end up in the wrong place. warnings : bool If `False`, all warnings that would normally be issued are silenced. Returns ------- newstr :str The string with automodapi entries replaced with the correct sphinx markup. """ spl = _automodapirex.split(sourcestr) if len(spl) > 1: # automodsumm is in this document # Use app.srcdir because api folder should be inside source folder not # at folder where sphinx is run. if dotoctree: toctreestr = ':toctree: ' api_dir = os.path.join(app.srcdir, app.config.automodapi_toctreedirnm) if docname is None: doc_path = '.' else: doc_path = os.path.join(app.srcdir, docname) toctreestr += os.path.relpath(api_dir, os.path.dirname(doc_path)) else: toctreestr = '' newstrs = [spl[0]] for grp in range(len(spl) // 3): modnm = spl[grp * 3 + 1] # find where this is in the document for warnings if docname is None: location = None else: location = (docname, spl[0].count('\n')) # initialize default options toskip = [] inhdiag = maindocstr = top_head = True hds = '-^' allowedpkgnms = [] allowothers = False # look for actual options unknownops = [] inherited_members = None for opname, args in _automodapiargsrex.findall(spl[grp * 3 + 2]): if opname == 'skip': toskip.append(args.strip()) elif opname == 'no-inheritance-diagram': inhdiag = False elif opname == 'no-main-docstr': maindocstr = False elif opname == 'headings': hds = args elif opname == 'no-heading': top_head = False elif opname == 'allowed-package-names': allowedpkgnms.append(args.strip()) elif opname == 'inherited-members': inherited_members = True elif opname == 'no-inherited-members': inherited_members = False elif opname == 'include-all-objects': allowothers = True else: unknownops.append(opname) # join all the allowedpkgnms if len(allowedpkgnms) == 0: allowedpkgnms = '' onlylocals = True else: allowedpkgnms = ':allowed-package-names: ' + ','.join(allowedpkgnms) onlylocals = allowedpkgnms # get the two heading chars if len(hds) < 2: msg = 'Not enough headings (got {0}, need 2), using default -^' if warnings: app.warn(msg.format(len(hds)), location) hds = '-^' h1, h2 = hds.lstrip()[:2] # tell sphinx that the remaining args are invalid. if len(unknownops) > 0 and app is not None: opsstrs = ','.join(unknownops) msg = 'Found additional options ' + opsstrs + ' in automodapi.' if warnings: app.warn(msg, location) ispkg, hascls, hasfuncs, hasother = _mod_info( modnm, toskip, onlylocals=onlylocals) # add automodule directive only if no-main-docstr isn't present if maindocstr: automodline = '.. automodule:: {modname}'.format(modname=modnm) else: automodline = '' if top_head: newstrs.append(automod_templ_modheader.format( modname=modnm, modhds=h1 * len(modnm), pkgormod='Package' if ispkg else 'Module', pkgormodhds=h1 * (8 if ispkg else 7), automoduleline=automodline)) # noqa else: newstrs.append(automod_templ_modheader.format( modname='', modhds='', pkgormod='', pkgormodhds='', automoduleline=automodline)) # construct the options for the class/function sections # start out indented at 4 spaces, but need to keep the indentation. clsfuncoptions = [] if toctreestr: clsfuncoptions.append(toctreestr) if toskip: clsfuncoptions.append(':skip: ' + ','.join(toskip)) if allowedpkgnms: clsfuncoptions.append(allowedpkgnms) if hascls: # This makes no sense unless there are classes. if inherited_members is True: clsfuncoptions.append(':inherited-members:') if inherited_members is False: clsfuncoptions.append(':no-inherited-members:') clsfuncoptionstr = '\n '.join(clsfuncoptions) if hasfuncs: newstrs.append(automod_templ_funcs.format( modname=modnm, funchds=h2 * 9, clsfuncoptions=clsfuncoptionstr)) if hascls: newstrs.append(automod_templ_classes.format( modname=modnm, clshds=h2 * 7, clsfuncoptions=clsfuncoptionstr)) if allowothers and hasother: newstrs.append(automod_templ_vars.format( modname=modnm, otherhds=h2 * 9, clsfuncoptions=clsfuncoptionstr)) if inhdiag and hascls: # add inheritance diagram if any classes are in the module if toskip: clsskip = ':skip: ' + ','.join(toskip) else: clsskip = '' diagram_entry = automod_templ_inh.format( modname=modnm, clsinhsechds=h2 * 25, allowedpkgnms=allowedpkgnms, skip=clsskip) diagram_entry = diagram_entry.replace(' \n', '') newstrs.append(diagram_entry) newstrs.append(spl[grp * 3 + 3]) newsourcestr = ''.join(newstrs) if app.config.automodapi_writereprocessed: # sometimes they are unicode, sometimes not, depending on how # sphinx has processed things if isinstance(newsourcestr, text_type): ustr = newsourcestr else: ustr = newsourcestr.decode(app.config.source_encoding) if docname is None: with io.open(os.path.join(app.srcdir, 'unknown.automodapi'), 'a', encoding='utf8') as f: f.write(u'\n**NEW DOC**\n\n') f.write(ustr) else: env = app.builder.env # Determine the filename associated with this doc (specifically # the extension) filename = docname + os.path.splitext(env.doc2path(docname))[1] filename += '.automodapi' with io.open(os.path.join(app.srcdir, filename), 'w', encoding='utf8') as f: f.write(ustr) return newsourcestr else: return sourcestr def _mod_info(modname, toskip=[], onlylocals=True): """ Determines if a module is a module or a package and whether or not it has classes or functions. """ hascls = hasfunc = hasother = False for localnm, fqnm, obj in zip(*find_mod_objs(modname, onlylocals=onlylocals)): if localnm not in toskip: hascls = hascls or inspect.isclass(obj) hasfunc = hasfunc or inspect.isroutine(obj) hasother = hasother or (not inspect.isclass(obj) and not inspect.isroutine(obj)) if hascls and hasfunc and hasother: break # find_mod_objs has already imported modname # TODO: There is probably a cleaner way to do this, though this is pretty # reliable for all Python versions for most cases that we care about. pkg = sys.modules[modname] ispkg = (hasattr(pkg, '__file__') and isinstance(pkg.__file__, str) and os.path.split(pkg.__file__)[1].startswith('__init__.py')) return ispkg, hascls, hasfunc, hasother def process_automodapi(app, docname, source): source[0] = automodapi_replace(source[0], app, True, docname) def setup(app): app.setup_extension('sphinx.ext.autosummary') # Note: we use __name__ here instead of just writing the module name in # case this extension is bundled into another package from . import automodsumm app.setup_extension(automodsumm.__name__) app.connect('source-read', process_automodapi) app.add_config_value('automodapi_toctreedirnm', 'api', True) app.add_config_value('automodapi_writereprocessed', False, True) astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/automodsumm.py0000644000077000000240000006363013232205045031025 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This directive will produce an "autosummary"-style table for public attributes of a specified module. See the `sphinx.ext.autosummary`_ extension for details on this process. The main difference from the `autosummary`_ directive is that `autosummary`_ requires manually inputting all attributes that appear in the table, while this captures the entries automatically. This directive requires a single argument that must be a module or package. It also accepts any options supported by the `autosummary`_ directive- see `sphinx.ext.autosummary`_ for details. It also accepts some additional options: * ``:classes-only:`` If present, the autosummary table will only contain entries for classes. This cannot be used at the same time with ``:functions-only:`` or ``:variables-only:``. * ``:functions-only:`` If present, the autosummary table will only contain entries for functions. This cannot be used at the same time with ``:classes-only:`` or ``:variables-only:``. * ``:variables-only:`` If present, the autosummary table will only contain entries for variables (everything except functions and classes). This cannot be used at the same time with ``:classes-only:`` or ``:functions-only:``. * ``:skip: obj1, [obj2, obj3, ...]`` If present, specifies that the listed objects should be skipped and not have their documentation generated, nor be included in the summary table. * ``:allowed-package-names: pkgormod1, [pkgormod2, pkgormod3, ...]`` Specifies the packages that functions/classes documented here are allowed to be from, as comma-separated list of package names. If not given, only objects that are actually in a subpackage of the package currently being documented are included. * ``:inherited-members:`` or ``:no-inherited-members:`` The global sphinx configuration option ``automodsumm_inherited_members`` decides if members that a class inherits from a base class are included in the generated documentation. The flags ``:inherited-members:`` or ``:no-inherited-members:`` allows overrriding this global setting. This extension also adds two sphinx configuration options: * ``automodsumm_writereprocessed`` Should be a bool, and if ``True``, will cause `automodsumm`_ to write files with any ``automodsumm`` sections replaced with the content Sphinx processes after ``automodsumm`` has run. The output files are not actually used by sphinx, so this option is only for figuring out the cause of sphinx warnings or other debugging. Defaults to ``False``. * ``automodsumm_inherited_members`` Should be a bool and if ``True``, will cause `automodsumm`_ to document class members that are inherited from a base class. This value can be overriden for any particular automodsumm directive by including the ``:inherited-members:`` or ``:no-inherited-members:`` options. Defaults to ``False``. .. _sphinx.ext.autosummary: http://sphinx-doc.org/latest/ext/autosummary.html .. _autosummary: http://sphinx-doc.org/latest/ext/autosummary.html#directive-autosummary .. _automod-diagram: automod-diagram directive ========================= This directive will produce an inheritance diagram like that of the `sphinx.ext.inheritance_diagram`_ extension. This directive requires a single argument that must be a module or package. It accepts no options. .. note:: Like 'inheritance-diagram', 'automod-diagram' requires `graphviz `_ to generate the inheritance diagram. .. _sphinx.ext.inheritance_diagram: http://sphinx-doc.org/latest/ext/inheritance.html """ import inspect import os import re import io from distutils.version import LooseVersion from sphinx import __version__ from sphinx.ext.autosummary import Autosummary from sphinx.ext.inheritance_diagram import InheritanceDiagram from docutils.parsers.rst.directives import flag from .utils import find_mod_objs, cleanup_whitespace SPHINX_LT_17 = LooseVersion(__version__) < LooseVersion('1.7') def _str_list_converter(argument): """ A directive option conversion function that converts the option into a list of strings. Used for 'skip' option. """ if argument is None: return [] else: return [s.strip() for s in argument.split(',')] class Automodsumm(Autosummary): required_arguments = 1 optional_arguments = 0 final_argument_whitespace = False has_content = False option_spec = dict(Autosummary.option_spec) option_spec['functions-only'] = flag option_spec['classes-only'] = flag option_spec['variables-only'] = flag option_spec['skip'] = _str_list_converter option_spec['allowed-package-names'] = _str_list_converter option_spec['inherited-members'] = flag option_spec['no-inherited-members'] = flag def run(self): env = self.state.document.settings.env modname = self.arguments[0] self.warnings = [] nodelist = [] try: localnames, fqns, objs = find_mod_objs(modname) except ImportError: self.warnings = [] self.warn("Couldn't import module " + modname) return self.warnings try: # set self.content to trick the autosummary internals. # Be sure to respect functions-only and classes-only. funconly = 'functions-only' in self.options clsonly = 'classes-only' in self.options varonly = 'variables-only' in self.options if [clsonly, funconly, varonly].count(True) > 1: self.warning('more than one of functions-only, classes-only, ' 'or variables-only defined. Ignoring.') clsonly = funconly = varonly = False skipnames = [] if 'skip' in self.options: option_skipnames = set(self.options['skip']) for lnm in localnames: if lnm in option_skipnames: option_skipnames.remove(lnm) skipnames.append(lnm) if len(option_skipnames) > 0: self.warn('Tried to skip objects {objs} in module {mod}, ' 'but they were not present. Ignoring.' .format(objs=option_skipnames, mod=modname)) if funconly: cont = [] for nm, obj in zip(localnames, objs): if nm not in skipnames and inspect.isroutine(obj): cont.append(nm) elif clsonly: cont = [] for nm, obj in zip(localnames, objs): if nm not in skipnames and inspect.isclass(obj): cont.append(nm) elif varonly: cont = [] for nm, obj in zip(localnames, objs): if nm not in skipnames and not (inspect.isclass(obj) or inspect.isroutine(obj)): cont.append(nm) else: cont = [nm for nm in localnames if nm not in skipnames] self.content = cont # for some reason, even though ``currentmodule`` is substituted in, # sphinx doesn't necessarily recognize this fact. So we just force # it internally, and that seems to fix things env.temp_data['py:module'] = modname env.ref_context['py:module'] = modname # can't use super because Sphinx/docutils has trouble return # super(Autosummary,self).run() nodelist.extend(Autosummary.run(self)) return self.warnings + nodelist finally: # has_content = False for the Automodsumm self.content = [] def get_items(self, names): self.genopt['imported-members'] = True return Autosummary.get_items(self, names) # <-------------------automod-diagram stuff-----------------------------------> class Automoddiagram(InheritanceDiagram): option_spec = dict(InheritanceDiagram.option_spec) option_spec['allowed-package-names'] = _str_list_converter option_spec['skip'] = _str_list_converter def run(self): try: ols = self.options.get('allowed-package-names', []) ols = True if len(ols) == 0 else ols # if none are given, assume only local nms, objs = find_mod_objs(self.arguments[0], onlylocals=ols)[1:] except ImportError: self.warnings = [] self.warn("Couldn't import module " + self.arguments[0]) return self.warnings # Check if some classes should be skipped skip = self.options.get('skip', []) clsnms = [] for n, o in zip(nms, objs): if n.split('.')[-1] in skip: continue if inspect.isclass(o): clsnms.append(n) oldargs = self.arguments try: if len(clsnms) > 0: self.arguments = [' '.join(clsnms)] return InheritanceDiagram.run(self) finally: self.arguments = oldargs # <---------------------automodsumm generation stuff--------------------------> def process_automodsumm_generation(app): env = app.builder.env filestosearch = [] for docname in env.found_docs: filename = env.doc2path(docname) if os.path.isfile(filename): filestosearch.append(docname + os.path.splitext(filename)[1]) liness = [] for sfn in filestosearch: lines = automodsumm_to_autosummary_lines(sfn, app) liness.append(lines) if app.config.automodsumm_writereprocessed: if lines: # empty list means no automodsumm entry is in the file outfn = os.path.join(app.srcdir, sfn) + '.automodsumm' with open(outfn, 'w') as f: for l in lines: f.write(l) f.write('\n') for sfn, lines in zip(filestosearch, liness): suffix = os.path.splitext(sfn)[1] if len(lines) > 0: generate_automodsumm_docs( lines, sfn, app=app, builder=app.builder, warn=app.warn, info=app.info, suffix=suffix, base_path=app.srcdir, inherited_members=app.config.automodsumm_inherited_members) # _automodsummrex = re.compile(r'^(\s*)\.\. automodsumm::\s*([A-Za-z0-9_.]+)\s*' # r'\n\1(\s*)(\S|$)', re.MULTILINE) _lineendrex = r'(?:\n|$)' _hdrex = r'^\n?(\s*)\.\. automodsumm::\s*(\S+)\s*' + _lineendrex _oprex1 = r'(?:\1(\s+)\S.*' + _lineendrex + ')' _oprex2 = r'(?:\1\4\S.*' + _lineendrex + ')' _automodsummrex = re.compile(_hdrex + '(' + _oprex1 + '?' + _oprex2 + '*)', re.MULTILINE) def automodsumm_to_autosummary_lines(fn, app): """ Generates lines from a file with an "automodsumm" entry suitable for feeding into "autosummary". Searches the provided file for `automodsumm` directives and returns a list of lines specifying the `autosummary` commands for the modules requested. This does *not* return the whole file contents - just an autosummary section in place of any :automodsumm: entries. Note that any options given for `automodsumm` are also included in the generated `autosummary` section. Parameters ---------- fn : str The name of the file to search for `automodsumm` entries. app : sphinx.application.Application The sphinx Application object Returns ------- lines : list of str Lines for all `automodsumm` entries with the entries replaced by `autosummary` and the module's members added. """ fullfn = os.path.join(app.builder.env.srcdir, fn) with io.open(fullfn, encoding='utf8') as fr: # Note: we use __name__ here instead of just writing the module name in # case this extension is bundled into another package from . import automodapi try: extensions = app.extensions except AttributeError: # Sphinx <1.6 extensions = app._extensions if automodapi.__name__ in extensions: # Must do the automodapi on the source to get the automodsumm # that might be in there docname = os.path.splitext(fn)[0] filestr = automodapi.automodapi_replace(fr.read(), app, True, docname, False) else: filestr = fr.read() spl = _automodsummrex.split(filestr) # 0th entry is the stuff before the first automodsumm line indent1s = spl[1::5] mods = spl[2::5] opssecs = spl[3::5] indent2s = spl[4::5] remainders = spl[5::5] # only grab automodsumm sections and convert them to autosummary with the # entries for all the public objects newlines = [] # loop over all automodsumms in this document for i, (i1, i2, modnm, ops, rem) in enumerate(zip(indent1s, indent2s, mods, opssecs, remainders)): allindent = i1 + (' ' if i2 is None else i2) # filter out functions-only, classes-only, and ariables-only # options if present. oplines = ops.split('\n') toskip = [] allowedpkgnms = [] funcsonly = clssonly = varsonly = False for i, ln in reversed(list(enumerate(oplines))): if ':functions-only:' in ln: funcsonly = True del oplines[i] if ':classes-only:' in ln: clssonly = True del oplines[i] if ':variables-only:' in ln: varsonly = True del oplines[i] if ':skip:' in ln: toskip.extend(_str_list_converter(ln.replace(':skip:', ''))) del oplines[i] if ':allowed-package-names:' in ln: allowedpkgnms.extend(_str_list_converter(ln.replace(':allowed-package-names:', ''))) del oplines[i] if [funcsonly, clssonly, varsonly].count(True) > 1: msg = ('Defined more than one of functions-only, classes-only, ' 'and variables-only. Skipping this directive.') lnnum = sum([spl[j].count('\n') for j in range(i * 5 + 1)]) app.warn('[automodsumm]' + msg, (fn, lnnum)) continue # Use the currentmodule directive so we can just put the local names # in the autosummary table. Note that this doesn't always seem to # actually "take" in Sphinx's eyes, so in `Automodsumm.run`, we have to # force it internally, as well. newlines.extend([i1 + '.. currentmodule:: ' + modnm, '', '.. autosummary::']) newlines.extend(oplines) ols = True if len(allowedpkgnms) == 0 else allowedpkgnms for nm, fqn, obj in zip(*find_mod_objs(modnm, onlylocals=ols)): if nm in toskip: continue if funcsonly and not inspect.isroutine(obj): continue if clssonly and not inspect.isclass(obj): continue if varsonly and (inspect.isclass(obj) or inspect.isroutine(obj)): continue newlines.append(allindent + nm) # add one newline at the end of the autosummary block newlines.append('') return newlines def generate_automodsumm_docs(lines, srcfn, app=None, suffix='.rst', warn=None, info=None, base_path=None, builder=None, template_dir=None, inherited_members=False): """ This function is adapted from `sphinx.ext.autosummary.generate.generate_autosummmary_docs` to generate source for the automodsumm directives that should be autosummarized. Unlike generate_autosummary_docs, this function is called one file at a time. """ from sphinx.jinja2glue import BuiltinTemplateLoader from sphinx.ext.autosummary import import_by_name, get_documenter from sphinx.ext.autosummary.generate import (_simple_info, _simple_warn) from sphinx.util.osutil import ensuredir from sphinx.util.inspect import safe_getattr from jinja2 import FileSystemLoader, TemplateNotFound from jinja2.sandbox import SandboxedEnvironment from .utils import find_autosummary_in_lines_for_automodsumm as find_autosummary_in_lines if info is None: info = _simple_info if warn is None: warn = _simple_warn # info('[automodsumm] generating automodsumm for: ' + srcfn) # Create our own templating environment - here we use Astropy's # templates rather than the default autosummary templates, in order to # allow docstrings to be shown for methods. template_dirs = [os.path.join(os.path.dirname(__file__), 'templates'), os.path.join(base_path, '_templates')] if builder is not None: # allow the user to override the templates template_loader = BuiltinTemplateLoader() template_loader.init(builder, dirs=template_dirs) else: if template_dir: template_dirs.insert(0, template_dir) template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) # read # items = find_autosummary_in_files(sources) items = find_autosummary_in_lines(lines, filename=srcfn) if len(items) > 0: msg = '[automodsumm] {1}: found {0} automodsumm entries to generate' info(msg.format(len(items), srcfn)) # gennms = [item[0] for item in items] # if len(gennms) > 20: # gennms = gennms[:10] + ['...'] + gennms[-10:] # info('[automodsumm] generating autosummary for: ' + ', '.join(gennms)) # remove possible duplicates items = list(set(items)) # keep track of new files new_files = [] # write for name, path, template_name, inherited_mem in sorted(items): if path is None: # The corresponding autosummary:: directive did not have # a :toctree: option continue path = os.path.abspath(os.path.join(base_path, path)) ensuredir(path) try: import_by_name_values = import_by_name(name) except ImportError as e: warn('[automodsumm] failed to import %r: %s' % (name, e)) continue # if block to accommodate Sphinx's v1.2.2 and v1.2.3 respectively if len(import_by_name_values) == 3: name, obj, parent = import_by_name_values elif len(import_by_name_values) == 4: name, obj, parent, module_name = import_by_name_values fn = os.path.join(path, name + suffix) # skip it if it exists if os.path.isfile(fn): continue new_files.append(fn) f = open(fn, 'w') try: if SPHINX_LT_17: doc = get_documenter(obj, parent) else: doc = get_documenter(app, obj, parent) if template_name is not None: template = template_env.get_template(template_name) else: tmplstr = 'autosummary_core/%s.rst' try: template = template_env.get_template(tmplstr % doc.objtype) except TemplateNotFound: template = template_env.get_template(tmplstr % 'base') def get_members_mod(obj, typ, include_public=[]): """ typ = None -> all """ items = [] for name in dir(obj): try: if SPHINX_LT_17: documenter = get_documenter(safe_getattr(obj, name), obj) else: documenter = get_documenter(app, safe_getattr(obj, name), obj) except AttributeError: continue if typ is None or documenter.objtype == typ: items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items def get_members_class(obj, typ, include_public=[], include_base=False): """ typ = None -> all include_base -> include attrs that are from a base class """ items = [] # using dir gets all of the attributes, including the elements # from the base class, otherwise use __slots__ or __dict__ if include_base: names = dir(obj) else: if hasattr(obj, '__slots__'): names = tuple(getattr(obj, '__slots__')) else: names = getattr(obj, '__dict__').keys() for name in names: try: if SPHINX_LT_17: documenter = get_documenter(safe_getattr(obj, name), obj) else: documenter = get_documenter(app, safe_getattr(obj, name), obj) except AttributeError: continue if typ is None or documenter.objtype == typ: items.append(name) public = [x for x in items if x in include_public or not x.startswith('_')] return public, items ns = {} if doc.objtype == 'module': ns['members'] = get_members_mod(obj, None) ns['functions'], ns['all_functions'] = \ get_members_mod(obj, 'function') ns['classes'], ns['all_classes'] = \ get_members_mod(obj, 'class') ns['exceptions'], ns['all_exceptions'] = \ get_members_mod(obj, 'exception') elif doc.objtype == 'class': if inherited_mem is not None: # option set in this specifc directive include_base = inherited_mem else: # use default value include_base = inherited_members api_class_methods = ['__init__', '__call__'] ns['members'] = get_members_class(obj, None, include_base=include_base) ns['methods'], ns['all_methods'] = \ get_members_class(obj, 'method', api_class_methods, include_base=include_base) ns['attributes'], ns['all_attributes'] = \ get_members_class(obj, 'attribute', include_base=include_base) ns['methods'].sort() ns['attributes'].sort() parts = name.split('.') if doc.objtype in ('method', 'attribute'): mod_name = '.'.join(parts[:-2]) cls_name = parts[-2] obj_name = '.'.join(parts[-2:]) ns['class'] = cls_name else: mod_name, obj_name = '.'.join(parts[:-1]), parts[-1] ns['fullname'] = name ns['module'] = mod_name ns['objname'] = obj_name ns['name'] = parts[-1] ns['objtype'] = doc.objtype ns['underline'] = len(obj_name) * '=' # We now check whether a file for reference footnotes exists for # the module being documented. We first check if the # current module is a file or a directory, as this will give a # different path for the reference file. For example, if # documenting astropy.wcs then the reference file is at # ../wcs/references.txt, while if we are documenting # astropy.config.logging_helper (which is at # astropy/config/logging_helper.py) then the reference file is set # to ../config/references.txt if '.' in mod_name: mod_name_dir = mod_name.replace('.', '/').split('/', 1)[1] else: mod_name_dir = mod_name if not os.path.isdir(os.path.join(base_path, mod_name_dir)) \ and os.path.isdir(os.path.join(base_path, mod_name_dir.rsplit('/', 1)[0])): mod_name_dir = mod_name_dir.rsplit('/', 1)[0] # We then have to check whether it exists, and if so, we pass it # to the template. if os.path.exists(os.path.join(base_path, mod_name_dir, 'references.txt')): # An important subtlety here is that the path we pass in has # to be relative to the file being generated, so we have to # figure out the right number of '..'s ndirsback = path.replace(base_path, '').count('/') ref_file_rel_segments = ['..'] * ndirsback ref_file_rel_segments.append(mod_name_dir) ref_file_rel_segments.append('references.txt') ns['referencefile'] = os.path.join(*ref_file_rel_segments) rendered = template.render(**ns) f.write(cleanup_whitespace(rendered)) finally: f.close() def setup(app): # need autodoc fixes # Note: we use __name__ here instead of just writing the module name in # case this extension is bundled into another package from . import autodoc_enhancements app.setup_extension(autodoc_enhancements.__name__) # need inheritance-diagram for automod-diagram app.setup_extension('sphinx.ext.inheritance_diagram') app.add_directive('automod-diagram', Automoddiagram) app.add_directive('automodsumm', Automodsumm) app.connect('builder-inited', process_automodsumm_generation) app.add_config_value('automodsumm_writereprocessed', False, True) app.add_config_value('automodsumm_inherited_members', False, 'env') astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/smart_resolver.py0000644000077000000240000000717713126316034031531 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ The classes in the astropy docs are documented by their API location, which is not necessarily where they are defined in the source. This causes a problem when certain automated features of the doc build, such as the inheritance diagrams or the `Bases` list of a class reference a class by its canonical location rather than its "user" location. In the `autodoc-process-docstring` event, a mapping from the actual name to the API name is maintained. Later, in the `missing-reference` event, unresolved references are looked up in this dictionary and corrected if possible. """ from docutils.nodes import literal, reference def process_docstring(app, what, name, obj, options, lines): if isinstance(obj, type): env = app.env if not hasattr(env, 'class_name_mapping'): env.class_name_mapping = {} mapping = env.class_name_mapping mapping[obj.__module__ + '.' + obj.__name__] = name def missing_reference_handler(app, env, node, contnode): if not hasattr(env, 'class_name_mapping'): env.class_name_mapping = {} mapping = env.class_name_mapping reftype = node['reftype'] reftarget = node['reftarget'] if reftype in ('obj', 'class', 'exc', 'meth'): reftarget = node['reftarget'] suffix = '' if reftarget not in mapping: if '.' in reftarget: front, suffix = reftarget.rsplit('.', 1) else: suffix = reftarget if suffix.startswith('_') and not suffix.startswith('__'): # If this is a reference to a hidden class or method, # we can't link to it, but we don't want to have a # nitpick warning. return node[0].deepcopy() if reftype in ('obj', 'meth') and '.' in reftarget: if front in mapping: reftarget = front suffix = '.' + suffix if (reftype in ('class', ) and '.' in reftarget and reftarget not in mapping): if '.' in front: reftarget, _ = front.rsplit('.', 1) suffix = '.' + suffix reftarget = reftarget + suffix prefix = reftarget.rsplit('.')[0] inventory = env.intersphinx_named_inventory if (reftarget not in mapping and prefix in inventory): if reftarget in inventory[prefix]['py:class']: newtarget = inventory[prefix]['py:class'][reftarget][2] if not node['refexplicit'] and \ '~' not in node.rawsource: contnode = literal(text=reftarget) newnode = reference('', '', internal=True) newnode['reftitle'] = reftarget newnode['refuri'] = newtarget newnode.append(contnode) return newnode if reftarget in mapping: newtarget = mapping[reftarget] + suffix if not node['refexplicit'] and '~' not in node.rawsource: contnode = literal(text=newtarget) newnode = env.domains['py'].resolve_xref( env, node['refdoc'], app.builder, 'class', newtarget, node, contnode) if newnode is not None: newnode['reftitle'] = reftarget return newnode def setup(app): app.connect('autodoc-process-docstring', process_docstring) app.connect('missing-reference', missing_reference_handler) astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/automodapi/utils.py0000644000077000000240000001574413126316034027621 0ustar adamstaff00000000000000import inspect import sys import re import os from warnings import warn from sphinx.ext.autosummary.generate import find_autosummary_in_docstring if sys.version_info[0] >= 3: def iteritems(dictionary): return dictionary.items() else: def iteritems(dictionary): return dictionary.iteritems() # We use \n instead of os.linesep because even on Windows, the generated files # use \n as the newline character. SPACE_NEWLINE = ' \n' SINGLE_NEWLINE = '\n' DOUBLE_NEWLINE = '\n\n' TRIPLE_NEWLINE = '\n\n\n' def cleanup_whitespace(text): """ Make sure there are never more than two consecutive newlines, and that there are no trailing whitespaces. """ # Get rid of overall leading/trailing whitespace text = text.strip() + '\n' # Get rid of trailing whitespace on each line while SPACE_NEWLINE in text: text = text.replace(SPACE_NEWLINE, SINGLE_NEWLINE) # Avoid too many consecutive newlines while TRIPLE_NEWLINE in text: text = text.replace(TRIPLE_NEWLINE, DOUBLE_NEWLINE) return text def find_mod_objs(modname, onlylocals=False): """ Returns all the public attributes of a module referenced by name. .. note:: The returned list *not* include subpackages or modules of `modname`,nor does it include private attributes (those that beginwith '_' or are not in `__all__`). Parameters ---------- modname : str The name of the module to search. onlylocals : bool If True, only attributes that are either members of `modname` OR one of its modules or subpackages will be included. Returns ------- localnames : list of str A list of the names of the attributes as they are named in the module `modname` . fqnames : list of str A list of the full qualified names of the attributes (e.g., ``astropy.utils.misc.find_mod_objs``). For attributes that are simple variables, this is based on the local name, but for functions or classes it can be different if they are actually defined elsewhere and just referenced in `modname`. objs : list of objects A list of the actual attributes themselves (in the same order as the other arguments) """ __import__(modname) mod = sys.modules[modname] if hasattr(mod, '__all__'): pkgitems = [(k, mod.__dict__[k]) for k in mod.__all__] else: pkgitems = [(k, mod.__dict__[k]) for k in dir(mod) if k[0] != '_'] # filter out modules and pull the names and objs out ismodule = inspect.ismodule localnames = [k for k, v in pkgitems if not ismodule(v)] objs = [v for k, v in pkgitems if not ismodule(v)] # fully qualified names can be determined from the object's module fqnames = [] for obj, lnm in zip(objs, localnames): if hasattr(obj, '__module__') and hasattr(obj, '__name__'): fqnames.append(obj.__module__ + '.' + obj.__name__) else: fqnames.append(modname + '.' + lnm) if onlylocals: valids = [fqn.startswith(modname) for fqn in fqnames] localnames = [e for i, e in enumerate(localnames) if valids[i]] fqnames = [e for i, e in enumerate(fqnames) if valids[i]] objs = [e for i, e in enumerate(objs) if valids[i]] return localnames, fqnames, objs def find_autosummary_in_lines_for_automodsumm(lines, module=None, filename=None): """Find out what items appear in autosummary:: directives in the given lines. Returns a list of (name, toctree, template, inherited_members) where *name* is a name of an object and *toctree* the :toctree: path of the corresponding autosummary directive (relative to the root of the file name), *template* the value of the :template: option, and *inherited_members* is the value of the :inherited-members: option. *toctree*, *template*, and *inherited_members* are ``None`` if the directive does not have the corresponding options set. .. note:: This is a slightly modified version of ``sphinx.ext.autosummary.generate.find_autosummary_in_lines`` which recognizes the ``inherited-members`` option. """ autosummary_re = re.compile(r'^(\s*)\.\.\s+autosummary::\s*') automodule_re = re.compile( r'^\s*\.\.\s+automodule::\s*([A-Za-z0-9_.]+)\s*$') module_re = re.compile( r'^\s*\.\.\s+(current)?module::\s*([a-zA-Z0-9_.]+)\s*$') autosummary_item_re = re.compile(r'^\s+(~?[_a-zA-Z][a-zA-Z0-9_.]*)\s*.*?') toctree_arg_re = re.compile(r'^\s+:toctree:\s*(.*?)\s*$') template_arg_re = re.compile(r'^\s+:template:\s*(.*?)\s*$') inherited_members_arg_re = re.compile(r'^\s+:inherited-members:\s*$') no_inherited_members_arg_re = re.compile(r'^\s+:no-inherited-members:\s*$') documented = [] toctree = None template = None inherited_members = None current_module = module in_autosummary = False base_indent = "" for line in lines: if in_autosummary: m = toctree_arg_re.match(line) if m: toctree = m.group(1) if filename: toctree = os.path.join(os.path.dirname(filename), toctree) continue m = template_arg_re.match(line) if m: template = m.group(1).strip() continue m = inherited_members_arg_re.match(line) if m: inherited_members = True continue m = no_inherited_members_arg_re.match(line) if m: inherited_members = False continue if line.strip().startswith(':'): warn(line) continue # skip options m = autosummary_item_re.match(line) if m: name = m.group(1).strip() if name.startswith('~'): name = name[1:] if current_module and \ not name.startswith(current_module + '.'): name = "%s.%s" % (current_module, name) documented.append((name, toctree, template, inherited_members)) continue if not line.strip() or line.startswith(base_indent + " "): continue in_autosummary = False m = autosummary_re.match(line) if m: in_autosummary = True base_indent = m.group(1) toctree = None template = None inherited_members = None continue m = automodule_re.search(line) if m: current_module = m.group(1).strip() # recurse into the automodule docstring documented.extend(find_autosummary_in_docstring( current_module, filename=filename)) continue m = module_re.match(line) if m: current_module = m.group(2) continue return documented astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/numpydoc/0000755000077000000240000000000013232443301025564 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/numpydoc/__init__.py0000644000077000000240000000016513171427757027722 0ustar adamstaff00000000000000from __future__ import division, absolute_import, print_function __version__ = '0.7.0' from .numpydoc import setup astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/numpydoc/docscrape.py0000644000077000000240000004452113171427757030132 0ustar adamstaff00000000000000"""Extract reference documentation from the NumPy source tree. """ from __future__ import division, absolute_import, print_function import inspect import textwrap import re import pydoc from warnings import warn import collections import copy import sys class Reader(object): """A line-based string reader. """ def __init__(self, data): """ Parameters ---------- data : str String with lines separated by '\n'. """ if isinstance(data, list): self._str = data else: self._str = data.split('\n') # store string as list of lines self.reset() def __getitem__(self, n): return self._str[n] def reset(self): self._l = 0 # current line nr def read(self): if not self.eof(): out = self[self._l] self._l += 1 return out else: return '' def seek_next_non_empty_line(self): for l in self[self._l:]: if l.strip(): break else: self._l += 1 def eof(self): return self._l >= len(self._str) def read_to_condition(self, condition_func): start = self._l for line in self[start:]: if condition_func(line): return self[start:self._l] self._l += 1 if self.eof(): return self[start:self._l+1] return [] def read_to_next_empty_line(self): self.seek_next_non_empty_line() def is_empty(line): return not line.strip() return self.read_to_condition(is_empty) def read_to_next_unindented_line(self): def is_unindented(line): return (line.strip() and (len(line.lstrip()) == len(line))) return self.read_to_condition(is_unindented) def peek(self, n=0): if self._l + n < len(self._str): return self[self._l + n] else: return '' def is_empty(self): return not ''.join(self._str).strip() class ParseError(Exception): def __str__(self): message = self.args[0] if hasattr(self, 'docstring'): message = "%s in %r" % (message, self.docstring) return message class NumpyDocString(collections.Mapping): sections = { 'Signature': '', 'Summary': [''], 'Extended Summary': [], 'Parameters': [], 'Returns': [], 'Yields': [], 'Raises': [], 'Warns': [], 'Other Parameters': [], 'Attributes': [], 'Methods': [], 'See Also': [], 'Notes': [], 'Warnings': [], 'References': '', 'Examples': '', 'index': {} } def __init__(self, docstring, config={}): orig_docstring = docstring docstring = textwrap.dedent(docstring).split('\n') self._doc = Reader(docstring) self._parsed_data = copy.deepcopy(self.sections) try: self._parse() except ParseError as e: e.docstring = orig_docstring raise def __getitem__(self, key): return self._parsed_data[key] def __setitem__(self, key, val): if key not in self._parsed_data: warn("Unknown section %s" % key) else: self._parsed_data[key] = val def __iter__(self): return iter(self._parsed_data) def __len__(self): return len(self._parsed_data) def _is_at_section(self): self._doc.seek_next_non_empty_line() if self._doc.eof(): return False l1 = self._doc.peek().strip() # e.g. Parameters if l1.startswith('.. index::'): return True l2 = self._doc.peek(1).strip() # ---------- or ========== return l2.startswith('-'*len(l1)) or l2.startswith('='*len(l1)) def _strip(self, doc): i = 0 j = 0 for i, line in enumerate(doc): if line.strip(): break for j, line in enumerate(doc[::-1]): if line.strip(): break return doc[i:len(doc)-j] def _read_to_next_section(self): section = self._doc.read_to_next_empty_line() while not self._is_at_section() and not self._doc.eof(): if not self._doc.peek(-1).strip(): # previous line was empty section += [''] section += self._doc.read_to_next_empty_line() return section def _read_sections(self): while not self._doc.eof(): data = self._read_to_next_section() name = data[0].strip() if name.startswith('..'): # index section yield name, data[1:] elif len(data) < 2: yield StopIteration else: yield name, self._strip(data[2:]) def _parse_param_list(self, content): r = Reader(content) params = [] while not r.eof(): header = r.read().strip() if ' : ' in header: arg_name, arg_type = header.split(' : ')[:2] else: arg_name, arg_type = header, '' desc = r.read_to_next_unindented_line() desc = dedent_lines(desc) params.append((arg_name, arg_type, desc)) return params _name_rgx = re.compile(r"^\s*(:(?P\w+):`(?P[a-zA-Z0-9_.-]+)`|" r" (?P[a-zA-Z0-9_.-]+))\s*", re.X) def _parse_see_also(self, content): """ func_name : Descriptive text continued text another_func_name : Descriptive text func_name1, func_name2, :meth:`func_name`, func_name3 """ items = [] def parse_item_name(text): """Match ':role:`name`' or 'name'""" m = self._name_rgx.match(text) if m: g = m.groups() if g[1] is None: return g[3], None else: return g[2], g[1] raise ParseError("%s is not a item name" % text) def push_item(name, rest): if not name: return name, role = parse_item_name(name) items.append((name, list(rest), role)) del rest[:] current_func = None rest = [] for line in content: if not line.strip(): continue m = self._name_rgx.match(line) if m and line[m.end():].strip().startswith(':'): push_item(current_func, rest) current_func, line = line[:m.end()], line[m.end():] rest = [line.split(':', 1)[1].strip()] if not rest[0]: rest = [] elif not line.startswith(' '): push_item(current_func, rest) current_func = None if ',' in line: for func in line.split(','): if func.strip(): push_item(func, []) elif line.strip(): current_func = line elif current_func is not None: rest.append(line.strip()) push_item(current_func, rest) return items def _parse_index(self, section, content): """ .. index: default :refguide: something, else, and more """ def strip_each_in(lst): return [s.strip() for s in lst] out = {} section = section.split('::') if len(section) > 1: out['default'] = strip_each_in(section[1].split(','))[0] for line in content: line = line.split(':') if len(line) > 2: out[line[1]] = strip_each_in(line[2].split(',')) return out def _parse_summary(self): """Grab signature (if given) and summary""" if self._is_at_section(): return # If several signatures present, take the last one while True: summary = self._doc.read_to_next_empty_line() summary_str = " ".join([s.strip() for s in summary]).strip() if re.compile('^([\w., ]+=)?\s*[\w\.]+\(.*\)$').match(summary_str): self['Signature'] = summary_str if not self._is_at_section(): continue break if summary is not None: self['Summary'] = summary if not self._is_at_section(): self['Extended Summary'] = self._read_to_next_section() def _parse(self): self._doc.reset() self._parse_summary() sections = list(self._read_sections()) section_names = set([section for section, content in sections]) has_returns = 'Returns' in section_names has_yields = 'Yields' in section_names # We could do more tests, but we are not. Arbitrarily. if has_returns and has_yields: msg = 'Docstring contains both a Returns and Yields section.' raise ValueError(msg) for (section, content) in sections: if not section.startswith('..'): section = (s.capitalize() for s in section.split(' ')) section = ' '.join(section) if self.get(section): if hasattr(self, '_obj'): # we know where the docs came from: try: filename = inspect.getsourcefile(self._obj) except TypeError: filename = None msg = ("The section %s appears twice in " "the docstring of %s in %s." % (section, self._obj, filename)) raise ValueError(msg) else: msg = ("The section %s appears twice" % section) raise ValueError(msg) if section in ('Parameters', 'Returns', 'Yields', 'Raises', 'Warns', 'Other Parameters', 'Attributes', 'Methods'): self[section] = self._parse_param_list(content) elif section.startswith('.. index::'): self['index'] = self._parse_index(section, content) elif section == 'See Also': self['See Also'] = self._parse_see_also(content) else: self[section] = content # string conversion routines def _str_header(self, name, symbol='-'): return [name, len(name)*symbol] def _str_indent(self, doc, indent=4): out = [] for line in doc: out += [' '*indent + line] return out def _str_signature(self): if self['Signature']: return [self['Signature'].replace('*', '\*')] + [''] else: return [''] def _str_summary(self): if self['Summary']: return self['Summary'] + [''] else: return [] def _str_extended_summary(self): if self['Extended Summary']: return self['Extended Summary'] + [''] else: return [] def _str_param_list(self, name): out = [] if self[name]: out += self._str_header(name) for param, param_type, desc in self[name]: if param_type: out += ['%s : %s' % (param, param_type)] else: out += [param] out += self._str_indent(desc) out += [''] return out def _str_section(self, name): out = [] if self[name]: out += self._str_header(name) out += self[name] out += [''] return out def _str_see_also(self, func_role): if not self['See Also']: return [] out = [] out += self._str_header("See Also") last_had_desc = True for func, desc, role in self['See Also']: if role: link = ':%s:`%s`' % (role, func) elif func_role: link = ':%s:`%s`' % (func_role, func) else: link = "`%s`_" % func if desc or last_had_desc: out += [''] out += [link] else: out[-1] += ", %s" % link if desc: out += self._str_indent([' '.join(desc)]) last_had_desc = True else: last_had_desc = False out += [''] return out def _str_index(self): idx = self['index'] out = [] out += ['.. index:: %s' % idx.get('default', '')] for section, references in idx.items(): if section == 'default': continue out += [' :%s: %s' % (section, ', '.join(references))] return out def __str__(self, func_role=''): out = [] out += self._str_signature() out += self._str_summary() out += self._str_extended_summary() for param_list in ('Parameters', 'Returns', 'Yields', 'Other Parameters', 'Raises', 'Warns'): out += self._str_param_list(param_list) out += self._str_section('Warnings') out += self._str_see_also(func_role) for s in ('Notes', 'References', 'Examples'): out += self._str_section(s) for param_list in ('Attributes', 'Methods'): out += self._str_param_list(param_list) out += self._str_index() return '\n'.join(out) def indent(str, indent=4): indent_str = ' '*indent if str is None: return indent_str lines = str.split('\n') return '\n'.join(indent_str + l for l in lines) def dedent_lines(lines): """Deindent a list of lines maximally""" return textwrap.dedent("\n".join(lines)).split("\n") def header(text, style='-'): return text + '\n' + style*len(text) + '\n' class FunctionDoc(NumpyDocString): def __init__(self, func, role='func', doc=None, config={}): self._f = func self._role = role # e.g. "func" or "meth" if doc is None: if func is None: raise ValueError("No function or docstring given") doc = inspect.getdoc(func) or '' NumpyDocString.__init__(self, doc) if not self['Signature'] and func is not None: func, func_name = self.get_func() try: try: signature = str(inspect.signature(func)) except (AttributeError, ValueError): # try to read signature, backward compat for older Python if sys.version_info[0] >= 3: argspec = inspect.getfullargspec(func) else: argspec = inspect.getargspec(func) signature = inspect.formatargspec(*argspec) signature = '%s%s' % (func_name, signature.replace('*', '\*')) except TypeError: signature = '%s()' % func_name self['Signature'] = signature def get_func(self): func_name = getattr(self._f, '__name__', self.__class__.__name__) if inspect.isclass(self._f): func = getattr(self._f, '__call__', self._f.__init__) else: func = self._f return func, func_name def __str__(self): out = '' func, func_name = self.get_func() signature = self['Signature'].replace('*', '\*') roles = {'func': 'function', 'meth': 'method'} if self._role: if self._role not in roles: print("Warning: invalid role %s" % self._role) out += '.. %s:: %s\n \n\n' % (roles.get(self._role, ''), func_name) out += super(FunctionDoc, self).__str__(func_role=self._role) return out class ClassDoc(NumpyDocString): extra_public_methods = ['__call__'] def __init__(self, cls, doc=None, modulename='', func_doc=FunctionDoc, config={}): if not inspect.isclass(cls) and cls is not None: raise ValueError("Expected a class or None, but got %r" % cls) self._cls = cls self.show_inherited_members = config.get( 'show_inherited_class_members', True) if modulename and not modulename.endswith('.'): modulename += '.' self._mod = modulename if doc is None: if cls is None: raise ValueError("No class or documentation string given") doc = pydoc.getdoc(cls) NumpyDocString.__init__(self, doc) if config.get('show_class_members', True): def splitlines_x(s): if not s: return [] else: return s.splitlines() for field, items in [('Methods', self.methods), ('Attributes', self.properties)]: if not self[field]: doc_list = [] for name in sorted(items): try: doc_item = pydoc.getdoc(getattr(self._cls, name)) doc_list.append((name, '', splitlines_x(doc_item))) except AttributeError: pass # method doesn't exist self[field] = doc_list @property def methods(self): if self._cls is None: return [] return [name for name, func in inspect.getmembers(self._cls) if ((not name.startswith('_') or name in self.extra_public_methods) and isinstance(func, collections.Callable) and self._is_show_member(name))] @property def properties(self): if self._cls is None: return [] return [name for name, func in inspect.getmembers(self._cls) if (not name.startswith('_') and (func is None or isinstance(func, property) or inspect.isgetsetdescriptor(func)) and self._is_show_member(name))] def _is_show_member(self, name): if self.show_inherited_members: return True # show all class members if name not in self._cls.__dict__: return False # class member is inherited, we do not show it return True astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/numpydoc/docscrape_sphinx.py0000644000077000000240000002510613171427757031521 0ustar adamstaff00000000000000from __future__ import division, absolute_import, print_function import sys import re import inspect import textwrap import pydoc import collections import os from jinja2 import FileSystemLoader from jinja2.sandbox import SandboxedEnvironment import sphinx from sphinx.jinja2glue import BuiltinTemplateLoader from .docscrape import NumpyDocString, FunctionDoc, ClassDoc if sys.version_info[0] >= 3: sixu = lambda s: s else: sixu = lambda s: unicode(s, 'unicode_escape') class SphinxDocString(NumpyDocString): def __init__(self, docstring, config={}): NumpyDocString.__init__(self, docstring, config=config) self.load_config(config) def load_config(self, config): self.use_plots = config.get('use_plots', False) self.class_members_toctree = config.get('class_members_toctree', True) self.template = config.get('template', None) if self.template is None: template_dirs = [os.path.join(os.path.dirname(__file__), 'templates')] template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) self.template = template_env.get_template('numpydoc_docstring.rst') # string conversion routines def _str_header(self, name, symbol='`'): return ['.. rubric:: ' + name, ''] def _str_field_list(self, name): return [':' + name + ':'] def _str_indent(self, doc, indent=4): out = [] for line in doc: out += [' '*indent + line] return out def _str_signature(self): return [''] if self['Signature']: return ['``%s``' % self['Signature']] + [''] else: return [''] def _str_summary(self): return self['Summary'] + [''] def _str_extended_summary(self): return self['Extended Summary'] + [''] def _str_returns(self, name='Returns'): out = [] if self[name]: out += self._str_field_list(name) out += [''] for param, param_type, desc in self[name]: if param_type: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) else: out += self._str_indent([param.strip()]) if desc: out += [''] out += self._str_indent(desc, 8) out += [''] return out def _str_param_list(self, name): out = [] if self[name]: out += self._str_field_list(name) out += [''] for param, param_type, desc in self[name]: if param_type: out += self._str_indent(['**%s** : %s' % (param.strip(), param_type)]) else: out += self._str_indent(['**%s**' % param.strip()]) if desc: out += [''] out += self._str_indent(desc, 8) out += [''] return out @property def _obj(self): if hasattr(self, '_cls'): return self._cls elif hasattr(self, '_f'): return self._f return None def _str_member_list(self, name): """ Generate a member listing, autosummary:: table where possible, and a table where not. """ out = [] if self[name]: out += ['.. rubric:: %s' % name, ''] prefix = getattr(self, '_name', '') if prefix: prefix = '~%s.' % prefix autosum = [] others = [] for param, param_type, desc in self[name]: param = param.strip() # Check if the referenced member can have a docstring or not param_obj = getattr(self._obj, param, None) if not (callable(param_obj) or isinstance(param_obj, property) or inspect.isgetsetdescriptor(param_obj)): param_obj = None if param_obj and (pydoc.getdoc(param_obj) or not desc): # Referenced object has a docstring autosum += [" %s%s" % (prefix, param)] else: others.append((param, param_type, desc)) if autosum: out += ['.. autosummary::'] if self.class_members_toctree: out += [' :toctree:'] out += [''] + autosum if others: maxlen_0 = max(3, max([len(x[0]) + 4 for x in others])) hdr = sixu("=") * maxlen_0 + sixu(" ") + sixu("=") * 10 fmt = sixu('%%%ds %%s ') % (maxlen_0,) out += ['', '', hdr] for param, param_type, desc in others: desc = sixu(" ").join(x.strip() for x in desc).strip() if param_type: desc = "(%s) %s" % (param_type, desc) out += [fmt % ("**" + param.strip() + "**", desc)] out += [hdr] out += [''] return out def _str_section(self, name): out = [] if self[name]: out += self._str_header(name) out += [''] content = textwrap.dedent("\n".join(self[name])).split("\n") out += content out += [''] return out def _str_see_also(self, func_role): out = [] if self['See Also']: see_also = super(SphinxDocString, self)._str_see_also(func_role) out = ['.. seealso::', ''] out += self._str_indent(see_also[2:]) return out def _str_warnings(self): out = [] if self['Warnings']: out = ['.. warning::', ''] out += self._str_indent(self['Warnings']) return out def _str_index(self): idx = self['index'] out = [] if len(idx) == 0: return out out += ['.. index:: %s' % idx.get('default', '')] for section, references in idx.items(): if section == 'default': continue elif section == 'refguide': out += [' single: %s' % (', '.join(references))] else: out += [' %s: %s' % (section, ','.join(references))] return out def _str_references(self): out = [] if self['References']: out += self._str_header('References') if isinstance(self['References'], str): self['References'] = [self['References']] out.extend(self['References']) out += [''] # Latex collects all references to a separate bibliography, # so we need to insert links to it if sphinx.__version__ >= "0.6": out += ['.. only:: latex', ''] else: out += ['.. latexonly::', ''] items = [] for line in self['References']: m = re.match(r'.. \[([a-z0-9._-]+)\]', line, re.I) if m: items.append(m.group(1)) out += [' ' + ", ".join(["[%s]_" % item for item in items]), ''] return out def _str_examples(self): examples_str = "\n".join(self['Examples']) if (self.use_plots and 'import matplotlib' in examples_str and 'plot::' not in examples_str): out = [] out += self._str_header('Examples') out += ['.. plot::', ''] out += self._str_indent(self['Examples']) out += [''] return out else: return self._str_section('Examples') def __str__(self, indent=0, func_role="obj"): ns = { 'signature': self._str_signature(), 'index': self._str_index(), 'summary': self._str_summary(), 'extended_summary': self._str_extended_summary(), 'parameters': self._str_param_list('Parameters'), 'returns': self._str_returns('Returns'), 'yields': self._str_returns('Yields'), 'other_parameters': self._str_param_list('Other Parameters'), 'raises': self._str_param_list('Raises'), 'warns': self._str_param_list('Warns'), 'warnings': self._str_warnings(), 'see_also': self._str_see_also(func_role), 'notes': self._str_section('Notes'), 'references': self._str_references(), 'examples': self._str_examples(), 'attributes': self._str_member_list('Attributes'), 'methods': self._str_member_list('Methods'), } ns = dict((k, '\n'.join(v)) for k, v in ns.items()) rendered = self.template.render(**ns) return '\n'.join(self._str_indent(rendered.split('\n'), indent)) class SphinxFunctionDoc(SphinxDocString, FunctionDoc): def __init__(self, obj, doc=None, config={}): self.load_config(config) FunctionDoc.__init__(self, obj, doc=doc, config=config) class SphinxClassDoc(SphinxDocString, ClassDoc): def __init__(self, obj, doc=None, func_doc=None, config={}): self.load_config(config) ClassDoc.__init__(self, obj, doc=doc, func_doc=None, config=config) class SphinxObjDoc(SphinxDocString): def __init__(self, obj, doc=None, config={}): self._f = obj self.load_config(config) SphinxDocString.__init__(self, doc, config=config) def get_doc_object(obj, what=None, doc=None, config={}, builder=None): if what is None: if inspect.isclass(obj): what = 'class' elif inspect.ismodule(obj): what = 'module' elif isinstance(obj, collections.Callable): what = 'function' else: what = 'object' template_dirs = [os.path.join(os.path.dirname(__file__), 'templates')] if builder is not None: template_loader = BuiltinTemplateLoader() template_loader.init(builder, dirs=template_dirs) else: template_loader = FileSystemLoader(template_dirs) template_env = SandboxedEnvironment(loader=template_loader) config['template'] = template_env.get_template('numpydoc_docstring.rst') if what == 'class': return SphinxClassDoc(obj, func_doc=SphinxFunctionDoc, doc=doc, config=config) elif what in ('function', 'method'): return SphinxFunctionDoc(obj, doc=doc, config=config) else: if doc is None: doc = pydoc.getdoc(obj) return SphinxObjDoc(obj, doc, config=config) astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/numpydoc/numpydoc.py0000644000077000000240000002253313171427757030024 0ustar adamstaff00000000000000""" ======== numpydoc ======== Sphinx extension that handles docstrings in the Numpy standard format. [1] It will: - Convert Parameters etc. sections to field lists. - Convert See Also section to a See also entry. - Renumber references. - Extract the signature from the docstring, if it can't be determined otherwise. .. [1] https://github.com/numpy/numpy/blob/master/doc/HOWTO_DOCUMENT.rst.txt """ from __future__ import division, absolute_import, print_function import sys import re import pydoc import sphinx import inspect import collections if sphinx.__version__ < '1.0.1': raise RuntimeError("Sphinx 1.0.1 or newer is required") from .docscrape_sphinx import get_doc_object, SphinxDocString if sys.version_info[0] >= 3: sixu = lambda s: s else: sixu = lambda s: unicode(s, 'unicode_escape') def rename_references(app, what, name, obj, options, lines, reference_offset=[0]): # replace reference numbers so that there are no duplicates references = [] for line in lines: line = line.strip() m = re.match(sixu('^.. \\[(%s)\\]') % app.config.numpydoc_citation_re, line, re.I) if m: references.append(m.group(1)) if references: for i, line in enumerate(lines): for r in references: if re.match(sixu('^\\d+$'), r): new_r = sixu("R%d") % (reference_offset[0] + int(r)) else: new_r = sixu("%s%d") % (r, reference_offset[0]) lines[i] = lines[i].replace(sixu('[%s]_') % r, sixu('[%s]_') % new_r) lines[i] = lines[i].replace(sixu('.. [%s]') % r, sixu('.. [%s]') % new_r) reference_offset[0] += len(references) def mangle_docstrings(app, what, name, obj, options, lines): cfg = {'use_plots': app.config.numpydoc_use_plots, 'show_class_members': app.config.numpydoc_show_class_members, 'show_inherited_class_members': app.config.numpydoc_show_inherited_class_members, 'class_members_toctree': app.config.numpydoc_class_members_toctree} u_NL = sixu('\n') if what == 'module': # Strip top title pattern = '^\\s*[#*=]{4,}\\n[a-z0-9 -]+\\n[#*=]{4,}\\s*' title_re = re.compile(sixu(pattern), re.I | re.S) lines[:] = title_re.sub(sixu(''), u_NL.join(lines)).split(u_NL) else: doc = get_doc_object(obj, what, u_NL.join(lines), config=cfg, builder=app.builder) if sys.version_info[0] >= 3: doc = str(doc) else: doc = unicode(doc) lines[:] = doc.split(u_NL) if (app.config.numpydoc_edit_link and hasattr(obj, '__name__') and obj.__name__): if hasattr(obj, '__module__'): v = dict(full_name=sixu("%s.%s") % (obj.__module__, obj.__name__)) else: v = dict(full_name=obj.__name__) lines += [sixu(''), sixu('.. htmlonly::'), sixu('')] lines += [sixu(' %s') % x for x in (app.config.numpydoc_edit_link % v).split("\n")] # call function to replace reference numbers so that there are no # duplicates rename_references(app, what, name, obj, options, lines) def mangle_signature(app, what, name, obj, options, sig, retann): # Do not try to inspect classes that don't define `__init__` if (inspect.isclass(obj) and (not hasattr(obj, '__init__') or 'initializes x; see ' in pydoc.getdoc(obj.__init__))): return '', '' if not (isinstance(obj, collections.Callable) or hasattr(obj, '__argspec_is_invalid_')): return if not hasattr(obj, '__doc__'): return doc = SphinxDocString(pydoc.getdoc(obj)) sig = doc['Signature'] or getattr(obj, '__text_signature__', None) if sig: sig = re.sub(sixu("^[^(]*"), sixu(""), sig) return sig, sixu('') def setup(app, get_doc_object_=get_doc_object): if not hasattr(app, 'add_config_value'): return # probably called by nose, better bail out global get_doc_object get_doc_object = get_doc_object_ app.connect('autodoc-process-docstring', mangle_docstrings) app.connect('autodoc-process-signature', mangle_signature) app.add_config_value('numpydoc_edit_link', None, False) app.add_config_value('numpydoc_use_plots', None, False) app.add_config_value('numpydoc_show_class_members', True, True) app.add_config_value('numpydoc_show_inherited_class_members', True, True) app.add_config_value('numpydoc_class_members_toctree', True, True) app.add_config_value('numpydoc_citation_re', '[a-z0-9_.-]+', True) # Extra mangling domains app.add_domain(NumpyPythonDomain) app.add_domain(NumpyCDomain) metadata = {'parallel_read_safe': True} return metadata # ------------------------------------------------------------------------------ # Docstring-mangling domains # ------------------------------------------------------------------------------ from docutils.statemachine import ViewList from sphinx.domains.c import CDomain from sphinx.domains.python import PythonDomain class ManglingDomainBase(object): directive_mangling_map = {} def __init__(self, *a, **kw): super(ManglingDomainBase, self).__init__(*a, **kw) self.wrap_mangling_directives() def wrap_mangling_directives(self): for name, objtype in list(self.directive_mangling_map.items()): self.directives[name] = wrap_mangling_directive( self.directives[name], objtype) class NumpyPythonDomain(ManglingDomainBase, PythonDomain): name = 'np' directive_mangling_map = { 'function': 'function', 'class': 'class', 'exception': 'class', 'method': 'function', 'classmethod': 'function', 'staticmethod': 'function', 'attribute': 'attribute', } indices = [] class NumpyCDomain(ManglingDomainBase, CDomain): name = 'np-c' directive_mangling_map = { 'function': 'function', 'member': 'attribute', 'macro': 'function', 'type': 'class', 'var': 'object', } def match_items(lines, content_old): """Create items for mangled lines. This function tries to match the lines in ``lines`` with the items (source file references and line numbers) in ``content_old``. The ``mangle_docstrings`` function changes the actual docstrings, but doesn't keep track of where each line came from. The manging does many operations on the original lines, which are hard to track afterwards. Many of the line changes come from deleting or inserting blank lines. This function tries to match lines by ignoring blank lines. All other changes (such as inserting figures or changes in the references) are completely ignored, so the generated line numbers will be off if ``mangle_docstrings`` does anything non-trivial. This is a best-effort function and the real fix would be to make ``mangle_docstrings`` actually keep track of the ``items`` together with the ``lines``. Examples -------- >>> lines = ['', 'A', '', 'B', ' ', '', 'C', 'D'] >>> lines_old = ['a', '', '', 'b', '', 'c'] >>> items_old = [('file1.py', 0), ('file1.py', 1), ('file1.py', 2), ... ('file2.py', 0), ('file2.py', 1), ('file2.py', 2)] >>> content_old = ViewList(lines_old, items=items_old) >>> match_items(lines, content_old) # doctest: +NORMALIZE_WHITESPACE [('file1.py', 0), ('file1.py', 0), ('file2.py', 0), ('file2.py', 0), ('file2.py', 2), ('file2.py', 2), ('file2.py', 2), ('file2.py', 2)] >>> # first 2 ``lines`` are matched to 'a', second 2 to 'b', rest to 'c' >>> # actual content is completely ignored. Notes ----- The algorithm tries to match any line in ``lines`` with one in ``lines_old``. It skips over all empty lines in ``lines_old`` and assigns this line number to all lines in ``lines``, unless a non-empty line is found in ``lines`` in which case it goes to the next line in ``lines_old``. """ items_new = [] lines_old = content_old.data items_old = content_old.items j = 0 for i, line in enumerate(lines): # go to next non-empty line in old: # line.strip() checks whether the string is all whitespace while j < len(lines_old) - 1 and not lines_old[j].strip(): j += 1 items_new.append(items_old[j]) if line.strip() and j < len(lines_old) - 1: j += 1 assert(len(items_new) == len(lines)) return items_new def wrap_mangling_directive(base_directive, objtype): class directive(base_directive): def run(self): env = self.state.document.settings.env name = None if self.arguments: m = re.match(r'^(.*\s+)?(.*?)(\(.*)?', self.arguments[0]) name = m.group(2).strip() if not name: name = self.arguments[0] lines = list(self.content) mangle_docstrings(env.app, objtype, name, None, None, lines) if self.content: items = match_items(lines, self.content) self.content = ViewList(lines, items=items, parent=self.content.parent) return base_directive.run(self) return directive astroquery-0.3.7/astropy_helpers/astropy_helpers/extern/setup_package.py0000644000077000000240000000027513171427757027142 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst def get_package_data(): return {'astropy_helpers.extern': ['automodapi/templates/*/*.rst', 'numpydoc/templates/*.rst']} astroquery-0.3.7/astropy_helpers/astropy_helpers/git_helpers.py0000644000077000000240000001450113232205045025302 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Utilities for retrieving revision information from a project's git repository. """ # Do not remove the following comment; it is used by # astropy_helpers.version_helpers to determine the beginning of the code in # this module # BEGIN import locale import os import subprocess import warnings def _decode_stdio(stream): try: stdio_encoding = locale.getdefaultlocale()[1] or 'utf-8' except ValueError: stdio_encoding = 'utf-8' try: text = stream.decode(stdio_encoding) except UnicodeDecodeError: # Final fallback text = stream.decode('latin1') return text def update_git_devstr(version, path=None): """ Updates the git revision string if and only if the path is being imported directly from a git working copy. This ensures that the revision number in the version string is accurate. """ try: # Quick way to determine if we're in git or not - returns '' if not devstr = get_git_devstr(sha=True, show_warning=False, path=path) except OSError: return version if not devstr: # Probably not in git so just pass silently return version if 'dev' in version: # update to the current git revision version_base = version.split('.dev', 1)[0] devstr = get_git_devstr(sha=False, show_warning=False, path=path) return version_base + '.dev' + devstr else: # otherwise it's already the true/release version return version def get_git_devstr(sha=False, show_warning=True, path=None): """ Determines the number of revisions in this repository. Parameters ---------- sha : bool If True, the full SHA1 hash will be returned. Otherwise, the total count of commits in the repository will be used as a "revision number". show_warning : bool If True, issue a warning if git returns an error code, otherwise errors pass silently. path : str or None If a string, specifies the directory to look in to find the git repository. If `None`, the current working directory is used, and must be the root of the git repository. If given a filename it uses the directory containing that file. Returns ------- devversion : str Either a string with the revision number (if `sha` is False), the SHA1 hash of the current commit (if `sha` is True), or an empty string if git version info could not be identified. """ if path is None: path = os.getcwd() if not os.path.isdir(path): path = os.path.abspath(os.path.dirname(path)) if sha: # Faster for getting just the hash of HEAD cmd = ['rev-parse', 'HEAD'] else: cmd = ['rev-list', '--count', 'HEAD'] def run_git(cmd): try: p = subprocess.Popen(['git'] + cmd, cwd=path, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) stdout, stderr = p.communicate() except OSError as e: if show_warning: warnings.warn('Error running git: ' + str(e)) return (None, b'', b'') if p.returncode == 128: if show_warning: warnings.warn('No git repository present at {0!r}! Using ' 'default dev version.'.format(path)) return (p.returncode, b'', b'') if p.returncode == 129: if show_warning: warnings.warn('Your git looks old (does it support {0}?); ' 'consider upgrading to v1.7.2 or ' 'later.'.format(cmd[0])) return (p.returncode, stdout, stderr) elif p.returncode != 0: if show_warning: warnings.warn('Git failed while determining revision ' 'count: {0}'.format(_decode_stdio(stderr))) return (p.returncode, stdout, stderr) return p.returncode, stdout, stderr returncode, stdout, stderr = run_git(cmd) if not sha and returncode == 128: # git returns 128 if the command is not run from within a git # repository tree. In this case, a warning is produced above but we # return the default dev version of '0'. return '0' elif not sha and returncode == 129: # git returns 129 if a command option failed to parse; in # particular this could happen in git versions older than 1.7.2 # where the --count option is not supported # Also use --abbrev-commit and --abbrev=0 to display the minimum # number of characters needed per-commit (rather than the full hash) cmd = ['rev-list', '--abbrev-commit', '--abbrev=0', 'HEAD'] returncode, stdout, stderr = run_git(cmd) # Fall back on the old method of getting all revisions and counting # the lines if returncode == 0: return str(stdout.count(b'\n')) else: return '' elif sha: return _decode_stdio(stdout)[:40] else: return _decode_stdio(stdout).strip() # This function is tested but it is only ever executed within a subprocess when # creating a fake package, so it doesn't get picked up by coverage metrics. def _get_repo_path(pathname, levels=None): # pragma: no cover """ Given a file or directory name, determine the root of the git repository this path is under. If given, this won't look any higher than ``levels`` (that is, if ``levels=0`` then the given path must be the root of the git repository and is returned if so. Returns `None` if the given path could not be determined to belong to a git repo. """ if os.path.isfile(pathname): current_dir = os.path.abspath(os.path.dirname(pathname)) elif os.path.isdir(pathname): current_dir = os.path.abspath(pathname) else: return None current_level = 0 while levels is None or current_level <= levels: if os.path.exists(os.path.join(current_dir, '.git')): return current_dir current_level += 1 if current_dir == os.path.dirname(current_dir): break current_dir = os.path.dirname(current_dir) return None astroquery-0.3.7/astropy_helpers/astropy_helpers/openmp_helpers.py0000644000077000000240000000605313171427757026042 0ustar adamstaff00000000000000# This module defines functions that can be used to check whether OpenMP is # available and if so what flags to use. To use this, import the # add_openmp_flags_if_available function in a setup_package.py file where you # are defining your extensions: # # from astropy_helpers.openmp_helpers import add_openmp_flags_if_available # # then call it with a single extension as the only argument: # # add_openmp_flags_if_available(extension) # # this will add the OpenMP flags if available. from __future__ import absolute_import, print_function import os import sys import glob import tempfile import subprocess from distutils import log from distutils.ccompiler import new_compiler from distutils.sysconfig import customize_compiler from distutils.errors import CompileError, LinkError from .setup_helpers import get_compiler_option __all__ = ['add_openmp_flags_if_available'] CCODE = """ #include #include int main(void) { #pragma omp parallel printf("nthreads=%d\\n", omp_get_num_threads()); return 0; } """ def add_openmp_flags_if_available(extension): """ Add OpenMP compilation flags, if available (if not a warning will be printed to the console and no flags will be added) Returns `True` if the flags were added, `False` otherwise. """ ccompiler = new_compiler() customize_compiler(ccompiler) tmp_dir = tempfile.mkdtemp() start_dir = os.path.abspath('.') if get_compiler_option() == 'msvc': compile_flag = '-openmp' link_flag = '' else: compile_flag = '-fopenmp' link_flag = '-fopenmp' try: os.chdir(tmp_dir) with open('test_openmp.c', 'w') as f: f.write(CCODE) os.mkdir('objects') # Compile, link, and run test program ccompiler.compile(['test_openmp.c'], output_dir='objects', extra_postargs=[compile_flag]) ccompiler.link_executable(glob.glob(os.path.join('objects', '*')), 'test_openmp', extra_postargs=[link_flag]) output = subprocess.check_output('./test_openmp').decode(sys.stdout.encoding or 'utf-8').splitlines() if 'nthreads=' in output[0]: nthreads = int(output[0].strip().split('=')[1]) if len(output) == nthreads: using_openmp = True else: log.warn("Unexpected number of lines from output of test OpenMP " "program (output was {0})".format(output)) using_openmp = False else: log.warn("Unexpected output from test OpenMP " "program (output was {0})".format(output)) using_openmp = False except (CompileError, LinkError): using_openmp = False finally: os.chdir(start_dir) if using_openmp: log.info("Compiling Cython extension with OpenMP support") extension.extra_compile_args.append(compile_flag) extension.extra_link_args.append(link_flag) else: log.warn("Cannot compile Cython extension with OpenMP, reverting to non-parallel code") return using_openmp astroquery-0.3.7/astropy_helpers/astropy_helpers/setup_helpers.py0000644000077000000240000006635513171427757025717 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This module contains a number of utilities for use during setup/build/packaging that are useful to astropy as a whole. """ from __future__ import absolute_import, print_function import collections import os import re import subprocess import sys import traceback import warnings from distutils import log from distutils.dist import Distribution from distutils.errors import DistutilsOptionError, DistutilsModuleError from distutils.core import Extension from distutils.core import Command from distutils.command.sdist import sdist as DistutilsSdist from setuptools import find_packages as _find_packages from .distutils_helpers import (add_command_option, get_compiler_option, get_dummy_distribution, get_distutils_build_option, get_distutils_build_or_install_option) from .version_helpers import get_pkg_version_module from .utils import (walk_skip_hidden, import_file, extends_doc, resolve_name, AstropyDeprecationWarning) from .commands.build_ext import generate_build_ext_command from .commands.build_py import AstropyBuildPy from .commands.install import AstropyInstall from .commands.install_lib import AstropyInstallLib from .commands.register import AstropyRegister from .commands.test import AstropyTest # These imports are not used in this module, but are included for backwards # compat with older versions of this module from .utils import get_numpy_include_path, write_if_different # noqa from .commands.build_ext import should_build_with_cython, get_compiler_version # noqa _module_state = {'registered_commands': None, 'have_sphinx': False, 'package_cache': None, 'exclude_packages': set(), 'excludes_too_late': False} try: import sphinx # noqa _module_state['have_sphinx'] = True except ValueError as e: # This can occur deep in the bowels of Sphinx's imports by way of docutils # and an occurrence of this bug: http://bugs.python.org/issue18378 # In this case sphinx is effectively unusable if 'unknown locale' in e.args[0]: log.warn( "Possible misconfiguration of one of the environment variables " "LC_ALL, LC_CTYPES, LANG, or LANGUAGE. For an example of how to " "configure your system's language environment on OSX see " "http://blog.remibergsma.com/2012/07/10/" "setting-locales-correctly-on-mac-osx-terminal-application/") except ImportError: pass except SyntaxError: # occurs if markupsafe is recent version, which doesn't support Python 3.2 pass PY3 = sys.version_info[0] >= 3 # This adds a new keyword to the setup() function Distribution.skip_2to3 = [] def adjust_compiler(package): """ This function detects broken compilers and switches to another. If the environment variable CC is explicitly set, or a compiler is specified on the commandline, no override is performed -- the purpose here is to only override a default compiler. The specific compilers with problems are: * The default compiler in XCode-4.2, llvm-gcc-4.2, segfaults when compiling wcslib. The set of broken compilers can be updated by changing the compiler_mapping variable. It is a list of 2-tuples where the first in the pair is a regular expression matching the version of the broken compiler, and the second is the compiler to change to. """ warnings.warn( 'Direct use of the adjust_compiler function in setup.py is ' 'deprecated and can be removed from your setup.py. This ' 'functionality is now incorporated directly into the build_ext ' 'command.', AstropyDeprecationWarning) def get_debug_option(packagename): """ Determines if the build is in debug mode. Returns ------- debug : bool True if the current build was started with the debug option, False otherwise. """ try: current_debug = get_pkg_version_module(packagename, fromlist=['debug'])[0] except (ImportError, AttributeError): current_debug = None # Only modify the debug flag if one of the build commands was explicitly # run (i.e. not as a sub-command of something else) dist = get_dummy_distribution() if any(cmd in dist.commands for cmd in ['build', 'build_ext']): debug = bool(get_distutils_build_option('debug')) else: debug = bool(current_debug) if current_debug is not None and current_debug != debug: build_ext_cmd = dist.get_command_class('build_ext') build_ext_cmd.force_rebuild = True return debug def add_exclude_packages(excludes): if _module_state['excludes_too_late']: raise RuntimeError( "add_package_excludes must be called before all other setup helper " "functions in order to properly handle excluded packages") _module_state['exclude_packages'].add(set(excludes)) def register_commands(package, version, release, srcdir='.'): if _module_state['registered_commands'] is not None: return _module_state['registered_commands'] if _module_state['have_sphinx']: try: from .commands.build_sphinx import (AstropyBuildSphinx, AstropyBuildDocs) except ImportError: AstropyBuildSphinx = AstropyBuildDocs = FakeBuildSphinx else: AstropyBuildSphinx = AstropyBuildDocs = FakeBuildSphinx _module_state['registered_commands'] = registered_commands = { 'test': generate_test_command(package), # Use distutils' sdist because it respects package_data. # setuptools/distributes sdist requires duplication of information in # MANIFEST.in 'sdist': DistutilsSdist, # The exact form of the build_ext command depends on whether or not # we're building a release version 'build_ext': generate_build_ext_command(package, release), # We have a custom build_py to generate the default configuration file 'build_py': AstropyBuildPy, # Since install can (in some circumstances) be run without # first building, we also need to override install and # install_lib. See #2223 'install': AstropyInstall, 'install_lib': AstropyInstallLib, 'register': AstropyRegister, 'build_sphinx': AstropyBuildSphinx, 'build_docs': AstropyBuildDocs } # Need to override the __name__ here so that the commandline options are # presented as being related to the "build" command, for example; normally # this wouldn't be necessary since commands also have a command_name # attribute, but there is a bug in distutils' help display code that it # uses __name__ instead of command_name. Yay distutils! for name, cls in registered_commands.items(): cls.__name__ = name # Add a few custom options; more of these can be added by specific packages # later for option in [ ('use-system-libraries', "Use system libraries whenever possible", True)]: add_command_option('build', *option) add_command_option('install', *option) add_command_hooks(registered_commands, srcdir=srcdir) return registered_commands def add_command_hooks(commands, srcdir='.'): """ Look through setup_package.py modules for functions with names like ``pre__hook`` and ``post__hook`` where ```` is the name of a ``setup.py`` command (e.g. build_ext). If either hook is present this adds a wrapped version of that command to the passed in ``commands`` `dict`. ``commands`` may be pre-populated with other custom distutils command classes that should be wrapped if there are hooks for them (e.g. `AstropyBuildPy`). """ hook_re = re.compile(r'^(pre|post)_(.+)_hook$') # Distutils commands have a method of the same name, but it is not a # *classmethod* (which probably didn't exist when distutils was first # written) def get_command_name(cmdcls): if hasattr(cmdcls, 'command_name'): return cmdcls.command_name else: return cmdcls.__name__ packages = filter_packages(find_packages(srcdir)) dist = get_dummy_distribution() hooks = collections.defaultdict(dict) for setuppkg in iter_setup_packages(srcdir, packages): for name, obj in vars(setuppkg).items(): match = hook_re.match(name) if not match: continue hook_type = match.group(1) cmd_name = match.group(2) if hook_type not in hooks[cmd_name]: hooks[cmd_name][hook_type] = [] hooks[cmd_name][hook_type].append((setuppkg.__name__, obj)) for cmd_name, cmd_hooks in hooks.items(): commands[cmd_name] = generate_hooked_command( cmd_name, dist.get_command_class(cmd_name), cmd_hooks) def generate_hooked_command(cmd_name, cmd_cls, hooks): """ Returns a generated subclass of ``cmd_cls`` that runs the pre- and post-command hooks for that command before and after the ``cmd_cls.run`` method. """ def run(self, orig_run=cmd_cls.run): self.run_command_hooks('pre_hooks') orig_run(self) self.run_command_hooks('post_hooks') return type(cmd_name, (cmd_cls, object), {'run': run, 'run_command_hooks': run_command_hooks, 'pre_hooks': hooks.get('pre', []), 'post_hooks': hooks.get('post', [])}) def run_command_hooks(cmd_obj, hook_kind): """Run hooks registered for that command and phase. *cmd_obj* is a finalized command object; *hook_kind* is either 'pre_hook' or 'post_hook'. """ hooks = getattr(cmd_obj, hook_kind, None) if not hooks: return for modname, hook in hooks: if isinstance(hook, str): try: hook_obj = resolve_name(hook) except ImportError as exc: raise DistutilsModuleError( 'cannot find hook {0}: {1}'.format(hook, exc)) else: hook_obj = hook if not callable(hook_obj): raise DistutilsOptionError('hook {0!r} is not callable' % hook) log.info('running {0} from {1} for {2} command'.format( hook_kind.rstrip('s'), modname, cmd_obj.get_command_name())) try: hook_obj(cmd_obj) except Exception: log.error('{0} command hook {1} raised an exception: %s\n'.format( hook_obj.__name__, cmd_obj.get_command_name())) log.error(traceback.format_exc()) sys.exit(1) def generate_test_command(package_name): """ Creates a custom 'test' command for the given package which sets the command's ``package_name`` class attribute to the name of the package being tested. """ return type(package_name.title() + 'Test', (AstropyTest,), {'package_name': package_name}) def update_package_files(srcdir, extensions, package_data, packagenames, package_dirs): """ This function is deprecated and maintained for backward compatibility with affiliated packages. Affiliated packages should update their setup.py to use `get_package_info` instead. """ info = get_package_info(srcdir) extensions.extend(info['ext_modules']) package_data.update(info['package_data']) packagenames = list(set(packagenames + info['packages'])) package_dirs.update(info['package_dir']) def get_package_info(srcdir='.', exclude=()): """ Collates all of the information for building all subpackages and returns a dictionary of keyword arguments that can be passed directly to `distutils.setup`. The purpose of this function is to allow subpackages to update the arguments to the package's ``setup()`` function in its setup.py script, rather than having to specify all extensions/package data directly in the ``setup.py``. See Astropy's own ``setup.py`` for example usage and the Astropy development docs for more details. This function obtains that information by iterating through all packages in ``srcdir`` and locating a ``setup_package.py`` module. This module can contain the following functions: ``get_extensions()``, ``get_package_data()``, ``get_build_options()``, ``get_external_libraries()``, and ``requires_2to3()``. Each of those functions take no arguments. - ``get_extensions`` returns a list of `distutils.extension.Extension` objects. - ``get_package_data()`` returns a dict formatted as required by the ``package_data`` argument to ``setup()``. - ``get_build_options()`` returns a list of tuples describing the extra build options to add. - ``get_external_libraries()`` returns a list of libraries that can optionally be built using external dependencies. - ``get_entry_points()`` returns a dict formatted as required by the ``entry_points`` argument to ``setup()``. - ``requires_2to3()`` should return `True` when the source code requires `2to3` processing to run on Python 3.x. If ``requires_2to3()`` is missing, it is assumed to return `True`. """ ext_modules = [] packages = [] package_data = {} package_dir = {} skip_2to3 = [] if exclude: warnings.warn( "Use of the exclude parameter is no longer supported since it does " "not work as expected. Use add_exclude_packages instead. Note that " "it must be called prior to any other calls from setup helpers.", AstropyDeprecationWarning) # Use the find_packages tool to locate all packages and modules packages = filter_packages(find_packages(srcdir, exclude=exclude)) # Update package_dir if the package lies in a subdirectory if srcdir != '.': package_dir[''] = srcdir # For each of the setup_package.py modules, extract any # information that is needed to install them. The build options # are extracted first, so that their values will be available in # subsequent calls to `get_extensions`, etc. for setuppkg in iter_setup_packages(srcdir, packages): if hasattr(setuppkg, 'get_build_options'): options = setuppkg.get_build_options() for option in options: add_command_option('build', *option) if hasattr(setuppkg, 'get_external_libraries'): libraries = setuppkg.get_external_libraries() for library in libraries: add_external_library(library) if hasattr(setuppkg, 'requires_2to3'): requires_2to3 = setuppkg.requires_2to3() else: requires_2to3 = True if not requires_2to3: skip_2to3.append( os.path.dirname(setuppkg.__file__)) for setuppkg in iter_setup_packages(srcdir, packages): # get_extensions must include any Cython extensions by their .pyx # filename. if hasattr(setuppkg, 'get_extensions'): ext_modules.extend(setuppkg.get_extensions()) if hasattr(setuppkg, 'get_package_data'): package_data.update(setuppkg.get_package_data()) # Locate any .pyx files not already specified, and add their extensions in. # The default include dirs include numpy to facilitate numerical work. ext_modules.extend(get_cython_extensions(srcdir, packages, ext_modules, ['numpy'])) # Now remove extensions that have the special name 'skip_cython', as they # exist Only to indicate that the cython extensions shouldn't be built for i, ext in reversed(list(enumerate(ext_modules))): if ext.name == 'skip_cython': del ext_modules[i] # On Microsoft compilers, we need to pass the '/MANIFEST' # commandline argument. This was the default on MSVC 9.0, but is # now required on MSVC 10.0, but it doesn't seem to hurt to add # it unconditionally. if get_compiler_option() == 'msvc': for ext in ext_modules: ext.extra_link_args.append('/MANIFEST') return { 'ext_modules': ext_modules, 'packages': packages, 'package_dir': package_dir, 'package_data': package_data, 'skip_2to3': skip_2to3 } def iter_setup_packages(srcdir, packages): """ A generator that finds and imports all of the ``setup_package.py`` modules in the source packages. Returns ------- modgen : generator A generator that yields (modname, mod), where `mod` is the module and `modname` is the module name for the ``setup_package.py`` modules. """ for packagename in packages: package_parts = packagename.split('.') package_path = os.path.join(srcdir, *package_parts) setup_package = os.path.relpath( os.path.join(package_path, 'setup_package.py')) if os.path.isfile(setup_package): module = import_file(setup_package, name=packagename + '.setup_package') yield module def iter_pyx_files(package_dir, package_name): """ A generator that yields Cython source files (ending in '.pyx') in the source packages. Returns ------- pyxgen : generator A generator that yields (extmod, fullfn) where `extmod` is the full name of the module that the .pyx file would live in based on the source directory structure, and `fullfn` is the path to the .pyx file. """ for dirpath, dirnames, filenames in walk_skip_hidden(package_dir): for fn in filenames: if fn.endswith('.pyx'): fullfn = os.path.relpath(os.path.join(dirpath, fn)) # Package must match file name extmod = '.'.join([package_name, fn[:-4]]) yield (extmod, fullfn) break # Don't recurse into subdirectories def get_cython_extensions(srcdir, packages, prevextensions=tuple(), extincludedirs=None): """ Looks for Cython files and generates Extensions if needed. Parameters ---------- srcdir : str Path to the root of the source directory to search. prevextensions : list of `~distutils.core.Extension` objects The extensions that are already defined. Any .pyx files already here will be ignored. extincludedirs : list of str or None Directories to include as the `include_dirs` argument to the generated `~distutils.core.Extension` objects. Returns ------- exts : list of `~distutils.core.Extension` objects The new extensions that are needed to compile all .pyx files (does not include any already in `prevextensions`). """ # Vanilla setuptools and old versions of distribute include Cython files # as .c files in the sources, not .pyx, so we cannot simply look for # existing .pyx sources in the previous sources, but we should also check # for .c files with the same remaining filename. So we look for .pyx and # .c files, and we strip the extension. prevsourcepaths = [] ext_modules = [] for ext in prevextensions: for s in ext.sources: if s.endswith(('.pyx', '.c', '.cpp')): sourcepath = os.path.realpath(os.path.splitext(s)[0]) prevsourcepaths.append(sourcepath) for package_name in packages: package_parts = package_name.split('.') package_path = os.path.join(srcdir, *package_parts) for extmod, pyxfn in iter_pyx_files(package_path, package_name): sourcepath = os.path.realpath(os.path.splitext(pyxfn)[0]) if sourcepath not in prevsourcepaths: ext_modules.append(Extension(extmod, [pyxfn], include_dirs=extincludedirs)) return ext_modules class DistutilsExtensionArgs(collections.defaultdict): """ A special dictionary whose default values are the empty list. This is useful for building up a set of arguments for `distutils.Extension` without worrying whether the entry is already present. """ def __init__(self, *args, **kwargs): def default_factory(): return [] super(DistutilsExtensionArgs, self).__init__( default_factory, *args, **kwargs) def update(self, other): for key, val in other.items(): self[key].extend(val) def pkg_config(packages, default_libraries, executable='pkg-config'): """ Uses pkg-config to update a set of distutils Extension arguments to include the flags necessary to link against the given packages. If the pkg-config lookup fails, default_libraries is applied to libraries. Parameters ---------- packages : list of str A list of pkg-config packages to look up. default_libraries : list of str A list of library names to use if the pkg-config lookup fails. Returns ------- config : dict A dictionary containing keyword arguments to `distutils.Extension`. These entries include: - ``include_dirs``: A list of include directories - ``library_dirs``: A list of library directories - ``libraries``: A list of libraries - ``define_macros``: A list of macro defines - ``undef_macros``: A list of macros to undefine - ``extra_compile_args``: A list of extra arguments to pass to the compiler """ flag_map = {'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries', '-D': 'define_macros', '-U': 'undef_macros'} command = "{0} --libs --cflags {1}".format(executable, ' '.join(packages)), result = DistutilsExtensionArgs() try: pipe = subprocess.Popen(command, shell=True, stdout=subprocess.PIPE) output = pipe.communicate()[0].strip() except subprocess.CalledProcessError as e: lines = [ ("{0} failed. This may cause the build to fail below." .format(executable)), " command: {0}".format(e.cmd), " returncode: {0}".format(e.returncode), " output: {0}".format(e.output) ] log.warn('\n'.join(lines)) result['libraries'].extend(default_libraries) else: if pipe.returncode != 0: lines = [ "pkg-config could not lookup up package(s) {0}.".format( ", ".join(packages)), "This may cause the build to fail below." ] log.warn('\n'.join(lines)) result['libraries'].extend(default_libraries) else: for token in output.split(): # It's not clear what encoding the output of # pkg-config will come to us in. It will probably be # some combination of pure ASCII (for the compiler # flags) and the filesystem encoding (for any argument # that includes directories or filenames), but this is # just conjecture, as the pkg-config documentation # doesn't seem to address it. arg = token[:2].decode('ascii') value = token[2:].decode(sys.getfilesystemencoding()) if arg in flag_map: if arg == '-D': value = tuple(value.split('=', 1)) result[flag_map[arg]].append(value) else: result['extra_compile_args'].append(value) return result def add_external_library(library): """ Add a build option for selecting the internal or system copy of a library. Parameters ---------- library : str The name of the library. If the library is `foo`, the build option will be called `--use-system-foo`. """ for command in ['build', 'build_ext', 'install']: add_command_option(command, str('use-system-' + library), 'Use the system {0} library'.format(library), is_bool=True) def use_system_library(library): """ Returns `True` if the build configuration indicates that the given library should use the system copy of the library rather than the internal one. For the given library `foo`, this will be `True` if `--use-system-foo` or `--use-system-libraries` was provided at the commandline or in `setup.cfg`. Parameters ---------- library : str The name of the library Returns ------- use_system : bool `True` if the build should use the system copy of the library. """ return ( get_distutils_build_or_install_option('use_system_{0}'.format(library)) or get_distutils_build_or_install_option('use_system_libraries')) @extends_doc(_find_packages) def find_packages(where='.', exclude=(), invalidate_cache=False): """ This version of ``find_packages`` caches previous results to speed up subsequent calls. Use ``invalide_cache=True`` to ignore cached results from previous ``find_packages`` calls, and repeat the package search. """ if exclude: warnings.warn( "Use of the exclude parameter is no longer supported since it does " "not work as expected. Use add_exclude_packages instead. Note that " "it must be called prior to any other calls from setup helpers.", AstropyDeprecationWarning) # Calling add_exclude_packages after this point will have no effect _module_state['excludes_too_late'] = True if not invalidate_cache and _module_state['package_cache'] is not None: return _module_state['package_cache'] packages = _find_packages( where=where, exclude=list(_module_state['exclude_packages'])) _module_state['package_cache'] = packages return packages def filter_packages(packagenames): """ Removes some packages from the package list that shouldn't be installed on the current version of Python. """ if PY3: exclude = '_py2' else: exclude = '_py3' return [x for x in packagenames if not x.endswith(exclude)] class FakeBuildSphinx(Command): """ A dummy build_sphinx command that is called if Sphinx is not installed and displays a relevant error message """ # user options inherited from sphinx.setup_command.BuildDoc user_options = [ ('fresh-env', 'E', ''), ('all-files', 'a', ''), ('source-dir=', 's', ''), ('build-dir=', None, ''), ('config-dir=', 'c', ''), ('builder=', 'b', ''), ('project=', None, ''), ('version=', None, ''), ('release=', None, ''), ('today=', None, ''), ('link-index', 'i', '')] # user options appended in astropy.setup_helpers.AstropyBuildSphinx user_options.append(('warnings-returncode', 'w', '')) user_options.append(('clean-docs', 'l', '')) user_options.append(('no-intersphinx', 'n', '')) user_options.append(('open-docs-in-browser', 'o', '')) def initialize_options(self): try: raise RuntimeError("Sphinx and its dependencies must be installed " "for build_docs.") except: log.error('error: Sphinx and its dependencies must be installed ' 'for build_docs.') sys.exit(1) astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/0000755000077000000240000000000013232443301023732 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/__init__.py0000644000077000000240000000066513126316034026056 0ustar adamstaff00000000000000""" This package contains utilities and extensions for the Astropy sphinx documentation. In particular, the `astropy.sphinx.conf` should be imported by the sphinx ``conf.py`` file for affiliated packages that wish to make use of the Astropy documentation format. Note that some sphinx extensions which are bundled as-is (numpydoc and sphinx-automodapi) are included in astropy_helpers.extern rather than astropy_helpers.sphinx.ext. """ astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/conf.py0000644000077000000240000002721713171427757025265 0ustar adamstaff00000000000000# -*- coding: utf-8 -*- # Licensed under a 3-clause BSD style license - see LICENSE.rst # # Astropy shared Sphinx settings. These settings are shared between # astropy itself and affiliated packages. # # Note that not all possible configuration values are present in this file. # # All configuration values have a default; values that are commented out # serve to show the default. import os import sys import warnings from os import path import sphinx from distutils.version import LooseVersion # -- General configuration ---------------------------------------------------- # The version check in Sphinx itself can only compare the major and # minor parts of the version number, not the micro. To do a more # specific version check, call check_sphinx_version("x.y.z.") from # your project's conf.py needs_sphinx = '1.3' on_rtd = os.environ.get('READTHEDOCS', None) == 'True' def check_sphinx_version(expected_version): sphinx_version = LooseVersion(sphinx.__version__) expected_version = LooseVersion(expected_version) if sphinx_version < expected_version: raise RuntimeError( "At least Sphinx version {0} is required to build this " "documentation. Found {1}.".format( expected_version, sphinx_version)) # Configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { 'python': ('https://docs.python.org/3/', (None, 'http://data.astropy.org/intersphinx/python3.inv')), 'pythonloc': ('http://docs.python.org/', path.abspath(path.join(path.dirname(__file__), 'local/python3_local_links.inv'))), 'numpy': ('https://docs.scipy.org/doc/numpy/', (None, 'http://data.astropy.org/intersphinx/numpy.inv')), 'scipy': ('https://docs.scipy.org/doc/scipy/reference/', (None, 'http://data.astropy.org/intersphinx/scipy.inv')), 'matplotlib': ('http://matplotlib.org/', (None, 'http://data.astropy.org/intersphinx/matplotlib.inv')), 'astropy': ('http://docs.astropy.org/en/stable/', None), 'h5py': ('http://docs.h5py.org/en/latest/', None)} if sys.version_info[0] == 2: intersphinx_mapping['python'] = ( 'https://docs.python.org/2/', (None, 'http://data.astropy.org/intersphinx/python2.inv')) intersphinx_mapping['pythonloc'] = ( 'http://docs.python.org/', path.abspath(path.join(path.dirname(__file__), 'local/python2_local_links.inv'))) # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. exclude_patterns = ['_build'] # Add any paths that contain templates here, relative to this directory. # templates_path = ['_templates'] # The suffix of source filenames. source_suffix = '.rst' # The encoding of source files. #source_encoding = 'utf-8-sig' # The master toctree document. master_doc = 'index' # The reST default role (used for this markup: `text`) to use for all # documents. Set to the "smart" one. default_role = 'obj' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. #language = None # This is added to the end of RST files - a good place to put substitutions to # be used globally. rst_epilog = """ .. _Astropy: http://astropy.org """ # A list of warning types to suppress arbitrary warning messages. We mean to # override directives in astropy_helpers.sphinx.ext.autodoc_enhancements, # thus need to ignore those warning. This can be removed once the patch gets # released in upstream Sphinx (https://github.com/sphinx-doc/sphinx/pull/1843). # Suppress the warnings requires Sphinx v1.4.2 suppress_warnings = ['app.add_directive', ] # -- Project information ------------------------------------------------------ # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: #today = '' # Else, today_fmt is used as the format for a strftime call. #today_fmt = '%B %d, %Y' # If true, '()' will be appended to :func: etc. cross-reference text. #add_function_parentheses = True # If true, the current module name will be prepended to all description # unit titles (such as .. function::). #add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. #show_authors = False # The name of the Pygments (syntax highlighting) style to use. #pygments_style = 'sphinx' # A list of ignored prefixes for module index sorting. #modindex_common_prefix = [] # -- Settings for extensions and extension options ---------------------------- # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ 'sphinx.ext.autodoc', 'sphinx.ext.intersphinx', 'sphinx.ext.todo', 'sphinx.ext.coverage', 'sphinx.ext.inheritance_diagram', 'sphinx.ext.viewcode', 'astropy_helpers.extern.numpydoc', 'astropy_helpers.extern.automodapi.automodapi', 'astropy_helpers.extern.automodapi.smart_resolver', 'astropy_helpers.sphinx.ext.tocdepthfix', 'astropy_helpers.sphinx.ext.doctest', 'astropy_helpers.sphinx.ext.changelog_links'] if not on_rtd and LooseVersion(sphinx.__version__) < LooseVersion('1.4'): extensions.append('sphinx.ext.pngmath') else: extensions.append('sphinx.ext.mathjax') try: import matplotlib.sphinxext.plot_directive extensions += [matplotlib.sphinxext.plot_directive.__name__] # AttributeError is checked here in case matplotlib is installed but # Sphinx isn't. Note that this module is imported by the config file # generator, even if we're not building the docs. except (ImportError, AttributeError): warnings.warn( "matplotlib's plot_directive could not be imported. " + "Inline plots will not be included in the output") # Don't show summaries of the members in each class along with the # class' docstring numpydoc_show_class_members = False autosummary_generate = True automodapi_toctreedirnm = 'api' # Class documentation should contain *both* the class docstring and # the __init__ docstring autoclass_content = "both" # Render inheritance diagrams in SVG graphviz_output_format = "svg" graphviz_dot_args = [ '-Nfontsize=10', '-Nfontname=Helvetica Neue, Helvetica, Arial, sans-serif', '-Efontsize=10', '-Efontname=Helvetica Neue, Helvetica, Arial, sans-serif', '-Gfontsize=10', '-Gfontname=Helvetica Neue, Helvetica, Arial, sans-serif' ] # -- Options for HTML output ------------------------------------------------- # Add any paths that contain custom themes here, relative to this directory. html_theme_path = [path.abspath(path.join(path.dirname(__file__), 'themes'))] # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. html_theme = 'bootstrap-astropy' # Custom sidebar templates, maps document names to template names. html_sidebars = { '**': ['localtoc.html'], 'search': [], 'genindex': [], 'py-modindex': [], } # 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. # included in the bootstrap-astropy theme html_favicon = path.join(html_theme_path[0], html_theme, 'static', 'astropy_logo.ico') # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. html_last_updated_fmt = '%d %b %Y' # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. #html_theme_options = {} # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". #html_title = None # A shorter title for the navigation bar. Default is the same as html_title. #html_short_title = None # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. #html_use_smartypants = True # Additional templates that should be rendered to pages, maps page names to # template names. #html_additional_pages = {} # If false, no module index is generated. #html_domain_indices = True # If false, no index is generated. #html_use_index = True # If true, the index is split into individual pages for each letter. #html_split_index = False # If true, links to the reST sources are added to the pages. #html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. #html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. #html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. #html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). #html_file_suffix = None # -- Options for LaTeX output ------------------------------------------------ # The paper size ('letter' or 'a4'). #latex_paper_size = 'letter' # The font size ('10pt', '11pt' or '12pt'). #latex_font_size = '10pt' # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. latex_toplevel_sectioning = 'part' # If true, show page references after internal links. #latex_show_pagerefs = False # If true, show URL addresses after external links. #latex_show_urls = False latex_elements = {} # Additional stuff for the LaTeX preamble. latex_elements['preamble'] = r""" % Use a more modern-looking monospace font \usepackage{inconsolata} % The enumitem package provides unlimited nesting of lists and enums. % Sphinx may use this in the future, in which case this can be removed. % See https://bitbucket.org/birkenfeld/sphinx/issue/777/latex-output-too-deeply-nested \usepackage{enumitem} \setlistdepth{15} % In the parameters section, place a newline after the Parameters % header. (This is stolen directly from Numpy's conf.py, since it % affects Numpy-style docstrings). \usepackage{expdlist} \let\latexdescription=\description \def\description{\latexdescription{}{} \breaklabel} % Support the superscript Unicode numbers used by the "unicode" units % formatter \DeclareUnicodeCharacter{2070}{\ensuremath{^0}} \DeclareUnicodeCharacter{00B9}{\ensuremath{^1}} \DeclareUnicodeCharacter{00B2}{\ensuremath{^2}} \DeclareUnicodeCharacter{00B3}{\ensuremath{^3}} \DeclareUnicodeCharacter{2074}{\ensuremath{^4}} \DeclareUnicodeCharacter{2075}{\ensuremath{^5}} \DeclareUnicodeCharacter{2076}{\ensuremath{^6}} \DeclareUnicodeCharacter{2077}{\ensuremath{^7}} \DeclareUnicodeCharacter{2078}{\ensuremath{^8}} \DeclareUnicodeCharacter{2079}{\ensuremath{^9}} \DeclareUnicodeCharacter{207B}{\ensuremath{^-}} \DeclareUnicodeCharacter{00B0}{\ensuremath{^{\circ}}} \DeclareUnicodeCharacter{2032}{\ensuremath{^{\prime}}} \DeclareUnicodeCharacter{2033}{\ensuremath{^{\prime\prime}}} % Make the "warning" and "notes" sections use a sans-serif font to % make them stand out more. \renewenvironment{notice}[2]{ \def\py@noticetype{#1} \csname py@noticestart@#1\endcsname \textsf{\textbf{#2}} }{\csname py@noticeend@\py@noticetype\endcsname} """ # Documents to append as an appendix to all manuals. #latex_appendices = [] # If false, no module index is generated. #latex_domain_indices = True # The name of an image file (relative to this directory) to place at the top of # the title page. #latex_logo = None # -- Options for the linkcheck builder ---------------------------------------- # A timeout value, in seconds, for the linkcheck builder linkcheck_timeout = 60 astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/0000755000077000000240000000000013232443301024532 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/__init__.py0000644000077000000240000000010213126316034026640 0ustar adamstaff00000000000000from __future__ import division, absolute_import, print_function astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/changelog_links.py0000644000077000000240000000554313171427757030265 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This sphinx extension makes the issue numbers in the changelog into links to GitHub issues. """ from __future__ import print_function import re from docutils.nodes import Text, reference BLOCK_PATTERN = re.compile('\[#.+\]', flags=re.DOTALL) ISSUE_PATTERN = re.compile('#[0-9]+') def process_changelog_links(app, doctree, docname): for rex in app.changelog_links_rexes: if rex.match(docname): break else: # if the doc doesn't match any of the changelog regexes, don't process return app.info('[changelog_links] Adding changelog links to "{0}"'.format(docname)) for item in doctree.traverse(): if not isinstance(item, Text): continue # We build a new list of items to replace the current item. If # a link is found, we need to use a 'reference' item. children = [] # First cycle through blocks of issues (delimited by []) then # iterate inside each one to find the individual issues. prev_block_end = 0 for block in BLOCK_PATTERN.finditer(item): block_start, block_end = block.start(), block.end() children.append(Text(item[prev_block_end:block_start])) block = item[block_start:block_end] prev_end = 0 for m in ISSUE_PATTERN.finditer(block): start, end = m.start(), m.end() children.append(Text(block[prev_end:start])) issue_number = block[start:end] refuri = app.config.github_issues_url + issue_number[1:] children.append(reference(text=issue_number, name=issue_number, refuri=refuri)) prev_end = end prev_block_end = block_end # If no issues were found, this adds the whole item, # otherwise it adds the remaining text. children.append(Text(block[prev_end:block_end])) # If no blocks were found, this adds the whole item, otherwise # it adds the remaining text. children.append(Text(item[prev_block_end:])) # Replace item by the new list of items we have generated, # which may contain links. item.parent.replace(item, children) def setup_patterns_rexes(app): app.changelog_links_rexes = [re.compile(pat) for pat in app.config.changelog_links_docpattern] def setup(app): app.connect('doctree-resolved', process_changelog_links) app.connect('builder-inited', setup_patterns_rexes) app.add_config_value('github_issues_url', None, True) app.add_config_value('changelog_links_docpattern', ['.*changelog.*', 'whatsnew/.*'], True) return {'parallel_read_safe': True, 'parallel_write_safe': True} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/doctest.py0000644000077000000240000000364113171427757026600 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This is a set of three directives that allow us to insert metadata about doctests into the .rst files so the testing framework knows which tests to skip. This is quite different from the doctest extension in Sphinx itself, which actually does something. For astropy, all of the testing is centrally managed from py.test and Sphinx is not used for running tests. """ import re from docutils.nodes import literal_block from docutils.parsers.rst import Directive class DoctestSkipDirective(Directive): has_content = True def run(self): # Check if there is any valid argument, and skip it. Currently only # 'win32' is supported in astropy.tests.pytest_plugins. if re.match('win32', self.content[0]): self.content = self.content[2:] code = '\n'.join(self.content) return [literal_block(code, code)] class DoctestOmitDirective(Directive): has_content = True def run(self): # Simply do not add any content when this directive is encountered return [] class DoctestRequiresDirective(DoctestSkipDirective): # This is silly, but we really support an unbounded number of # optional arguments optional_arguments = 64 def setup(app): app.add_directive('doctest-requires', DoctestRequiresDirective) app.add_directive('doctest-skip', DoctestSkipDirective) app.add_directive('doctest-skip-all', DoctestSkipDirective) app.add_directive('doctest', DoctestSkipDirective) # Code blocks that use this directive will not appear in the generated # documentation. This is intended to hide boilerplate code that is only # useful for testing documentation using doctest, but does not actually # belong in the documentation itself. app.add_directive('testsetup', DoctestOmitDirective) return {'parallel_read_safe': True, 'parallel_write_safe': True} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/edit_on_github.py0000644000077000000240000001346413171427757030122 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ This extension makes it easy to edit documentation on github. It adds links associated with each docstring that go to the corresponding view source page on Github. From there, the user can push the "Edit" button, edit the docstring, and submit a pull request. It has the following configuration options (to be set in the project's ``conf.py``): * ``edit_on_github_project`` The name of the github project, in the form "username/projectname". * ``edit_on_github_branch`` The name of the branch to edit. If this is a released version, this should be a git tag referring to that version. For a dev version, it often makes sense for it to be "master". It may also be a git hash. * ``edit_on_github_source_root`` The location within the source tree of the root of the Python package. Defaults to "lib". * ``edit_on_github_doc_root`` The location within the source tree of the root of the documentation source. Defaults to "doc", but it may make sense to set it to "doc/source" if the project uses a separate source directory. * ``edit_on_github_docstring_message`` The phrase displayed in the links to edit a docstring. Defaults to "[edit on github]". * ``edit_on_github_page_message`` The phrase displayed in the links to edit a RST page. Defaults to "[edit this page on github]". * ``edit_on_github_help_message`` The phrase displayed as a tooltip on the edit links. Defaults to "Push the Edit button on the next page" * ``edit_on_github_skip_regex`` When the path to the .rst file matches this regular expression, no "edit this page on github" link will be added. Defaults to ``"_.*"``. """ import inspect import os import re import sys from docutils import nodes from sphinx import addnodes def import_object(modname, name): """ Import the object given by *modname* and *name* and return it. If not found, or the import fails, returns None. """ try: __import__(modname) mod = sys.modules[modname] obj = mod for part in name.split('.'): obj = getattr(obj, part) return obj except: return None def get_url_base(app): return 'http://github.com/%s/tree/%s/' % ( app.config.edit_on_github_project, app.config.edit_on_github_branch) def doctree_read(app, doctree): # Get the configuration parameters if app.config.edit_on_github_project == 'REQUIRED': raise ValueError( "The edit_on_github_project configuration variable must be " "provided in the conf.py") source_root = app.config.edit_on_github_source_root url = get_url_base(app) docstring_message = app.config.edit_on_github_docstring_message # Handle the docstring-editing links for objnode in doctree.traverse(addnodes.desc): if objnode.get('domain') != 'py': continue names = set() for signode in objnode: if not isinstance(signode, addnodes.desc_signature): continue modname = signode.get('module') if not modname: continue fullname = signode.get('fullname') if fullname in names: # only one link per name, please continue names.add(fullname) obj = import_object(modname, fullname) anchor = None if obj is not None: try: lines, lineno = inspect.getsourcelines(obj) except: pass else: anchor = '#L%d' % lineno if anchor: real_modname = inspect.getmodule(obj).__name__ path = '%s%s%s.py%s' % ( url, source_root, real_modname.replace('.', '/'), anchor) onlynode = addnodes.only(expr='html') onlynode += nodes.reference( reftitle=app.config.edit_on_github_help_message, refuri=path) onlynode[0] += nodes.inline( '', '', nodes.raw('', ' ', format='html'), nodes.Text(docstring_message), classes=['edit-on-github', 'viewcode-link']) signode += onlynode def html_page_context(app, pagename, templatename, context, doctree): if (templatename == 'page.html' and not re.match(app.config.edit_on_github_skip_regex, pagename)): doc_root = app.config.edit_on_github_doc_root if doc_root != '' and not doc_root.endswith('/'): doc_root += '/' doc_path = os.path.relpath(doctree.get('source'), app.builder.srcdir) url = get_url_base(app) page_message = app.config.edit_on_github_page_message context['edit_on_github'] = url + doc_root + doc_path context['edit_on_github_page_message'] = page_message def setup(app): app.add_config_value('edit_on_github_project', 'REQUIRED', True) app.add_config_value('edit_on_github_branch', 'master', True) app.add_config_value('edit_on_github_source_root', 'lib', True) app.add_config_value('edit_on_github_doc_root', 'doc', True) app.add_config_value('edit_on_github_docstring_message', '[edit on github]', True) app.add_config_value('edit_on_github_page_message', 'Edit This Page on Github', True) app.add_config_value('edit_on_github_help_message', 'Push the Edit button on the next page', True) app.add_config_value('edit_on_github_skip_regex', '_.*', True) app.connect('doctree-read', doctree_read) app.connect('html-page-context', html_page_context) return {'parallel_read_safe': True, 'parallel_write_safe': True} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/tests/0000755000077000000240000000000013232443301025674 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/tests/__init__.py0000644000077000000240000000000013126316034027777 0ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/ext/tocdepthfix.py0000644000077000000240000000137013171427757027451 0ustar adamstaff00000000000000from sphinx import addnodes def fix_toc_entries(app, doctree): # Get the docname; I don't know why this isn't just passed in to the # callback # This seems a bit unreliable as it's undocumented, but it's not "private" # either: docname = app.builder.env.temp_data['docname'] if app.builder.env.metadata[docname].get('tocdepth', 0) != 0: # We need to reprocess any TOC nodes in the doctree and make sure all # the files listed in any TOCs are noted for treenode in doctree.traverse(addnodes.toctree): app.builder.env.note_toctree(docname, treenode) def setup(app): app.connect('doctree-read', fix_toc_entries) return {'parallel_read_safe': True, 'parallel_write_safe': True} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/local/0000755000077000000240000000000013232443301025024 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/local/python2_local_links.inv0000644000077000000240000000106213027011015031511 0ustar adamstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 2.7 and 3.5 # The remainder of this file should be compressed using zlib. xœ¥”=OÃ0@wÿŠ“ºÀà Z!¤n€U µbwœ+1ríp¶KïÇIi›”QeIä˽wþ8g³"Wf ʬÐxK%¬œ²†lS²ï(ý¦¥Ï­‰‘×Í×1 “k&ƒQrÃóp)”ÉÀ.ÀçÊÁBi—Û 3H¤]„ÎaÁ)ó_Z¥I¤‹Ú>d“H¯ï‰,ÅÐ× _M…_Âð"æ’ òbvIî—zЀ8›<ŸŒ?oÙ',O…wg¯B<•o@œÍËâdÁžá»}5ºdsµDüqã¨ÛØÄ8KK®ÂÁÈßô6úo²9 ¤«£%üè|‡¶@Ó­9ȯ]Τ52ÅvMÁ‡ØQÉCý®üR çÚò#ùunÏÑóœPdSkõýeð›]íW³¸Þ€ÉKõ쨰ɨ¥ÍdÎ RÆŸÿû¼êü_­/ªÖø“'RÉšãG4Hâ¯Õ·ØíÒÛÁ½„·ä·±fžªC{ÃÒÖß| åEª»;åö½¤-¿³ï2½ä{ÉÁÌ]iäÄÇMë;û–¨«HÏãm‹8û‹´RKastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/local/python2_local_links.txt0000644000077000000240000000314613027011015031541 0ustar adamstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 2.7 and 3.5 # The remainder of this file should be compressed using zlib. # python2 IndexError py:exception -1 2/library/exceptions.html#IndexError - IOError py:exception -1 2/library/exceptions.html#IOError - KeyError py:exception -1 2/library/exceptions.html#KeyError - ValueError py:exception -1 2/library/exceptions.html#ValueError - TypeError py:exception -1 2/library/exceptions.html#TypeError - # python3 only TimeoutError py:exception -1 3/library/exceptions.html#TimeoutError - bytes py:function -1 3/library/functions.html#bytes - urllib.request.urlopen py:function -1 3/library/urllib.request.html#urllib.request.urlopen - concurrent.futures.Future py:class -1 3/library/concurrent.futures.html#concurrent.futures.Future - concurrent.futures.ThreadPoolExecutor py:class -1 3/library/concurrent.futures.html#concurrent.futures.ThreadPoolExecutor - queue.Queue py:class -1 3/library/queue.html#queue.Queue - print() py:function -1 3/library/functions.html#print - # python3 only collections.abc collections.Generator py:class -1 3/library/collections.abc.html#collections.abc.Generator - collections.ByteString py:class -1 3/library/collections.abc.html#collections.abc.ByteString - collections.Awaitable py:class -1 3/library/collections.abc.html#collections.abc.Awaitable - collections.Coroutine py:class -1 3/library/collections.abc.html#collections.abc.Coroutine - collections.AsyncIterable py:class -1 3/library/collections.abc.html#collections.abc.AsyncIterable - collections.AsyncIterator py:class -1 3/library/collections.abc.html#collections.abc.AsyncIterator - astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/local/python3_local_links.inv0000644000077000000240000000122213027011015031510 0ustar adamstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 3.5 # The remainder of this file should be compressed using zlib. xœ­ÕÁŽÚ0Ð{¾b$.í!YTUâÖîa·ª*!Qq­{h\;µ¶Ù¯ïgÉšlÏÇvÆ ØV…ÔAê#jolG´N Ëdk~#÷kØ4¾0šZv]ï–Ù'`ZÀ*ûHÍ? ‹%“Z ³_H{©\aj% Gব,:‡j'õ/xU2Ï(ºjõ%­PR\Â7’(ºjÖ¥5ýJ?Àò,³ÍCÕöf…/Õ¢ëOûˆ4©µäF´±ûZszš ºouÐO“Ü ‘Ïål;ƒ”Ýð4’û¬`îç›6éyDí¼ðM…ç”AÄ-}Jwq‰!dÞj´!#âÈT·"ç Ú«hè2£oS¡žßˆ~`· “¨t8«¤²Rûwï§ÒjnKÛñcŸRxÂržŒÿ?íéèÒÉ%Ÿ+æ\ˆOb»ÓÆ ’ø3sË»£ü¿ö`„ôV¾Ò»áv@ˆ>2¥bç;!ý•I,=Whª_ÑôÉé'Ôñö™l!þ©Qó¨%Œþ^ûÓBÝ#Ô }inuüÜÂD¹#e³ªŠ\‹ž¸:ï{ø¡tuþ;‰/wx†–yó®–.–¿ !þn²X{0Bz×Þo±øH ùÏ/LúØòxA&UÝXS{ºžâ®¸™ÌÜ5šß£¸‡Ð\’ÈRBiòJFü?astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/local/python3_local_links.txt0000644000077000000240000000540413027011015031541 0ustar adamstaff00000000000000# Sphinx inventory version 2 # Project: Python # Version: 2.7 and 3.5 # The remainder of this file should be compressed using zlib. # python2 only links cPickle py:module -1 2/library/pickle.html#module-cPickle - unicode py:function -1 2/library/functions.html#unicode - bsddb py:module -1 2/library/bsddb.html#module-bsddb - dict.has_key py:method -1 2/library/stdtypes.html#dict.has_key - dict.iteritems py:method -1 2/library/stdtypes.html#dict.iteritems - dict.iterkeys py:method -1 2/library/stdtypes.html#dict.iterkeys - dict.itervalues py:method -1 2/library/stdtypes.html#dict.itervalues - urllib2.urlopen py:function -1 2/library/urllib2.html#urllib2.urlopen - # python3 print() py:function -1 3/library/functions.html#print - # python3 collections.abc collections.Container py:class -1 3/library/collections.abc.html#collections.abc.Container - collections.Hashable py:class -1 3/library/collections.abc.html#collections.abc.Hashable - collections.Sized py:class -1 3/library/collections.abc.html#collections.abc.Sized - collections.Callable py:class -1 3/library/collections.abc.html#collections.abc.Callable - collections.Iterable py:class -1 3/library/collections.abc.html#collections.abc.Iterable - collections.Iterator py:class -1 3/library/collections.abc.html#collections.abc.Iterator - collections.Generator py:class -1 3/library/collections.abc.html#collections.abc.Generator - collections.Sequence py:class -1 3/library/collections.abc.html#collections.abc.Sequence - collections.MutableSequence py:class -1 3/library/collections.abc.html#collections.abc.MutableSequence - collections.ByteString py:class -1 3/library/collections.abc.html#collections.abc.ByteString - collections.Set py:class -1 3/library/collections.abc.html#collections.abc.Set - collections.MutableSet py:class -1 3/library/collections.abc.html#collections.abc.MutableSet - collections.Mapping py:class -1 3/library/collections.abc.html#collections.abc.Mapping - collections.MutableMapping py:class -1 3/library/collections.abc.html#collections.abc.MutableMapping - collections.MappingView py:class -1 3/library/collections.abc.html#collections.abc.MappingView - collections.ItemsView py:class -1 3/library/collections.abc.html#collections.abc.ItemsView - collections.KeysView py:class -1 3/library/collections.abc.html#collections.abc.KeysView - collections.ValuesView py:class -1 3/library/collections.abc.html#collections.abc.ValuesView - collections.Awaitable py:class -1 3/library/collections.abc.html#collections.abc.Awaitable - collections.Coroutine py:class -1 3/library/collections.abc.html#collections.abc.Coroutine - collections.AsyncIterable py:class -1 3/library/collections.abc.html#collections.abc.AsyncIterable - collections.AsyncIterator py:class -1 3/library/collections.abc.html#collections.abc.AsyncIterator - astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/setup_package.py0000644000077000000240000000044413126316034027125 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst def get_package_data(): # Install the theme files return { 'astropy_helpers.sphinx': [ 'local/*.inv', 'themes/bootstrap-astropy/*.*', 'themes/bootstrap-astropy/static/*.*']} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/0000755000077000000240000000000013232443301025217 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/0000755000077000000240000000000013232443301030733 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/globaltoc.html0000644000077000000240000000011112354456432033575 0ustar adamstaff00000000000000

Table of Contents

{{ toctree(maxdepth=-1, titles_only=true) }} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/layout.html0000644000077000000240000000655112610145732033153 0ustar adamstaff00000000000000{% extends "basic/layout.html" %} {# Collapsible sidebar script from default/layout.html in Sphinx #} {% set script_files = script_files + ['_static/sidebar.js'] %} {# Add the google webfonts needed for the logo #} {% block extrahead %} {% if not embedded %}{% endif %} {% endblock %} {% block header %}
{{ theme_logotext1 }}{{ theme_logotext2 }}{{ theme_logotext3 }}
  • Index
  • Modules
  • {% block sidebarsearch %} {% include "searchbox.html" %} {% endblock %}
{% endblock %} {% block relbar1 %} {% endblock %} {# Silence the bottom relbar. #} {% block relbar2 %}{% endblock %} {%- block footer %}

{%- if edit_on_github %} {{ edit_on_github_page_message }}   {%- endif %} {%- if show_source and has_source and sourcename %} {{ _('Page Source') }} {%- endif %}   Back to Top

{%- if show_copyright %} {%- if hasdoc('copyright') %} {% trans path=pathto('copyright'), copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
{%- else %} {% trans copyright=copyright|e %}© Copyright {{ copyright }}.{% endtrans %}
{%- endif %} {%- endif %} {%- if show_sphinx %} {% trans sphinx_version=sphinx_version|e %}Created using Sphinx {{ sphinx_version }}.{% endtrans %}   {%- endif %} {%- if last_updated %} {% trans last_updated=last_updated|e %}Last built {{ last_updated }}.{% endtrans %}
{%- endif %}

{%- endblock %} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/localtoc.html0000644000077000000240000000004212354456432033432 0ustar adamstaff00000000000000

Page Contents

{{ toc }} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/searchbox.html0000644000077000000240000000042012354456432033610 0ustar adamstaff00000000000000{%- if pagename != "search" %}
{%- endif %} astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/0000755000077000000240000000000013232443301032222 5ustar adamstaff00000000000000././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout.svgastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_link0000644000077000000240000001212112544425160034670 0ustar adamstaff00000000000000 ././@LongLink0000000000000000000000000000015700000000000011220 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.pngastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_link0000644000077000000240000000327512354456432034707 0ustar adamstaff00000000000000‰PNG  IHDR[â8A bKGDÿÿÿ ½§“ oFFsvek pHYs × ×B(›x vpAg\@0¢Ð¬IDATXÃå˜iŒ_SÆϘÚ+Új‹fF« BH‘XbOÐέ†ª}‰-Z¤Abû¢$¤Öi…V#¸T•ZCÕ– µIi™ÚU”d¦ª÷ý›;·÷?™)Ó*OrsïyÏsÏûžçžóžs®è!ج’ôLOùÙ`[À–=é`œ3|¼±;»1`{ÛͶﱽÔv]mú«ßØÞX°=˜l¦y’Zjs„á@30ŒlÈ<,éÝ’ÆöÆ @+ð60SÒ϶ûÇG½í‰ñü¡¤mo œ¬‘t—íþÀ%À `¶¤4üÔ pÐX<,’Ô1¦„:`•R~qÂPà` ð.°0kœÐ¨WJéŒs¶@R>)é÷ÎÀ´Ntž$éS`6p6pTØím¢5…—ÿÆHš“s8˜Éã{à@`»¿ ÷J:×v=ð%``/à9`çàœ/iší~À\`ÿbŸ{ƒçœH7KBäÝ€§"Æ“o€f¥´:¡/°hRÊʱ' J™\"ö`ànàÜ*ý[!©ÍöåÀ”ˆÿ `'I­ØÆö¶µ}Ÿí ¶o´Ý9÷#Ûg›Ùþ6ì l²}’í—m¿h[¶›lO·ýeð~ŽòtÛgE;õnÇÛkmϳ=Ëö^ÑÎKQ¿&âš~*¸² Ò NøÑ §ìµNxÊ ×æl30¡L-'ÌwÂ~¥uö ÛOÒ lOŒ˜Ïm)†ÙÞ©`»"×±ÁakÈÙšs\"5äߟ[m,ˆÝfû˜Bý±¹ú 9{ígÃþ[Œþ¼Ø“ªØà„'(Ê8á}'ëðú;aqÑ^{N•:l_q-ãÔHZ"éëx©.„Ü5ÇkŠû×ÀOñ|[ì86—„¤_Y?Ü-éé‚í¸¸ÿB6m‰8×wDqkÚ×… ÚÊ(eY´5$ʯwdz"ðD%¿—iZMh²´1/éѪbÛîmûZÛŸ‘åÒ¸0Çë] ŒV’-Ž_Ù¾9öÕ냲…ª1îK%­)Ôå®AÝðÓBûº08­À9•lî *±íN¶à'’ž M/ÎØÛÛo×;·GcJ=IÏÛ€€þÀeÀ›¶û®§àÕ:T6’܆ò}ÖæÊ³€£œP à„F 7°¸“6J}Kú h,ÌÐa¡S‡ÎŒŠV`¤¤‹%½üXU é[I—»WEÀÿˆÔ°<îM¶‹;¤Á¹çeÝh³1ÏWÊjà% 2úF3;I!±ËF6’Z ¦âÇ¥†ÈcÀrIKªtªÝ›=¢"€¤VIS€rªà·¸°½Y7Å®ï·ÎÈù8/ŠmÀü®4æ„}Õdg‡<¦çÄóhàÁ.4§.p*Úv»ø*žw·}=YJ9ÖÝÙ¼,²=øì”…9ú;À @_`†í¹ÀÊ.þ'IÉöê#{lï |Hv868·Hú¦ðÞÞNRòûï-ÈRãÍ%£öM Þ ûµJÿšQÕÐVCvNé öŒ¶¸&ìk"À“ÉrrÉv$Ä•Ç:ŽŒidi¥8%®WiµU!i­íÑÀcáçÒ\õÀý¹XóÌsÂL²…w7`2°¸o?)8áNàqàÖ.ŠØd{rxS˜yÙ¾ÓÞ¸˜,¡¯î—ôží1À²³ýòàöŽúß‘”æåOtÁ\ V $MSë©A{UÒGeÑFºj&;öö#›IIZg‹dK| ó€=ÉÆJYTM'lE¶»¤”–ÎÔ‹³Äé]ü(¯Hú üMq¨¹h=ÞÛÏ ¯lˆkþ~›<&wmGÿk±pYº™½!üõäÿì%âÿÈ#ÀædëÀX¥·h=…ÿ’ØSß»À3p5™Ø‹óÛĞƟ ½§pÅ%tEXtdate:create2012-10-18T20:57:33+02:00¢p_f%tEXtdate:modify2012-10-18T20:57:33+02:00Ó-çÚtEXtSoftwarewww.inkscape.org›î<IEND®B`‚././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.icoastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo0000644000077000000240000010033412544425160034677 0ustar adamstaff00000000000000@@ (@F  (n@ ( –P (¾Y(@€ ÿÿ ÿ* ÿVýy ý›¬±ûÕúûüí÷ùüìýýýíýýýí§ªû× ü«ý‹ýoüKÿ ÿ ÿÿîûHýýÌúìýó ûøûü°µÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ˜Ÿÿÿûþ ûúûöýòúéûÇýÿIóÿ¿ÿ!ýyûÏüðüúÿÿÿÿÿÿ ÿÿ>KÿÿÏÓÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡ÿÿ ÿÿÿÿÿÿÿÿÿÿÿÿûúÿðûÚü—û?ã ÿÿý|ûÚýöÿÿÿÿÿÿþÿýÿýÿLYþÿÌÏÿÿûüÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿerþÿýÿýÿýÿýÿýÿþÿÿÿÿÿÿÿüûûíú½ÿZÿÿüJûÇýöÿÿÿÿþÿýÿýÿýÿ*<þÿ™¡ÿÿêíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉÎÿÿ3Eýÿ ýÿýÿýÿýÿýÿýÿýÿýÿþÿÿÿÿÿÿÿÿðûÄüXÿÿü•üêÿÿÿÿþÿýÿýÿýÿ1ýÿ“þÿäèÿÿûûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿÿÿüïù´ÿ=ÿø$û®ýúÿÿÿÿýÿýÿýÿýÿ.Cþÿ·¿ÿÿùúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”Ÿþÿ*ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿÿÿúâû†ÿÿ3üÃüþÿÿýÿýÿýÿýÿýÿ^pþÿÓÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷øÿÿ…“þÿ+ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿÿÿÿÿýöü¸ÿ7 ÿ(øÃ!ÿÿ ÿÿ ýÿ ýÿ ýÿýÿýÿsƒþÿåéÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÍþÿPfýÿ %ýÿýÿýÿ ýÿ ýÿ ýÿ ýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿýÿþÿÿÿ ÿÿûÙ ÿi#ÿ úº#ÿÿ"ÿÿ"ýÿ"ýÿ"ýÿ ýÿ ýÿy‹ÿÿîðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâåþÿu‡ýÿ =ýÿýÿýÿ!ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ!ýÿ!ÿÿ!ÿÿ ûìýƒÿÿ$ý›$ýÿ$ÿÿ$ýÿ$ýÿ$ýÿ"ýÿýÿmþÿëîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýýÿÿ¦²þÿ8Týÿ%ýÿýÿ!ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ#ýÿ#ýÿ#ýÿ"ýÿ"ýÿ"ýÿ"ýÿ#ýÿ#ýÿ#ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ$ýÿ#ýÿ#ýÿ$þÿ$ÿÿ#üõ!ü’'ÿ &ÿj'ûñ(ÿÿ&ýÿ&ýÿ&ýÿ&ýÿ!ýÿNiþÿÞãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçëþÿmƒýÿ5ýÿ ýÿ ýÿ%ýÿ&ýÿ&ýÿ&ýÿ%ýÿ%ýÿ$ýÿ#ýÿ#ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ"ýÿ#ýÿ#ýÿ$ýÿ$ýÿ%ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&ýÿ&þÿ&ÿÿ%ýø&üš3ÿ)ÿ%(ûØ*ÿÿ)ýÿ)ýÿ)ýÿ(ýÿ%ýÿ'IþÿÇÐÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙßþÿUqýÿ'ýÿ!ýÿ'ýÿ)ýÿ(ýÿ(ýÿ(ýÿ'ýÿ&ýÿ#ýÿ(ýÿ"DþÿPkþÿp†þÿ‡™þÿ’£þÿ‘¢þÿ„˜þÿm„þÿNjþÿ!Cþÿ&ýÿ"ýÿ%ýÿ&ýÿ'ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ýÿ(ÿÿ&üú'ü˜9ÿ ÿ+ý”*þÿ+ÿÿ*þÿ+þÿ+þÿ)þÿ*þÿ®ÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàåÿÿQoþÿ%þÿ%þÿ+þÿ+þÿ+þÿ+þÿ*þÿ'þÿ$þÿ"Gþÿt‹ÿÿ¶ÂÿÿÔÛÿÿäèÿÿïñÿÿöøÿÿúûÿÿúûÿÿö÷ÿÿîñÿÿãèÿÿÔÛÿÿ¹Åÿÿ}’ÿÿ/Rþÿ'þÿ&þÿ)þÿ)þÿ*þÿ*þÿ*þÿ*þÿ*þÿ*ÿÿ'ûù'ý‰Uª+ÿ;-üæ.ÿÿ-þÿ-þÿ-þÿ,þÿ)þÿVtÿÿêîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíñÿÿ]zþÿ(þÿ'þÿ-þÿ-þÿ-þÿ-þÿ,þÿ$þÿFþÿ‰ÿÿÒÚÿÿðóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿóõÿÿ×Þÿÿ£³ÿÿ?`ÿÿ)þÿ)þÿ,þÿ,þÿ,þÿ,þÿ,þÿ,þÿ.ÿÿ,üñ.ýt@ÿ/ý™/þÿ0ÿÿ0þÿ0þÿ0þÿ-þÿ :þÿ¿Ìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿz“þÿ1þÿ(þÿ0þÿ/þÿ.þÿ/þÿ,þÿ+þÿZwÿÿÇÑÿÿøúÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜâÿÿ”§ÿÿ#Lþÿ'þÿ.þÿ/þÿ/þÿ/þÿ/þÿ/þÿ0ÿÿ.üâ-ÿI0ÿ%0ýá2ÿÿ1þÿ1þÿ1þÿ0þÿ/þÿbÿÿðóÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¯¿þÿHþÿ)þÿ1þÿ2þÿ2þÿ1þÿ.þÿ8þÿx’ÿÿæëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿÄÏÿÿTsÿÿ+þÿ/þÿ1þÿ0þÿ0þÿ0þÿ1ÿÿ1ÿÿ/üÈ2ÿ$@¿3ýn3üø5ÿÿ3þÿ3þÿ3þÿ1þÿ8þÿÀÌÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿëïÿÿEkþÿ,þÿ2þÿ4þÿ3þÿ4þÿ1þÿ8þÿ€šÿÿñôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôöÿÿÕÞÿÿËÕÿÿËÖÿÿ×ßÿÿõöÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâçÿÿqÿÿ1þÿ0þÿ3þÿ2þÿ2þÿ2þÿ3ÿÿ2þÿ0üŸ@ÿã 2ü¶6üþ6ÿÿ6þÿ6þÿ5þÿ5þÿDlþÿèíÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”«þÿ @þÿ/þÿ6þÿ5þÿ5þÿ4þÿ0þÿt‘ÿÿñôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿäéÿÿ—­þÿ\~þÿ?eþÿ1\þÿ,Xþÿ,Xþÿ2]þÿ?fþÿZ}þÿ§þÿÖßÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïòÿÿu’ÿÿ3þÿ3þÿ5þÿ5þÿ5þÿ5þÿ6ÿÿ4üð4ÿX8ÿ 5ûå:ÿÿ8þÿ8þÿ8þÿ7þÿ7þÿ–®ÿÿûüÿÿÿÿÿÿÿÿÿÿÿÿÿÿðôÿÿ@jþÿ0þÿ8þÿ8þÿ8þÿ8þÿ.þÿRxÿÿæëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñóÿÿާþÿ:eþÿEþÿ1þÿ*þÿ-þÿ.þÿ.þÿ-þÿ*þÿ0þÿCþÿ3]þÿj‹þÿËÖþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿíòÿÿlŒÿÿ1þÿ6þÿ8þÿ7þÿ7þÿ8þÿ8ÿÿ5ýÌ5ÿ:ÿO9üô<ÿÿ:þÿ:þÿ:þÿ8þÿ BþÿÏÚÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÁþÿMþÿ3þÿ;þÿ:þÿ;þÿ7þÿOþÿ»ËÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕÞþÿ^„þÿ@þÿ/þÿ4þÿ9þÿ:þÿ:þÿ:þÿ9þÿ9þÿ9þÿ8þÿ4þÿ.þÿ6þÿ/]þÿ‹¥þÿóõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàçÿÿMuÿÿ3þÿ9þÿ9þÿ9þÿ9þÿ;ÿÿ8ûý8ÿÿ<ÿ{;ü÷=ÿÿ<þÿ<þÿ<þÿ;þÿ9hþÿæìÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿcˆþÿ<þÿ:þÿ<þÿ<þÿ<þÿ2þÿx™ÿÿõøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒÝþÿOyþÿ6þÿ5þÿ<þÿ=þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ<þÿ9þÿ2þÿ Aþÿf‹þÿàçÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÅÓÿÿ!Sþÿ9þÿ;þÿ;þÿ;þÿ<þÿ=ÿÿ9üÝ;ÿ'=ý¢?ûý@ÿÿ?þÿ?þÿ=þÿ?þÿkÿÿðôÿÿÿÿÿÿÿÿÿÿÿÿÿÿñôÿÿ7gþÿ5þÿ>þÿ>þÿ>þÿ;þÿMþÿ¾Îÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêïÿÿc‰þÿ8þÿ9þÿ?þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ>þÿ?þÿ>þÿ7þÿ:þÿ[„þÿàèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ‘¬ÿÿ=þÿ<þÿ>þÿ>þÿ>þÿ@ÿÿ>üþ>ýˆÿAþ¿BÿÿBÿÿAþÿAþÿ?þÿBþÿ•°ÿÿúüÿÿÿÿÿÿÿÿÿÿÿÿÿÿÉ×ÿÿ#[þÿ9þÿAþÿAþÿAþÿ:þÿUÿÿäëÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ”°þÿ Fþÿ9þÿAþÿ@þÿ@þÿ@þÿ>þÿ:þÿ6þÿ5þÿ5þÿ7þÿ;þÿ?þÿ@þÿ@þÿ@þÿ@þÿAþÿ;þÿ=þÿeþÿñõÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿãëÿÿ>oþÿ>þÿ@þÿ@þÿ@þÿAþÿBÿÿ?üÝ<ÿBûÒDÿÿCÿÿCþÿCþÿAþÿDþÿ³Çÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢ºþÿTþÿ>þÿCþÿCþÿCþÿ9þÿŒ«ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿâêÿÿEvþÿ7þÿCþÿCþÿCþÿ>þÿ4þÿDþÿBsþÿs˜þÿƒ£ÿÿ„£ÿÿjÿÿ0fþÿ>þÿ:þÿBþÿBþÿBþÿBþÿCþÿ;þÿ Fþÿˆ¦þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ§¾ÿÿCþÿ@þÿBþÿBþÿBþÿDÿÿBûúBýhUÿEûãGÿÿEþÿEþÿEþÿBþÿFþÿÈÖÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‡¨þÿOþÿAþÿEþÿEþÿDþÿ@þÿ®Äÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ©ÁþÿYþÿ?þÿFþÿCþÿ9þÿ&aþÿ¡ÿÿ¨ÀÿÿÔàÿÿöùÿÿÿÿÿÿÿÿÿÿïóÿÿÈÖÿÿ—³ÿÿ?rÿÿ?þÿBþÿEþÿEþÿEþÿEþÿ=þÿ$_þÿÇÖþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâêÿÿ4kþÿCþÿDþÿDþÿDþÿDÿÿEýþBüÄ@ÿ FúêJÿÿHþÿHþÿHþÿEþÿIþÿÕáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿxžþÿMþÿDþÿGþÿGþÿFþÿ Oþÿ¾Ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‚¥þÿIþÿEþÿ?þÿHþÿ_Šÿÿ¿ÑÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒßÿÿbŽÿÿHþÿEþÿGþÿGþÿGþÿEþÿEþÿ\‰þÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿùûÿÿ‰ªÿÿEþÿEþÿGþÿGþÿGþÿIÿÿDûñJÿ4IûåLÿÿJþÿJþÿJþÿGþÿLþÿÙäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿtœþÿNþÿGþÿJþÿJþÿHþÿZþÿÃÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿp™þÿBþÿ=þÿ ]ÿÿЬÿÿêðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿèïÿÿ]ŒÿÿBþÿIþÿIþÿIþÿJþÿAþÿ `þÿÆ×þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÚÿÿ PþÿGþÿIþÿIþÿIþÿKÿÿHüùJÿxLúàNÿÿLÿÿLþÿLþÿIþÿNþÿÖãÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ{¢þÿ RþÿIþÿLþÿLþÿJþÿ\þÿÃÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿrœþÿ;þÿ.hÿÿ¬ÄÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËÛÿÿ+iÿÿGþÿKþÿKþÿKþÿHþÿNþÿo™þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçîÿÿ5pþÿJþÿKþÿKþÿKþÿKÿÿKüþLü¿OûÓPÿÿNÿÿNþÿNþÿLþÿOþÿÈÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ°þÿYþÿJþÿNþÿNþÿMþÿRþÿ¼Ðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€¦þÿ5nÿÿ®ÈÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿøûÿÿŠ®ÿÿFþÿMþÿNþÿNþÿNþÿFþÿ9uþÿô÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿðõÿÿnšÿÿMþÿKþÿMþÿMþÿMþÿOÿÿLûéPüºQþÿQÿÿQþÿQþÿOþÿRþÿ±Éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¬ÆÿÿbþÿJþÿPþÿPþÿPþÿHþÿ¨ÃÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÏÿÿ¹ÐÿÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÀÕÿÿ\þÿNþÿPþÿPþÿPþÿIþÿ!gþÿÈÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿûýÿÿ™¹ÿÿPþÿNþÿPþÿPþÿPþÿRÿÿPüïRýŸQüüTÿÿSþÿSþÿQþÿTþÿ‘µÿÿùûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÚæÿÿ'mþÿJþÿSþÿSþÿSþÿJþÿ}§ÿÿõøÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ùÿÿþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿûüÿÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿØäÿÿAÿÿNþÿRþÿRþÿRþÿMþÿ`þÿ›¼þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿºÐÿÿTþÿPþÿRþÿRþÿRþÿTÿÿPüíVÿ}UüøVÿÿUþÿUþÿSþÿTþÿf™ÿÿïôÿÿÿÿÿÿÿÿÿÿÿÿÿÿûýÿÿF„þÿOþÿTþÿUþÿUþÿQþÿ9{ÿÿØåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑàÿÿœ½ÿÿéðÿÿÿÿÿÿÿÿÿÿÿÿÿÿæîÿÿ_“ÿÿNþÿTþÿTþÿTþÿPþÿ Zþÿ~¨þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑàÿÿVþÿQþÿTþÿTþÿTþÿVÿÿRüíVÿPWüóYÿÿWþÿWþÿVþÿUþÿ0wþÿåîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆ±þÿ _þÿSþÿWþÿWþÿVþÿXþÿ¡ÁÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿçïÿÿSÿÿ:}þÿÖäÿÿÿÿÿÿÿÿÿÿÿÿÿÿìóÿÿjÿÿPþÿVþÿVþÿVþÿTþÿYþÿjœþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÛçÿÿ ]þÿSþÿVþÿVþÿVþÿXÿÿVüíZÿ"Xúì\ÿÿYþÿYþÿYþÿWþÿ^þÿÃÙÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜéÿÿ-vþÿQþÿYþÿYþÿYþÿRþÿ;€ÿÿÙæÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿßêÿÿb™ÿÿQþÿ9þÿÛèÿÿÿÿÿÿÿÿÿÿÿÿÿÿëòÿÿhœÿÿSþÿYþÿYþÿYþÿWþÿZþÿb™þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÞéÿÿeþÿWþÿXþÿXþÿXþÿ[ÿÿXüífÿ XüÇ]ýþ\ÿÿ\þÿ\þÿZþÿZþÿ~¬ÿÿ÷úÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿzªþÿ^þÿWþÿ\þÿ[þÿ[þÿWþÿd›ÿÿêòÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¿×ÿÿOÿÿXþÿKþÿNŽþÿó÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿáìÿÿV’ÿÿVþÿ[þÿ[þÿ[þÿYþÿ\þÿeœþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÝéÿÿ dþÿYþÿ[þÿ[þÿ[þÿ^ÿÿ[üífÿ_ý„]üù_ÿÿ^þÿ^þÿ]þÿ\þÿ*xþÿÜèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàëÿÿ<„þÿXþÿ]þÿ^þÿ^þÿ\þÿ_þÿdÿÿÓäÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÑâÿÿ‡³ÿÿ)wÿÿTþÿ[þÿYþÿt§þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÒâÿÿ4þÿYþÿ]þÿ]þÿ]þÿZþÿaþÿr¥þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙçÿÿ`þÿZþÿ]þÿ]þÿ]þÿ`ÿÿ]üíÿbÿ<`ûñcÿÿ`þÿ`þÿ`þÿ^þÿ]þÿ˜¿ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ®ÌþÿoþÿYþÿ`þÿ`þÿ`þÿ]þÿ[þÿBˆÿÿ—¾ÿÿÏáÿÿøúÿÿÿÿÿÿüýÿÿäîÿÿ´Ðÿÿ‹·ÿÿ?‡ÿÿZþÿYþÿ`þÿWþÿ"vþÿ½Õþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹Óÿÿeþÿ]þÿ_þÿ_þÿ_þÿ\þÿhþÿеþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÈÜÿÿ`þÿ\þÿ_þÿ_þÿ_þÿbÿÿ]üímíbýÌdýþbþÿbþÿbþÿbþÿaþÿ/€þÿÚèÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‘»þÿiþÿ[þÿaþÿbþÿbþÿaþÿZþÿ_þÿ;†þÿr¨ÿÿ°ÿÿy¬ÿÿW—þÿoþÿWþÿ[þÿaþÿbþÿ_þÿ]þÿp§þÿøûÿÿÿÿÿÿÿÿÿÿÿÿÿÿùûÿÿ‰·ÿÿYþÿaþÿbþÿbþÿbþÿ]þÿrþÿ¬Ìþÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ­Ìÿÿbþÿ_þÿaþÿaþÿaþÿdÿÿ_üíUªeýwdüùgÿÿeþÿeþÿeþÿdþÿ`þÿy®ÿÿùûÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþÿÿºþÿoþÿ\þÿbþÿdþÿdþÿdþÿcþÿ_þÿZþÿYþÿZþÿ\þÿaþÿdþÿdþÿdþÿaþÿ]þÿGþÿÔäþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿØçÿÿ9‡ÿÿ_þÿdþÿdþÿdþÿdþÿ\þÿ(|þÿÜêÿÿÿÿÿÿÿÿÿÿÿÿÿÿ÷ûÿÿ‰·ÿÿeþÿbþÿdþÿdþÿdþÿgÿÿdüígÿ%füâjÿÿgþÿgþÿgþÿgþÿeþÿpþÿ°Ïÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ Æþÿ3…þÿcþÿ_þÿfþÿgþÿgþÿgþÿfþÿfþÿfþÿfþÿfþÿfþÿfþÿ_þÿcþÿG‘þÿÆÝþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ˜Áÿÿcþÿeþÿfþÿfþÿfþÿeþÿ`þÿGþÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿÿZ›þÿeþÿeþÿfþÿfþÿfþÿiÿÿfüíÿiý—hýýkÿÿiþÿiþÿiþÿhþÿeþÿ5‡þÿÍáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿËáþÿg¥þÿ'}þÿeþÿ`þÿdþÿfþÿgþÿhþÿhþÿgþÿeþÿaþÿbþÿwþÿj§þÿØèþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÐäÿÿ5‡ÿÿcþÿhþÿhþÿhþÿhþÿdþÿ pþÿ‰¹þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàíÿÿ&þÿfþÿgþÿhþÿhþÿhþÿkÿÿhüíjÿ0kúánÿÿkþÿkþÿkþÿkþÿjþÿeþÿN˜ÿÿ×éÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¹Öþÿi¨þÿ=þÿ|þÿ qþÿhþÿdþÿfþÿlþÿvþÿ0…þÿXžþÿ«Îþÿüýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿïöÿÿd¦ÿÿdþÿjþÿkþÿkþÿkþÿkþÿdþÿ*„þÿØéÿÿÿÿÿÿÿÿÿÿÿÿÿÿþÿÿÿ¼ØÿÿkþÿhþÿjþÿjþÿjþÿjþÿmÿÿküínýmüþpÿÿnþÿnþÿnþÿnþÿmþÿgþÿSœÿÿÑåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿáîÿÿ«Ïþÿ‡ºþÿmªþÿ_¤þÿe§þÿx±þÿ˜ÃþÿÊáÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòøÿÿ|µÿÿnþÿkþÿmþÿmþÿmþÿmþÿjþÿmþÿl«þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿôùÿÿq®ÿÿlþÿlþÿmþÿmþÿmþÿmþÿpÿÿküïuÿ%mýÔrÿÿpþÿpþÿpþÿpþÿpþÿoþÿiþÿD•ÿÿ·×ÿÿûýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿìôÿÿ~·ÿÿ tþÿkþÿoþÿoþÿnþÿjþÿkþÿiþÿ.‰þÿÒåÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÙêÿÿ#‚þÿmþÿnþÿoþÿoþÿoþÿoþÿrÿÿoüérÿgpûôuÿÿqþÿrþÿrþÿrþÿrþÿqþÿlþÿþÿÁÿÿáîÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÕèÿÿj¬ÿÿsþÿoþÿqþÿqþÿpþÿsþÿ~þÿtþÿtþÿ¿þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ•ÄÿÿnþÿoþÿqþÿqþÿqþÿqþÿqÿÿrýþnüÂ`ÿtü«vÿÿuÿÿtþÿtþÿtþÿtþÿtþÿtþÿqþÿsþÿR ÿÿ²Õÿÿãðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿâïÿÿ§Ïÿÿ:“ÿÿoþÿrþÿtþÿtþÿtþÿmþÿ%ˆþÿ—Æþÿn°þÿb©þÿóøÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÜìÿÿ0þÿrþÿrþÿsþÿsþÿsþÿsþÿuÿÿsüúrýyxÿ1výÓzÿÿwþÿwþÿwþÿwþÿwþÿwþÿvþÿuþÿpþÿ {þÿW¤ÿÿ©ÒÿÿÑæÿÿëôÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿð÷ÿÿÔèÿÿ«ÑÿÿT¢ÿÿxþÿqþÿuþÿuþÿuþÿvþÿsþÿ vþÿp²þÿÿÿÿÿï÷ÿÿåñÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüýÿÿ‰Àÿÿsþÿuþÿvþÿvþÿvþÿvþÿvþÿyÿÿuüéwÿ/xÿ[wûê|ÿÿyþÿxþÿxþÿxþÿxþÿyþÿyþÿxþÿwþÿtþÿvþÿ+þÿh°ÿÿ›Êÿÿ¼ÜÿÿÊãÿÿÒçÿÿÔèÿÿÒèÿÿÍåÿÿÃàÿÿ§Ñÿÿt¶ÿÿ2“þÿwþÿsþÿwþÿxþÿxþÿxþÿxþÿxþÿqþÿ7”þÿÙëÿÿÿÿÿÿÿÿÿÿýÿÿÿýþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÃßÿÿ…þÿvþÿxþÿxþÿwþÿwþÿwþÿyÿÿxÿÿwüª’ÿ|û„xûù~ÿÿ{þÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿzþÿxþÿwþÿuþÿxþÿ…þÿ)þÿ-’þÿ)þÿŠþÿ|þÿuþÿwþÿxþÿzþÿzþÿzþÿ{þÿ{þÿ{þÿ{þÿvþÿ €þÿ‰ÁþÿþþÿÿÿÿÿÿÿÿÿÿþþÿÿúüÿÿþÿÿÿÿÿÿÿÝíÿÿO¤ÿÿvþÿyþÿyþÿyþÿyþÿyþÿzþÿ|ÿÿwûï|ÿHÿŽÿ {ü—~ýú€ÿÿ}þÿ}þÿ}þÿ}þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ{þÿ{þÿ{þÿzþÿ{þÿ{þÿ{þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿ|þÿwþÿP¥þÿôùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿýþÿÿõúÿÿ†Áÿÿyþÿ{þÿ}þÿ|þÿ|þÿ|þÿ|þÿ}ÿÿ}ÿÿzû«’ÿ€ÿ€ý¢‚ýýƒÿÿ€þÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿþÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿyþÿ!þÿ«ÕþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿëõÿÿÀþÿ„þÿ}þÿ~þÿ~þÿ~þÿ~þÿþÿ‚ÿÿ~ûä}ÿ7„ÿú¨ƒüû…ÿÿ‚ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ€ÿÿ}ÿÿb±ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿüþÿÿ¿ßÿÿ/˜ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿ€ÿÿƒÿÿ€ýùý€ÿ€ÿüž…üù‡ÿÿ„ÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿƒÿÿ‚ÿÿ„ÿÿn¹ÿÿúýÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿòùÿÿÇäÿÿšÎÿÿ; ÿÿƒÿÿƒÿÿƒÿÿƒÿÿ‚ÿÿ…ÿÿ…ÿÿ€ü²ˆÿ’ÿ…ý’„üòŠÿÿ‡ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿƒÿÿ‚ÿÿÿÿ€ÿÿ‚ÿÿ]±ÿÿåóÿÿùýÿÿÿÿÿÿÿÿÿÿàðÿÿ¼àÿÿƒÄÿÿ“ÿÿƒÿÿ„ÿÿ…ÿÿ…ÿÿ…ÿÿ…ÿÿ†ÿÿˆÿÿ‚ýÌ‚ÿ+€ÿ‰ýu‰üáŒÿÿŠÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‰ÿÿ‘ÿÿ•ÿÿ •ÿÿ%–ÿÿg¸ÿÿËçÿÿ³Ûÿÿ¬ØÿÿÕëÿÿ©ÖÿÿL«ÿÿ‰ÿÿ…ÿÿ†ÿÿ†ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‰ÿÿŒÿÿ†ýÔ‡ÿ@‹üMˆüÈüûŽÿÿ‹ÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿŠÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ†ÿÿ•ÿÿxÁÿÿ«Øÿÿ¦ÖÿÿÓêÿÿëöÿÿs¾ÿÿ‰ÿÿ’ÿÿ&›ÿÿˆÿÿˆÿÿˆÿÿˆÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‰ÿÿ‹ÿÿŽÿÿ‰ýÔˆÿGŠÿ#Šý™‹üìÿÿÿÿÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŒÿÿŠÿÿ•ÿÿV³ÿÿsÀÿÿ]¶ÿÿµÝÿÿ´Ýÿÿ‰ÿÿŠÿÿ‹ÿÿŠÿÿŠÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿŒÿÿÿÿýþ‰üÆŒÿ<€ÿÿTŽüÇýó‘ÿÿ‘ÿÿÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿÿÿÿÿ”ÿÿ‘Îÿÿ–Ñÿÿ†ÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿŽÿÿÿÿ’ÿÿŽýóŽþ­Šÿ%ŒÿÿqŒýÔýõ“ÿÿ”ÿÿ‘ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹ÿÿžÿÿ’ÐÿÿsÁÿÿ‹ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’ÿÿ”ÿÿ’ýûüÜýs€ê €ÿ™ÿ”ÿw‘ýÒ“ÿð“ÿÿ—ÿÿ–ÿÿ”ÿÿ“ÿÿ“ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿÿÿœÿÿP´ÿÿ7ªÿÿÿÿ’ÿÿ’ÿÿ’ÿÿ’ÿÿ“ÿÿ•ÿÿ–ÿÿ”ýûüç‘ýœ•ÿ0€ÿªÿ”ÿ˜ÿW“þµ”üè–ýô”ýþ™ÿÿ™ÿÿ˜ÿÿ—ÿÿ–ÿÿ–ÿÿ–ÿÿ•ÿÿ•ÿÿ•ÿÿ–ÿÿ–ÿÿ–ÿÿ—ÿÿ˜ÿÿ™ÿÿ˜ÿÿ”þÿ•ýó’úâ“ýš”ÿ7™ÿÿÿŽÿ šÿ&—ýi˜ü¯–üà˜ýï•ýõ•ýú–ýþ™ÿÿšÿÿ›ÿÿœÿÿ›ÿÿ™ÿÿ™ÿÿ˜ÿÿ—ýû•ý÷™ÿð—úâ—þ°–ÿd‘ÿªÿªÿ™æ ™ÿ›ÿ8™ÿi—ýŽšþ«—üÇ—ûØ—üá—üê•ýè˜ûÚ™ýΘþ¹™ý˜›ÿu˜ÿE›ÿ™ÿ €ÿ( @ ÿüdýŸüÁþþÿÿÿÿÿÿ¢¦ûíþº ýšüW ÿÿ,þ«úûýÿýÿuþÿÿÿÿÿÿÿÿÿ‰þÿýÿýÿýÿúüüÀüJÿÿý‡úûýÿýÿ>Pýÿ½Ãþÿÿÿÿÿÿÿÿÿúúÿÿ&:ýÿýÿýÿýÿýÿýÿýÿýÍüKÿ þºýÿýÿýÿbsþÿýýÿÿÿÿÿÿÿÿÿÿúûÿÿ\nþÿýÿýÿýÿýÿýÿýÿýÿýÿýÿý¦ ÿ+ÿþ»!ýÿ!ýÿ!ýÿŠ™þÿÿÿÿÿÿÿÿÿôöÿÿÈÏÿÿ0Jýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿ ýÿüÛÿ+%ý‹%ýÿ%ýÿ%ýÿp…þÿÿÿÿÿÿÿÿÿúûÿÿs‡þÿ(ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ%ýÿ$ýÿ$ýÿ$úí"ÿ5+ÿ0*úý*ýÿ*ýÿ>^ýÿüüÿÿÿÿÿÿõ÷ÿÿ@_ýÿ)ýÿ)ýÿ)ýÿ)ýÿ$Gýÿyþÿ¥³þÿ»Æþÿ¯¼þÿ¢þÿPlþÿ 1ýÿ)ýÿ)ýÿ)ýÿ)ýÿ)úð'ÿ..þ¶.þÿ.þÿ0þÿÌÕÿÿÿÿÿÿþþÿÿXvþÿ.þÿ.þÿ.þÿCþÿ²Àÿÿþþÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿêîÿÿ{’þÿ3þÿ-þÿ-þÿ-þÿ*üÞ$ÿ3ÿ#3ûþ3þÿ3þÿXyþÿÿÿÿÿÿÿÿÿ¤¶ÿÿ2þÿ2þÿ2þÿ8_þÿìðÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÍ×ÿÿ#Nþÿ2þÿ2þÿ2þÿ2ýž7ÿt7þÿ7þÿ7þÿ·ÇÿÿÿÿÿÿúûÿÿOþÿ7þÿ7þÿOþÿèíÿÿÿÿÿÿÿÿÿÿÓÜÿÿ`‚þÿKþÿ6þÿ =þÿ;eþÿ§ÿÿóöÿÿÿÿÿÿÿÿÿÿàçÿÿJþÿ6þÿ6þÿ6þÿ7ÿO:þ³<þÿ;þÿIþÿúûÿÿÿÿÿÿ¸Èÿÿ;þÿ;þÿ;þÿ¯Âÿÿÿÿÿÿÿÿÿÿ¡·ÿÿ@þÿ;þÿ;þÿ;þÿ;þÿ;þÿ;þÿPþÿÀÏÿÿÿÿÿÿÿÿÿÿÎÙÿÿ@þÿ;þÿ:þÿ:üÛUÿ@üÞ@þÿ@þÿCrþÿÿÿÿÿÿÿÿÿjþÿ@þÿ@þÿ(^þÿýýÿÿÿÿÿÿÇÕÿÿCþÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ?þÿ FþÿÅÓÿÿÿÿÿÿÿÿÿÿs–þÿ?þÿ?þÿ?þÿAÿSAûõDþÿDþÿgþÿÿÿÿÿÿÿÿÿAtþÿDþÿDþÿj’þÿÿÿÿÿÿÿÿÿM|þÿDþÿDþÿ7lþÿ­ÂþÿÑÝÿÿÂÒÿÿHyþÿDþÿDþÿDþÿTþÿðôÿÿÿÿÿÿîòÿÿNþÿCþÿCþÿDüÈIûøIþÿIþÿ|¡þÿÿÿÿÿÿÿÿÿ)fþÿIþÿIþÿ°ÿÿÿÿÿÿÿÿÿÿWþÿ Qþÿ¥¿ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿˆªÿÿHþÿHþÿHþÿxžþÿÿÿÿÿÿÿÿÿ\ŠþÿHþÿHþÿHþÿFÿ!MûçMþÿMþÿošþÿÿÿÿÿÿÿÿÿ6sþÿMþÿMþÿ‰­ÿÿÿÿÿÿÿÿÿÿ#eþÿÁÔÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿýþÿÿ8sþÿLþÿLþÿ^þÿýþÿÿÿÿÿÿªÃÿÿLþÿLþÿLþÿMÿcRýÓRþÿRþÿ\þÿÿÿÿÿÿÿÿÿYŽþÿQþÿQþÿh˜þÿÿÿÿÿÿÿÿÿËÜÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿþþÿÿÿÿÿÿœ»ÿÿQþÿQþÿQþÿÏÞÿÿÿÿÿÿÛæÿÿQþÿQþÿQþÿOý§Vþ®VþÿVþÿ"mþÿÿÿÿÿÿÿÿÿž¿ÿÿVþÿVþÿcþÿöùÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ³ÿÿãìÿÿÿÿÿÿÂÖÿÿUþÿUþÿUþÿ­ÈÿÿÿÿÿÿöùÿÿUþÿUþÿUþÿSýÏ\ÿl[þÿ[þÿZþÿÜèÿÿÿÿÿÿó÷ÿÿjþÿZþÿZþÿz©þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ’¹ÿÿ[þÿçïÿÿÿÿÿÿ»ÓÿÿZþÿZþÿZþÿŸÁÿÿÿÿÿÿþþÿÿ]þÿYþÿYþÿWúàaÿ*_þÿ_þÿ_þÿr§þÿÿÿÿÿÿÿÿÿžÂÿÿ_þÿ_þÿ_þÿ€¯þÿýþÿÿÿÿÿÿÿÿÿÿßëÿÿG‹þÿ^þÿ*yþÿÿÿÿÿÿÿÿÿ—½ÿÿ^þÿ^þÿ^þÿ²Îÿÿÿÿÿÿðöÿÿ^þÿ^þÿ^þÿ[ûòÿaýÔcþÿcþÿhþÿáíÿÿÿÿÿÿÿÿÿÿn¦þÿcþÿcþÿcþÿeþÿ({þÿlþÿcþÿcþÿdþÿ±ÏÿÿÿÿÿÿÿÿÿÿA‹þÿcþÿcþÿcþÿÛéÿÿÿÿÿÿÖæÿÿbþÿbþÿbþÿ_ûóiÿ_hþÿhþÿhþÿH“þÿüýÿÿÿÿÿÿÿÿÿÿ•Àÿÿqþÿhþÿgþÿgþÿgþÿgþÿ mþÿŸÆÿÿÿÿÿÿÿÿÿÿÌáÿÿhþÿgþÿgþÿ zþÿÿÿÿÿÿÿÿÿšÃÿÿgþÿgþÿgþÿgüÜfÿkúálþÿlþÿlþÿj©þÿþþÿÿÿÿÿÿÿÿÿÿíõÿÿ“ÁÿÿQ›þÿ8ŒþÿG•þÿ€¶þÿâîÿÿÿÿÿÿÿÿÿÿîõÿÿ#€þÿlþÿlþÿkþÿ‡¹ÿÿÿÿÿÿÿÿÿÿVþÿkþÿkþÿkþÿiþ³pÿ]qþÿqþÿqþÿqþÿNœþÿð÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿàîÿÿ7þÿpþÿpþÿpþÿ~þÿñ÷ÿÿÿÿÿÿåðÿÿtþÿpþÿpþÿpþÿoÿwtþ­uþÿuþÿuþÿuþÿ€þÿŽÂÿÿñ÷ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿñ÷ÿÿ“Åÿÿ~þÿuþÿtþÿ yþÿÇàÿÿÉáÿÿÿÿÿÿÿÿÿÿs³þÿtþÿtþÿtþÿtûþvÿ'yÿ{ûçyþÿyþÿyþÿyþÿyþÿ|þÿ@›þÿl²þÿ€¼þÿq´þÿJ þÿ þÿyþÿyþÿyþÿyþÿŽÃþÿÿÿÿÿêôÿÿÿÿÿÿÌäÿÿ|þÿyþÿyþÿyþÿwþ¼}ÿ5~ûô~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ~þÿ}þÿ}þÿ}þÿ}þÿ"ŽþÿäñÿÿÿÿÿÿÿÿÿÿèóÿÿP¥þÿ}þÿ}þÿ}þÿ}þÿ{ÿ<ƒÿD‚üó‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿ‚ÿÿŸÐÿÿÿÿÿÿÿÿÿÿýþÿÿÑéÿÿsºÿÿ‚ÿÿ‚ÿÿÿÿý–‰ÿ6…üå‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ‡ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿ†ÿÿŠÿÿœÐÿÿÓêÿÿ¼ßÿÿi¸ÿÿˆÿÿ†ÿÿ†ÿÿ†ÿÿ‡üÇŽÿ ÿ‹þ»‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ‹ÿÿ%œÿÿ‘ÍÿÿÊæÿÿ3¢ÿÿŽÿÿ‹ÿÿ‹ÿÿ‹ÿÿŠÿÿŠÿÿŠüÇŽÿÿÿ‘ÿaŽüÞÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ‹ÌÿÿÿÿÿÿÿÿÿÿÿÿŒüþý˜Žÿ €ÿ”ÿ_’ýÔ”ÿÿ”ÿÿ”ÿÿ”ÿÿ”ÿÿ”ÿÿ$£ÿÿ”ÿÿ“ÿÿ“ÿÿ“ÿÿ“þ½“ÿ;•ÿ$—ÿl˜þ°™ýÑ•üæ˜üû˜üé™ýÑ–þ²˜ÿwšÿ&(0 ÿù\ýš&2üÅùùýîÜÞûì$1üÉý¢ÿeÿ1ÿýiýÐÿÿ9Eÿÿ²¸ÿÿÿÿÿÿ¸¿ÿÿ ÿÿÿÿÿÿüðý ûBÿýÿÿÿÿl{ÿÿìïÿÿÿÿÿÿÚÞÿÿ;Oýÿýÿýÿþÿÿÿÿÿüîûÿÿ "ýŸÿÿ ÿÿƒ“þÿÿÿÿÿÿÿÿÿ¡®þÿ)Cýÿýÿýÿýÿýÿýÿýÿ!ÿÿ"ÿÿ þ¾ø&&ýk'üý ÿÿg~ýÿüüÿÿñóÿÿgþÿ#ýÿýÿ#ýÿ-MýÿTnýÿ[týÿGcýÿ<ýÿýÿ!ÿÿ'ÿÿ'ýÐ&ÿ(1ÿ+ûÙ'ÿÿ&Nþÿèìÿÿÿÿÿÿeþÿþÿ!þÿ5Xþÿ­»þÿéíÿÿÿÿÿÿÿÿÿÿþþÿÿÙàÿÿŽ¡þÿEþÿ$ÿÿ.ÿÿ*üÄÿ3ÿd4ÿÿ1ÿÿˆ þÿÿÿÿÿ£µÿÿ1þÿ&þÿMpþÿçìÿÿÿÿÿÿïóÿÿÇÒÿÿÀÌÿÿÒÜÿÿÿÿÿÿÿÿÿÿÓÜÿÿ@eþÿ*ÿÿ5ÿÿ1ýŒÿ8ý¨7ÿÿFþÿÝåÿÿøúÿÿ;gþÿ&þÿ(Xþÿâêÿÿÿÿÿÿ¤¹ÿÿ4\þÿ2þÿ)þÿ @þÿMsþÿ»Ëþÿÿÿÿÿáèÿÿ1^þÿ1ÿÿ8ýó8ÿD>ûÕ;ÿÿ8iþÿÿÿÿÿÈÖÿÿKþÿ2þÿŒ¨þÿÿÿÿÿ¯Ãÿÿ;þÿ,þÿCþÿ Gþÿ9þÿ,þÿFþÿ¬Àÿÿÿÿÿÿ·ÉÿÿEþÿ=ÿÿ>ú¨UÕBúê@ÿÿ[‡þÿÿÿÿÿ¢»ÿÿ>þÿOþÿÅÕÿÿþþÿÿ3jþÿ@þÿ^‰þÿ»ÍþÿÓßÿÿ…¦þÿSþÿ7þÿWþÿÙãÿÿÿÿÿÿOþÿ=ÿÿDüòCú5KùæFÿÿbþÿÿÿÿÿ›¸ÿÿ@þÿ]þÿ×âÿÿõ÷ÿÿ+iþÿš¸ÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¢¾ÿÿJþÿ@þÿo™þÿÿÿÿÿžºÿÿKÿÿLÿÿIýpQýÔNÿÿP‡þÿÿÿÿÿ±ÊÿÿPþÿ WþÿÀÓþÿüýÿÿÁÕÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿþþÿÿó÷ÿÿ?|ÿÿ?þÿ3sþÿùûÿÿ×äÿÿ YþÿOÿÿPþ­Vþ±Uÿÿ#nþÿøúÿÿäíÿÿ"nþÿFþÿv¦þÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿÿ¦Äÿÿ¾Ôÿÿÿÿÿÿc—ÿÿDþÿ"mþÿâìÿÿôøÿÿbþÿTÿÿQýÑ]ýv_ÿÿ_ÿÿ¶Ñþÿÿÿÿÿ~­ÿÿQþÿdþÿ©Éþÿÿÿÿÿÿÿÿÿûüÿÿ”»þÿeþÿµÐÿÿÿÿÿÿU’ÿÿLþÿ"rþÿàëÿÿôøÿÿhþÿZÿÿYúâaû:büö^ÿÿGþÿÿÿÿÿôøÿÿO”þÿUþÿdþÿFŽþÿR•þÿ1þÿVþÿBŠþÿøûÿÿåïÿÿ!vþÿUþÿ0€þÿúüÿÿÛéÿÿ jþÿaÿÿ_úèqÿ fü¬mÿÿgþÿ½þÿÿÿÿÿñ÷ÿÿw®ÿÿvþÿbþÿ`þÿhþÿQ—þÿßìÿÿÿÿÿÿ‚µÿÿaþÿaþÿb¢þÿÿÿÿÿ¦ÊÿÿjþÿhÿÿgýÔnûHoýômÿÿtþÿ’Âþÿÿÿÿÿÿÿÿÿàîÿÿ«Ïÿÿ¡ÉÿÿÆßÿÿÿÿÿÿÿÿÿÿ¥Ìþÿ rþÿdþÿrþÿÇßÿÿÿÿÿÿ]£þÿhþÿqÿÿmý©ªÿrý“zÿÿqÿÿtþÿX¤þÿÇàÿÿüþÿÿÿÿÿÿÿÿÿÿÿÿÿÿàîÿÿt´ÿÿ xþÿjþÿQžþÿ±ÓÿÿÿÿÿÿÏåÿÿþÿnÿÿyÿÿtýgózüÈ‚ÿÿwÿÿuþÿ ~þÿ3•þÿ^¬þÿe¯þÿFŸþÿ…þÿvþÿqþÿ‰þÿÙëþÿÿÿÿÿóùÿÿV§ÿÿrþÿÿÿwüÞxÿ ‚ù+ûÕˆÿÿ€ÿÿ}þÿ|þÿ{þÿ{þÿ|þÿ|þÿ|þÿ|ÿÿ„ÂÿÿÿÿÿÿÿÿÿÿÍæÿÿ'’þÿ}ÿÿ„ÿÿ~ýs…ÿ,‡üÄÿÿŠÿÿ†ÿÿ†ÿÿ…ÿÿ…ÿÿ…ÿÿ ‰ÿÿ“ÿÿ§ÖÿÿÑéÿÿ‘Ëÿÿ6ŸÿÿŽÿÿŒÿÿ„ý¨™ÿ ÿŠý™ýô•ÿÿŽÿÿŒÿÿ‹ÿÿŒÿÿ>¨ÿÿžÓÿÿ4£ÿÿ ÿÿ‹ÿÿŒÿÿŽÿÿŠý¦ŒÿüL’ý¨’üøšÿÿ—ÿÿ–ÿÿ”ÿÿ;°ÿÿ™ÿÿ“ÿÿ—ÿÿ”ýÙŽýsŽÿ ™ÿ”ÿ9™ÿq–þ²—ýÓ–üç•üä—ýΕý©™ÿf•ÿ$(  ÿÿÿ* ýmîïý“cmýƒüU#ÿÿÿÿ1ÿ üª üû‘šþÿþþþþ4Eüþüÿüîý• ÿÿ1ÿúá6ýÿßãýýô÷ýüG\üûûûûý ûþüÿ ûí'ûHUÿ'þ¶+ýÿÝâýøÆÒýþ#ýÿ!üþl„üþ§³ýþœªýýKiüú!üþ$üý0üPUÿAÿC$ýÿvýýöùýþ 3üþ DþÿåëþÿúûÿÿÁÎþÿÏÙýþÿÿÿÿÅÐýü;þÿ-üñ>ÿ%>ýˆ4ýÿ×àýü”ªýþ$ýÿÏÚþÿÉ×þÿ4ýÿ"ýÿ"ýÿ RýþáêþÿÄÒýú6ýÿ;ý¨Aý¨Jþÿ÷ùýüRýþTþÿÿÿÿÿ0aþÿIxþÿ¼Îþÿœ¸þÿ Býÿ UýþþþþþW‚þÿ7üöUÿ-Mý RþÿôøýüXˆýþ_þÿöøþÿ´Ëþÿÿÿÿÿûüþÿÿÿÿÿœ»þÿ5ýÿ¾Ïýþ°ÉýüAýÿ Tÿt\ÿtOýÿÈÚýü­ÈýþCýÿ»Òþÿÿÿÿÿÿÿÿÿ¶Ïþÿ¡ÂþÿÐàþÿBýÿ—·ýþÏßýüNýÿYý lÿ-XüöNþÿþþþþKŒýþWýÿWšþÿGþÿ\ýÿÔãþÿ¢ÆþÿIýÿ­Êýþ¿ÖýüVýÿdý¨mý¨dýÿ‰ºýúÿÿÿÿ¡Æýþ@ŽþÿN–þÿÔåþÿíõþÿuþÿdýÿïöýþy°ýü_ýÿoýˆuÿ%uýñmýÿQ¡ýüÕéþÿúýýþùýþÿ´Øþÿþÿ{þÿºÙýþêóýþ}üýqýÿvÿCUÿ|ÿP€ýývýþvýú ‚ýýýþtýþoýþ¬Ôþÿþþþþ¼ýøtþÿ€þ¶Uÿ‡ÿHˆþí‰ÿÿ…þþ…þý ŒþûN©þû–ÎýüZ²ýý‹ÿÿ…þá„ÿªÿŠÿý”ýî‘þÿýþ:ªýþ þÿ†þúþª“ÿÿÿ€ÿÿÿ—ÿ–ÿU—ÿ€ÿˆ™ÿl¤ÿ*ÿÿÿ././@LongLink0000000000000000000000000000015100000000000011212 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.svgastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo0000644000077000000240000001103212544425160034673 0ustar adamstaff00000000000000 ././@LongLink0000000000000000000000000000015400000000000011215 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo_32.pngastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo0000644000077000000240000000353412354456432034710 0ustar adamstaff00000000000000‰PNG  IHDR szzôsBIT|dˆ pHYsÓÇòŽtEXtSoftwarewww.inkscape.org›î<ÙIDATX…Å—PT×Ç?÷ñc‘P° ˆ „FƒUBìȘ&Ådi”I# ±ÒÄJhC2æÇŒ5ÑÔtw:íÛª5ÑÒSÒÆª©é„Ú¡%¨ZÉF2Vk­JFŒ`ÁŠ(JdÙ÷öÝþqaß., É?½3gæ½sÏïýžûΞº®óÿ\Ñ_ÄÉ•ìÎ#šÅHŠl ø2pèZ€Ý8ØãéÔ¯KL”Wš;†AC°È‹h4¥z>ÕÀ$?ñôé—#¹hJ~‹»œ›´`;&y˜#D²ËÂß b0¨Â¤Åu‹»2RìqKàJr'âã7˜<6.´;`Îã2Ò‹@‹†Ž&°Ìa‹$`›+Æâ1ôWB]Ç, w.rÆM¶|»r€Þh?G6B—m"ù‘GêÕïKàƒ…“œ0º#Ñ&¢: WBÅaˆË°mL6¸pÏ€+àΔƒx¥Áti@D1Çä;«áz§ v³ú7zCýrׇóE9ÎÐäš ‹,“é_Gÿ±hbÞˆy•ˆ;¾Ñ Ðñ!,e÷ÙUÄ—¦AÚlˆO†„©ˆ€-^;V€¬…~ï;MçÅðKxUZùK%:Lü剜"¸ë9äžáT½rÝë†3WCúWaá8úè9ô³`p4XW·;KšxBjó«ËwÙÉ¥„Ö÷á“ýÐÚׇ.WêLDå_e5Êw`ÎDîzFíG;ßz9ì¾?@ÈghI^Ž ÄâUˆ¥›Ô³áƒÆMÈl…+çíãÇÄs%bñZˆK„»Ÿ‚Ão@ûÅ`ó!8¹ò—À¬o‚)Ô!ÔÊpu¹4W›;Uü0ˆ0×i'÷Ý@V— ë\Ð}>üÖßôÁž Èu Àôƒˆï¾ ¦übdëÇ‘‰Yáþ>rµ¡z—c0iØI,\1D‹‰ÜX §)‡Ìùׇˆ×üˆ__…Šm cáB3ì߬|f̃¹ÙI.œ²KŸ;ò“NÖ¤AqÐ!~*Üùr8Þg)ã¬BÄß…¬;!*â'#î©DÔôÁürdÓN;Ql’ à|(€Ùá Xôj®€[Ã`aPy÷ã* ÷ר—¦Ô¥h¹bâO½¶Î 9el¢­ïë 0HÆi¦a29HáReÜÝ 5*Ã@ä)}豄 ¢cU5ö»aÙIr mý0›Jú€nARÂPÊør‡j­&5â“+Þðçõ£AL:éµKðAƒÍ\îÿ´ž eà'_Œ໩âlg'ò›Èm/!7|ü¾p7z‘¯T@ß5å—0 KÕÞ¹Àg†öƒ ú@/fHN|ׯ@b bÁÃÈú8X‹lü,yf} ºÚ ®ú•ˆU; )U1·o»bSµ j€~Ú¦‚aS2!&A”8¼/‡‚û ¿Ž7ªhu¯Ž.@ùó0¿D=¿_oo nIøý/© Ió”è70è¦FÞ§¬&%ÀýÁ¶,Ô*}t â—ƒ{Ë#ÿ$'Ï@ütbÅËʾç?ÈuO„Ú j&Á¡DèºÎK î-T㎉E4| )épá,ò;·Ûí³ôˆµ¿…¨!ÊÎ7ÿ¼Èö3ˆiÙ0ý6X°“Ô¾¹ò8önðôB°ÚSjOEÑšÅNi 0ýÈÚ-ˆg<0c&”T@Ãe]· ùßKˆ» .²ó ;©Þzäæç¡³-Tû³™R[åt:iºÝy±è„·‹,, å4âÑçÝEBÛY8{Z5˜öðîFô÷A¬¦¤ƒÐK]àä?‘úÓð»upíjèLñ©,ñ<«÷…" ^?aReÁ ÀAO/¬YŽØü–±áHKCî}K7ÿÙ¼V='N†´ èhß@$.:4Á}žr½säFp"jÊw^ùÆqo?%Š…føä$¢äâþ2HÍ€÷€°O6àƒžËà75E)iנس\o™FÌ„ë*õj¬þ”î{YU†¬¢üI´¿…ܹ㠦!bò¦¦Qà©Ð[Ç¢&âX¾¶Æ])àWHTÿ]º í…ŸAÖ­Ê`Їu×W ëâXq;¤dÍúgõÚ± "20¼Ö¯Ð·k·að:µobÝ3¹u‹2pÄ!}rô¸nÒ,TjÝäN$9Là¿¡k“{rÀâAMP*a¦Öri.©išÜ[ï—ËÊÎ h“Ш™ì÷¼¨7O$éç0 Ë•Lg§$3ó3Çãÿ¼ G®ÿ.Á½8<ßÇIEND®B`‚././@LongLink0000000000000000000000000000015600000000000011217 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.cssastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-as0000644000077000000240000002744313007171661034604 0ustar adamstaff00000000000000/*! * Bootstrap v1.4.0 * * Copyright 2011 Twitter, Inc * Licensed under the Apache License v2.0 * http://www.apache.org/licenses/LICENSE-2.0 * * Heavily modified by Kyle Barbary for the AstroPy Project for use with Sphinx. */ @import url("basic.css"); body { background-color: #ffffff; margin: 0; font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: 13px; font-weight: normal; line-height: 18px; color: #404040; } /* Hyperlinks ----------------------------------------------------------------*/ a { color: #0069d6; text-decoration: none; line-height: inherit; font-weight: inherit; } a:hover { color: #00438a; text-decoration: underline; } /* Typography ----------------------------------------------------------------*/ h1,h2,h3,h4,h5,h6 { color: #404040; margin: 0.7em 0 0 0; line-height: 1.5em; } h1 { font-size: 24px; margin: 0; } h2 { font-size: 21px; line-height: 1.2em; margin: 1em 0 0.5em 0; border-bottom: 1px solid #404040; } h3 { font-size: 18px; } h4 { font-size: 16px; } h5 { font-size: 14px; } h6 { font-size: 13px; text-transform: uppercase; } p { font-size: 13px; font-weight: normal; line-height: 18px; margin-top: 0px; margin-bottom: 9px; } ul, ol { margin-left: 0; padding: 0 0 0 25px; } ul ul, ul ol, ol ol, ol ul { margin-bottom: 0; } ul { list-style: disc; } ol { list-style: decimal; } li { line-height: 18px; color: #404040; } ul.unstyled { list-style: none; margin-left: 0; } dl { margin-bottom: 18px; } dl dt, dl dd { line-height: 18px; } dl dd { margin-left: 9px; } hr { margin: 20px 0 19px; border: 0; border-bottom: 1px solid #eee; } strong { font-style: inherit; font-weight: bold; } em { font-style: italic; font-weight: inherit; line-height: inherit; } .muted { color: #bfbfbf; } address { display: block; line-height: 18px; margin-bottom: 18px; } code, pre { padding: 0 3px 2px; font-family: monospace; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; } tt { font-family: monospace; } code { padding: 1px 3px; } pre { display: block; padding: 8.5px; margin: 0 0 18px; line-height: 18px; border: 1px solid #ddd; border: 1px solid rgba(0, 0, 0, 0.12); -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; white-space: pre; word-wrap: break-word; } img { margin: 9px 0; } /* format inline code with a rounded box */ tt, code { margin: 0 2px; padding: 0 5px; border: 1px solid #ddd; border: 1px solid rgba(0, 0, 0, 0.12); border-radius: 3px; } code.xref, a code { margin: 0; padding: 0 1px 0 1px; background-color: none; border: none; } /* all code has same box background color, even in headers */ h1 tt, h2 tt, h3 tt, h4 tt, h5 tt, h6 tt, h1 code, h2 code, h3 code, h4 code, h5 code, h6 code, pre, code, tt { background-color: #f8f8f8; } /* override box for links & other sphinx-specifc stuff */ tt.xref, a tt, tt.descname, tt.descclassname { padding: 0 1px 0 1px; border: none; } /* override box for related bar at the top of the page */ .related tt { border: none; padding: 0 1px 0 1px; background-color: transparent; font-weight: bold; } th { background-color: #dddddd; } .viewcode-back { font-family: sans-serif; } div.viewcode-block:target { background-color: #f4debf; border-top: 1px solid #ac9; border-bottom: 1px solid #ac9; } table.docutils { border-spacing: 5px; border-collapse: separate; } /* Topbar --------------------------------------------------------------------*/ div.topbar { height: 40px; position: absolute; top: 0; left: 0; right: 0; z-index: 10000; padding: 0px 10px; background-color: #222; background-color: #222222; background-repeat: repeat-x; background-image: -khtml-gradient(linear, left top, left bottom, from(#333333), to(#222222)); background-image: -moz-linear-gradient(top, #333333, #222222); background-image: -ms-linear-gradient(top, #333333, #222222); background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #333333), color-stop(100%, #222222)); background-image: -webkit-linear-gradient(top, #333333, #222222); background-image: -o-linear-gradient(top, #333333, #222222); background-image: linear-gradient(top, #333333, #222222); filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#333333', endColorstr='#222222', GradientType=0); overflow: auto; } div.topbar a.brand { font-family: 'Source Sans Pro', sans-serif; font-size: 26px; color: #ffffff; font-weight: 600; text-decoration: none; float: left; display: block; height: 32px; padding: 8px 12px 0px 45px; margin-left: -10px; background: transparent url("astropy_logo_32.png") no-repeat 10px 4px; background-image: url("astropy_logo.svg"), none; background-size: 32px 32px; } #logotext1 { } #logotext2 { font-weight:200; color: #ff5000; } #logotext3 { font-weight:200; } div.topbar .brand:hover, div.topbar ul li a.homelink:hover { background-color: #333; background-color: rgba(255, 255, 255, 0.05); } div.topbar ul { font-size: 110%; list-style: none; margin: 0; padding: 0 0 0 10px; float: right; color: #bfbfbf; text-align: center; text-decoration: none; height: 100%; } div.topbar ul li { float: left; display: inline; height: 30px; margin: 5px; padding: 0px; } div.topbar ul li a { color: #bfbfbf; text-decoration: none; padding: 5px; display: block; height: auto; text-align: center; vertical-align: middle; border-radius: 4px; } div.topbar ul li a:hover { color: #ffffff; text-decoration: none; } div.topbar ul li a.homelink { width: 112px; display: block; height: 20px; padding: 5px 0px; background: transparent url("astropy_linkout_20.png") no-repeat 10px 5px; background-image: url("astropy_linkout.svg"), none; background-size: 91px 20px; } div.topbar form { text-align: left; margin: 0 0 0 5px; position: relative; filter: alpha(opacity=100); -khtml-opacity: 1; -moz-opacity: 1; opacity: 1; } div.topbar input { background-color: #444; background-color: rgba(255, 255, 255, 0.3); font-family: "Helvetica Neue", Helvetica, Arial, sans-serif; font-size: normal; font-weight: 13px; line-height: 1; padding: 4px 9px; color: #ffffff; color: rgba(255, 255, 255, 0.75); border: 1px solid #111; -webkit-border-radius: 4px; -moz-border-radius: 4px; border-radius: 4px; -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1), 0 1px 0px rgba(255, 255, 255, 0.25); -webkit-transition: none; -moz-transition: none; -ms-transition: none; -o-transition: none; transition: none; } div.topbar input:-moz-placeholder { color: #e6e6e6; } div.topbar input::-webkit-input-placeholder { color: #e6e6e6; } div.topbar input:hover { background-color: #bfbfbf; background-color: rgba(255, 255, 255, 0.5); color: #ffffff; } div.topbar input:focus, div.topbar input.focused { outline: 0; background-color: #ffffff; color: #404040; text-shadow: 0 1px 0 #ffffff; border: 0; padding: 5px 10px; -webkit-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); -moz-box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); box-shadow: 0 0 3px rgba(0, 0, 0, 0.15); } /* Relation bar (breadcrumbs, prev, next) ------------------------------------*/ div.related { height: 21px; width: auto; margin: 0 10px; position: absolute; top: 42px; clear: both; left: 0; right: 0; z-index: 10000; font-size: 100%; vertical-align: middle; background-color: #fff; border-bottom: 1px solid #bbb; } div.related ul { padding: 0; margin: 0; } /* Footer --------------------------------------------------------------------*/ footer { display: block; margin: 10px 10px 0px; padding: 10px 0 0 0; border-top: 1px solid #bbb; } .pull-right { float: right; width: 30em; text-align: right; } /* Sphinx sidebar ------------------------------------------------------------*/ div.sphinxsidebar { font-size: inherit; border-radius: 3px; background-color: #eee; border: 1px solid #bbb; word-wrap: break-word; /* overflow-wrap is the canonical name for word-wrap in the CSS3 text draft. We include it here mainly for future-proofing. */ overflow-wrap: break-word; } div.sphinxsidebarwrapper { padding: 0px 0px 0px 5px; } div.sphinxsidebar h3 { font-family: 'Trebuchet MS', sans-serif; font-size: 1.4em; font-weight: normal; margin: 5px 0px 0px 5px; padding: 0; line-height: 1.6em; } div.sphinxsidebar h4 { font-family: 'Trebuchet MS', sans-serif; font-size: 1.3em; font-weight: normal; margin: 5px 0 0 0; padding: 0; } div.sphinxsidebar p { } div.sphinxsidebar p.topless { margin: 5px 10px 10px 10px; } div.sphinxsidebar ul { margin: 0px 0px 0px 5px; padding: 0; } div.sphinxsidebar ul ul { margin-left: 15px; list-style-type: disc; } /* If showing the global TOC (toctree), color the current page differently */ div.sphinxsidebar a.current { color: #404040; } div.sphinxsidebar a.current:hover { color: #404040; } /* document, documentwrapper, body, bodywrapper ----------------------------- */ div.document { margin-top: 72px; margin-left: 10px; margin-right: 10px; } div.documentwrapper { float: left; width: 100%; } div.body { background-color: #ffffff; padding: 0 0 0px 20px; } div.bodywrapper { margin: 0 0 0 230px; max-width: 55em; } /* Header links ------------------------------------------------------------- */ a.headerlink { font-size: 0.8em; padding: 0 4px 0 4px; text-decoration: none; } a.headerlink:hover { background-color: #0069d6; color: white; text-docoration: none; } /* Admonitions and warnings ------------------------------------------------- */ /* Shared by admonitions and warnings */ div.admonition, div.warning { padding: 0px; border-radius: 3px; -moz-border-radius: 3px; -webkit-border-radius: 3px; } div.admonition p, div.warning p { margin: 0.5em 1em 0.5em 1em; padding: 0; } div.admonition pre, div.warning pre { margin: 0.4em 1em 0.4em 1em; } div.admonition p.admonition-title, div.warning p.admonition-title { margin: 0; padding: 0.1em 0 0.1em 0.5em; color: white; font-weight: bold; font-size: 1.1em; } div.admonition ul, div.admonition ol, div.warning ul, div.warning ol { margin: 0.1em 0.5em 0.5em 3em; padding: 0; } /* Admonitions only */ div.admonition { border: 1px solid #609060; background-color: #e9ffe9; } div.admonition p.admonition-title { background-color: #70A070; } /* Warnings only */ div.warning { border: 1px solid #900000; background-color: #ffe9e9; } div.warning p.admonition-title { background-color: #b04040; } /* Figures ------------------------------------------------------------------ */ .figure.align-center { clear: none; } /* This is a div for containing multiple figures side-by-side, for use with * .. container:: figures */ div.figures { border: 1px solid #CCCCCC; background-color: #F8F8F8; margin: 1em; text-align: center; } div.figures .figure { clear: none; float: none; display: inline-block; border: none; margin-left: 0.5em; margin-right: 0.5em; } .field-list th { white-space: nowrap; } table.field-list { border-spacing: 0px; margin-left: 1px; border-left: 5px solid rgb(238, 238, 238) !important; } table.field-list th.field-name { display: inline-block; padding: 1px 8px 1px 5px; white-space: nowrap; background-color: rgb(238, 238, 238); border-radius: 0 3px 3px 0; -webkit-border-radius: 0 3px 3px 0; } ././@LongLink0000000000000000000000000000014600000000000011216 Lustar 00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/copybutton.jsastroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/copybutton.j0000644000077000000240000000532113116602220034602 0ustar adamstaff00000000000000$(document).ready(function() { /* Add a [>>>] button on the top-right corner of code samples to hide * the >>> and ... prompts and the output and thus make the code * copyable. */ var div = $('.highlight-python .highlight,' + '.highlight-python3 .highlight,' + '.highlight-default .highlight') var pre = div.find('pre'); // get the styles from the current theme pre.parent().parent().css('position', 'relative'); var hide_text = 'Hide the prompts and output'; var show_text = 'Show the prompts and output'; var border_width = pre.css('border-top-width'); var border_style = pre.css('border-top-style'); var border_color = pre.css('border-top-color'); var button_styles = { 'cursor':'pointer', 'position': 'absolute', 'top': '0', 'right': '0', 'border-color': border_color, 'border-style': border_style, 'border-width': border_width, 'color': border_color, 'text-size': '75%', 'font-family': 'monospace', 'padding-left': '0.2em', 'padding-right': '0.2em', 'border-radius': '0 3px 0 0' } // create and add the button to all the code blocks that contain >>> div.each(function(index) { var jthis = $(this); if (jthis.find('.gp').length > 0) { var button = $('>>>'); button.css(button_styles) button.attr('title', hide_text); button.data('hidden', 'false'); jthis.prepend(button); } // tracebacks (.gt) contain bare text elements that need to be // wrapped in a span to work with .nextUntil() (see later) jthis.find('pre:has(.gt)').contents().filter(function() { return ((this.nodeType == 3) && (this.data.trim().length > 0)); }).wrap(''); }); // define the behavior of the button when it's clicked $('.copybutton').click(function(e){ e.preventDefault(); var button = $(this); if (button.data('hidden') === 'false') { // hide the code output button.parent().find('.go, .gp, .gt').hide(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'hidden'); button.css('text-decoration', 'line-through'); button.attr('title', show_text); button.data('hidden', 'true'); } else { // show the code output button.parent().find('.go, .gp, .gt').show(); button.next('pre').find('.gt').nextUntil('.gp, .go').css('visibility', 'visible'); button.css('text-decoration', 'none'); button.attr('title', hide_text); button.data('hidden', 'false'); } }); }); astroquery-0.3.7/astropy_helpers/astropy_helpers/sphinx/themes/bootstrap-astropy/static/sidebar.js0000644000077000000240000001155312354456432034213 0ustar adamstaff00000000000000/* * sidebar.js * ~~~~~~~~~~ * * This script makes the Sphinx sidebar collapsible. * * .sphinxsidebar contains .sphinxsidebarwrapper. This script adds * in .sphixsidebar, after .sphinxsidebarwrapper, the #sidebarbutton * used to collapse and expand the sidebar. * * When the sidebar is collapsed the .sphinxsidebarwrapper is hidden * and the width of the sidebar and the margin-left of the document * are decreased. When the sidebar is expanded the opposite happens. * This script saves a per-browser/per-session cookie used to * remember the position of the sidebar among the pages. * Once the browser is closed the cookie is deleted and the position * reset to the default (expanded). * * :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS. * :license: BSD, see LICENSE for details. * */ $(function() { // global elements used by the functions. // the 'sidebarbutton' element is defined as global after its // creation, in the add_sidebar_button function var bodywrapper = $('.bodywrapper'); var sidebar = $('.sphinxsidebar'); var sidebarwrapper = $('.sphinxsidebarwrapper'); // for some reason, the document has no sidebar; do not run into errors if (!sidebar.length) return; // original margin-left of the bodywrapper and width of the sidebar // with the sidebar expanded var bw_margin_expanded = bodywrapper.css('margin-left'); var ssb_width_expanded = sidebar.width(); // margin-left of the bodywrapper and width of the sidebar // with the sidebar collapsed var bw_margin_collapsed = 12; var ssb_width_collapsed = 12; // custom colors var dark_color = '#404040'; var light_color = '#505050'; function sidebar_is_collapsed() { return sidebarwrapper.is(':not(:visible)'); } function toggle_sidebar() { if (sidebar_is_collapsed()) expand_sidebar(); else collapse_sidebar(); } function collapse_sidebar() { sidebarwrapper.hide(); sidebar.css('width', ssb_width_collapsed); bodywrapper.css('margin-left', bw_margin_collapsed); sidebarbutton.css({ 'margin-left': '-1px', 'height': bodywrapper.height(), 'border-radius': '3px' }); sidebarbutton.find('span').text('»'); sidebarbutton.attr('title', _('Expand sidebar')); document.cookie = 'sidebar=collapsed'; } function expand_sidebar() { bodywrapper.css('margin-left', bw_margin_expanded); sidebar.css('width', ssb_width_expanded); sidebarwrapper.show(); sidebarbutton.css({ 'margin-left': ssb_width_expanded - 12, 'height': bodywrapper.height(), 'border-radius': '0px 3px 3px 0px' }); sidebarbutton.find('span').text('«'); sidebarbutton.attr('title', _('Collapse sidebar')); document.cookie = 'sidebar=expanded'; } function add_sidebar_button() { sidebarwrapper.css({ 'float': 'left', 'margin-right': '0', 'width': ssb_width_expanded - 18 }); // create the button sidebar.append('
«
'); var sidebarbutton = $('#sidebarbutton'); // find the height of the viewport to center the '<<' in the page var viewport_height; if (window.innerHeight) viewport_height = window.innerHeight; else viewport_height = $(window).height(); var sidebar_offset = sidebar.offset().top; var sidebar_height = Math.max(bodywrapper.height(), sidebar.height()); sidebarbutton.find('span').css({ 'font-family': '"Lucida Grande",Arial,sans-serif', 'display': 'block', 'top': Math.min(viewport_height/2, sidebar_height/2 + sidebar_offset) - 10, 'width': 12, 'position': 'fixed', 'text-align': 'center' }); sidebarbutton.click(toggle_sidebar); sidebarbutton.attr('title', _('Collapse sidebar')); sidebarbutton.css({ 'color': '#FFFFFF', 'background-color': light_color, 'border': '1px solid ' + light_color, 'border-radius': '0px 3px 3px 0px', 'font-size': '1.2em', 'cursor': 'pointer', 'height': sidebar_height, 'padding-top': '1px', 'margin': '-1px', 'margin-left': ssb_width_expanded - 12 }); sidebarbutton.hover( function () { $(this).css('background-color', dark_color); }, function () { $(this).css('background-color', light_color); } ); } function set_position_from_cookie() { if (!document.cookie) return; var items = document.cookie.split(';'); for(var k=0; k= (3, 3): from importlib import invalidate_caches else: def invalidate_caches(): return None # Python 2/3 compatibility if sys.version_info[0] < 3: string_types = (str, unicode) # noqa else: string_types = (str,) # Note: The following Warning subclasses are simply copies of the Warnings in # Astropy of the same names. class AstropyWarning(Warning): """ The base warning class from which all Astropy warnings should inherit. Any warning inheriting from this class is handled by the Astropy logger. """ class AstropyDeprecationWarning(AstropyWarning): """ A warning class to indicate a deprecated feature. """ class AstropyPendingDeprecationWarning(PendingDeprecationWarning, AstropyWarning): """ A warning class to indicate a soon-to-be deprecated feature. """ def _get_platlib_dir(cmd): """ Given a build command, return the name of the appropriate platform-specific build subdirectory directory (e.g. build/lib.linux-x86_64-2.7) """ plat_specifier = '.{0}-{1}'.format(cmd.plat_name, sys.version[0:3]) return os.path.join(cmd.build_base, 'lib' + plat_specifier) def get_numpy_include_path(): """ Gets the path to the numpy headers. """ # We need to go through this nonsense in case setuptools # downloaded and installed Numpy for us as part of the build or # install, since Numpy may still think it's in "setup mode", when # in fact we're ready to use it to build astropy now. if sys.version_info[0] >= 3: import builtins if hasattr(builtins, '__NUMPY_SETUP__'): del builtins.__NUMPY_SETUP__ import imp import numpy imp.reload(numpy) else: import __builtin__ if hasattr(__builtin__, '__NUMPY_SETUP__'): del __builtin__.__NUMPY_SETUP__ import numpy reload(numpy) try: numpy_include = numpy.get_include() except AttributeError: numpy_include = numpy.get_numpy_include() return numpy_include class _DummyFile(object): """A noop writeable object.""" errors = '' # Required for Python 3.x 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 if sys.platform == 'win32': import ctypes def _has_hidden_attribute(filepath): """ Returns True if the given filepath has the hidden attribute on MS-Windows. Based on a post here: http://stackoverflow.com/questions/284115/cross-platform-hidden-file-detection """ if isinstance(filepath, bytes): filepath = filepath.decode(sys.getfilesystemencoding()) try: attrs = ctypes.windll.kernel32.GetFileAttributesW(filepath) assert attrs != -1 result = bool(attrs & 2) except (AttributeError, AssertionError): result = False return result else: def _has_hidden_attribute(filepath): return False def is_path_hidden(filepath): """ Determines if a given file or directory is hidden. Parameters ---------- filepath : str The path to a file or directory Returns ------- hidden : bool Returns `True` if the file is hidden """ name = os.path.basename(os.path.abspath(filepath)) if isinstance(name, bytes): is_dotted = name.startswith(b'.') else: is_dotted = name.startswith('.') return is_dotted or _has_hidden_attribute(filepath) def walk_skip_hidden(top, onerror=None, followlinks=False): """ A wrapper for `os.walk` that skips hidden files and directories. This function does not have the parameter `topdown` from `os.walk`: the directories must always be recursed top-down when using this function. See also -------- os.walk : For a description of the parameters """ for root, dirs, files in os.walk( top, topdown=True, onerror=onerror, followlinks=followlinks): # These lists must be updated in-place so os.walk will skip # hidden directories dirs[:] = [d for d in dirs if not is_path_hidden(d)] files[:] = [f for f in files if not is_path_hidden(f)] yield root, dirs, files def write_if_different(filename, data): """Write `data` to `filename`, if the content of the file is different. Parameters ---------- filename : str The file name to be written to. data : bytes The data to be written to `filename`. """ assert isinstance(data, bytes) if os.path.exists(filename): with open(filename, 'rb') as fd: original_data = fd.read() else: original_data = None if original_data != data: with open(filename, 'wb') as fd: fd.write(data) def import_file(filename, name=None): """ Imports a module from a single file as if it doesn't belong to a particular package. The returned module will have the optional ``name`` if given, or else a name generated from the filename. """ # Specifying a traditional dot-separated fully qualified name here # results in a number of "Parent module 'astropy' not found while # handling absolute import" warnings. Using the same name, the # namespaces of the modules get merged together. So, this # generates an underscore-separated name which is more likely to # be unique, and it doesn't really matter because the name isn't # used directly here anyway. mode = 'U' if sys.version_info[0] < 3 else 'r' if name is None: basename = os.path.splitext(filename)[0] name = '_'.join(os.path.relpath(basename).split(os.sep)[1:]) if import_machinery: loader = import_machinery.SourceFileLoader(name, filename) mod = loader.load_module() else: with open(filename, mode) as fd: mod = imp.load_module(name, fd, filename, ('.py', mode, 1)) return mod def resolve_name(name): """Resolve a name like ``module.object`` to an object and return it. Raise `ImportError` if the module or name is not found. """ parts = name.split('.') cursor = len(parts) - 1 module_name = parts[:cursor] attr_name = parts[-1] while cursor > 0: try: ret = __import__('.'.join(module_name), fromlist=[attr_name]) break except ImportError: if cursor == 0: raise cursor -= 1 module_name = parts[:cursor] attr_name = parts[cursor] ret = '' for part in parts[cursor:]: try: ret = getattr(ret, part) except AttributeError: raise ImportError(name) return ret if sys.version_info[0] >= 3: def iteritems(dictionary): return dictionary.items() else: def iteritems(dictionary): return dictionary.iteritems() def extends_doc(extended_func): """ A function decorator for use when wrapping an existing function but adding additional functionality. This copies the docstring from the original function, and appends to it (along with a newline) the docstring of the wrapper function. Examples -------- >>> def foo(): ... '''Hello.''' ... >>> @extends_doc(foo) ... def bar(): ... '''Goodbye.''' ... >>> print(bar.__doc__) Hello. Goodbye. """ def decorator(func): if not (extended_func.__doc__ is None or func.__doc__ is None): func.__doc__ = '\n\n'.join([extended_func.__doc__.rstrip('\n'), func.__doc__.lstrip('\n')]) return func return decorator # Duplicated from astropy.utils.decorators.deprecated # When fixing issues in this function fix them in astropy first, then # port the fixes over to astropy-helpers def deprecated(since, message='', name='', alternative='', pending=False, obj_type=None): """ Used to mark a function or class as deprecated. To mark an attribute as deprecated, use `deprecated_attribute`. Parameters ---------- since : str The release at which this API became deprecated. This is required. message : str, optional Override the default deprecation message. The format specifier ``func`` may be used for the name of the function, and ``alternative`` may be used in the deprecation message to insert the name of an alternative to the deprecated function. ``obj_type`` may be used to insert a friendly name for the type of object being deprecated. name : str, optional The name of the deprecated function or class; if not provided the name is automatically determined from the passed in function or class, though this is useful in the case of renamed functions, where the new function is just assigned to the name of the deprecated function. For example:: def new_function(): ... oldFunction = new_function alternative : str, optional An alternative function or class name that the user may use in place of the deprecated object. The deprecation warning will tell the user about this alternative if provided. pending : bool, optional If True, uses a AstropyPendingDeprecationWarning instead of a AstropyDeprecationWarning. obj_type : str, optional The type of this object, if the automatically determined one needs to be overridden. """ method_types = (classmethod, staticmethod, types.MethodType) def deprecate_doc(old_doc, message): """ Returns a given docstring with a deprecation message prepended to it. """ if not old_doc: old_doc = '' old_doc = textwrap.dedent(old_doc).strip('\n') new_doc = (('\n.. deprecated:: %(since)s' '\n %(message)s\n\n' % {'since': since, 'message': message.strip()}) + old_doc) if not old_doc: # This is to prevent a spurious 'unexpected unindent' warning from # docutils when the original docstring was blank. new_doc += r'\ ' return new_doc def get_function(func): """ Given a function or classmethod (or other function wrapper type), get the function object. """ if isinstance(func, method_types): func = func.__func__ return func def deprecate_function(func, message): """ Returns a wrapped function that displays an ``AstropyDeprecationWarning`` when it is called. """ if isinstance(func, method_types): func_wrapper = type(func) else: func_wrapper = lambda f: f func = get_function(func) def deprecated_func(*args, **kwargs): if pending: category = AstropyPendingDeprecationWarning else: category = AstropyDeprecationWarning warnings.warn(message, category, stacklevel=2) return func(*args, **kwargs) # If this is an extension function, we can't call # functools.wraps on it, but we normally don't care. # This crazy way to get the type of a wrapper descriptor is # straight out of the Python 3.3 inspect module docs. if type(func) != type(str.__dict__['__add__']): deprecated_func = functools.wraps(func)(deprecated_func) deprecated_func.__doc__ = deprecate_doc( deprecated_func.__doc__, message) return func_wrapper(deprecated_func) def deprecate_class(cls, message): """ Returns a wrapper class with the docstrings updated and an __init__ function that will raise an ``AstropyDeprectationWarning`` warning when called. """ # Creates a new class with the same name and bases as the # original class, but updates the dictionary with a new # docstring and a wrapped __init__ method. __module__ needs # to be manually copied over, since otherwise it will be set # to *this* module (astropy.utils.misc). # This approach seems to make Sphinx happy (the new class # looks enough like the original class), and works with # extension classes (which functools.wraps does not, since # it tries to modify the original class). # We need to add a custom pickler or you'll get # Can't pickle : it's not found as ... # errors. Picklability is required for any class that is # documented by Sphinx. members = cls.__dict__.copy() members.update({ '__doc__': deprecate_doc(cls.__doc__, message), '__init__': deprecate_function(get_function(cls.__init__), message), }) return type(cls.__name__, cls.__bases__, members) def deprecate(obj, message=message, name=name, alternative=alternative, pending=pending): if obj_type is None: if isinstance(obj, type): obj_type_name = 'class' elif inspect.isfunction(obj): obj_type_name = 'function' elif inspect.ismethod(obj) or isinstance(obj, method_types): obj_type_name = 'method' else: obj_type_name = 'object' else: obj_type_name = obj_type if not name: name = get_function(obj).__name__ altmessage = '' if not message or type(message) == type(deprecate): if pending: message = ('The %(func)s %(obj_type)s will be deprecated in a ' 'future version.') else: message = ('The %(func)s %(obj_type)s is deprecated and may ' 'be removed in a future version.') if alternative: altmessage = '\n Use %s instead.' % alternative message = ((message % { 'func': name, 'name': name, 'alternative': alternative, 'obj_type': obj_type_name}) + altmessage) if isinstance(obj, type): return deprecate_class(obj, message) else: return deprecate_function(obj, message) if type(message) == type(deprecate): return deprecate(message) return deprecate def deprecated_attribute(name, since, message=None, alternative=None, pending=False): """ Used to mark a public attribute as deprecated. This creates a property that will warn when the given attribute name is accessed. To prevent the warning (i.e. for internal code), use the private name for the attribute by prepending an underscore (i.e. ``self._name``). Parameters ---------- name : str The name of the deprecated attribute. since : str The release at which this API became deprecated. This is required. message : str, optional Override the default deprecation message. The format specifier ``name`` may be used for the name of the attribute, and ``alternative`` may be used in the deprecation message to insert the name of an alternative to the deprecated function. alternative : str, optional An alternative attribute that the user may use in place of the deprecated attribute. The deprecation warning will tell the user about this alternative if provided. pending : bool, optional If True, uses a AstropyPendingDeprecationWarning instead of a AstropyDeprecationWarning. Examples -------- :: class MyClass: # Mark the old_name as deprecated old_name = misc.deprecated_attribute('old_name', '0.1') def method(self): self._old_name = 42 """ private_name = '_' + name @deprecated(since, name=name, obj_type='attribute') def get(self): return getattr(self, private_name) @deprecated(since, name=name, obj_type='attribute') def set(self, val): setattr(self, private_name, val) @deprecated(since, name=name, obj_type='attribute') def delete(self): delattr(self, private_name) return property(get, set, delete) def minversion(module, version, inclusive=True, version_path='__version__'): """ Returns `True` if the specified Python module satisfies a minimum version requirement, and `False` if not. By default this uses `pkg_resources.parse_version` to do the version comparison if available. Otherwise it falls back on `distutils.version.LooseVersion`. Parameters ---------- module : module or `str` An imported module of which to check the version, or the name of that module (in which case an import of that module is attempted-- if this fails `False` is returned). version : `str` The version as a string that this module must have at a minimum (e.g. ``'0.12'``). inclusive : `bool` The specified version meets the requirement inclusively (i.e. ``>=``) as opposed to strictly greater than (default: `True`). version_path : `str` A dotted attribute path to follow in the module for the version. Defaults to just ``'__version__'``, which should work for most Python modules. Examples -------- >>> import astropy >>> minversion(astropy, '0.4.4') True """ if isinstance(module, types.ModuleType): module_name = module.__name__ elif isinstance(module, string_types): module_name = module try: module = resolve_name(module_name) except ImportError: return False else: raise ValueError('module argument must be an actual imported ' 'module, or the import name of the module; ' 'got {0!r}'.format(module)) if '.' not in version_path: have_version = getattr(module, version_path) else: have_version = resolve_name('.'.join([module.__name__, version_path])) try: from pkg_resources import parse_version except ImportError: from distutils.version import LooseVersion as parse_version if inclusive: return parse_version(have_version) >= parse_version(version) else: return parse_version(have_version) > parse_version(version) # Copy of the classproperty decorator from astropy.utils.decorators class classproperty(property): """ Similar to `property`, but allows class-level properties. That is, a property whose getter is like a `classmethod`. The wrapped method may explicitly use the `classmethod` decorator (which must become before this decorator), or the `classmethod` may be omitted (it is implicit through use of this decorator). .. note:: classproperty only works for *read-only* properties. It does not currently allow writeable/deleteable properties, due to subtleties of how Python descriptors work. In order to implement such properties on a class a metaclass for that class must be implemented. Parameters ---------- fget : callable The function that computes the value of this property (in particular, the function when this is used as a decorator) a la `property`. doc : str, optional The docstring for the property--by default inherited from the getter function. lazy : bool, optional If True, caches the value returned by the first call to the getter function, so that it is only called once (used for lazy evaluation of an attribute). This is analogous to `lazyproperty`. The ``lazy`` argument can also be used when `classproperty` is used as a decorator (see the third example below). When used in the decorator syntax this *must* be passed in as a keyword argument. Examples -------- :: >>> class Foo(object): ... _bar_internal = 1 ... @classproperty ... def bar(cls): ... return cls._bar_internal + 1 ... >>> Foo.bar 2 >>> foo_instance = Foo() >>> foo_instance.bar 2 >>> foo_instance._bar_internal = 2 >>> foo_instance.bar # Ignores instance attributes 2 As previously noted, a `classproperty` is limited to implementing read-only attributes:: >>> class Foo(object): ... _bar_internal = 1 ... @classproperty ... def bar(cls): ... return cls._bar_internal ... @bar.setter ... def bar(cls, value): ... cls._bar_internal = value ... Traceback (most recent call last): ... NotImplementedError: classproperty can only be read-only; use a metaclass to implement modifiable class-level properties When the ``lazy`` option is used, the getter is only called once:: >>> class Foo(object): ... @classproperty(lazy=True) ... def bar(cls): ... print("Performing complicated calculation") ... return 1 ... >>> Foo.bar Performing complicated calculation 1 >>> Foo.bar 1 If a subclass inherits a lazy `classproperty` the property is still re-evaluated for the subclass:: >>> class FooSub(Foo): ... pass ... >>> FooSub.bar Performing complicated calculation 1 >>> FooSub.bar 1 """ def __new__(cls, fget=None, doc=None, lazy=False): if fget is None: # Being used as a decorator--return a wrapper that implements # decorator syntax def wrapper(func): return cls(func, lazy=lazy) return wrapper return super(classproperty, cls).__new__(cls) def __init__(self, fget, doc=None, lazy=False): self._lazy = lazy if lazy: self._cache = {} fget = self._wrap_fget(fget) super(classproperty, self).__init__(fget=fget, doc=doc) # There is a buglet in Python where self.__doc__ doesn't # get set properly on instances of property subclasses if # the doc argument was used rather than taking the docstring # from fget if doc is not None: self.__doc__ = doc def __get__(self, obj, objtype=None): if self._lazy and objtype in self._cache: return self._cache[objtype] if objtype is not None: # The base property.__get__ will just return self here; # instead we pass objtype through to the original wrapped # function (which takes the class as its sole argument) val = self.fget.__wrapped__(objtype) else: val = super(classproperty, self).__get__(obj, objtype=objtype) if self._lazy: if objtype is None: objtype = obj.__class__ self._cache[objtype] = val return val def getter(self, fget): return super(classproperty, self).getter(self._wrap_fget(fget)) def setter(self, fset): raise NotImplementedError( "classproperty can only be read-only; use a metaclass to " "implement modifiable class-level properties") def deleter(self, fdel): raise NotImplementedError( "classproperty can only be read-only; use a metaclass to " "implement modifiable class-level properties") @staticmethod def _wrap_fget(orig_fget): if isinstance(orig_fget, classmethod): orig_fget = orig_fget.__func__ # Using stock functools.wraps instead of the fancier version # found later in this module, which is overkill for this purpose @functools.wraps(orig_fget) def fget(obj): return orig_fget(obj.__class__) # Set the __wrapped__ attribute manually for support on Python 2 fget.__wrapped__ = orig_fget return fget def find_data_files(package, pattern): """ Include files matching ``pattern`` inside ``package``. Parameters ---------- package : str The package inside which to look for data files pattern : str Pattern (glob-style) to match for the data files (e.g. ``*.dat``). This supports the Python 3.5 ``**``recursive syntax. For example, ``**/*.fits`` matches all files ending with ``.fits`` recursively. Only one instance of ``**`` can be included in the pattern. """ if sys.version_info[:2] >= (3, 5): return glob.glob(os.path.join(package, pattern), recursive=True) else: if '**' in pattern: start, end = pattern.split('**') if end.startswith(('/', os.sep)): end = end[1:] matches = glob.glob(os.path.join(package, start, end)) for root, dirs, files in os.walk(os.path.join(package, start)): for dirname in dirs: matches += glob.glob(os.path.join(root, dirname, end)) return matches else: return glob.glob(os.path.join(package, pattern)) astroquery-0.3.7/astropy_helpers/astropy_helpers/version.py0000644000077000000240000000104013130766170024464 0ustar adamstaff00000000000000# Autogenerated by Astropy-affiliated package astropy_helpers's setup.py on 2017-07-10 15:07:04.936661 from __future__ import unicode_literals import datetime version = "2.0" githash = "ed2e7897862ae9e979b336df670d7a5541cdd8f0" major = 2 minor = 0 bugfix = 0 release = True timestamp = datetime.datetime(2017, 7, 10, 15, 7, 4, 936661) debug = False try: from ._compiler import compiler except ImportError: compiler = "unknown" try: from .cython_version import cython_version except ImportError: cython_version = "unknown" astroquery-0.3.7/astropy_helpers/astropy_helpers/version_helpers.py0000644000077000000240000002303413232205045026205 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Utilities for generating the version string for Astropy (or an affiliated package) and the version.py module, which contains version info for the package. Within the generated astropy.version module, the `major`, `minor`, and `bugfix` variables hold the respective parts of the version number (bugfix is '0' if absent). The `release` variable is True if this is a release, and False if this is a development version of astropy. For the actual version string, use:: from astropy.version import version or:: from astropy import __version__ """ from __future__ import division import datetime import imp import os import pkgutil import sys import time from distutils import log import pkg_resources from . import git_helpers from .distutils_helpers import is_distutils_display_option from .utils import invalidate_caches PY3 = sys.version_info[0] == 3 def _version_split(version): """ Split a version string into major, minor, and bugfix numbers. If any of those numbers are missing the default is zero. Any pre/post release modifiers are ignored. Examples ======== >>> _version_split('1.2.3') (1, 2, 3) >>> _version_split('1.2') (1, 2, 0) >>> _version_split('1.2rc1') (1, 2, 0) >>> _version_split('1') (1, 0, 0) >>> _version_split('') (0, 0, 0) """ parsed_version = pkg_resources.parse_version(version) if hasattr(parsed_version, 'base_version'): # New version parsing for setuptools >= 8.0 if parsed_version.base_version: parts = [int(part) for part in parsed_version.base_version.split('.')] else: parts = [] else: parts = [] for part in parsed_version: if part.startswith('*'): # Ignore any .dev, a, b, rc, etc. break parts.append(int(part)) if len(parts) < 3: parts += [0] * (3 - len(parts)) # In principle a version could have more parts (like 1.2.3.4) but we only # support .. return tuple(parts[:3]) # This is used by setup.py to create a new version.py - see that file for # details. Note that the imports have to be absolute, since this is also used # by affiliated packages. _FROZEN_VERSION_PY_TEMPLATE = """ # Autogenerated by {packagetitle}'s setup.py on {timestamp!s} from __future__ import unicode_literals import datetime {header} major = {major} minor = {minor} bugfix = {bugfix} release = {rel} timestamp = {timestamp!r} debug = {debug} try: from ._compiler import compiler except ImportError: compiler = "unknown" try: from .cython_version import cython_version except ImportError: cython_version = "unknown" """[1:] _FROZEN_VERSION_PY_WITH_GIT_HEADER = """ {git_helpers} _packagename = "{packagename}" _last_generated_version = "{verstr}" _last_githash = "{githash}" # Determine where the source code for this module # lives. If __file__ is not a filesystem path then # it is assumed not to live in a git repo at all. if _get_repo_path(__file__, levels=len(_packagename.split('.'))): version = update_git_devstr(_last_generated_version, path=__file__) githash = get_git_devstr(sha=True, show_warning=False, path=__file__) or _last_githash else: # The file does not appear to live in a git repo so don't bother # invoking git version = _last_generated_version githash = _last_githash """[1:] _FROZEN_VERSION_PY_STATIC_HEADER = """ version = "{verstr}" githash = "{githash}" """[1:] def _get_version_py_str(packagename, version, githash, release, debug, uses_git=True): epoch = int(os.environ.get('SOURCE_DATE_EPOCH', time.time())) timestamp = datetime.datetime.utcfromtimestamp(epoch) major, minor, bugfix = _version_split(version) if packagename.lower() == 'astropy': packagetitle = 'Astropy' else: packagetitle = 'Astropy-affiliated package ' + packagename header = '' if uses_git: header = _generate_git_header(packagename, version, githash) elif not githash: # _generate_git_header will already generate a new git has for us, but # for creating a new version.py for a release (even if uses_git=False) # we still need to get the githash to include in the version.py # See https://github.com/astropy/astropy-helpers/issues/141 githash = git_helpers.get_git_devstr(sha=True, show_warning=True) if not header: # If _generate_git_header fails it returns an empty string header = _FROZEN_VERSION_PY_STATIC_HEADER.format(verstr=version, githash=githash) return _FROZEN_VERSION_PY_TEMPLATE.format(packagetitle=packagetitle, timestamp=timestamp, header=header, major=major, minor=minor, bugfix=bugfix, rel=release, debug=debug) def _generate_git_header(packagename, version, githash): """ Generates a header to the version.py module that includes utilities for probing the git repository for updates (to the current git hash, etc.) These utilities should only be available in development versions, and not in release builds. If this fails for any reason an empty string is returned. """ loader = pkgutil.get_loader(git_helpers) source = loader.get_source(git_helpers.__name__) or '' source_lines = source.splitlines() if not source_lines: log.warn('Cannot get source code for astropy_helpers.git_helpers; ' 'git support disabled.') return '' idx = 0 for idx, line in enumerate(source_lines): if line.startswith('# BEGIN'): break git_helpers_py = '\n'.join(source_lines[idx + 1:]) if PY3: verstr = version else: # In Python 2 don't pass in a unicode string; otherwise verstr will # be represented with u'' syntax which breaks on Python 3.x with x # < 3. This is only an issue when developing on multiple Python # versions at once verstr = version.encode('utf8') new_githash = git_helpers.get_git_devstr(sha=True, show_warning=False) if new_githash: githash = new_githash return _FROZEN_VERSION_PY_WITH_GIT_HEADER.format( git_helpers=git_helpers_py, packagename=packagename, verstr=verstr, githash=githash) def generate_version_py(packagename, version, release=None, debug=None, uses_git=True, srcdir='.'): """Regenerate the version.py module if necessary.""" try: version_module = get_pkg_version_module(packagename) try: last_generated_version = version_module._last_generated_version except AttributeError: last_generated_version = version_module.version try: last_githash = version_module._last_githash except AttributeError: last_githash = version_module.githash current_release = version_module.release current_debug = version_module.debug except ImportError: version_module = None last_generated_version = None last_githash = None current_release = None current_debug = None if release is None: # Keep whatever the current value is, if it exists release = bool(current_release) if debug is None: # Likewise, keep whatever the current value is, if it exists debug = bool(current_debug) version_py = os.path.join(srcdir, packagename, 'version.py') if (last_generated_version != version or current_release != release or current_debug != debug): if '-q' not in sys.argv and '--quiet' not in sys.argv: log.set_threshold(log.INFO) if is_distutils_display_option(): # Always silence unnecessary log messages when display options are # being used log.set_threshold(log.WARN) log.info('Freezing version number to {0}'.format(version_py)) with open(version_py, 'w') as f: # This overwrites the actual version.py f.write(_get_version_py_str(packagename, version, last_githash, release, debug, uses_git=uses_git)) invalidate_caches() if version_module: imp.reload(version_module) def get_pkg_version_module(packagename, fromlist=None): """Returns the package's .version module generated by `astropy_helpers.version_helpers.generate_version_py`. Raises an ImportError if the version module is not found. If ``fromlist`` is an iterable, return a tuple of the members of the version module corresponding to the member names given in ``fromlist``. Raises an `AttributeError` if any of these module members are not found. """ if not fromlist: # Due to a historical quirk of Python's import implementation, # __import__ will not return submodules of a package if 'fromlist' is # empty. # TODO: For Python 3.1 and up it may be preferable to use importlib # instead of the __import__ builtin return __import__(packagename + '.version', fromlist=['']) else: mod = __import__(packagename + '.version', fromlist=fromlist) return tuple(getattr(mod, member) for member in fromlist) astroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/0000755000077000000240000000000013232443301024113 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/dependency_links.txt0000644000077000000240000000000113130766171030173 0ustar adamstaff00000000000000 astroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/not-zip-safe0000644000077000000240000000000113130766171026353 0ustar adamstaff00000000000000 astroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/PKG-INFO0000644000077000000240000000753513130766171025234 0ustar adamstaff00000000000000Metadata-Version: 1.1 Name: astropy-helpers Version: 2.0 Summary: Utilities for building and installing Astropy, Astropy affiliated packages, and their respective documentation. Home-page: https://github.com/astropy/astropy-helpers Author: The Astropy Developers Author-email: astropy.team@gmail.com License: BSD Description: astropy-helpers =============== * Stable versions: https://pypi.org/project/astropy-helpers/ * Development version, issue tracker: https://github.com/astropy/astropy-helpers This project provides a Python package, ``astropy_helpers``, which includes many build, installation, and documentation-related tools used by the Astropy project, but packaged separately for use by other projects that wish to leverage this work. The motivation behind this package and details of its implementation are in the accepted `Astropy Proposal for Enhancement (APE) 4 `_. The ``astropy_helpers.extern`` sub-module includes modules developed elsewhere that are bundled here for convenience. At the moment, this consists of the following two sphinx extensions: * `numpydoc `_, a Sphinx extension developed as part of the Numpy project. This is used to parse docstrings in Numpy format * `sphinx-automodapi `_, a Sphinx developed as part of the Astropy project. This used to be developed directly in ``astropy-helpers`` but is now a standalone package. Issues with these sub-modules should be reported in their respective repositories, and we will regularly update the bundled versions to reflect the latest released versions. ``astropy_helpers`` includes a special "bootstrap" module called ``ah_bootstrap.py`` which is intended to be used by a project's setup.py in order to ensure that the ``astropy_helpers`` package is available for build/installation. This is similar to the ``ez_setup.py`` module that is shipped with some projects to bootstrap `setuptools `_. As described in APE4, the version numbers for ``astropy_helpers`` follow the corresponding major/minor version of the `astropy core package `_, but with an independent sequence of micro (bugfix) version numbers. Hence, the initial release is 0.4, in parallel with Astropy v0.4, which will be the first version of Astropy to use ``astropy-helpers``. For examples of how to implement ``astropy-helpers`` in a project, see the ``setup.py`` and ``setup.cfg`` files of the `Affiliated package template `_. .. image:: https://travis-ci.org/astropy/astropy-helpers.svg :target: https://travis-ci.org/astropy/astropy-helpers .. image:: https://coveralls.io/repos/astropy/astropy-helpers/badge.svg :target: https://coveralls.io/r/astropy/astropy-helpers Platform: UNKNOWN Classifier: Development Status :: 5 - Production/Stable Classifier: Intended Audience :: Developers Classifier: Framework :: Setuptools Plugin Classifier: Framework :: Sphinx :: Extension Classifier: Framework :: Sphinx :: Theme Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 3 Classifier: Topic :: Software Development :: Build Tools Classifier: Topic :: Software Development :: Libraries :: Python Modules Classifier: Topic :: System :: Archiving :: Packaging astroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/SOURCES.txt0000644000077000000240000000627413130766171026022 0ustar adamstaff00000000000000CHANGES.rst LICENSE.rst MANIFEST.in README.rst ah_bootstrap.py ez_setup.py setup.cfg setup.py astropy_helpers/__init__.py astropy_helpers/distutils_helpers.py astropy_helpers/git_helpers.py astropy_helpers/setup_helpers.py astropy_helpers/test_helpers.py astropy_helpers/utils.py astropy_helpers/version.py astropy_helpers/version_helpers.py astropy_helpers.egg-info/PKG-INFO astropy_helpers.egg-info/SOURCES.txt astropy_helpers.egg-info/dependency_links.txt astropy_helpers.egg-info/not-zip-safe astropy_helpers.egg-info/top_level.txt astropy_helpers/commands/__init__.py astropy_helpers/commands/_dummy.py astropy_helpers/commands/_test_compat.py astropy_helpers/commands/build_ext.py astropy_helpers/commands/build_py.py astropy_helpers/commands/build_sphinx.py astropy_helpers/commands/install.py astropy_helpers/commands/install_lib.py astropy_helpers/commands/register.py astropy_helpers/commands/setup_package.py astropy_helpers/commands/test.py astropy_helpers/commands/src/compiler.c astropy_helpers/compat/__init__.py astropy_helpers/extern/__init__.py astropy_helpers/extern/setup_package.py astropy_helpers/extern/automodapi/__init__.py astropy_helpers/extern/automodapi/autodoc_enhancements.py astropy_helpers/extern/automodapi/automodapi.py astropy_helpers/extern/automodapi/automodsumm.py astropy_helpers/extern/automodapi/smart_resolver.py astropy_helpers/extern/automodapi/utils.py astropy_helpers/extern/automodapi/templates/autosummary_core/base.rst astropy_helpers/extern/automodapi/templates/autosummary_core/class.rst astropy_helpers/extern/automodapi/templates/autosummary_core/module.rst astropy_helpers/extern/numpydoc/__init__.py astropy_helpers/extern/numpydoc/docscrape.py astropy_helpers/extern/numpydoc/docscrape_sphinx.py astropy_helpers/extern/numpydoc/linkcode.py astropy_helpers/extern/numpydoc/numpydoc.py astropy_helpers/sphinx/__init__.py astropy_helpers/sphinx/conf.py astropy_helpers/sphinx/setup_package.py astropy_helpers/sphinx/ext/__init__.py astropy_helpers/sphinx/ext/changelog_links.py astropy_helpers/sphinx/ext/doctest.py astropy_helpers/sphinx/ext/edit_on_github.py astropy_helpers/sphinx/ext/tocdepthfix.py astropy_helpers/sphinx/ext/tests/__init__.py astropy_helpers/sphinx/local/python2_local_links.inv astropy_helpers/sphinx/local/python3_local_links.inv astropy_helpers/sphinx/themes/bootstrap-astropy/globaltoc.html astropy_helpers/sphinx/themes/bootstrap-astropy/layout.html astropy_helpers/sphinx/themes/bootstrap-astropy/localtoc.html astropy_helpers/sphinx/themes/bootstrap-astropy/searchbox.html astropy_helpers/sphinx/themes/bootstrap-astropy/theme.conf astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout.svg astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_linkout_20.png astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.ico astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo.svg astropy_helpers/sphinx/themes/bootstrap-astropy/static/astropy_logo_32.png astropy_helpers/sphinx/themes/bootstrap-astropy/static/bootstrap-astropy.css astropy_helpers/sphinx/themes/bootstrap-astropy/static/copybutton.js astropy_helpers/sphinx/themes/bootstrap-astropy/static/sidebar.js licenses/LICENSE_COPYBUTTON.rst licenses/LICENSE_NUMPYDOC.rstastroquery-0.3.7/astropy_helpers/astropy_helpers.egg-info/top_level.txt0000644000077000000240000000002013130766171026647 0ustar adamstaff00000000000000astropy_helpers astroquery-0.3.7/astropy_helpers/CHANGES.rst0000644000077000000240000004024513232205045021006 0ustar adamstaff00000000000000astropy-helpers Changelog ************************* 2.0.3 (2018-01-20) ------------------ - Make sure that astropy-helpers 3.x.x is not downloaded on Python 2. [#363] - The bundled version of sphinx-automodapi has been updated to v0.7. [#365] - Add --auto-use and --no-auto-use command-line flags to match the ``auto_use`` configuration option, and add an alias ``--use-system-astropy-helpers`` for ``--no-auto-use``. [#366] 2.0.2 (2017-10-13) ------------------ - Added new helper function add_openmp_flags_if_available that can add OpenMP compilation flags to a C/Cython extension if needed. [#346] - Update numpydoc to v0.7. [#343] - The function ``get_git_devstr`` now returns ``'0'`` instead of ``None`` when no git repository is present. This allows generation of development version strings that are in a format that ``setuptools`` expects (e.g. "1.1.3.dev0" instead of "1.1.3.dev"). [#330] - It is now possible to override generated timestamps to make builds reproducible by setting the ``SOURCE_DATE_EPOCH`` environment variable [#341] - Mark Sphinx extensions as parallel-safe. [#344] - Switch to using mathjax instead of imgmath for local builds. [#342] - Deprecate ``exclude`` parameter of various functions in setup_helpers since it could not work as intended. Add new function ``add_exclude_packages`` to provide intended behavior. [#331] - Allow custom Sphinx doctest extension to recognize and process standard doctest directives ``testsetup`` and ``doctest``. [#335] 2.0.1 (2017-07-28) ------------------ - Fix compatibility with Sphinx <1.5. [#326] 2.0 (2017-07-06) ---------------- - Add support for package that lies in a subdirectory. [#249] - Removing ``compat.subprocess``. [#298] - Python 3.3 is no longer supported. [#300] - The 'automodapi' Sphinx extension (and associated dependencies) has now been moved to a standalone package which can be found at https://github.com/astropy/sphinx-automodapi - this is now bundled in astropy-helpers under astropy_helpers.extern.automodapi for convenience. Version shipped with astropy-helpers is v0.6. [#278, #303, #309, #323] - The ``numpydoc`` Sphinx extension has now been moved to ``astropy_helpers.extern``. [#278] - Fix ``build_docs`` error catching, so it doesn't hide Sphinx errors. [#292] - Fix compatibility with Sphinx 1.6. [#318] - Updating ez_setup.py to the last version before it's removal. [#321] 1.3.1 (2017-03-18) ------------------ - Fixed the missing button to hide output in documentation code blocks. [#287] - Fixed bug when ``build_docs`` when running with the clean (-l) option. [#289] - Add alternative location for various intersphinx inventories to fall back to. [#293] 1.3 (2016-12-16) ---------------- - ``build_sphinx`` has been deprecated in favor of the ``build_docs`` command. [#246] - Force the use of Cython's old ``build_ext`` command. A new ``build_ext`` command was added in Cython 0.25, but it does not work with astropy-helpers currently. [#261] 1.2 (2016-06-18) ---------------- - Added sphinx configuration value ``automodsumm_inherited_members``. If ``True`` this will include members that are inherited from a base class in the generated API docs. Defaults to ``False`` which matches the previous behavior. [#215] - Fixed ``build_sphinx`` to recognize builds that succeeded but have output *after* the "build succeeded." statement. This only applies when ``--warnings-returncode`` is given (which is primarily relevant for Travis documentation builds). [#223] - Fixed ``build_sphinx`` the sphinx extensions to not output a spurious warning for sphinx versions > 1.4. [#229] - Add Python version dependent local sphinx inventories that contain otherwise missing references. [#216] - ``astropy_helpers`` now require Sphinx 1.3 or later. [#226] 1.1.2 (2016-03-9) ----------------- - The CSS for the sphinx documentation was altered to prevent some text overflow problems. [#217] 1.1.1 (2015-12-23) ------------------ - Fixed crash in build with ``AttributeError: cython_create_listing`` with older versions of setuptools. [#209, #210] 1.1 (2015-12-10) ---------------- - The original ``AstropyTest`` class in ``astropy_helpers``, which implements the ``setup.py test`` command, is deprecated in favor of moving the implementation of that command closer to the actual Astropy test runner in ``astropy.tests``. Now a dummy ``test`` command is provided solely for informing users that they need ``astropy`` installed to run the tests (however, the previous, now deprecated implementation is still provided and continues to work with older versions of Astropy). See the related issue for more details. [#184] - Added a useful new utility function to ``astropy_helpers.utils`` called ``find_data_files``. This is similar to the ``find_packages`` function in setuptools in that it can be used to search a package for data files (matching a pattern) that can be passed to the ``package_data`` argument for ``setup()``. See the docstring to ``astropy_helpers.utils.find_data_files`` for more details. [#42] - The ``astropy_helpers`` module now sets the global ``_ASTROPY_SETUP_`` flag upon import (from within a ``setup.py``) script, so it's not necessary to have this in the ``setup.py`` script explicitly. If in doubt though, there's no harm in setting it twice. Putting it in ``astropy_helpers`` just ensures that any other imports that occur during build will have this flag set. [#191] - It is now possible to use Cython as a ``setup_requires`` build requirement, and still build Cython extensions even if Cython wasn't available at the beginning of the build processes (that is, is automatically downloaded via setuptools' processing of ``setup_requires``). [#185] - Moves the ``adjust_compiler`` check into the ``build_ext`` command itself, so it's only used when actually building extension modules. This also deprecates the stand-alone ``adjust_compiler`` function. [#76] - When running the ``build_sphinx`` / ``build_docs`` command with the ``-w`` option, the output from Sphinx is streamed as it runs instead of silently buffering until the doc build is complete. [#197] 1.0.7 (unreleased) ------------------ - Fix missing import in ``astropy_helpers/utils.py``. [#196] 1.0.6 (2015-12-04) ------------------ - Fixed bug where running ``./setup.py build_sphinx`` could return successfully even when the build was not successful (and should have returned a non-zero error code). [#199] 1.0.5 (2015-10-02) ------------------ - Fixed a regression in the ``./setup.py test`` command that was introduced in v1.0.4. 1.0.4 (2015-10-02) ------------------ - Fixed issue with the sphinx documentation css where the line numbers for code blocks were not aligned with the code. [#179, #180] - Fixed crash that could occur when trying to build Cython extension modules when Cython isn't installed. Normally this still results in a failed build, but was supposed to provide a useful error message rather than crash outright (this was a regression introduced in v1.0.3). [#181] - Fixed a crash that could occur on Python 3 when a working C compiler isn't found. [#182] - Quieted warnings about deprecated Numpy API in Cython extensions, when building Cython extensions against Numpy >= 1.7. [#183, #186] - Improved support for py.test >= 2.7--running the ``./setup.py test`` command now copies all doc pages into the temporary test directory as well, so that all test files have a "common root directory". [#189, #190] 1.0.3 (2015-07-22) ------------------ - Added workaround for sphinx-doc/sphinx#1843, a but in Sphinx which prevented descriptor classes with a custom metaclass from being documented correctly. [#158] - Added an alias for the ``./setup.py build_sphinx`` command as ``./setup.py build_docs`` which, to a new contributor, should hopefully be less cryptic. [#161] - The fonts in graphviz diagrams now match the font of the HTML content. [#169] - When the documentation is built on readthedocs.org, MathJax will be used for math rendering. When built elsewhere, the "pngmath" extension is still used for math rendering. [#170] - Fix crash when importing astropy_helpers when running with ``python -OO`` [#171] - The ``build`` and ``build_ext`` stages now correctly recognize the presence of C++ files in Cython extensions (previously only vanilla C worked). [#173] 1.0.2 (2015-04-02) ------------------ - Various fixes enabling the astropy-helpers Sphinx build command and Sphinx extensions to work with Sphinx 1.3. [#148] - More improvement to the ability to handle multiple versions of astropy-helpers being imported in the same Python interpreter session in the (somewhat rare) case of nested installs. [#147] - To better support high resolution displays, use SVG for the astropy logo and linkout image, falling back to PNGs for browsers that support it. [#150, #151] - Improve ``setup_helpers.get_compiler_version`` to work with more compilers, and to return more info. This will help fix builds of Astropy on less common compilers, like Sun C. [#153] 1.0.1 (2015-03-04) ------------------ - Released in concert with v0.4.8 to address the same issues. 0.4.8 (2015-03-04) ------------------ - Improved the ``ah_bootstrap`` script's ability to override existing installations of astropy-helpers with new versions in the context of installing multiple packages simultaneously within the same Python interpreter (e.g. when one package has in its ``setup_requires`` another package that uses a different version of astropy-helpers. [#144] - Added a workaround to an issue in matplotlib that can, in rare cases, lead to a crash when installing packages that import matplotlib at build time. [#144] 1.0 (2015-02-17) ---------------- - Added new pre-/post-command hook points for ``setup.py`` commands. Now any package can define code to run before and/or after any ``setup.py`` command without having to manually subclass that command by adding ``pre__hook`` and ``post__hook`` callables to the package's ``setup_package.py`` module. See the PR for more details. [#112] - The following objects in the ``astropy_helpers.setup_helpers`` module have been relocated: - ``get_dummy_distribution``, ``get_distutils_*``, ``get_compiler_option``, ``add_command_option``, ``is_distutils_display_option`` -> ``astropy_helpers.distutils_helpers`` - ``should_build_with_cython``, ``generate_build_ext_command`` -> ``astropy_helpers.commands.build_ext`` - ``AstropyBuildPy`` -> ``astropy_helpers.commands.build_py`` - ``AstropyBuildSphinx`` -> ``astropy_helpers.commands.build_sphinx`` - ``AstropyInstall`` -> ``astropy_helpers.commands.install`` - ``AstropyInstallLib`` -> ``astropy_helpers.commands.install_lib`` - ``AstropyRegister`` -> ``astropy_helpers.commands.register`` - ``get_pkg_version_module`` -> ``astropy_helpers.version_helpers`` - ``write_if_different``, ``import_file``, ``get_numpy_include_path`` -> ``astropy_helpers.utils`` All of these are "soft" deprecations in the sense that they are still importable from ``astropy_helpers.setup_helpers`` for now, and there is no (easy) way to produce deprecation warnings when importing these objects from ``setup_helpers`` rather than directly from the modules they are defined in. But please consider updating any imports to these objects. [#110] - Use of the ``astropy.sphinx.ext.astropyautosummary`` extension is deprecated for use with Sphinx < 1.2. Instead it should suffice to remove this extension for the ``extensions`` list in your ``conf.py`` and add the stock ``sphinx.ext.autosummary`` instead. [#131] 0.4.7 (2015-02-17) ------------------ - Fixed incorrect/missing git hash being added to the generated ``version.py`` when creating a release. [#141] 0.4.6 (2015-02-16) ------------------ - Fixed problems related to the automatically generated _compiler module not being created properly. [#139] 0.4.5 (2015-02-11) ------------------ - Fixed an issue where ah_bootstrap.py could blow up when astropy_helper's version number is 1.0. - Added a workaround for documentation of properties in the rare case where the class's metaclass has a property of the same name. [#130] - Fixed an issue on Python 3 where importing a package using astropy-helper's generated version.py module would crash when the current working directory is an empty git repository. [#114, #137] - Fixed an issue where the "revision count" appended to .dev versions by the generated version.py did not accurately reflect the revision count for the package it belongs to, and could be invalid if the current working directory is an unrelated git repository. [#107, #137] - Likewise, fixed a confusing warning message that could occur in the same circumstances as the above issue. [#121, #137] 0.4.4 (2014-12-31) ------------------ - More improvements for building the documentation using Python 3.x. [#100] - Additional minor fixes to Python 3 support. [#115] - Updates to support new test features in Astropy [#92, #106] 0.4.3 (2014-10-22) ------------------ - The generated ``version.py`` file now preserves the git hash of installed copies of the package as well as when building a source distribution. That is, the git hash of the changeset that was installed/released is preserved. [#87] - In smart resolver add resolution for class links when they exist in the intersphinx inventory, but not the mapping of the current package (e.g. when an affiliated package uses an astropy core class of which "actual" and "documented" location differs) [#88] - Fixed a bug that could occur when running ``setup.py`` for the first time in a repository that uses astropy-helpers as a submodule: ``AttributeError: 'NoneType' object has no attribute 'mkdtemp'`` [#89] - Fixed a bug where optional arguments to the ``doctest-skip`` Sphinx directive were sometimes being left in the generated documentation output. [#90] - Improved support for building the documentation using Python 3.x. [#96] - Avoid error message if .git directory is not present. [#91] 0.4.2 (2014-08-09) ------------------ - Fixed some CSS issues in generated API docs. [#69] - Fixed the warning message that could be displayed when generating a version number with some older versions of git. [#77] - Fixed automodsumm to work with new versions of Sphinx (>= 1.2.2). [#80] 0.4.1 (2014-08-08) ------------------ - Fixed git revision count on systems with git versions older than v1.7.2. [#70] - Fixed display of warning text when running a git command fails (previously the output of stderr was not being decoded properly). [#70] - The ``--offline`` flag to ``setup.py`` understood by ``ah_bootstrap.py`` now also prevents git from going online to fetch submodule updates. [#67] - The Sphinx extension for converting issue numbers to links in the changelog now supports working on arbitrary pages via a new ``conf.py`` setting: ``changelog_links_docpattern``. By default it affects the ``changelog`` and ``whatsnew`` pages in one's Sphinx docs. [#61] - Fixed crash that could result from users with missing/misconfigured locale settings. [#58] - The font used for code examples in the docs is now the system-defined ``monospace`` font, rather than ``Minaco``, which is not available on all platforms. [#50] 0.4 (2014-07-15) ---------------- - Initial release of astropy-helpers. See `APE4 `_ for details of the motivation and design of this package. - The ``astropy_helpers`` package replaces the following modules in the ``astropy`` package: - ``astropy.setup_helpers`` -> ``astropy_helpers.setup_helpers`` - ``astropy.version_helpers`` -> ``astropy_helpers.version_helpers`` - ``astropy.sphinx`` - > ``astropy_helpers.sphinx`` These modules should be considered deprecated in ``astropy``, and any new, non-critical changes to those modules will be made in ``astropy_helpers`` instead. Affiliated packages wishing to make use those modules (as in the Astropy package-template) should use the versions from ``astropy_helpers`` instead, and include the ``ah_bootstrap.py`` script in their project, for bootstrapping the ``astropy_helpers`` package in their setup.py script. astroquery-0.3.7/astropy_helpers/ez_setup.py0000644000077000000240000003037113126316034021416 0ustar adamstaff00000000000000#!/usr/bin/env python """ Setuptools bootstrapping installer. Maintained at https://github.com/pypa/setuptools/tree/bootstrap. Run this script to install or upgrade setuptools. This method is DEPRECATED. Check https://github.com/pypa/setuptools/issues/581 for more details. """ import os import shutil import sys import tempfile import zipfile import optparse import subprocess import platform import textwrap import contextlib from distutils import log try: from urllib.request import urlopen except ImportError: from urllib2 import urlopen try: from site import USER_SITE except ImportError: USER_SITE = None # 33.1.1 is the last version that supports setuptools self upgrade/installation. DEFAULT_VERSION = "33.1.1" DEFAULT_URL = "https://pypi.io/packages/source/s/setuptools/" DEFAULT_SAVE_DIR = os.curdir DEFAULT_DEPRECATION_MESSAGE = "ez_setup.py is deprecated and when using it setuptools will be pinned to {0} since it's the last version that supports setuptools self upgrade/installation, check https://github.com/pypa/setuptools/issues/581 for more info; use pip to install setuptools" MEANINGFUL_INVALID_ZIP_ERR_MSG = 'Maybe {0} is corrupted, delete it and try again.' log.warn(DEFAULT_DEPRECATION_MESSAGE.format(DEFAULT_VERSION)) 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) try: with ContextualZipFile(filename) as archive: archive.extractall() except zipfile.BadZipfile as err: if not err.args: err.args = ('', ) err.args = err.args + ( MEANINGFUL_INVALID_ZIP_ERR_MSG.format(filename), ) raise # 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.""" py_desig = 'py{sys.version_info[0]}.{sys.version_info[1]}'.format(sys=sys) tp = 'setuptools-{version}-{py_desig}.egg' egg = os.path.join(to_dir, tp.format(**locals())) 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. """ 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. """ # 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 _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()) astroquery-0.3.7/astropy_helpers/LICENSE.rst0000644000077000000240000000272312403272746021032 0ustar adamstaff00000000000000Copyright (c) 2014, Astropy Developers All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of the Astropy Team nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. astroquery-0.3.7/astropy_helpers/licenses/0000755000077000000240000000000013232443301021003 5ustar adamstaff00000000000000astroquery-0.3.7/astropy_helpers/licenses/LICENSE_ASTROSCRAPPY.rst0000644000077000000240000000315413171427757024657 0ustar adamstaff00000000000000# The OpenMP helpers include code heavily adapted from astroscrappy, released # under the following license: # # Copyright (c) 2015, Curtis McCully # All rights reserved. # # Redistribution and use in source and binary forms, with or without modification, # are permitted provided that the following conditions are met: # # * Redistributions of source code must retain the above copyright notice, this # list of conditions and the following disclaimer. # * Redistributions in binary form must reproduce the above copyright notice, this # list of conditions and the following disclaimer in the documentation and/or # other materials provided with the distribution. # * Neither the name of the Astropy Team nor the names of its contributors may be # used to endorse or promote products derived from this software without # specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE # DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR # ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES # (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; # LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON # ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. astroquery-0.3.7/astropy_helpers/licenses/LICENSE_COPYBUTTON.rst0000644000077000000240000000471112354456432024425 0ustar adamstaff00000000000000Copyright 2014 Python Software Foundation License: PSF PYTHON SOFTWARE FOUNDATION LICENSE VERSION 2 -------------------------------------------- . 1. This LICENSE AGREEMENT is between the Python Software Foundation ("PSF"), and the Individual or Organization ("Licensee") accessing and otherwise using this software ("Python") in source or binary form and its associated documentation. . 2. Subject to the terms and conditions of this License Agreement, PSF hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use Python alone or in any derivative version, provided, however, that PSF's License Agreement and PSF's notice of copyright, i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006 Python Software Foundation; All Rights Reserved" are retained in Python alone or in any derivative version prepared by Licensee. . 3. In the event Licensee prepares a derivative work that is based on or incorporates Python or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to Python. . 4. PSF is making Python available to Licensee on an "AS IS" basis. PSF MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, PSF MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF PYTHON WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. . 5. PSF SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF PYTHON FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING PYTHON, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. . 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. . 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between PSF and Licensee. This License Agreement does not grant permission to use PSF trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. . 8. By copying, installing or otherwise using Python, Licensee agrees to be bound by the terms and conditions of this License Agreement. astroquery-0.3.7/astropy_helpers/licenses/LICENSE_NUMPYDOC.rst0000644000077000000240000001350712354456432024160 0ustar adamstaff00000000000000------------------------------------------------------------------------------- The files - numpydoc.py - docscrape.py - docscrape_sphinx.py - phantom_import.py have the following license: Copyright (C) 2008 Stefan van der Walt , Pauli Virtanen Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- The files - compiler_unparse.py - comment_eater.py - traitsdoc.py have the following license: This software is OSI Certified Open Source Software. OSI Certified is a certification mark of the Open Source Initiative. Copyright (c) 2006, Enthought, Inc. All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: * Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. * Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. * Neither the name of Enthought, Inc. nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ------------------------------------------------------------------------------- The file - plot_directive.py originates from Matplotlib (http://matplotlib.sf.net/) which has the following license: Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved. 1. This LICENSE AGREEMENT is between John D. Hunter (“JDHâ€), and the Individual or Organization (“Licenseeâ€) accessing and otherwise using matplotlib software in source or binary form and its associated documentation. 2. Subject to the terms and conditions of this License Agreement, JDH hereby grants Licensee a nonexclusive, royalty-free, world-wide license to reproduce, analyze, test, perform and/or display publicly, prepare derivative works, distribute, and otherwise use matplotlib 0.98.3 alone or in any derivative version, provided, however, that JDH’s License Agreement and JDH’s notice of copyright, i.e., “Copyright (c) 2002-2008 John D. Hunter; All Rights Reserved†are retained in matplotlib 0.98.3 alone or in any derivative version prepared by Licensee. 3. In the event Licensee prepares a derivative work that is based on or incorporates matplotlib 0.98.3 or any part thereof, and wants to make the derivative work available to others as provided herein, then Licensee hereby agrees to include in any such work a brief summary of the changes made to matplotlib 0.98.3. 4. JDH is making matplotlib 0.98.3 available to Licensee on an “AS IS†basis. JDH MAKES NO REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED. BY WAY OF EXAMPLE, BUT NOT LIMITATION, JDH MAKES NO AND DISCLAIMS ANY REPRESENTATION OR WARRANTY OF MERCHANTABILITY OR FITNESS FOR ANY PARTICULAR PURPOSE OR THAT THE USE OF MATPLOTLIB 0.98.3 WILL NOT INFRINGE ANY THIRD PARTY RIGHTS. 5. JDH SHALL NOT BE LIABLE TO LICENSEE OR ANY OTHER USERS OF MATPLOTLIB 0.98.3 FOR ANY INCIDENTAL, SPECIAL, OR CONSEQUENTIAL DAMAGES OR LOSS AS A RESULT OF MODIFYING, DISTRIBUTING, OR OTHERWISE USING MATPLOTLIB 0.98.3, OR ANY DERIVATIVE THEREOF, EVEN IF ADVISED OF THE POSSIBILITY THEREOF. 6. This License Agreement will automatically terminate upon a material breach of its terms and conditions. 7. Nothing in this License Agreement shall be deemed to create any relationship of agency, partnership, or joint venture between JDH and Licensee. This License Agreement does not grant permission to use JDH trademarks or trade name in a trademark sense to endorse or promote products or services of Licensee, or any third party. 8. By copying, installing or otherwise using matplotlib 0.98.3, Licensee agrees to be bound by the terms and conditions of this License Agreement. astroquery-0.3.7/astropy_helpers/README.rst0000644000077000000240000000503313232205045020667 0ustar adamstaff00000000000000astropy-helpers =============== * Stable versions: https://pypi.org/project/astropy-helpers/ * Development version, issue tracker: https://github.com/astropy/astropy-helpers This project provides a Python package, ``astropy_helpers``, which includes many build, installation, and documentation-related tools used by the Astropy project, but packaged separately for use by other projects that wish to leverage this work. The motivation behind this package and details of its implementation are in the accepted `Astropy Proposal for Enhancement (APE) 4 `_. The ``astropy_helpers.extern`` sub-module includes modules developed elsewhere that are bundled here for convenience. At the moment, this consists of the following two sphinx extensions: * `numpydoc `_, a Sphinx extension developed as part of the Numpy project. This is used to parse docstrings in Numpy format * `sphinx-automodapi `_, a Sphinx extension developed as part of the Astropy project. This used to be developed directly in ``astropy-helpers`` but is now a standalone package. Issues with these sub-modules should be reported in their respective repositories, and we will regularly update the bundled versions to reflect the latest released versions. ``astropy_helpers`` includes a special "bootstrap" module called ``ah_bootstrap.py`` which is intended to be used by a project's setup.py in order to ensure that the ``astropy_helpers`` package is available for build/installation. This is similar to the ``ez_setup.py`` module that is shipped with some projects to bootstrap `setuptools `_. As described in APE4, the version numbers for ``astropy_helpers`` follow the corresponding major/minor version of the `astropy core package `_, but with an independent sequence of micro (bugfix) version numbers. Hence, the initial release is 0.4, in parallel with Astropy v0.4, which will be the first version of Astropy to use ``astropy-helpers``. For examples of how to implement ``astropy-helpers`` in a project, see the ``setup.py`` and ``setup.cfg`` files of the `Affiliated package template `_. .. image:: https://travis-ci.org/astropy/astropy-helpers.svg :target: https://travis-ci.org/astropy/astropy-helpers .. image:: https://coveralls.io/repos/astropy/astropy-helpers/badge.svg :target: https://coveralls.io/r/astropy/astropy-helpers astroquery-0.3.7/astroquery/0000755000077000000240000000000013232443301016171 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/__init__.py0000644000077000000240000000125013067234073020312 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Accessing Online Astronomical Data. Astroquery is an astropy affiliated package that contains a collection of tools to access online Astronomical data. Each web service has its own sub-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 astroquery import * astroquery-0.3.7/astroquery/_astropy_init.py0000644000077000000240000001215313067234073021442 0ustar adamstaff00000000000000# 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. Works only on platforms with a working ``lsof`` command. 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 import astropy.config.configuration as 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.update_default_config( __package__, config_dir, version=__version__) except TypeError as orig_error: try: config.update_default_config( __package__, config_dir) except config.ConfigurationDefaultMissingError as e: wmsg = (e.args[0] + " Cannot install default profile. If " "you are importing from source, this is expected.") warn(config.ConfigurationDefaultMissingWarning(wmsg)) del e except: raise orig_error astroquery-0.3.7/astroquery/alfalfa/0000755000077000000240000000000013232443301017557 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alfalfa/__init__.py0000644000077000000240000000075613067234073021712 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ ALFALFA Spectra Archive Query Tool ----------------------------------- :Author: Jordan Mirocha (mirochaj@gmail.com) This package is for querying the ALFALFA data repository hosted at http://arecibo.tc.cornell.edu/hiarchive/alfalfa/ """ from .core import Alfalfa, AlfalfaClass import warnings warnings.warn("Experimental: ALFALFA has not yet been refactored to have " "its API match the rest of astroquery.") astroquery-0.3.7/astroquery/alfalfa/core.py0000644000077000000240000001473413202623241021072 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ Author: Jordan Mirocha Affiliation: University of Colorado at Boulder Created on: Fri May 3 09:45:13 2013 """ from __future__ import print_function import requests import numpy as np import numpy.ma as ma from astropy import units as u from astropy import coordinates as coord from ..utils import commons, prepend_docstr_nosections from ..query import BaseQuery __all__ = ['Alfalfa', 'AlfalfaClass'] # have to skip because it tries to use the internet, which is not allowed __doctest_skip__ = ['AlfalfaClass.query_region', 'Alfalfa.query_region'] class AlfalfaClass(BaseQuery): FITS_PREFIX = "http://arecibo.tc.cornell.edu/hiarchive/alfalfa/spectraFITS" CATALOG_PREFIX = "http://egg.astro.cornell.edu/alfalfa/data/a40files/a40.datafile1.csv" PLACEHOLDER = -999999 def get_catalog(self): """ Download catalog of ALFALFA source properties. Notes ----- This catalog has ~15,000 entries, so after it's downloaded, it is made global to save some time later. Returns ------- result : Dictionary of results, each element is a masked array. """ if hasattr(self, 'ALFALFACAT'): return self.ALFALFACAT result = requests.get(self.CATALOG_PREFIX) iterable_lines = result.iter_lines() # Read header cols = [col for col in next(iterable_lines).rstrip('\n').split(',')] catalog = {} for col in cols: catalog[col] = [] # Parse result for line in iterable_lines: # skip blank lines or trailing newlines if line == "": continue l = line.rstrip('\n').split(',') for i, col in enumerate(cols): item = l[i].strip() if item == '\"\"': catalog[col].append(self.PLACEHOLDER) elif item.isdigit(): catalog[col].append(int(item)) elif item.replace('.', '').isdigit(): catalog[col].append(float(item)) else: catalog[col].append(item) result.close() # Mask out blank elements for col in cols: mask = np.zeros(len(catalog[col]), dtype='bool') # need to turn list -> array for boolean comparison colArr = np.array(catalog[col]) # placeholder must share Type with the array ph = np.array(self.PLACEHOLDER, dtype=colArr.dtype) mask[colArr == ph] = True catalog[col] = ma.array(catalog[col], mask=mask) # Make this globally available so we don't have to re-download it # again in this session self.ALFALFACAT = catalog return catalog def query_region(self, coordinates, radius=3. * u.arcmin, optical_counterpart=False): """ Perform object cross-ID in ALFALFA. Search for objects near position (ra, dec) within some radius. Parameters ---------- coordinates : str or `astropy.coordinates` object The target around which to search. It may be specified as a string in which case it is resolved using online services or as the appropriate `astropy.coordinates` object. ICRS coordinates may also be entered as strings as specified in the `astropy.coordinates` module. radius : str or `~astropy.units.Quantity` object, optional The string must be parsable by `astropy.coordinates.Angle`. The appropriate `~astropy.units.Quantity` object from `astropy.units` may also be used. Defaults to 3 arcmin. optical_counterpart : bool Search for position match using radio positions or position of any optical counterpart identified by ALFALFA team? Keep in mind that the ALFA beam size is about 3x3 arcminutes. See documentation for astropy.coordinates.angles for more information about ('ra', 'dec', 'unit') parameters. Examples -------- >>> from astroquery.alfalfa import Alfalfa >>> from astropy import coordinates as coords >>> C = coords.SkyCoord('0h8m05.63s +14d50m23.3s') >>> agc = Alfalfa.query_region(C,'3 arcmin') Returns ------- result : AGC number for object nearest supplied position. """ coordinates = commons.parse_coordinates(coordinates) ra = coordinates.ra.degree dec = coordinates.dec.degree dr = coord.Angle(radius).deg cat = self.get_catalog() # Use RA and DEC to find appropriate AGC if optical_counterpart: ra_ref = cat['RAdeg_OC'] dec_ref = cat['DECdeg_OC'] else: ra_ref = cat['RAdeg_HI'] dec_ref = cat['Decdeg_HI'] dra = np.abs(ra_ref - ra) \ * np.cos(dec * np.pi / 180.) ddec = np.abs(dec_ref - dec) sep = np.sqrt(dra ** 2 + ddec ** 2) i_minsep = np.argmin(sep) minsep = sep[i_minsep] # Matched object within our search radius? if minsep < dr: return cat['AGCNr'][i_minsep] else: return None def get_spectrum_async(self, agc, show_progress=True): """ Download spectrum from ALFALFA catalogue. Parameters ---------- agc : int Identification number for object in ALFALFA catalog. ascii : bool Download spectrum from remote server in ASCII or FITS format? Returns ------- result : A file context manager See Also -------- get_catalog : method that downloads ALFALFA catalog query_region : find object in catalog closest to supplied position (use this to determine AGC number first) """ agc = str(agc).zfill(6) link = "%s/A%s.fits" % (self.FITS_PREFIX, agc) result = commons.FileContainer(link, show_progress=show_progress) return result @prepend_docstr_nosections(get_spectrum_async.__doc__) def get_spectrum(self, agc, show_progress=True): """ Returns ------- spectrum : `~astropy.io.fits.HDUList` Spectrum is in ``hdulist[0].data[0][2]`` """ result = self.get_spectrum_async(agc, show_progress=show_progress) hdulist = result.get_fits() return hdulist Alfalfa = AlfalfaClass() astroquery-0.3.7/astroquery/alfalfa/tests/0000755000077000000240000000000013232443301020721 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alfalfa/tests/__init__.py0000644000077000000240000000000013067234073023032 0ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alfalfa/tests/data/0000755000077000000240000000000013232443301021632 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alfalfa/tests/data/alfalfa_cat_small.txt0000644000077000000240000001020213067234073026005 0ustar adamstaff00000000000000AGCNr,Name,RAdeg_HI,Decdeg_HI,RAdeg_OC,DECdeg_OC,Vhelio,W50,errW50,HIflux,errflux,SNR,RMS,Dist,logMsun,HIcode,OCcode,NoteFlag 331061,456-013,0.01042,15.87222,0.00875,15.88167,6007,260,45,1.13,0.09,6.5,2.40,85.2,9.29,1,I,"" 331405,"",0.01375,26.01639,0.01458,26.01389,10409,315,8,2.62,0.09,16.1,2.05,143.8,10.11,1,I,"" 102896,"",0.02833,28.20194,0.02500,28.20194,16254,406,17,2.37,0.12,11.2,2.31,227.4,10.46,1,I,* 102574,"",0.03792,28.09528,0.00000,0.00000,-368,23,3,1.29,0.08,11.2,5.05,"","",9,U,* 102975,"",0.05125,29.02695,0.00000,0.00000,-367,23,3,2.85,0.07,26.7,4.69,"","",9,U,* 102571,"",0.07167,27.39972,0.07208,27.40083,4654,104,3,2.00,0.06,19.0,2.29,65.9,9.31,1,I,"" 102976,"",0.07917,28.99195,0.00000,0.00000,-365,26,2,2.53,0.11,18.3,5.76,"","",9,U,* 102728,"",0.08833,31.01056,0.08917,31.02194,566,21,6,0.31,0.03,7.5,1.92,9.1,6.78,1,I,"" 102575,"",0.11667,28.14583,0.00000,0.00000,-371,33,7,0.47,0.03,8.6,2.11,"","",9,U,* 12896,478-010,0.12542,26.32445,0.13083,26.32528,7653,170,10,3.14,0.08,22.0,2.44,104.5,9.91,1,I,* 102729,"",0.13375,30.86444,0.13333,30.86917,4618,53,6,0.70,0.04,10.5,2.02,65.4,8.85,1,I,"" 102576,"",0.14708,26.45333,0.00000,0.00000,-430,21,2,0.60,0.04,11.7,2.50,"","",9,U,* 102730,"",0.16708,31.93611,0.16458,31.93833,12631,79,23,0.66,0.05,7.3,2.25,175.8,9.68,1,I,"" 102578,"",0.17625,26.55305,0.00000,0.00000,-429,22,3,0.67,0.04,12.8,2.44,"","",9,U,* 101866,"",0.20875,14.27000,0.19958,14.27750,10877,291,149,0.79,0.11,4.1,2.52,150.3,9.62,2,I,* 12901,499-035,0.24792,28.90861,0.24542,28.91139,6896,395,5,5.03,0.11,25.2,2.24,93.7,10.02,1,I,* 102731,FGC290A,0.28875,30.87250,0.27667,30.87972,7366,257,8,1.33,0.08,8.9,2.08,100.5,9.50,1,I,"" 102977,"",0.28625,28.79389,0.00000,0.00000,-364,22,3,2.03,0.11,13.8,6.64,"","",9,U,* 102861,"",0.29208,32.07361,0.00000,0.00000,-181,22,0,7.30,0.06,55.0,4.69,"","",9,U,* 102732,"",0.31167,31.37167,0.31250,31.37417,12532,292,5,1.54,0.09,9.1,2.20,174.3,10.04,1,I,"" 101869,"",0.36292,14.40861,0.38083,14.40750,12639,183,16,1.00,0.09,6.4,2.57,175.4,9.86,1,I,* 102733,"",0.37417,31.23833,0.37500,31.23417,12581,134,12,1.03,0.08,8.6,2.29,175.0,9.87,1,I,"" 12911,N7806,0.38125,31.44139,0.37542,31.44194,4767,231,23,1.40,0.08,9.4,2.19,67.5,9.18,1,I,* 331082,433-016,0.39375,15.08000,0.39167,15.08167,6368,118,8,2.72,0.08,21.4,2.60,85.9,9.67,1,I,"" 748776,"",0.42667,13.83861,0.42208,13.84250,6337,53,5,0.65,0.05,8.7,2.27,89.9,9.09,1,I,"" 102862,"",0.42833,30.70528,0.00000,0.00000,-193,22,0,3.33,0.05,31.8,4.27,"","",9,U,* 102734,"",0.42792,32.10778,0.42333,32.10778,12560,226,9,1.61,0.08,10.7,2.23,174.8,10.06,1,I,"" 102978,"",0.46917,29.32472,0.00000,0.00000,-368,26,2,5.34,0.09,37.5,5.96,"","",9,U,* 101873,"",0.48292,16.14167,0.47375,16.13778,12786,256,17,1.34,0.10,7.3,2.57,177.6,10.00,1,I,"" 102735,"",0.50083,30.98306,0.50542,30.98278,2878,152,2,1.79,0.07,13.8,2.34,40.6,8.84,1,I,* 102863,"",0.52292,31.70639,0.00000,0.00000,-177,22,0,8.27,0.08,56.1,5.80,"","",9,U,* 102979,"",0.53167,29.54472,0.00000,0.00000,-370,26,2,6.98,0.09,53.0,5.55,"","",9,U,* 749126,"",0.55500,16.05500,0.00000,0.00000,-365,22,0,6.82,0.06,55.6,4.90,"","",9,U,* 101877,"",0.56000,14.48917,0.56167,14.48778,5149,185,4,2.97,0.09,19.8,2.46,72.9,9.57,1,I,"" 102980,"",0.59167,28.31194,0.58042,28.33056,6819,45,6,0.72,0.04,11.2,2.09,92.6,9.16,1,I,"" 12920,478-014,0.59625,27.21417,0.59583,27.21056,7613,281,2,2.88,0.10,16.0,2.40,103.9,9.86,1,I,"" 102864,"",0.62125,31.03111,0.00000,0.00000,-188,20,0,7.81,0.08,58.1,5.77,"","",9,U,* 749127,"",0.68625,13.87444,0.00000,0.00000,-173,27,1,2.48,0.05,20.8,4.07,"","",9,U,* 100006,499-039,0.70958,31.48639,0.70917,31.48500,4947,109,2,1.20,0.06,12.1,2.11,70.1,9.14,1,I,"" 100008,Eder Dw,0.72583,29.57972,0.73500,29.58417,4842,119,7,1.33,0.05,15.5,1.75,68.5,9.17,1,I,"" 101879,"",0.73000,14.36528,0.72958,14.36000,5758,62,10,0.36,0.05,4.4,2.28,81.6,8.75,2,I,"" 102981,"",0.73708,28.29833,0.73167,28.27722,4583,65,15,0.53,0.05,6.5,2.25,64.8,8.72,1,I,* 748777,"",0.78667,15.04667,0.79583,15.04445,13800,98,10,0.88,0.07,7.8,2.51,192.1,9.88,1,I,"" 7,I5381,0.79417,15.96778,0.79667,15.96500,11223,678,22,3.99,0.16,10.9,2.42,155.2,10.36,1,I,* 100051,433-025,2.00375,14.83972,2.02333,14.83972,13632,136,13,0.77,0.08,5.6,2.63,189.7,9.81,2,I,"" astroquery-0.3.7/astroquery/alfalfa/tests/data/alfalfa_sp.fits0000644000077000000240000024310013067234073024623 0ustar adamstaff00000000000000SIMPLE = T /Dummy Created by MWRFITS v1.4a BITPIX = 8 /Dummy primary header created by MWRFITS NAXIS = 0 /No data is associated with this header EXTEND = T /Extensions may (will!) be present END XTENSION= 'BINTABLE' /Written by IDL: Thu Jul 8 12:45:08 2010 BITPIX = 8 / NAXIS = 2 /Binary table NAXIS1 = 32768 /Number of bytes per row NAXIS2 = 1 /Number of rows PCOUNT = 0 /Random parameter count GCOUNT = 1 /Group count TFIELDS = 4 /Number of columns COMMENT COMMENT *** End of mandatory fields *** COMMENT COMMENT COMMENT *** Column names *** COMMENT TTYPE1 = 'VHELIO ' /Heliocentric velocity [km/s] TTYPE2 = 'FREQ ' /Radio frequency [MHz] TTYPE3 = 'FLUXDENS ' /Flux Density [mJy] TTYPE4 = 'BASELINE ' /Subtracted Polynomial baseline fit TUNIT1 = 'KM/S ' /Units of velocity axis TUNIT2 = 'MHz ' /Units of frequency axis TUNIT3 = 'mJy ' /Units of flux density axis TUNIT4 = 'mJy ' /Units of subtracted baseline COMMENT COMMENT *** Column formats *** COMMENT TFORM1 = '1024D ' / TFORM2 = '1024D ' / TFORM3 = '1024D ' / TFORM4 = '1024D ' / TELESCOP= 'Arecibo Radio Telescope' /Designation of Telescope INSTRUME= 'ALFA ' /Instrument in use BEAM = '3.5x3.8 ' /Beam size [arcminutes] OBJECT = 'AGC 100051' /Name of observed object ORIGIN = 'CORNELL ' /File creation location RA = 2.0037095 /Right Ascension in degrees DEC = 14.839847 /Declination in degrees EQUINOX = 2000.00 /Epoch for coordinates (years) RESTFRQ = 1.4204058E+09 /Rest Freqeuncy [Hz] COMMENT BW = 24.975586 /Bandwidth [MHz] CHAN = 1024 /Number of spectral channels COMMENT COMMENT Arecibo Legacy Fast ALFA Survey COMMENT Cornell University COMMENT http://egg.astro.cornell.edu/alfalfa/ COMMENT Last updated: Thu Jul 8 12:45:08 2010 G. Hallenbeck COMMENT ALFALFA archive at http://arecibo.tc.cornell.edu/hiarchive/alfalfa/ COMMENT This spectrum has been baselined. END @Ñ~•¡æ@Ñ|©8à @Ñ{6ß“-@Ñyĉºw€@ÑxR7UÝ@ÑvßèeQT@ÑumœèÈ@ÑsûTà4ª@Ñr‰KŠè@ÑqÏ*¾„@Ño¤‘}Âë@Ñn2WD‹ö@ÑlÀ  "@ÑkMí-:%@ÑiÛ½O @Ñhiäf7@Ñf÷gíLž@Ñe…Bi­S@Ñd Y|@Ñb¡¼¬Ÿ@Ña.æ“2z@Ñ_¼ÎÝ@@Ñ^Jºš ¤@Ñ\Ø©ÊH\@Ñ[fœm¨ @ÑYô’„?@ÑX‚Œ ¡¯@ÑW‰ #@ÑUž‰y–î@ÑT,[ñ@ÑRº”±%@ÑQHŸy&e@ÑOÖ­³é @ÑNd¿a`p@ÑLòÔ€Z@ÑK€í€eZWÚ@Ñ= d†æ@Ñ;œÞàÊ_@Ñ:+ Ïø@Ñ8¹f/]h@Ñ7G¯”Q@Ñ5ÕûE®f@Ñ4dJûŸK@Ñ2òž#Z£@Ñ1€ô¼ÔF@Ñ0NÇÿ²@Ñ.¬DЯ@Ñ-, 3:ß@Ñ+ºq“1ä@Ñ*HÙd©˜@Ñ(×D§•y@Ñ'e³[é_@Ñ%ô%˜Ü@Ñ$‚›—¤@Ñ# Ùk@Ñ!ŸšQç@Ñ .„ôº@Ѽ“൙@ÑK­ˆJ@ÑÙ¤ë`L@Ñh2š1Š@Ñöùï‚@Ñ…XJŽ@ÑðLÐ@Ñ¢‹¾;k@Ñ1*¡1¤@Ñ¿Ìô× @ÑNr¹“@ÑÝíþÃ@Ñ kÈ“hT@Ñ úx©Oú@Ñ ‰,/©i@Ñ ã&hE@Ѧ€f@Ñ5[då^@ÑĬŠò@ÑRáddÅ@ÑᩌfŸ@Ñpu$„4@ÐþÿD,±9@Ðýޤáb@ÐüìS@Ðú«ÅåÒ@Ðù:¢­ ”@Ð÷É‚äË`@ÐöXfŒRÆ@ÐôçM£“ @Ðóv8*@Ðò&!J@Ðð”‡3–@Ðï# \ß)@Ðí²¢¸@ÐìAVž @ÐêÏÿz˜¬@Ðé_ ê|@Ðçî‡,@Ðæ}‚br@Ðå cp@Ðã›.³£¤@Ðâ*Brñ @Ðà¹Y¡KÛ@ÐßHt>§í@ÐÝ×’Jøö@ÐÜf³Æ2ª@ÐÚõذH¿@ÐÙ… .ú@ÐØ,ÐÙ@ÐÖ£\:»@ÐÕ2ެGÎ@ÐÓÁÄ¿óÛ@ÐÒPþB2¼@ÐÐà;2ø7@ÐÏo{’7Þ@ÐÍþ¿_å›@ÐÌŽ›õ@ÐËQFZ@ÐɬŸ_3@ÐÈ;ðåóZ@ÐÆËEÛD@ÐÅZž>O”@ÐÃéú¨"@ÐÂyYO ¥@ÐÁ»üpÏ@п˜"Èi@о'‹¡L@м¶ø˜!@лFhý v@йÕÜÏ´]@иeTs@жôξ ~@е„LÙÉ2@дÎcX@в£SY¶@б2Û½û@ЯÂg $@ЮQöÎ¥ž@Ьá‰zÿl@Ыq”¡1@Ъ¹~´@ШV‹©@Чöp»ý@Ð¥¯š?R@Ф?AzU€@ТÎì"¦>@С^š7é?@ПîKºp@О~©r@Ð ¹æ @ЛtÍx-@К-4¿a@И¼ö¤¯–@ЗL¼³<€@Е܆.Yæ@ДlSû@Ð’ü#jC@Б‹÷*šÈ@ÐÎWå@ÐŽ«¨ð¸b@Ð;†ö8@ЋËhgò–@Њ[MEÛÛ@Јë5ç@Ї{!F ¡@І h5¯@Є›ö_ @Ѓ*øð{@кòV|@ЀJï(V2@Ð~Úïeý?@Ð}jóe&@Ð{úú$ˆ@Ðz‹¥FQ@Ðy‘§5@Ðw«#é—ü@Ðv;8­ ’@ÐtËPÛø™@Ðs[lvOê@Ðqë‹|^@Ðp{­í½@Ðo ÓÉ_Î@Ðm›ýêX@Ðl,)ã!@Ðj¼Yá~@ÐiLjnÚ@ÐgÜÄ^iV@Ðflþ½aT@Ðdý<‡J™@Ðc}¼í@ÐbÂ[À<@Ð`® f4:@Ð_>UÛh®@Ð]Τ»Q„@Ð\^÷âq@ÐZïL»`@ÐY¥ÚÌ@ÐXe +@ÐV bYÃÌ@ÐU0ŸæŒ@ÐSÁ,‚hD@ÐRQ–¶<ß@ÐPâTX@ÐOru\­¸@ÐNéÏ1–@ÐL“a«×™@ÐK#Üò“u@ÐI´[£Y@ÐHDݾ1@ÐFÕcBв@ÐEeì1jq@ÐCöx‰Ý@ÐB‡L¢@ÐA›xÈ@Ð?¨2 Ñm@Ð>8Ì .k@Ð<Éiv'‰@Ð;Z H° @Ð9ꮄ½x@Ð8{V*Aé@Ð7 91à@Ð5œ¯±$@Ð4-a“#{@Ð2¾Þ ¿@Ð1NÏ’0Û@Ð/ß‹¯ƒ˜@Ð.pK5ø»@Ð-%„B@Ð+‘Ô~ã@Ð*"ž?­w@Ð(³kj2×@Ð'D;ýï@Ð%Õùâs@Ð$eç^ôb@Ð"öÂ,Ç‚@Ð!‡ cO›@Ð ‚€™@Щg NT@Ð:Oz¬“@ÐË;SV@Ð\*”êP@Ðí>±[@Ð~PØb@Ð ËSQ@Р ®Ë@Ð1 ùà@Р¬AV@ÐSÇ‘ö@ÐäJù½@Ð u-6lq@Ð >‰Ýí@Ð —SEB@Ð (khŒØ@й†ó±æ@ÐJ¥æ¥4@ÐÛÈAZ›@ÐlîÆ@Ðþ-Û;@ÐC¿Ž'@Ïþ@çq¥#@ÏûcN38ï@Ïø…»Ã¿f@Ïõ¨0# @ÏòÊ«QBÕ@Ïïí-N{@Ïí¶m—@Ïê2E³Dÿ@ÏçTÜ}g@ÏäwyQþ¦@ÏášV°m@ÏÞ¼È)z–@ÏÛßyÊD­@ÏÙ28öŠ@ÏÖ$ñuwá@ÏÓG·°¬@ÏÐj„Wˆz@ÏÍWüç"@Ïʰ2o´W@ÏÇÓ¯×Ì@ÏÄõû½9|@ÏÂê—Àö@Ï¿;à?V6@ϼ^ܳàî@ϹßõH¬@϶¤êum@ϳÇúÞO@ϰë…½.@Ï®0ù§”@Ï«1V9ö@ϨT‚FV@Ï¥wµ^a@Ï¢šîÄGã@ÏŸ¾/54@Ïœávr d@ÏšÄz¶ì@Ï—(O$@Ï”Ktï#À@Ï‘n×Zµ–@ÏŽ’@‘¹Y@Ï‹µ°”@ψÙ'a¶N@Ï…ü¤ú~å@σ )^XÆ@Ï€C´+É@Ï}gF†ß|@ÏzŠßK\@Ïw®~Úˆâ@ÏtÒ%4N@ÏqõÒX“h@Ïo†G@—@Ïl=A=¥@Ïiaƒr"@Ïf„ÊÐÆ @Ïc¨™è!4@Ï`ÌoÉkv@Ï]ðLtŒ…@Ï[/él6@ÏX8'ò‡@ÏU\ 0N@ÏR€’@ÏO¤œ{.@ÏLÈ©ö@ÏIì.’@ÏG&$x´@ÏD4?ãè4@ÏAX`l= @Ï>|‡½^ó@Ï; µ×5à@Ï8Ä깩‰@Ï5é&d¢ @Ï3 hØû@Ï01²À*@Ï-Vµº@Ï*zXãÏ^@Ï'ž¶wõ@Ï$ÃÔ‰@Ï!ç…øš@Ï ÷ã¼e@Ï0p— y@ÏTð÷@ÏyvTе@Ïž^`f@Ï—/@Ï ç1ÇÔm@Ï Ó'B–@Ï0{M³4@ÏU*;h@Ïyßï;ä@Îÿžœj#¥@ÎüÃ_«­@Îùè)³Át@Î÷ ú‚G2@Îô1Ò&µ@ÎñV°rGû@Îî{•“’Ú@Îë zï*@ÎèÅt(Dæ@Îåêm›{æ@ÎãmÔ|&@Îà4tÓ-}@ÎÝY‚—wÂ@ÎÚ~—!Bò@Î×£²pw@ÎÔÈÔ„ü@ÎÑíý^¹i@ÎÏ,ý—†@ÎÌ8ca~ @ÎÉ] ŠU@ÎÆ‚äxe@Îè/*t @ÎÀÍ€¡‹¿@νòØÝ3¢@λ7ÝS°@θ=¡Óœ@εc *›b@βˆ}w’ý@ί­÷ˆ¢Ž@άÓx]±¤@Ωøÿö¨‚@ΧŽSnÝ@ΤD#sìù@Ρi¿X d@Ξaÿ¯>@Λµ jÄ@Θڻ™/@ΖrŠÙú@Γ&0?¬"@ÎKô·[@Îq¿òeÈ@Ί—‘ðb@·½j°œ@΄ãJ3É¥@΂ 0yŽE@Î/ÑÞ@Î|UL|m@Îy{ Ùuî@Îv¡ (¦7@ÎsÇ9õD@Îpí$ K7@În9¢æ@Îk9Uù«r@Îh_y…³@Îe…¢í£@Îb«Ó‰@@Î_Ò æœ©@Î\øI·@ÎZå­d@ÎWDÙ‡Ñ@ÎTk+éxÖ@ÎQ‘… è“@ÎN·äñ>à@ÎKÞK–c¸@ÎI¸ü?a@ÎF+-"¹@ÎCQ¨ º\@Î@x)±)ð@Î=ž²ïú@Î:ÅA@ôæ@Î7ë×) @@Î5sÑZs@Î299‹0@Î/_Áaš¾@Î,†rIpô@Î)­)ðõò@Î&ÓèX´@Î#ú­~¬@Î!!yd­s@ÎHL ý@Îo%n„€@Ζ’*F@μìt×@ÎãÚr­@Î Îvåj@Î 1É–@Î XËsï¾@ÎÔWq@Φãk6n@ÎÍù„th@Íþõ[ù¤@Íü9ñ®B@ÍùCdEyõ@Íöj•WE'@Íó‘Í&÷®@Íð¹ ´yÑ@ÍíàPÿ³B@ÍëŒj@Íè.ïÎìý@ÍåVIR½c@Íâ}©“åš@Íߥ’Mw@ÍÜÌ~MÝA@ÍÙóòÆ|ó@Í×mü®@ÍÔBïîŒn@ÍÑjxÌR@ÍÎ’ ¼}@Í˹ž2Dé@ÍÈá;M·@ÍÆÞ¸¿@ÍÃ0‰€²@ÍÀX:0{ @ͽò–)@ͺ§°˜¹í@Í·ÏuæÎ²@Í´÷Að¼O@Ͳ¶jä@ͯFî7·@ͬnÎt«Ã@Í©–µm(@ͦ¾£ Ñä@Í£æ—ß;@Í¡’º(@Íž6”ŸvÍ@Í›^?Ñ$@͘†¬›™@Í•®Â±,@Í’Ößü€@Íÿ oX@Í'-Slª@ÍŠO^SÜN@͇w–¦ˆ@Í„ŸÔƒ³ž@ÍȲëh@Í~ðeœ6O@Í|¸?|)@ÍyAœ¥=@Íviq³™«@Ís‘Ø„A“@ÍpºF…@ÍmâºRLU@Ík 5Oo@Íh3·†@Íe\?uɹ@Íb„Ξ±*@Í_­d€¥@Í\Ö@ÍYþ¤oR @ÍW'N{Ü•@ÍTOÿAŽ@ÍQx¶¾ß­@ÍN¡tõ)5@ÍKÊ9ã×ÿ@ÍHóŠÔt@ÍF×ê@ÍCD±V½@Í@mЬ÷@Í=–wWñ]@Í:¿d— @Í7èXå~@Í5S§‚@Ì×hYÎQ@ÌÔ’8©œÛ@ÌѼ9N`@ÌÎæ }M˜@ÌÌýuƒ@ÌÉ9÷!ÖË@ÌÆc÷‚1@ÌÃþ–z @ÌÀ¸ ^š@̽â ÚyZ@Ì» < 0@̸6]í¾@̵`†ƒ¥J@Ì²ŠµÍ”@̯´ëÊËG@̬ß({3C@̪ kÞ´,@̧3µõ6H@̤^¾¡Ú@Ì¡ˆ^:ßM@Ìž²¼iÖ@Ì›Ý!Kp3@Ì™Œß”U@Ì–1ÿ&+"@Ì“\x@̆÷ÊRD@̱~'³"@ÌŠÜ 7'Á@̈žø˜e@Ì…19kí@Ì‚[Ú‘d@̆‚gæ@Ì|±0ðZ@ÌyÛæ*S_@Ìw¢º†@Ìt1d²w¼@Ìq\.sD@Ìn†ýÿ•‰@Ìk±Ô¯Æ«@Ìhܲîï@Ìf–"ö¿@Ìc2€åÆa@Ì`]rYEô@Ì]ˆj}^@ÌZ³iQö¹@ÌWÞnÖøw@ÌU { K_@ÌR4ñ×ÿ@ÌO_§‡†y@ÌLŠÇÍ?@ÌIµîÂê3@ÌFáhp!@ÌD P½¹F@ÌA7‹Â­Â@Ì>bÍw6@Ì;ŽÛ:D@Ì8¹dî£@Ì5亱X†@Ì3#Bê@Ì0;zDJ±@Ì-fäXF@Ì*’T“SÉ@Ì'½ËÁ%¤@Ì$éI¶@Ì"Î(íš@Ì@Yb´e@ÌkëJòä@Ì—ƒá‘^@ÌÃ#&x=@ÌîÉÄ@ÌuºÀ_@ÌF) òR@Ì qã@Ì£±ûÂ@ÌÉk £ï@Ìõ9îÑ@Ì! ÄÄÒ@ËýLé&]@ËúxË4³¶@Ë÷¤³ðG@ËôУY³U@Ëñü™oÞI@Ëï(–3@ËìT™£i@Ë連¿ðh@Ëæ¬´‰‚«@ËãØËÿ³œ@Ëáê"kÉ@ËÞ1ñ“x@ËÛ]:mí@ËØ‰l”Ò“@ËÕµ¥hº÷@ËÒáäè´^@ËÐ+§@ËÍ:wì{r@ËÊfËp@ËÇ“%Ÿk?@ËÄ¿†zWY@ËÁëîÆË@Ë¿\2¡Ü@˼DÑÑ@˹qL˜<É@˶ÎËÍS@˳ÊWªkH@˰öç3þÇ@Ë®#}hpƒ@Ë«PG¨œ@˨|½Ñ¢@Ë¥©h ý@Ë¢Öå @Ë Ðnr[@Ë/Ž¢) @Ëš\S€»@Ë—‰)ô@Ë”µñ:D´@Ë‘âÊQÑ@Ë©œ9“@ËŒ<Ëä<@ˉi|¥:@ˆ–p($¦@˃ÃjT‹@Ë€ðk*V\@Ë~r©nÁ@Ë{J€Ñ¼Ò@Ëxw•£(Ó@Ëu¤±›x@ËrÑÓ@ý@Ëoþü 5ç@Ëm,+‚.„@ËjYaŸÏl@Ëg†žf,@Ëd³áÔ«å@Ëaá+ë¸K@Ë_|«Ç@Ë\;Ô—ž@ËYi2";ƒ@ËV––Ùâº@ËSÄ9uÔ@ËPñt@Ý\@ËNìðš@ËKLlFÊö@ËHyòE"#@ËE§~êï‹@ËBÕ8t@Ë@¬,Žj@Ë=0LÈ1#@Ë:]ô ë¼@Ë7‹¡ô¦ë@Ë4¹V…K@Ë1ç¼ÀÒ@Ë/Óšð]@Ë,BœÂn@Ë)pkKH@Ë&žAïŸ@Ë#Ì•·@Ë ú³ŒD@Ë'êx)°@ËUÚâ܈@˃Ñó@˱Ϫ$@ËßÔ‰¾@Ë ß¦´@Ë ;ð°c”@Ë jý¨É@˘'ð^à@ËÆMˆn @ËôyÅ¿`@Êÿ"¬¨:ä@ÊüPæ/É;@Êù&\Ró@Êö­m-Àw@ÊóÛº£úx@Êñ ¾é`@Êî8i~uš@ÊëfÊâ‡Ø@Êè•2ë„@Êåá—à,@Êâòè÷^@Êà ’Þ6…@ÊÝOw†R@ÊÚ}ž´Ï1@Ê׬.•ù®@ÊÔÚÅî4@ÊÒ bC•u@ÊÏ8Ø@ÊÌf°ž@@ÊÉ•a’Ðå@ÊÆÄIX6@ÊÃò×£ @ÊÁ!œ Ë@ʾPh@ã@Ê»:‚ñ(@ʸ®hÀà@ʵÜòñX¿@ʳ Ù¡Q@ʰ:Åêƒ'@Ê­i¹Zæ¨@ʪ˜³m´ˆ@ʧǴ"ÕV@ʤö»z1 @Ê¢%És±ô@ÊŸTÞ>»@ÊœƒùLÀÎ@Ê™³, •@Ê–âC­F @Ê”rÐ|@Ê‘@¨”‡Ý@ÊŽoäút,@Ê‹Ÿ(É@ʈÎqªo:@Ê…ýÁôO@ʃ-ßQ?@Ê€\vk^B@Ê}‹Ú˜^ö@Êz»Ef;¡@Êwê¶ÔÜõ@Êu.ä+‚@ÊrI­”ù@Êoy2ärÅ@Êl¨¾Õ<½@ÊiØQfVK@Êgê—¨!@Êd7Ši©@Êag0Ú–¼@Ê^–Ýìæ@Ê[Æ‘M’@ÊXöKîY˜@ÊV& ß`@ÊSUÔo]Ã@ÊP…¢Ÿ'*@ÊMµwnVH@ÊJåRÜÓ«@ÊH4ê‡â@ÊEE—[Å@ÊBu ã7à@Ê?¥ÎŸ@Ê<ÔÿWªØ@Ê:€@Ê75 G%ô@Ê4e¬Ì<@Ê1•3°î]@Ê.ÅQSu@Ê+õu”HÎ@Ê)% sR„@Ê&UÑðzº@Ê#† ©Ù@Ê ¶HÄÈÝ@ÊæŽÀ0@ÊÚx„@ÊG,¢Ú@Êw…ÒÎþ@ʧå >@@ÊØL *@Ê ¹0L@Ê 9,¸„|@Êi¦úö$@Êš'Úm÷@ÊʯVÔÍ@Éþû=p@Éü+Ò&•@Éù\mx¹@Éögò@Éó½·ó¥'@Éðîg»'@ÉîàÄ@ÉëOÙ@²Œ@É耜=eY@Éå±eÖ’@Éââ6 Ä@Éà ÛA…@ÉÝCêG~€@ÉÚtÎOcØ@É×¥¸òÚ@ÉÔÖª1Ê#@ÉÒ¢ W@ÉÏ8 ¹³@ÉÌi¥’ŠÆ@ÉÉš±>x@ÉÆËÃ…jº@ÉÃüÜgK$@ÉÁ-ûäì@ɾ_!ûx@É»N­•õ@ɸÁúD›@ɵò»álj@ɳ#übö;@ɰUC~Êå@É­†‘4Òõ@ɪ·å„÷ @ɧé@o @É¥¡ó6±@É¢L #@ÉŸ}xÈÏV@Éœ®î"ë@É™àjï@É—ì‰d@É”Cu§#6@É‘u^,à@ÉŽ¦›®iÄ@É‹Ø8—Âà@ɉ Ü Â@Ɇ;†5l@Ƀm6éÆ@É€žî6nO@É}Ьö²@É{pš}@Éx4;°¡‰@Éuf _•ˆ@Ér—å¦ÔR@ÉoÉĆFt@Élû©ýÔÇ@Éj-– h"@Ég_ˆ´é@Éd‘ô@r@ÉaÃËW@É^õˆ:±@É\'•@dø@ÉYY¨Þ-Á@ÉV‹ÃX¿@ÉS½ãßΦ@ÉPð Cxq@ÉN"9>>®@ÉKTmÐ 5@ÉH†¨øÃÞ@ÉE¸ê¸T\@ÉBë3¤`@É@ûœÄ@É=O×&^@É:‚3™)á@É7´–I@É4æÿA·@É2om'¹@É/Kåà*¹@É,~bé3@É)°æˆ+@É&ãp¼ùô@É$‡‰ @É!H˜çÁ6@É{6Ý‹ @É­ÛhÏ£@Éà†‰w—@É8?k‰@ÉEðŠ”œ@Éx¯jÛ@É «tà(ë@É Þ@êe²@ɉzÒ@ÉCì½PÚ@ÉvÌ…ÐÄ@Èÿ©²âãE@ÈüÜŸÔq4@Èú“Zch@È÷Bt¢¹@ÈôuŽ#ý@Èñ¨•e«é@ÈîÛ£v@È´´É‘!@ȱESAî@È®xøL=Ç@È«¬£èiK@ȨàVY~@ȦÕ÷7@È£GÎ'+M@È {” Þ˜@ȯ`}ú@Èšã3ƒft@Ș  ³@È•JíAÕª@È’~Óúª/@ȲÁDs@@Ȍ浳@ÈŠ¯Š†„@ȇN°†¢B@È„‚¸V2@ȶÆ0Šã@È~êÚÞ)t@È|ö¾@ÈySêGs@Èv‡@H˜Ú@Ès»o6÷~@Èp蘆L_@Èn#àÀv@ÈkX#a|›@ÈhŒl)§@ÈeÀ¼Lp•@Èbõ™:b@È`)ouo¿@È]]Òàùª@ÈZ’<ÛÁB@ÈWÆ­e¯@ÈTû$~¬I@ÈR/¢&¡¯@ÈOd&]xj@ÈL˜±# @ÈIÍBwl«@ÈGÚZ\N@ÈD6xËУ@ÈAk˲Í@È>ŸÉYëÆ@È;Ô{vdA@È9 4!<@È6=óY·±@È3r¹ d@È0§…tôØ@È-ÜXWQ]@È+1Çc(@È(FÅ@È%zøPJ@È"¯åhñ0@ÈäÙñ7@ÈÓB3)@ÈNÔ @ȃÛP ¹@ȸé*ž,@Èíý’y@È#†3R@È X:Ú@È b§ @È®ºâ@È÷ÅÕA@È-ˆ"ß@ÇþbCÇHþ@Çû—Œ’œ³@ÇøÌÛê±@Çö1Íp@Çó7Ž<ÁÁ@Çðlñ7äÌ@Çí¢Z¾Â@Çê×ÊÑBŠ@Çè AoOY@ÇåB¾˜Ñ2@ÇâxBM±~@Çß­ÌØË@ÇÜã]Y0:@ÇÚô¯ ë@Ç×N’‘¶@ÇÔ„6ýq˜@Çѹáô£Œ@ÇÎï“v’Ž@ÇÌ%Kƒ'ã@ÇÉ[ L@ÇÆÏ;èz@ÇÃÆšçåü@ÇÀüm-x@Ǿ2EÞ¨5@Ç»h%)>ä@Ǹž ýÚÌ@ǵÓ÷\dÃ@dz êDÅë@ǰ?ã¶ç@Ç­uã²±r@Ǫ«ê8 î@ǧá÷Få°@Ç¥ ß!Ž@Ç¢N%ªª@”ñIÿU @”ñbÿU¡@”ñ{ÿU @”ñ”ÿU @”ñ­ÿU @”ñÆÿU¡@”ñßÿU @”ñøÿU @”òÿU @”ò*ÿUŸ@”òCÿU @”ò\ÿU @”òuÿU @”òŽÿU @”ò§ÿU @”òÀÿU¡@”òÙÿU @”òòÿU @”ó ÿU¡@”ó$ÿU @”ó=ÿUŸ@”óVÿU @”óoÿU¡@”óˆÿU @”ó¡ÿU @”óºÿU @”óÓÿU¡@”óìÿU @”ôÿU @”ôÿU @”ô7ÿU @”ôPÿU @”ôiÿU @”ô‚ÿU @”ô›ÿU¡@”ô´ÿU @”ôÍÿU¡@”ôæÿU @”ôÿÿU @”õÿU @”õ1ÿU¡@”õJÿUŸ@”õcÿU @”õ|ÿU @”õ•ÿU¡@”õ®ÿU @”õÇÿU @”õàÿU @”õùÿU @”öÿU @”ö+ÿU @”öDÿU @”ö]ÿU¡@”övÿU @”öÿU @”ö¨ÿUŸ@”öÁÿUŸ@”öÚÿU¡@”öóÿU @”÷ ÿU¡@”÷%ÿU @”÷>ÿU @”÷WÿU @”÷pÿU @”÷‰ÿU @”÷¢ÿU @”÷»ÿU @”÷ÔÿUŸ@”÷íÿU¡@”øÿU @”øÿU @”ø8ÿU @”øQÿUŸ@”øjÿU @”øƒÿU @”øœÿU @”øµÿU¡@”øÎÿU @”øçÿU @”ùÿU @”ùÿUŸ@”ù2ÿU @”ùKÿUŸ@”ùdÿU @”ù}ÿUŸ@”ù–ÿU @”ù¯ÿU @”ùÈÿU @”ùáÿU @”ùúÿU @”úÿU @”ú,ÿU @”úEÿU¡@”ú^ÿU @”úwÿU @”úÿU @”ú©ÿU @”úÂÿU @”úÛÿU @”úôÿU @”û ÿU @”û&ÿUŸ@”û?ÿU @”ûXÿU @”ûqÿU @”ûŠÿU @”û£ÿU @”û¼ÿU @”ûÕÿUŸ@”ûîÿU @”üÿU @”ü ÿU @”ü9ÿU @”üRÿU @”ükÿU @”ü„ÿU @”üÿU¡@”ü¶ÿU @”üÏÿU @”üèÿU @”ýÿU @”ýÿU @”ý3ÿU @”ýLÿU @”ýeÿU @”ý~ÿU @”ý—ÿU @”ý°ÿU @”ýÉÿU @”ýâÿU @”ýûÿU @”þÿU @”þ-ÿU¡@”þFÿUŸ@”þ_ÿU @”þxÿU @”þ‘ÿU @”þªÿU @”þÃÿUŸ@”þÜÿU @”þõÿU @”ÿÿU @”ÿ'ÿU @”ÿ@ÿUŸ@”ÿYÿU @”ÿrÿU @”ÿ‹ÿUŸ@”ÿ¤ÿUŸ@”ÿ½ÿU¡@”ÿÖÿU @”ÿïÿU @•ÿU @•!ÿUŸ@•:ÿU @•SÿU @•lÿU @•…ÿUŸ@•žÿU @•·ÿU @•ÐÿU @•éÿU @•ÿU @•ÿU @•4ÿU @•MÿU @•fÿU @•ÿU @•˜ÿU @•±ÿU @•ÊÿU @•ãÿU @•üÿU @•ÿU @•.ÿUŸ@•GÿU @•`ÿU @•yÿUŸ@•’ÿU @•«ÿU @•ÄÿU @•ÝÿU @•öÿU @•ÿU @•(ÿU @•AÿU @•ZÿU¡@•sÿU @•ŒÿU @•¥ÿU @•¾ÿU @•×ÿU @•ðÿU @• ÿU @•"ÿU @•;ÿU @•TÿU @•mÿU @•†ÿU @•ŸÿU @•¸ÿU @•ÑÿU @•êÿU @•ÿU @•ÿUŸ@•5ÿU @•NÿU @•gÿU @•€ÿU @•™ÿU @•²ÿU @•ËÿU @•äÿU @•ýÿU @•ÿU @•/ÿU @•HÿU @•aÿU @•zÿUŸ@•“ÿU¡@•¬ÿU @•ÅÿU @•ÞÿU¡@•÷ÿU @•ÿU @•)ÿUŸ@•BÿU @•[ÿU¡@•tÿU @•ÿU @•¦ÿU @•¿ÿU @•ØÿU @•ñÿU @• ÿU @•#ÿU @•<ÿUŸ@•UÿU @•nÿU @•‡ÿU @• ÿU¡@•¹ÿU @•ÒÿU @•ëÿU @• ÿU @• ÿU @• 6ÿU¡@• OÿU @• hÿUŸ@• ÿU @• šÿU¡@• ³ÿUŸ@• ÌÿU¡@• åÿU @• þÿU @• ÿU¡@• 0ÿU @• IÿU @• bÿU¡@• {ÿU @• ”ÿU @• ­ÿU @• ÆÿU @• ßÿU @• øÿU @• ÿU @• *ÿUŸ@• CÿU @• \ÿU @• uÿU @• ŽÿU @• §ÿU @• ÀÿU @• ÙÿU @• òÿU @• ÿU¡@• $ÿU¡@• =ÿU¡@• VÿU @• oÿU @• ˆÿU @• ¡ÿU¡@• ºÿU @• ÓÿU @• ìÿUŸ@• ÿUŸ@• ÿU @• 7ÿU @• PÿU¡@• iÿU @• ‚ÿUŸ@• ›ÿU @• ´ÿU¡@• ÍÿU @• æÿU @• ÿÿU @•ÿU @•1ÿU @•JÿU @•cÿU @•|ÿU @••ÿU @•®ÿU @•ÇÿU @•àÿU @•ùÿU @•ÿU @•+ÿU @•DÿUŸ@•]ÿU @•vÿU @•ÿU @•¨ÿU @•ÁÿU @•ÚÿU @•óÿU @• ÿU @•%ÿU @•>ÿU @•WÿU @•pÿU @•‰ÿU @•¢ÿU @•»ÿU @•ÔÿU @•íÿU @•ÿU @•ÿU¡@•8ÿUŸ@•QÿU @•jÿU @•ƒÿU @•œÿU @•µÿU @•ÎÿU @•çÿU @•ÿU¡@•ÿU @•2ÿUŸ@•KÿU¡@•dÿU @•}ÿU¡@•–ÿU @•¯ÿU @•ÈÿU @•áÿU @•úÿU @•ÿU @•,ÿUŸ@•EÿUŸ@•^ÿU @•wÿU @•ÿU @•©ÿU @•ÂÿU @•ÛÿU @•ôÿU @• ÿU @•&ÿUŸ@•?ÿU @•XÿU @•qÿU @•ŠÿU @•£ÿU @•¼ÿU @•ÕÿU @•îÿU @•ÿUŸ@• ÿU @•9ÿU¡@•RÿU¡@•kÿUŸ@•„ÿU @•ÿU @•¶ÿU @•ÏÿU @•èÿU @•ÿU @•ÿU @•3ÿU @•LÿUŸ@•eÿUŸ@•~ÿU @•—ÿU¡@•°ÿU @•ÉÿU @•âÿU @•ûÿU¡@•ÿUŸ@•-ÿU @•FÿU @•_ÿU @•xÿU @•‘ÿU @•ªÿU @•ÃÿU @•ÜÿU¡@•õÿU @•ÿU @•'ÿU @•@ÿU¡@•YÿU¡@•rÿU @•‹ÿU @•¤ÿU @•½ÿU @•ÖÿU @•ïÿU @•ÿU @•!ÿU @•:ÿU @•SÿU¡@•lÿU @•…ÿU @•žÿU¡@•·ÿU @•ÐÿU @•éÿU @•ÿU @•ÿU @•4ÿU @•MÿU @•fÿU @•ÿU @•˜ÿU¡@•±ÿUŸ@•ÊÿU @•ãÿU @•üÿU @•ÿU @•.ÿU @•GÿU @•`ÿUŸ@•yÿU¡@•’ÿU @•«ÿU @•ÄÿU @•ÝÿU @•öÿU @•ÿU @•(ÿU @•AÿU @•ZÿU @•sÿU @•ŒÿUŸ@•¥ÿU @•¾ÿU @•×ÿU @•ðÿU¡@• ÿU @•"ÿU¡@•;ÿU @•TÿU @•mÿU @•†ÿU¡@•ŸÿU @•¸ÿU @•ÑÿU @•êÿU @•ÿU @•ÿU @•5ÿU @•NÿU @•gÿU @•€ÿU @•™ÿU @•²ÿUŸ@•ËÿU @•äÿU @•ýÿU @•ÿU @•/ÿU @•HÿU @•aÿU¡@•zÿU @•“ÿU @•¬ÿU @•ÅÿU @•ÞÿU @•÷ÿU @• ÿUŸ@• )ÿU @• BÿU @• [ÿU @• tÿU¡@• ÿU @• ¦ÿUŸ@• ¿ÿU @• ØÿU @• ñÿU @•! ÿU @•!#ÿUŸ@•!<ÿU @•!UÿU @•!nÿU @•!‡ÿU @•! ÿU @•!¹ÿU @•!ÒÿU @•!ëÿU @•"ÿU @•"ÿU @•"6ÿU @•"OÿU @•"hÿU @•"ÿU¡@•"šÿU¡@•"³ÿU¡@•"ÌÿUŸ@•"åÿU @•"þÿU @•#ÿU¡@•#0ÿU @•#IÿUŸ@•#bÿUŸ@•#{ÿU @•#”ÿU @•#­ÿU @•#ÆÿUŸ@•#ßÿU @•#øÿU @•$ÿU @•$*ÿU @•$CÿU @•$\ÿU @•$uÿUŸ@•$ŽÿU @•$§ÿU @•$ÀÿU @•$ÙÿU¡@•$òÿU @•% ÿU @•%$ÿU @•%=ÿU @•%VÿU @•%oÿU @•%ˆÿU @•%¡ÿU @•%ºÿU @•%ÓÿU @•%ìÿU¡@•&ÿUŸ@•&ÿU @•&7ÿU @•&PÿU @•&iÿU @•&‚ÿU @•&›ÿU @•&´ÿU @•&ÍÿU @•&æÿU @•&ÿÿU @•'ÿUŸ@•'1ÿU @•'JÿU @•'cÿUŸ@•'|ÿU @•'•ÿU @•'®ÿU @•'ÇÿU @•'àÿU @•'ùÿU @•(ÿU @•(+ÿUŸ@•(DÿU @•(]ÿUŸ@•(vÿU @•(ÿU @•(¨ÿU @•(ÁÿUŸ@•(ÚÿU @•(óÿU @•) ÿU @•)%ÿU @•)>ÿU¡@•)WÿU @•)pÿU @•)‰ÿU @•)¢ÿU @•)»ÿU @•)ÔÿUŸ@•)íÿU @•*ÿU @•*ÿU @•*8ÿU @•*QÿU @•*jÿU¡@•*ƒÿU @•*œÿU @•*µÿU @•*ÎÿU @•*çÿU @•+ÿU @•+ÿU @•+2ÿU @•+KÿU @•+dÿU¡@•+}ÿU @•+–ÿU @•+¯ÿU @•+ÈÿU @•+áÿU @•+úÿU @•,ÿU @•,,ÿU @•,EÿU¡@•,^ÿUŸ@•,wÿU @•,ÿU @•,©ÿU @•,ÂÿU @•,ÛÿU @•,ôÿUŸ@•- ÿU @•-&ÿU @•-?ÿU @•-XÿU @•-qÿU @•-ŠÿU @•-£ÿU @•-¼ÿU @•-ÕÿU @•-îÿU @•.ÿU @•. ÿU @•.9ÿU @•.RÿU @•.kÿU @•.„ÿU @•.ÿUŸ@•.¶ÿU @•.ÏÿU @•.èÿU @•/ÿU @•/ÿU @•/3ÿU @•/LÿU @•/eÿU @•/~ÿU @•/—ÿU @•/°ÿU @•/ÉÿU @•/âÿUŸ@•/ûÿU @•0ÿU @•0-ÿU @•0FÿU @•0_ÿU @•0xÿU @•0‘ÿU @•0ªÿU @•0ÃÿU @•0ÜÿU @•0õÿU @•1ÿU @•1'ÿUŸ@•1@ÿU @•1YÿU @•1rÿU @•1‹ÿU @•1¤ÿU @•1½ÿU @•1ÖÿU¡@•1ïÿUŸ@•2ÿU @•2!ÿU @•2:ÿU @•2SÿU¡@•2lÿU @•2…ÿU @•2žÿU @•2·ÿU @•2ÐÿU @•2éÿU @•3ÿU @•3ÿU @•34ÿU @•3MÿU @•3fÿU @•3ÿU¡@•3˜ÿU @•3±ÿU @•3ÊÿU @•3ãÿU @•3üÿU @•4ÿU @•4.ÿU @•4GÿU¡@•4`ÿU @•4yÿU @•4’ÿU @•4«ÿU @•4ÄÿUŸ@•4ÝÿU @•4öÿU¡@•5ÿU @•5(ÿU @•5AÿU @•5ZÿU @•5sÿUŸ@•5ŒÿU @•5¥ÿUŸ@•5¾ÿU @•5×ÿU @•5ðÿU¡@•6 ÿU¡@•6"ÿU @•6;ÿU @•6TÿU @•6mÿU @•6†ÿU @•6ŸÿU @•6¸ÿU @•6ÑÿU @•6êÿU @•7ÿU @•7ÿU @•75ÿU @•7NÿU @•7gÿU @•7€ÿU¡@•7™ÿU @•7²ÿU @•7ËÿU @•7äÿU @•7ýÿU @•8ÿU @•8/ÿU @•8HÿU¡@•8aÿU @•8zÿU @•8“ÿU @•8¬ÿU @•8ÅÿU¡@•8ÞÿU @•8÷ÿU @•9ÿU @•9)ÿU @•9BÿU @•9[ÿU @•9tÿU @•9ÿU @•9¦ÿU @•9¿ÿU @•9ØÿU @•9ñÿUŸ@•: ÿU @•:#ÿU @•:<ÿU @•:UÿU @•:nÿUŸ@•:‡ÿU @•: ÿU @•:¹ÿU @•:ÒÿU @•:ëÿU @•;ÿU @•;ÿU @•;6ÿU @•;OÿU @•;hÿU @•;ÿU @•;šÿU¡@•;³ÿU @•;ÌÿUŸ@•;åÿUŸ@•;þÿU @•<ÿU @•<0ÿU @• ÿU @•>$ÿU¡@•>=ÿU @•>VÿU @•>oÿU @•>ˆÿU¡@•>¡ÿU @•>ºÿU @•>ÓÿU¡@•>ìÿU @•?ÿU @•?ÿU @•?7ÿU @•?PÿUŸ@•?iÿU @•?‚ÿU @•?›ÿU @•?´ÿUŸ@•?ÍÿUŸ@•?æÿU @•?ÿÿU @•@ÿU @•@1ÿU @•@JÿU @•@cÿUŸ@•@|ÿU @•@•ÿU¡@•@®ÿU @•@ÇÿU @•@àÿU @•@ùÿU @•AÿU @•A+ÿU @•ADÿU @•A]ÿU @•AvÿU @•AÿU @•A¨ÿU @•AÁÿU @•AÚÿU @•AóÿU¡@•B ÿU @•B%ÿU @•B>ÿU @•BWÿU @•BpÿU @•B‰ÿU @•B¢ÿU @•B»ÿU¡@•BÔÿU @•BíÿU @•CÿU @•CÿU @•C8ÿU @•CQÿU @•CjÿU @•CƒÿU @•CœÿU @•CµÿU @•CÎÿUŸ@•CçÿUŸ@•DÿU @•DÿU @•D2ÿUŸ@•DKÿU @•DdÿUŸ@•D}ÿU @•D–ÿU @•D¯ÿU @•DÈÿU @•DáÿU¡@•DúÿU @•EÿU @•E,ÿU @•EEÿU @•E^ÿU @•EwÿU @•EÿU @•E©ÿU @•EÂÿU @•EÛÿU @•EôÿU @•F ÿU¡@•F&ÿU @•F?ÿU @•FXÿU @•FqÿU @•FŠÿU @•F£ÿU @•F¼ÿU @•FÕÿU @•FîÿU @•GÿU¡@•G ÿU @•G9ÿU @•GRÿU @•GkÿU @•G„ÿU @•GÿU @•G¶ÿU¡@•GÏÿU @•GèÿU @•HÿU @•HÿUŸ@•H3ÿU @•HLÿU @•HeÿU @•H~ÿU @•H—ÿU¡@•H°ÿU @•HÉÿU @•HâÿU @•HûÿU @•IÿU @•I-ÿU @•IFÿU @•I_ÿU @•IxÿU @•I‘ÿU @•IªÿU @•IÃÿU @•IÜÿU @•IõÿU¡@•JÿU @•J'ÿU¡@•J@ÿUŸ@•JYÿU @•JrÿU @•J‹ÿU @•J¤ÿU¡@•J½ÿU @•JÖÿU @•JïÿU @•KÿUŸ@•K!ÿUŸ@•K:ÿU¡@•KSÿU @•KlÿU @•K…ÿUŸ@•KžÿU¡@•K·ÿU @•KÐÿU @•KéÿU¡@•LÿU @•LÿU @•L4ÿU @•LMÿU @•LfÿUŸ@•LÿU @•L˜ÿU @•L±ÿU @•LÊÿU @•LãÿU¡@•LüÿU¡@•MÿU @•M.ÿU @•MGÿU @•M`ÿU @•MyÿU @•M’ÿU @•M«ÿU¡@•MÄÿUŸ@•MÝÿUŸ@•MöÿU @•NÿU @•N(ÿUŸ@•NAÿU @•NZÿU @•NsÿUŸ@•NŒÿU @•N¥ÿU @•N¾ÿUŸ@•N×ÿU @•NðÿU @•O ÿU¡@•O"ÿUŸ@•O;ÿU @•OTÿU @•OmÿU @•O†ÿU @•OŸÿU @•O¸ÿUŸ@•OÑÿUŸ@•OêÿU @•PÿU @•PÿU @•P5ÿU @•PNÿU @•PgÿU @•P€ÿU @•P™ÿU @•P²ÿU @•PËÿU @•PäÿU @•PýÿU @•QÿU @•Q/ÿU @•QHÿU @•QaÿU @•QzÿU¡@•Q“ÿU @•Q¬ÿUŸ@•QÅÿU @•QÞÿU @•Q÷ÿU @•RÿU @•R)ÿU @•RBÿUŸ@•R[ÿU @•RtÿUŸ@•RÿUŸ@•R¦ÿU @•R¿ÿU @•RØÿU¡@•RñÿUŸ@•S ÿU @•S#ÿU @•S<ÿU @•SUÿUŸ@•SnÿUŸ@•S‡ÿU @•S ÿU¡@•S¹ÿUŸ@•SÒÿU @•SëÿU @•TÿU @•TÿU¡@•T6ÿU @•TOÿU @•ThÿU @•TÿU @•TšÿU @•T³ÿU @•TÌÿU @•TåÿU @•TþÿU @•UÿU @•U0ÿU À¼á“]À#“•Íaìh@¥Û”ö/@L €0Dº@®WKFÇÄ?ü§_H¬SX¿²L:Žx(r¿òÆÙCBÚÀ è[À¾À È5«àò"¿èññzoi¿ûUZŒlGÀUNp©òäÀµ -âPí@òÌ2 ¡@òtº-?ö™Kµð¨%¿ì?‘`ÀWÞÄž£À¶•`ň?ÖЋ.~B?ûä­Lž R@›UÑ<¿â¢§fº¿ú ØðA@ý¿ñ“›Cÿ¶9¿¿l¥+¨=@,ÃïêjÖ@\ó0™N@ (ãy˜@Ì­L?"Í@Dà6©ˆ¿þ8É×î<Àv~ÿ£ÀÂ6x€dÀ[(ŒÕX}¿öƒÙ¿ZQ@Ìj/Uú¤@ô *.O@T¶¹Aƒå@ ›dO8ê@)ÐXx#@°nd0½?ú0bKŸl¤À : Ù!@TÀ’õÓŒu@%:È5÷¿éÈ3Ál½z¿ñAî¼+Ö~?í¦¦z¨ñ¿Òc)4émÀÓà|JêXÀ÷L¢(ÀäØBÙŒ˜?ò²8é%@öòš@ {ŒU°@«ûuBÒ?áþ­Àå¡zY?ê_“E EÊ@(„1`µ®@?Ê9U ¿ðïg¹ääÙÀÉRê•7?Ï*>MI™ß'J}ÀÝ“žÎ¢¿ö‚¢¯"‰c?êµjU(?ìâÉ)K]‘?Ñ\QÛ¨×ê¿åùîƒÖ7t¿÷\æe±8K¿ð‹pgSA&¿Ü^6~|J@ ÐŒ”·œ@š©¼n»@ §ßŸè}ÀKÇ@«ÍÀ,äïÌŒ?Èw‚X U @h‹«+^:?€N¡©Û#¿û‘×)¿ï_ žJd¿³ÊCTy1?×Å$æ¾M?æÞvÁ4~?äןo¿×?ºD d½Àº…¡‰j¢ÀkÍòî[¶¿ô²\/ëˆ$?ü¼Ô‹;Žù@ …Ýpˆ?üÚc è@„?ûŠùgû®?ÿwp1;¿ìÊ{î?€ÀSE®‰~9ÀŠ1¬J¤ÀE6ßE|ÀpÏuÏýêÀªí°\?ðsÇa §<í™AŽ¿æþHƒ’À)­œ¿óEšÝdÒ?Û^ê/‘c?ø `"So@ 6â#lê@šŸR.Ob¿ÍØP³êRêÀÔŸ7ãWÀ°mÈjÀøf ͆ÂÀuì §F2¿áêÎ/ð¦?ü"Hò¼Úã?ÛV;I‡7Ÿ¿üoþmÁÀq ˆ&΄@‡r•;de@"Ð|<P¿ÿ "æ?窽vŸ[@ÓSë=Í@4ÖtµÂä?ÒžiæšÄÀ ˜p  ÀÆ—û1¿ð0DãúÆ‚?äH­‡ÈŽ?åÁ0sñµ¿àò°p_£Â¿óî)bÜ?æN¼= "@ ‚SpË@Ó6RNMT?Ö‡ú—ÑýÀ§·z§¾ÀemÄo3«¿í‘ !|~?ñBž{€ÙŸ¿æží-âu¿ìE†) ²?ô ^M™þé@ '³u/šD@ € ËZ‹Ú?þß_æ‘?â—7 .v?­q@ŒŸ'?úõAVÅG@¬­–š5À@^â¶`ó/@¹{½é.@žiÏÝÁk?õwã¤ì)ÅÀ’=½Bú¿áÖæó>?÷àƒ¿w†Ž¿éB ¥H¡XÀ,Îí…[À `ÎQ•ÌPÀ ‡õ]ïÀN#»ÇÀ ¨>¯fG¿ö¢ih2?ÿ¾\TnÎC@ < dÁá?ûÅWr–Y¿Þå™îjM™?å[ÂŒÀåã@ÀÑ'Éj?ÿ *+‹ž\?øæ'E´?õ2ˆ<­v‘?ò_ÝüNA@ 74Ý™Û@К¸é@õau'p†@ röòwV±@Lè p46@ JVgÉ:?×í¶ßñÀ/Eýã×ÀTÙ1åQ”Àa»k$h¿ù-Um l¿ázܽ:줿햦EE´.À$KÜÊ¿ûC¶Ðç7æ?l›¸_âÚG¿äû%´ð鳿â$wk` c@謘¾þ?@ ~•|z©C?ÇgÑ`×qÀ˾hã¤YÀˆ!“! Ÿ¿þŽïœš-²@ :¥WÄí@Ðq½y@F™Ç Ö@—èK“€x@âå ùWË?ù–G—‘ô#¿Ñù¼K–bæ@im)gœ@æ››/ ?õîÆlû°?úxŸø€?þ.7Jp?ð&÷3YY?ýä¤Ó½Ô@Ã)ìõ¿ô-”¢É)À8}ÚGÀbGJ#†ÀÇôé,+ÀŒð‡˜LÖ?›ÿÏÀG:¨¿ü³Á>À'‹Ö2?Ìøl2Ýì¶@¡ëæ’ò?þ<)Œó0«À”DÊ£íh¿ù?i°û Ù?Ùàçñ+ÿ*?Ògy@ ®¡?åûħÂ@šfö÷´‚@Ï;™}[?òáÕípšk¿¤.¹vÆJ@â8zÈ¥@<L&üË@ ß÷€ïi@ Œ)$¿@âÈDǽ?Ô¬Ò:W(›Àé½…ÐÏ¥À!œþß`À‹pÝY¢/@Hq¤! @GªŠßK@ V'žÄ·–@ Ç (?G=@Ž©’lÙà¿Ò“Ç8„ØŽ¿ú—Çht›ÝÀýô4‹¡À"(›/ïjüÀƒ{¡¦»?óW,Ù½ã@ P©{0û@'0¢1s@ Ú›lí@KÔhóF‰¿üŠ„¦¹·À;ïZ )ÀÍý³È{À$ÄKÙZL¿úºg‘y N¿º6Ío±;hÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿø@ <™ýz»I@ Yw)9ì¬@ @VA‰ãŠ@ —š™|æ@ýTx˜Í@-ˆú‹Ádø@žÐË/þÀ¹ >ÈôÀ¶ÅôÍ@²ÚY—·Ü@¨ Öïw¬@ôø¨O@z@ר+?óšY fG@ ãKðƉ@âf¿É Î«BÖ?æ)&P0È;?ù˜H3(|?ÔéiûT”ý?ÛËPò\íÒ@ î_Θ@ù‡»<¯?ú<Í„kÓ¿¶íÔÃ1~@©q§nJn@QŽ×Æð¿Ânâ9px?óÞÒ*Ü´ÀJ1ö[€ÀÞvo¿ø¿ù©šÓcÀé£ =a•?÷Âgîˆ ?ÿü9 @Ì@ :Etí@—$á%?LÿrDšÀƒ€þB„¤ÀºsFbè?ì3ÑÊd–º¿ã4Ÿ!ä®À¼;²vfÀó†@[ÀË Ši&ÓÀóQyZ¿óúF˜ƒ»?ã7Q¾V ¥@ Ì8ù$@xŽæõë[@è½”é[@ Uö½"ðÍÀÞúùAJ¶Àî0 !À ½OÀ -wú·À·2ÝQ4CÀœÚë¿—$¿ü\#_Ê ÀŽâGÂý.ÀY5—C Àæ…[VWÀNþõªÀÅùƒ1UÀ{§~DÀ'_·¬L@:À»””g@Õ·»™‹@™£¼¶d@[µün´ÀÀã‚ÓÅÀ†oCIý ?ñ' &‰8@2'Ð!¹@ÍÊm¤Èò@! ˜iã@^©ÁXü@GØzlf¨@â[@ DéZH­È?à5PÌ ?üÚº6›ÜÁ@ ÕŒU^3 ?ÝÚêI$®À…Âôüè¤?þ-Ÿ £·@ƒx߃JQ@ )·P{ú—¿új©,Š¿é®à B?ô9¾?ûã\9 O?ð‹òSWúÀ!Z[öõ3À Å7‚ÓjÀgæº>5•¿ÕO¼#$øy?ú ™5?ø[r_kH¿Óu4Í(߿˕d¯šý?þÒ¢ôbE?üŒ óFÌ]Àuµ&ÎfÀ D&…€u˜¿òén² ¦Z?­¥¢µÂl_@­ªÑ ¹@…%¬E9¿ö}YŠðÀaë?p4 ¿ð6 Ð ¿ûpd‰æÞ'¿õ%bêé•¿åŽÉ¨‰Lä¿ð™cÙ>•Àñ1ê8„²À@¯ñ3ëÀç<.ƒ?á4×ói@céB?ë?âß#…¾>¿ï$$,ác!À·/31¹”Àÿç`¦Ï?¯ÖÂ¨Ž¹?þÃ{^?cò?ñŽç—XX"?È}I²9’?äŒ$pñ< ¿Ã}ëð8SÅ¿ÿí¹[Éï¿þÛæå8úÀåÂföz¿ò©¥òß»'?ñ q¹„ñ?óú>Fš,¿Ý+.^ʈs¿ã¾ìž˜?õb…ô|¦â?û ;crpË?˜òFvÞ¿ów®O‰¿õóTî3œ?ïø@’Qd?ú‚ã6rß³?ôb“Ó÷x?³F,0¾¥À†ê[ÜĦÀÔì z@ E\¤¦a@‚ 5H›ö@<¯ý¼i¹@-„Äîä,?ú´°ß7ä?ã¾eØäÙè¿åÊJi&`ÀÛV˺T¿ú~¦ƒ×µ¿Ã©@âA¡?àe %ú¹°?É/õLF©?ë8*N'?×oª<ÿÑ¿üdPǯ»©Àûîè²Å¿ôFmx\-£ÀMZèø¥ˆÀ–›¢‹pÀ³¸¡ÜÂYÀßEY~À"…\ƒ?Ô¬û™(8þ@‚½ŒÂ@ëŠvÆÌ?øY“=S`¿åL”ß“?ñÕ?óž@âð]¶M?û~Ç Dv?ÿÐæ"Ά²@ ŸÓ!F ¦@´C«.#Ì?Ý­RjÞ±¿ðly(]¦-¿ï¥ÏS ¿R@Ô2æ òÄ@ Ax@?ØE°!‘º¿õ‰¡¹* ¿§Ü‚¼sBó?ºË Ò¦>?Ù™L–C«?÷±1g¨í?û²Ällqv?úþhhw‚?í³Z9ЦW?ÍÇ4Õ¢ñ²?üA3ïkŠ@ìýçÌ@qÞPº ?çÑf¤bc?ñöðÒsÉ»?פûÙóÀlT~†mÀ$Ǭb¿ôêS ¼~q?¤S‡˜µ0 ¿XJÓ‚½a¿ì(Ì¢uƒÀ¿ÊY(‚ÝÃ@¹ê¯!@+ÃsyŸ@ZÐeiä@¼U«î¹¿@v½±¬c?á/´¿âmŽ?Üj÷S'?ø¡“ë—x™@¨Gÿ~q§@Æ 9±Ø¿õd¬;i÷cÀ ´…#õ¿úh†Œœ@ `b˜Ú÷k@ _6laè@"£¾ƒK@ªˆõÚl?æ=»pv¿¿ÁÃc#v³ýÀ >”ì¹»¨À (fýZ:¿ñk“%ñø¿Ý=¼ê.¶¸¿Â÷e;˜E÷¿êëSïŒñÀ ˆR <À À {û¿å½µƒÊ?ýÂ((„d?Î&$p›¶˜À+˜ÍQ ô¿û!¹7‘?þY‡¾^s@ÒæW)tj?ûÊBïá@°ÕK;~Â@{=ñ@1@2ë·ah?ú~©YÒyº?÷ßj”-©¿ÃÎ ·ÄÀ^ÏmƒÈ?Ä?Ñ„qÑ @÷w”|û?ðî-Kæ´¿ídÉØÕ ÁÀšöþœ¿À©Â\¼•꿾Q\ºôGw@ )t™W’¿ÇºªGxWšÀ¾¶3o6?æã—wŸ?óPEL J?õvì)éu@£À8ÔDB@ÜéV´r˜?÷õþÒÛA?ò‚‰¢†É¿Ù¸«~·M¿ú3; cŸj¿ùûUêhj¿ø±È{?Ì”Ó v‹@ÒÊšÔ@ ÓÝDb£q@в`>@ÀQ»ÎÈ@óÍîÞƒ.@„.Pî&@4Î2½@½A-´-ñ@4?*ç›@˜„Çäg¥?óPCX]U:@ ØÞ‚Ìî@Á—ß0–@jRüJ?õRøO\?üáJ'û/^@U¥ö Y@HrʰI`@&¤Iè‡~@!ñ÷*…@Zø=©C9@›Ýœ¼9Ò@·Q´dM@ëNTÁ@èR¡ÝŸh@?øÄV(@ I@î@¾¤ {v?ÑD†\w@Š-˜?îŽÜ$™i¿ÿ_'6žÅ?®§å²ÕX@ÅAQà Ó@Z€Á’@ %“Yüƒ×@´æ÷Ÿ@Êúé!}@ -—nóî@M¹G­y)?ð&š‡ãúQ@êÉÍÄþ@6.óŽ@=R[Ì /@ Pî™4wŽ@ /Ožm†œ?ÿ‚Ôÿ„/?Ñv¾ãDó?ðë\©ü?óŠ{Ó8{Ž¿ó[O<¶BA?ÊmâÒ™ªK@ÒŽ¿û/ÑÐâƒ@J͑ӈ@&Wš=ô¿Ü,—¿ãÿú4¾z &¿äŽCÊ q@ö߈·G™@‚Ü:Û‘å@cõ‹°š@/àñÓ@ ÁÎWkƒ@ÐA¬ž ?ø†»Ž´Ï¿î©YÓÚw¿éG“9ÆY?ãøøÖ^^@$nóJ?ç¶k¡£“¿ò…~¨§­?ß qWÌ@ ‘* w@s¸¨1N@luÏ)‚?ïw¸e5È?äÔü¤Øé¿”½}¿à ¿ûL!iWW?ô*ýª€êØ@ ƒšG'kj?ñxݯ>µ¤?ªÒªwpc%?ðØÄ2S[èÀ8ñµÒÀðSصfØÀ©ÌV‡zóÀ÷M ¿Ü°`Ü  @ @n¹«ô@ÊùiECì@ êãŠ)tÐ@ 0Ê-–@Š?ù"Ž3Ë¿ïÂQV¢ìi¿ó:D”r0‘?Õ “Üì?üÞo{p„2@,ŽüÑ †@ _PÉŽ‹Ó@”©µXä@à]K.G?×»,JHr¿¸ëK8&?öºRwÐÿ?óugð¿íô]îÁ+¿ÿ”ÎßSÔ¿ò%X$3i•¿ë ðÃHn¿ç8Á¼G¸¿è† x·OÀô½L?<§À[e²naµÀ¿»8o‹Ù¿ñŽÓü‚À¨½š!ÀZ,à((Àƒ#~ F0ÀNÊ,Æ·u¿ù{ëGx,ÀØ$ŠZ ¿úÌJ‘q?ód÷(vÚc@Ò£¸ @­±ÚR8Ñ@˜ TNP?çwÂдNÀæiË/|¿×ïIjo?ôä™É-•?ñÚk„lV@àµOW þ?îw t#ÀÑò3+õÀ¸›—õv¿ö;Ûó$‰b¿ôæ°,¥¿þ±Ì¢óqò¿õ²å‰}Ùþ¿ñ(ÜÍ¿û×x¥õ1k¿ãj¥ædJ?âvCG52¿Ô»G ÔÔÀMÞ÷6ÀÞ5.4‰ÀÑ—Þ}\ ÀCn_áåÀ Sk†‰ æÀ4‹{w`¿þóº29_¾À›o¶`À …a Ð[¿ò—[žKÜü?óC5´_9?ã–FÛ&l?䮨û`¸?ïÓìƒÅŽ?É+âO¯œ ¿è8Ø?ù4=¿â=Ãíœû¿õ”Nëa!¿÷¸sÐb97?ø¶Té6{@ 'HÅøóÐ?ññÞˆÓ?Á¡g'E›?ôpÿ¸¥Ñ‹¿¼ø`‚áY¿ñ|'ªÙÄA?þLIÕxaI?øžÔ¡¤Ð[¿óf>\¡ì¿æÔõøl¿Â*K ¯¥¿óF·[‡Vs¿òËþÊ,=¿÷²üü0G¿ðZ0[®¶©?ðzïœÆyÅ?öJÀ÷D×?æ¼tŠ:Û?ðÉçØiß@yx•|qM@s@›yp&?úÌ%Vço?ì‘ßk®¿¶5š&&£?üÒ“cpÇ›@(¦¸F²Í@0Niw@š@Xåaj@¶aà0¹@\sO;W?ûjð .?ø»9g¿õÍ‘ê'‰Ê¿õ¸Ì<ŸD¿æëá̪b=À<¿gÀ|l«µTÀ½Þk¢ Ü¿úx“cjÆ@$ÚPP@gtß¡@û°»ê,?Ý ;sDsÀ"M&2å¿×)Ä‹~ÒÜ@ 9v~v?üÒê<É]?óßÉOÅ.†?óú>0•>¿¤»_ =(¢¿Ø{|ÝPq/?ôëéß ?òvó@Î?ñ¿«®‰ºÆªk?ô(t¦~ý½?éGÁ(Bµt¿ê"¤é¥ª¿÷—N蜕+¿öÐY´b¿æJŠÓY»¿ô“ÚÄhýòÀ½¿¥7º¿ý§§‰!w¿÷‹\Zaã¿ÙŒxü²Ö¿ÝøšÍž@vÀ¡À6zC¶À ?ÐK§÷À~3›.¿øŠ#ÂÑ\;¿êh <'¦`¿éªq‚$å©@ž$ ªKy@\5Þ ? @ÌЀšP@ÙèKL(Œ@™‡¶ÿ’÷@Yª|w`S@PÛõ@Ûw¹¡“ @!ˆZ@_KOœGb@!ö55Ú@å öÞ@¨ÊZÐÖ@lòÐþ‘­@1™^b_?ÿízÛ|îK?ÿx¼Ø…¹Z?ÿ÷‹þú€?þ’)ÏVA”?þ R|Ù±?ý¯pnKÉ1?ý?‚»Ñ¯?üЇŒ­p?üb~q„Ü^?ûõf > ?û‰=7l§¸?ûÔ<D?ú³µÀo•Ó?úJTÛaëÉ?ùáß¼Ï?ùzSå_Ï?ù°"æð?ø­ô¢xœ?øIÒ6’‚?÷å0yGƒŽ?÷‚%{+ñð?÷ý»ü˜?ö¾¸ ië¸?ö^S¼Å?õþÎéÓn?õ )&‰.?õBaÅ̺?ôåušX ?ô‰e¸\?ô.0Jèh'?óÓÔ<+{)?ózPuëIa?ó!£âÅ™ ?òÉÍmïë®?òrÌ7~?òžH?ñÇCþIý/?ñr»>¦ È?ñ>A±?ðÌëà—î?ðz6ÞšÍ?ð(µ/Ø?ï°jʹǼ?ïU%Ó?îs. è8ž?íÖí’Ô‘7?í<=¯7I?ì£{¨ú?ì …MlÚï?ëuyÝå8]?êàöv¢ò?êMùwârÙ?é¼€ZvÔ?é,‰2;ô?èžR?肱¿Ë?ç…šÝ2éF?æû–ñûB?æs µ_Ã?åëôÇNÎ?åfQt‘ù?ä⮼"‹?ä_]ËipU?ãÞ lwa¥?ã^ S\?âß¡)ŽÌ?âb‰?yûÏ?áæÖÍŒ¼È?ál‡Ó®’—?àóšR÷*?à| M­¨½?àÛÇH§i?ß" ˆÜo?Þ;•çÁ?ÝVÎý@¯?Üu2"ÅÖå?Û–<ÅÉY”?Ú¹êÁ?Ùà8.»/?Ù !&«?Ø4¡Ä;¿b?×b¶'ÕÑ?Ö“ZqãDR?ÕÆŠÅÄj?ÔüCI8€”?Ô4€$]²Æ?Óo=±ï?Ò¬wޏ.?Ñì*x±‚°?Ñ.Rs3W£?Ðrë±N?ÏsäÔ,}Ö?ÎÅ« aw?Ìžr]áØ?Ë:ãg˜âE?ÉÜG×ZÃ?Èôƒö@?Ç,…¢;Cl?ÅÛ½3c«)?Ä“ÉpC?ÃHú¸¯„?Âd[_ü?ÀƇ¦ÙRŽ?¿ Ïdq?¼®&¢÷?ºL& N&?·òÔÀe©?µ¢_ã&??³Z¥àêz?±•µ§:5?­ÊFî à]?©nȇ?¥#¹:^>Ö? éÖ˜ûD*?™v•¼zµ?‘P•“íp{?‚¢Œ®­ ?UËn0¿yñM!&Ø¿ŒT \Ê¿•·² ºÎ¿%ÇÌÌî¿¢9f¸õ¦c¿¥ÐzƈN¿©Wágü%¦¿¬Ï¶e·Þ¿° º”¾æ¿±Èdÿ³mp ç"¿µ ÁƒÎŠå¿¶ ŽüuZ¿¸.æ5ML^¿¹µÔÐ'¥t¿»5heYôD¿¼­®ƒ¾e¿¾´°²-D¿¿ˆˆh±à¿Àu›Ž,0´¿Á#g.#h¿ÁÍ­ŠÉÜ•¿Âtu‡ù-¸¿ÃŸø ò¿Ã·¤¿Dš»¿ÄT7Ÿk¿Äí)º í!¿Å‚ÜÙÉ«G¿Æ9%eӿƤE&¤Û¿Ç0b”(þ¿Ç¸†Y€š¿È=Ȇ÷óü¿È¿ÔaÍ0÷¿É>°\g˜¿Éºbã V¬¿Ê2ò_‹ã¿Ê¨e50˜¿ËÁÃ)$ݿˊcÕaœ¿ËöQlÕJ…¿Ì_‘/ ‚@¿ÌÅÓöœÑR¿Í) ð&>¿Í‰{®®•¨¿ÍæíÃYÍ¿ÎAz—[ӿΙ*Iç‡í¿Îîg$¬¿Ï@ á{œ¿ÏDˆy„Ü¿ÏÛºÔX^޿й &¿¿Ð689 Ýp¿ÐX]÷—›—¿Ðy-P¼4¿Ð˜©G-­;¿Ð¶Ôßšï«¿ÐÓ³nm¿ÐïFòkËŠ¿Ñ “eùÅÈ¿Ñ"›mÓ ¿Ñ:aþ‚Ó>¿ÑPên¹'¿Ñf6ŽÌж¿ÑzJo'`Š¿Ñ(œ«fš¿ÑžÔ%ÛŠ¿Ñ¯Oˆ¿Ñ¾žXkõ¿ÑÌŠÐcοÑٿ̾ƒl¿Ñ嘹hZ¿ÑðP,hÃB¿ÑùéíWµ¿Òfxüv¿Ò Ê*‚šÒ¿Ò("/f¿ÒRØÉÇ¿Ò}¨Œd¿Ò™…䬨¿Ò«asf¿Ò´Š\;®¿Ò¸³sø¿Òº欿Ò»³M6¿ÒÀ3)ð¿ÒÊQî.¿ÒÜÆFg,¿Ò úICuL¿Ò%ŽP Ô¿ÑüaGS0Ú¿Ñó°#Ôý²¿ÑêÐþžˆ¿Ñß‘ùšR•¿ÑÔ*Fkð¿ÑÇà\vOʿѺ¶àpvF¿Ñ¬°sPjj¿ÑÏ´Ê]¿ÑŽ?!G¿Ñ}‰®Ô¤°¿Ñl)šòº¿ÑYù˜ïqm¿ÑFü;ßÇ„¿Ñ34yÌr¿Ñ£±¢ú¿Ñ M¨¿Ðó4cί™¿ÐÜZŠÁŠq¿ÐÄ—\€u¿Ð¬o ƒ¿Ð“biØE¿ÐyŸ, v–¿Ð_'Ѓ©-¿ÐCþÏH=Ë¿Ð(&ŸD¿Ð ¡´#¿ÏÜå¬Ûä¿Ï¡6æ|4¿Ïd=óöi\¿Ï%þþª9:¿Îæ~×h44¿Î¥ÂJC%†¿ÎcÎþ0¿Î §åÕ¿ÍÜQñçt¿Í–ÓfS˜ ¿ÍP0*äoÚ¿Ílîpп̿Ž[Øv¨¿Ìu™AuJ¿Ì*‘È:,¿ËÞ}ð ,¿Ë‘_gÈX¿ËC=ƒÆ°Z¿ÊôçYÍ®¿Ê£ÿ2Ž<¿ÊRë§CöÜ¿ÊæÃ1ü¿É­ò¼'è¿ÉZ8*†Ì¿ÉTîdzˆ¿È¯³M<×Ä¿ÈY5¼ Ü¿ÈàžðΘ¿Ç©¸TõãÌ¿ÇPÁ8_tØ¿Æöÿž¶€¿ÆœwØÄ2¬¿ÆA.2–Ñ`¿Åå&ó|М¿Åˆf^H ¿Å*ð° u”¿ÄÌÊ"˜¼ð¿Ämöê ¨(¿Ä{5þæä¿Ã®[1KN\¿ÃM›Û¿Âì>ɬ­¬¿ÂŠJ¤Ä`¿Â'«:j¤¿ÁĪð6U\¿Áa‚ ˆœ¿ÀüÜj£ãT¿À˜-®­k¿À2ÿNlK¿¿šªŠ£©€¿¾Îg"ý°¿¾<AÎ8¿½31€o À¿¼dO G@¿»”œKà ¿ºÄ!ÀnÔð¿¹òæV‰Ü€¿¹ ñü¡÷¨¿¸NLT@u@¿·züõrí¿¶§ nËF°¿µÒE_²x¿´ý_ôÊ­è¿´'´ï+˜¿³Q…#Ű¿²zÙ]ÜXX¿±£·‡fø¿°Ì'd¿ë`¿¯è`sžU ¿®7²~ÍiÀ¿¬†SJ†ÌпªÔQ#LÒ0¿©!ºBªa ¿§nœÏ2ü`¿¥»Ü‚º ¿¤k>Là¿¢R©iü€¿ ý°¶¨€¿Ò"Ï•@¿šgâRÚâ¿–ýWb.‰¿“’œ_{€¿'ÌB‚ À¿‰zº,‚¤¯¶8¯€¿wŸ£ #¤¿cîw›È?M{kßx?qSð0Ì ?~õäèþ(?†Jr42½?DÈK?‘ò‹²W?•W J…2?˜ºÕLÑ?œdáh€?Ÿ~ŸÊ$º€?¡o6ˆ_  ?£Z1‚`?¤Ì®= ?¦z&îŽÒ€?¨&¸¡ ?©ÒUž+ÍÀ?«|ó®-?­&†d€q ?®ÏùŠÀ?°;-\=¢?±BÝ÷ ?±àº @¦?²²ÿ>à?³ƒ¼é7 ?´T;²tÿ?µ$¹ÉÏð?µóg?ß?¶Ák,]Bp?·Žù„#Ç?¸[½óê?¹'³ß°?¹òÓW¿?º½…æ•0?»†€;ÿ?€?¼O-ñ’€?½š!Eà?½ÝBÄmÄÀ?¾¢÷20?¿g±¦EZà?À¶Ìüç@?Àwäâ¨?À×ê“}˜À?Á8;[+Ú ?Á˜¿ºU8?Á÷>J‡Žè?ÂU뉯ç€?´ ˜ð?Ñu8¸p?Ãn…U‡40?ÃÊáR Õ?Ä&£›<@?ÄÈ;Áæà?ÄÜN‚Î,?Å63™Ë<À?Åu9‚" ?ÅèyÂ?Æ@ öÛ?Æ—NËü ?Æíì%Iµ@?ÇCÚê^5À?Ç™ðu®?Çí¤Š!P?ÈAz,Sg€?È”™$G7à?Èæþá™ °?É8©Q:‹?ɉ–dÚ¹ ?ÉÙÄæÊÐ?Ê)0V‰µ?ÊwÙ/¬J ?Êż¢õ5P?ËعÈû@?Ë_+‚Iü?˪³Xr0?Ëõmx’nÀ?Ì?XÚSá0?̈sU¶`?Ìл’?Í.5|Ð?Í^ÊóÇÐ?ͤ†@?Íéz†vÀ?Î-ˆçU¥P?ÎpºC>_?γ lI<`?Îô}®<®ð?Ï5 YÀ?Ït¶Ã¬]P?ϳ{Fj¿À?ÏñX@–P?Ð& Ôï?Ð5*–ïíà?ÐR¸û²È?ÐoÐp&ßP?ÐŒp1W(?Ш—|@“È?ÐÄEÚÿx?Ðßy±|™P?Ðú3"Ú£x?Ñq, Mx?Ñ.3{³h?ÑGx.ÞÈ?Ñ`?ÀÒÅÈ?Ñx‰xLH?ÑSœãAØ?ѧžŽad¨?ѾiKŸ^h?ÑÔ³.¨ÇX?Ñê{“è#€?ÑÿÁÚ&ä°?Ò…bhè?Ò(Å¢ü0?Ò<ÊMÖØ?ÒO¹wÓ°?ÒblÖæ?Òt˜Û\,¸?Ò†?mÄß0?Ò—_,Ñ×H?Ò§÷Œ¢Ûø?Ò¸¶ p?ÒÇ êÅà?ÒÖ{Ù€?Òå¹V€?Òòð]¤`?ÓQJÀ?Ó 'ÍôP?Ór£ÿfÐ?Ó%1›y‹°?Ó0d?Zl@?Ó; Õýð?ÓE"Ç#à?ÓN­ÏG® ?ÓWªÊ€YÐ?Ó`PØÐp?Ógøü_©?ÓoIi‚i0?Óv 7 à?Ó|;,LP?ÓÛzi`?Ó†ë9­@?Ó‹iì@ƒ ?ÓW<ÊVð?Ó’²ØPšP?Ó•|n89€?Ó—³°E 0?Ó™XR™Ûð?Óšj ¸Yp?Óšè”%0?ÓšÓ¨3Íp?Óš+nË?Ó˜îi/‡?Ó—˜ÒUð?Ó”¸Xwp?Ó‘¾n °?ÓŽ/¤2\ ?ÓŠ ÆcD0?Ó…R¢ÓÆð?Ó€ È?ÓzÏ*?Ós¥ÇXn@?Ól•ÊWz@?Ódï²8Ð?Ó\³[lôà?ÓSà¤ÃWÀ?ÓJwojVà?Ó@wžï<ð?Ó5á>A ?Ó*³Æ¢‰ ?Óï‘Æ& ?Ó”g²@?Ó¢7ÎHð?Òøóá’Ð?Òéøº ?ÒÛAãs€?ÒËòE:^?Ò¼ RY°?Ò«'àæÀ?ÒšzÅÒf@?ÒˆÏ.ŒØ?ÒvŒfÎ~p?Òc²u´† ?ÒPAd» ?Ò<9?½°?Ò'šô™ð?Òcôúz0?Ñü–òÆ…À?Ñæ3#¯xÀ?ÑÏ8Ÿjü ?Ñ·§€ §?ÑŸâ ûÀ?цÁä5j0?Ñmm§¾P@?ÑSƒP5ø`?Ñ9‹™0?Ñìê Wà?ÑA.hD?Ðåÿý¨^Ð?ÐÉ)‡8‘?Ы½üâ´p?н’ÏŽ?Ðo(†ÏÐ?ÐOþûïP?Ð0ACMù`?Ðï“Gæ`?ÏÞWÀ@?Ï›"žòãÀ?ÏW …©HÀ?ÏÌš$À?ÎËioaŽ€?΃á³@?Î;5¿ÒsÀ?Íñfx·€?ͦtm¨€?ÍZ`I§4€?Í *»Öƒ@?̾ÔxÁ€?Ìo^8õÀ?Ìȹ±þ@?Ë;N–?ËzC ŒP?Ë&TsO—@?ÊÑIÀ:¸À?Ê{#É­Ó€?Ê#ãiÆã@?Éˉa¾?ÉrîÀ?ÉŒžAo@?È»ë|ó2À?È_4|Ÿ?Èh‘úÉ?Ç¢ˆº0¥@?ÇB•ô®ÿ€?Æá‘F@}@?Æ{¸mŸ€?ÆVY|¿À?Ÿ"¿¿±R†o`¿²G#\®É€¿³|D _–¿´²°V ¿µêcx²¹¿·#Xù]ŒAÎ…¿¹˜ø®êF¿ºÕ™–]z€¿¼jCÈ6€¿½ReùNÓ¿¾’‡ï™ñ€¿¿ÓËUÖ‡¿À‹¨Ú怿Á,Ѷ§€¿ÁϸÛr€¿ÂqâØèU¿Ã3_¾ƒ€¿Ã¹È`€¿Ä]W‰–j€¿Å&¥I¿Å§nÖ—Ì¿ÆM/7™è¿Æód›´¿Çš _Çt€¿ÈA#ß•Œ€¿Èè¨o¸‡€¿É—`§¿Ê8íþ¿Êá© †¿ËŠÇU»€¿Ì4D¦S¿ÌÞuŽs¿ÍˆR;wm€¿Î2ݧ€¿Îݼ¥€¿ÏˆìŽ;®¿Ð5¾»z@¿ÐpÒŸÀ¿ÐÆ$¥+…€¿ÑQ)/xÀ¿ÑrŸèÝ¿ÑÉ ö(À¿Ò™EÊãÀ¿ÒvB‡-ª@¿ÒÍ7º+€¿Ó#åÒ &€¿ÓzÜаr¿ÓÑê¨\õ¿Ô) ͸©€¿Ô€D²w€¿Ô×Åîñ€¿Õ.çuØ@¿Õ†P*€˜€¿ÕÝÆNjŒ€¿Ö5HF¬€¿ÖŒÔv¿Ñ@¿Öäi?Á4¿×<l퀿ד¦ µ€¿×ëJ×ÛW@¿ØBñ <±¿Øš˜Ã…´€¿Øò>”˜eÀ¿ÙIác÷ÛÀ¿Ù¡È?À¿Ùù3ÎЀ¿ÚP¦ÉqÝÀ¿Ú¨,‡¸É@¿Úÿ¦³L ¿ÛWŽu*@¿Û®qYÄÀ¿Ü¾PÔˆ¿Ü\ø°Ã7¿Ü´±¸¦€¿Ý .Š#¿¿Ýb&nyÀ¿Ý¹;äÀ¿ÞÇì$@¿ÞflDg€¿Þ¼ò/Tø¿ßW×-À¿ßi˜ðuyÀ¿ß¿¶§V€¿à ÖB¬à¿à5½8d“à¿à`Žöæ½`¿à‹J‹GÀ¿àµïS÷à¿àà{c¬p@¿á ü`¿á5HÎ¥`¿á_†lé@¿á‰¨Òð2 ¿á³®H•Ü¿áÝ•Ñ\2`¿â^o•ðÀ¿â1$f[ ¿âZŽïÁ@¿âƒôÐjö`¿â­7Ãøa ¿âÖVÆÎéà¿âÿPÔ$…`¿ã($åÿ° ¿ãPÑõ7rÀ¿ãyVùs] ¿ã¡²é+‰€¿ãÉ乨šà¿ãñë_¿€¿äÅÌ&­@¿äAròˤ€¿ähñÃ}nÀ¿äA-—_ ¿ä·`ER¿äÞM…ƒ®@¿åLb@¿å+]µç ¿åQᣵ@À¿åwþ[ú¿åãl¹(€¿åü¬k¿åéÚåêÀ¿æ>ªæY€¿æ3=þò ¿æWþèQy ¿æ|ƒÐ?@¿æ Èy>À¿æÄÍí.lÀ¿æè’O à¿ç yö«`¿ç/SH €¿çRM’à¿çu/°ê¿ç—o÷e@¿ç¹•¾ro ¿çÛrXðŸÀ¿çý™ÇÞ¿èKR°ì@¿è?ET5€¿è_ñm®%À¿è€NmF@¿è [ù ¿èÀQ‘5À¿èß~̪ø€¿èþ“Z²ÕÀ¿éRÃåÛ¿é;»ÏQ›€¿éYÍBÔ9@¿éw…ã[€¿é”äs©5¿é±ç¶Ê€À¿éÎŽm „€¿éê×X@¿êÁ4þx@¿ê"JÁÙ À¿ê=r»õÀ¿êX7ÛÔj@¿êr˜Þ*|€¿êŒ”zæ4À¿ê¦)i¬$¿ê¿V`ñd€¿êØûš€¿êðs<àó@¿ë`ˆˆ&@¿ëનs¿ë6òSɤÀ¿ëM”3DÀ¿ëcÄ÷@€¿ëyƒL¸‡@¿ëŽÍßuí¿ë££Z7€¿ë¸eûiÀ¿ëËé«j¿ëßWÑkA@¿ëòK}Ûœ@¿ìÃUhI€¿ì½ûŽû€¿ì(:î@¿ì96;³ç@¿ìI±À5@¿ìY©B‚±@¿ìi\‹»€¿ìx ÉÓ¢¿âöaüäK¿â¬ÉÒ™¼€¿âaþ°­Ð€¿âþ´ªê¿áÈÇúëó¿ázXžœc¿á*®¹¸9¿àÙÈe þ¿à‡£¸4¿à4>É $¿ß¿/]Œ¿ßXö±¿Þdöƒä%¿Ý´)õl¿Ý~ D¿ÜJ`@qá¿Û‘¦ëÁt¿ÚÖN%¤¿ÚRöR¿ÙW®†x¿Ø”`Ž¿×ÎbIuQ¿×±zEP¿Ö:I¢¨W¿Õl&Ë鸿ԛDüõÙ¿ÓÇ :Z6¿Òñ4†E\¿Òýà†ê¿Ñ;øF•¿Ð]³q ¿Îöà?¼Æ¿Í-ËVš¿Ë^÷œ™¶¿ÉŠ]ë²@¿Ç¯õÐz¿ÅÏ·#^Ü¿Ã険•ø¿Áý•e芿À ¡ðÍt¿¼'nCûp¿¸+™vé¿´#´ôÞp¿°°.Úx¿§ÞõÀ迟 ­ß€¿ŒQÑdÀ?g^A'€?”2G?4à?¢Õk÷H?«ªÞ¼°È?²LÎÒIH?¶Ðå;û ?»aÉEˆ?¿ÿz±x¸?ÂU Ú±f?İÛϦr?Ç/Á}ö?É|>Ø@?Ëë‹Ûz?Îa¥.K ?Ðo3j­I?Ѱì¸ì?ÒöÕ Å?Ô>z™D?ÕŠVÏz ?ÖÙ_öì?Ø,R"¶!?Ù‚yv½)?ÚܽpY?Ü91Z’ø?ݙʴG3?Þýè3$?à2Ç ãì€?àè`¦Ù¤?áŸÂã7+?âXðúê?ãêdR¿€?ãдœ€?äOzc}?åO¾µes€?æž?æÖ!Å÷,€?çœìÅ?ècïUè„€?é-£´“þ€?éù9}È<?êÆ²÷½€?ë–iy€?ìgZÛÝ€?í:ŒVbÍ?î«fw¢?îæ¹—.?5Q¶€?ðMVGÈ~À?ð»Êú©?ñ+;Û¤@?ñ›ª¬F€?ò ÌI¶€?òƒ/×À?òòðhakÀ?óg_¡äñÀ?óÜÒ¡?ôSHÇdo?ôÊÅ ø ÀXTENSION= 'BINTABLE' /Written by IDL: Thu Jul 8 16:06:31 2010 BITPIX = 8 / NAXIS = 2 /Binary table NAXIS1 = 32768 /Number of bytes per row NAXIS2 = 1 /Number of rows PCOUNT = 0 /Random parameter count GCOUNT = 1 /Group count TFIELDS = 4 /Number of columns COMMENT COMMENT *** End of mandatory fields *** COMMENT COMMENT COMMENT *** Column names *** COMMENT TTYPE1 = 'VHELIO ' /Heliocentric velocity [km/s] TTYPE2 = 'FREQ ' /Radio frequency [MHz] TTYPE3 = 'FLUXDENS ' /Flux Density [mJy] TTYPE4 = 'BASELINE ' /Subtracted Polynomial baseline fit TUNIT1 = 'KM/S ' /Units of velocity axis TUNIT2 = 'MHz ' /Units of frequency axis TUNIT3 = 'mJy ' /Units of flux density axis TUNIT4 = 'mJy ' /Units of subtracted baseline COMMENT COMMENT *** Column formats *** COMMENT TFORM1 = '1024D ' / TFORM2 = '1024D ' / TFORM3 = '1024D ' / TFORM4 = '1024D ' / TELESCOP= 'Arecibo Radio Telescope' /Designation of Telescope INSTRUME= 'ALFA ' /Instrument in use BEAM = '3.5x3.8 ' /Beam size [arcminutes] OBJECT = 'AGC 100051' /Name of observed object ORIGIN = 'CORNELL ' /File creation location RA = 2.0037095 /Right Ascension in degrees DEC = 14.839847 /Declination in degrees EQUINOX = 2000.00 /Epoch for coordinates (years) RESTFRQ = 1.4204058E+09 /Rest Freqeuncy [Hz] COMMENT BW = 24.975586 /Bandwidth [MHz] CHAN = 1024 /Number of spectral channels COMMENT COMMENT Arecibo Legacy Fast ALFA Survey COMMENT Cornell University COMMENT http://egg.astro.cornell.edu/alfalfa/ COMMENT Last updated: Thu Jul 8 16:06:31 2010 G. Hallenbeck COMMENT ALFALFA archive at http://arecibo.tc.cornell.edu/hiarchive/alfalfa/ COMMENT This spectrum has been baselined. END @Ñ~•¡æ@Ñ|©8à @Ñ{6ß“-@Ñyĉºw€@ÑxR7UÝ@ÑvßèeQT@ÑumœèÈ@ÑsûTà4ª@Ñr‰KŠè@ÑqÏ*¾„@Ño¤‘}Âë@Ñn2WD‹ö@ÑlÀ  "@ÑkMí-:%@ÑiÛ½O @Ñhiäf7@Ñf÷gíLž@Ñe…Bi­S@Ñd Y|@Ñb¡¼¬Ÿ@Ña.æ“2z@Ñ_¼ÎÝ@@Ñ^Jºš ¤@Ñ\Ø©ÊH\@Ñ[fœm¨ @ÑYô’„?@ÑX‚Œ ¡¯@ÑW‰ #@ÑUž‰y–î@ÑT,[ñ@ÑRº”±%@ÑQHŸy&e@ÑOÖ­³é @ÑNd¿a`p@ÑLòÔ€Z@ÑK€í€eZWÚ@Ñ= d†æ@Ñ;œÞàÊ_@Ñ:+ Ïø@Ñ8¹f/]h@Ñ7G¯”Q@Ñ5ÕûE®f@Ñ4dJûŸK@Ñ2òž#Z£@Ñ1€ô¼ÔF@Ñ0NÇÿ²@Ñ.¬DЯ@Ñ-, 3:ß@Ñ+ºq“1ä@Ñ*HÙd©˜@Ñ(×D§•y@Ñ'e³[é_@Ñ%ô%˜Ü@Ñ$‚›—¤@Ñ# Ùk@Ñ!ŸšQç@Ñ .„ôº@Ѽ“൙@ÑK­ˆJ@ÑÙ¤ë`L@Ñh2š1Š@Ñöùï‚@Ñ…XJŽ@ÑðLÐ@Ñ¢‹¾;k@Ñ1*¡1¤@Ñ¿Ìô× @ÑNr¹“@ÑÝíþÃ@Ñ kÈ“hT@Ñ úx©Oú@Ñ ‰,/©i@Ñ ã&hE@Ѧ€f@Ñ5[då^@ÑĬŠò@ÑRáddÅ@ÑᩌfŸ@Ñpu$„4@ÐþÿD,±9@Ðýޤáb@ÐüìS@Ðú«ÅåÒ@Ðù:¢­ ”@Ð÷É‚äË`@ÐöXfŒRÆ@ÐôçM£“ @Ðóv8*@Ðò&!J@Ðð”‡3–@Ðï# \ß)@Ðí²¢¸@ÐìAVž @ÐêÏÿz˜¬@Ðé_ ê|@Ðçî‡,@Ðæ}‚br@Ðå cp@Ðã›.³£¤@Ðâ*Brñ @Ðà¹Y¡KÛ@ÐßHt>§í@ÐÝ×’Jøö@ÐÜf³Æ2ª@ÐÚõذH¿@ÐÙ… .ú@ÐØ,ÐÙ@ÐÖ£\:»@ÐÕ2ެGÎ@ÐÓÁÄ¿óÛ@ÐÒPþB2¼@ÐÐà;2ø7@ÐÏo{’7Þ@ÐÍþ¿_å›@ÐÌŽ›õ@ÐËQFZ@ÐɬŸ_3@ÐÈ;ðåóZ@ÐÆËEÛD@ÐÅZž>O”@ÐÃéú¨"@ÐÂyYO ¥@ÐÁ»üpÏ@п˜"Èi@о'‹¡L@м¶ø˜!@лFhý v@йÕÜÏ´]@иeTs@жôξ ~@е„LÙÉ2@дÎcX@в£SY¶@б2Û½û@ЯÂg $@ЮQöÎ¥ž@Ьá‰zÿl@Ыq”¡1@Ъ¹~´@ШV‹©@Чöp»ý@Ð¥¯š?R@Ф?AzU€@ТÎì"¦>@С^š7é?@ПîKºp@О~©r@Ð ¹æ @ЛtÍx-@К-4¿a@И¼ö¤¯–@ЗL¼³<€@Е܆.Yæ@ДlSû@Ð’ü#jC@Б‹÷*šÈ@ÐÎWå@ÐŽ«¨ð¸b@Ð;†ö8@ЋËhgò–@Њ[MEÛÛ@Јë5ç@Ї{!F ¡@І h5¯@Є›ö_ @Ѓ*øð{@кòV|@ЀJï(V2@Ð~Úïeý?@Ð}jóe&@Ð{úú$ˆ@Ðz‹¥FQ@Ðy‘§5@Ðw«#é—ü@Ðv;8­ ’@ÐtËPÛø™@Ðs[lvOê@Ðqë‹|^@Ðp{­í½@Ðo ÓÉ_Î@Ðm›ýêX@Ðl,)ã!@Ðj¼Yá~@ÐiLjnÚ@ÐgÜÄ^iV@Ðflþ½aT@Ðdý<‡J™@Ðc}¼í@ÐbÂ[À<@Ð`® f4:@Ð_>UÛh®@Ð]Τ»Q„@Ð\^÷âq@ÐZïL»`@ÐY¥ÚÌ@ÐXe +@ÐV bYÃÌ@ÐU0ŸæŒ@ÐSÁ,‚hD@ÐRQ–¶<ß@ÐPâTX@ÐOru\­¸@ÐNéÏ1–@ÐL“a«×™@ÐK#Üò“u@ÐI´[£Y@ÐHDݾ1@ÐFÕcBв@ÐEeì1jq@ÐCöx‰Ý@ÐB‡L¢@ÐA›xÈ@Ð?¨2 Ñm@Ð>8Ì .k@Ð<Éiv'‰@Ð;Z H° @Ð9ꮄ½x@Ð8{V*Aé@Ð7 91à@Ð5œ¯±$@Ð4-a“#{@Ð2¾Þ ¿@Ð1NÏ’0Û@Ð/ß‹¯ƒ˜@Ð.pK5ø»@Ð-%„B@Ð+‘Ô~ã@Ð*"ž?­w@Ð(³kj2×@Ð'D;ýï@Ð%Õùâs@Ð$eç^ôb@Ð"öÂ,Ç‚@Ð!‡ cO›@Ð ‚€™@Щg NT@Ð:Oz¬“@ÐË;SV@Ð\*”êP@Ðí>±[@Ð~PØb@Ð ËSQ@Р ®Ë@Ð1 ùà@Р¬AV@ÐSÇ‘ö@ÐäJù½@Ð u-6lq@Ð >‰Ýí@Ð —SEB@Ð (khŒØ@й†ó±æ@ÐJ¥æ¥4@ÐÛÈAZ›@ÐlîÆ@Ðþ-Û;@ÐC¿Ž'@Ïþ@çq¥#@ÏûcN38ï@Ïø…»Ã¿f@Ïõ¨0# @ÏòÊ«QBÕ@Ïïí-N{@Ïí¶m—@Ïê2E³Dÿ@ÏçTÜ}g@ÏäwyQþ¦@ÏášV°m@ÏÞ¼È)z–@ÏÛßyÊD­@ÏÙ28öŠ@ÏÖ$ñuwá@ÏÓG·°¬@ÏÐj„Wˆz@ÏÍWüç"@Ïʰ2o´W@ÏÇÓ¯×Ì@ÏÄõû½9|@ÏÂê—Àö@Ï¿;à?V6@ϼ^ܳàî@ϹßõH¬@϶¤êum@ϳÇúÞO@ϰë…½.@Ï®0ù§”@Ï«1V9ö@ϨT‚FV@Ï¥wµ^a@Ï¢šîÄGã@ÏŸ¾/54@Ïœávr d@ÏšÄz¶ì@Ï—(O$@Ï”Ktï#À@Ï‘n×Zµ–@ÏŽ’@‘¹Y@Ï‹µ°”@ψÙ'a¶N@Ï…ü¤ú~å@σ )^XÆ@Ï€C´+É@Ï}gF†ß|@ÏzŠßK\@Ïw®~Úˆâ@ÏtÒ%4N@ÏqõÒX“h@Ïo†G@—@Ïl=A=¥@Ïiaƒr"@Ïf„ÊÐÆ @Ïc¨™è!4@Ï`ÌoÉkv@Ï]ðLtŒ…@Ï[/él6@ÏX8'ò‡@ÏU\ 0N@ÏR€’@ÏO¤œ{.@ÏLÈ©ö@ÏIì.’@ÏG&$x´@ÏD4?ãè4@ÏAX`l= @Ï>|‡½^ó@Ï; µ×5à@Ï8Ä깩‰@Ï5é&d¢ @Ï3 hØû@Ï01²À*@Ï-Vµº@Ï*zXãÏ^@Ï'ž¶wõ@Ï$ÃÔ‰@Ï!ç…øš@Ï ÷ã¼e@Ï0p— y@ÏTð÷@ÏyvTе@Ïž^`f@Ï—/@Ï ç1ÇÔm@Ï Ó'B–@Ï0{M³4@ÏU*;h@Ïyßï;ä@Îÿžœj#¥@ÎüÃ_«­@Îùè)³Át@Î÷ ú‚G2@Îô1Ò&µ@ÎñV°rGû@Îî{•“’Ú@Îë zï*@ÎèÅt(Dæ@Îåêm›{æ@ÎãmÔ|&@Îà4tÓ-}@ÎÝY‚—wÂ@ÎÚ~—!Bò@Î×£²pw@ÎÔÈÔ„ü@ÎÑíý^¹i@ÎÏ,ý—†@ÎÌ8ca~ @ÎÉ] ŠU@ÎÆ‚äxe@Îè/*t @ÎÀÍ€¡‹¿@νòØÝ3¢@λ7ÝS°@θ=¡Óœ@εc *›b@βˆ}w’ý@ί­÷ˆ¢Ž@άÓx]±¤@Ωøÿö¨‚@ΧŽSnÝ@ΤD#sìù@Ρi¿X d@Ξaÿ¯>@Λµ jÄ@Θڻ™/@ΖrŠÙú@Γ&0?¬"@ÎKô·[@Îq¿òeÈ@Ί—‘ðb@·½j°œ@΄ãJ3É¥@΂ 0yŽE@Î/ÑÞ@Î|UL|m@Îy{ Ùuî@Îv¡ (¦7@ÎsÇ9õD@Îpí$ K7@În9¢æ@Îk9Uù«r@Îh_y…³@Îe…¢í£@Îb«Ó‰@@Î_Ò æœ©@Î\øI·@ÎZå­d@ÎWDÙ‡Ñ@ÎTk+éxÖ@ÎQ‘… è“@ÎN·äñ>à@ÎKÞK–c¸@ÎI¸ü?a@ÎF+-"¹@ÎCQ¨ º\@Î@x)±)ð@Î=ž²ïú@Î:ÅA@ôæ@Î7ë×) @@Î5sÑZs@Î299‹0@Î/_Áaš¾@Î,†rIpô@Î)­)ðõò@Î&ÓèX´@Î#ú­~¬@Î!!yd­s@ÎHL ý@Îo%n„€@Ζ’*F@μìt×@ÎãÚr­@Î Îvåj@Î 1É–@Î XËsï¾@ÎÔWq@Φãk6n@ÎÍù„th@Íþõ[ù¤@Íü9ñ®B@ÍùCdEyõ@Íöj•WE'@Íó‘Í&÷®@Íð¹ ´yÑ@ÍíàPÿ³B@ÍëŒj@Íè.ïÎìý@ÍåVIR½c@Íâ}©“åš@Íߥ’Mw@ÍÜÌ~MÝA@ÍÙóòÆ|ó@Í×mü®@ÍÔBïîŒn@ÍÑjxÌR@ÍÎ’ ¼}@Í˹ž2Dé@ÍÈá;M·@ÍÆÞ¸¿@ÍÃ0‰€²@ÍÀX:0{ @ͽò–)@ͺ§°˜¹í@Í·ÏuæÎ²@Í´÷Að¼O@Ͳ¶jä@ͯFî7·@ͬnÎt«Ã@Í©–µm(@ͦ¾£ Ñä@Í£æ—ß;@Í¡’º(@Íž6”ŸvÍ@Í›^?Ñ$@͘†¬›™@Í•®Â±,@Í’Ößü€@Íÿ oX@Í'-Slª@ÍŠO^SÜN@͇w–¦ˆ@Í„ŸÔƒ³ž@ÍȲëh@Í~ðeœ6O@Í|¸?|)@ÍyAœ¥=@Íviq³™«@Ís‘Ø„A“@ÍpºF…@ÍmâºRLU@Ík 5Oo@Íh3·†@Íe\?uɹ@Íb„Ξ±*@Í_­d€¥@Í\Ö@ÍYþ¤oR @ÍW'N{Ü•@ÍTOÿAŽ@ÍQx¶¾ß­@ÍN¡tõ)5@ÍKÊ9ã×ÿ@ÍHóŠÔt@ÍF×ê@ÍCD±V½@Í@mЬ÷@Í=–wWñ]@Í:¿d— @Í7èXå~@Í5S§‚@Ì×hYÎQ@ÌÔ’8©œÛ@ÌѼ9N`@ÌÎæ }M˜@ÌÌýuƒ@ÌÉ9÷!ÖË@ÌÆc÷‚1@ÌÃþ–z @ÌÀ¸ ^š@̽â ÚyZ@Ì» < 0@̸6]í¾@̵`†ƒ¥J@Ì²ŠµÍ”@̯´ëÊËG@̬ß({3C@̪ kÞ´,@̧3µõ6H@̤^¾¡Ú@Ì¡ˆ^:ßM@Ìž²¼iÖ@Ì›Ý!Kp3@Ì™Œß”U@Ì–1ÿ&+"@Ì“\x@̆÷ÊRD@̱~'³"@ÌŠÜ 7'Á@̈žø˜e@Ì…19kí@Ì‚[Ú‘d@̆‚gæ@Ì|±0ðZ@ÌyÛæ*S_@Ìw¢º†@Ìt1d²w¼@Ìq\.sD@Ìn†ýÿ•‰@Ìk±Ô¯Æ«@Ìhܲîï@Ìf–"ö¿@Ìc2€åÆa@Ì`]rYEô@Ì]ˆj}^@ÌZ³iQö¹@ÌWÞnÖøw@ÌU { K_@ÌR4ñ×ÿ@ÌO_§‡†y@ÌLŠÇÍ?@ÌIµîÂê3@ÌFáhp!@ÌD P½¹F@ÌA7‹Â­Â@Ì>bÍw6@Ì;ŽÛ:D@Ì8¹dî£@Ì5亱X†@Ì3#Bê@Ì0;zDJ±@Ì-fäXF@Ì*’T“SÉ@Ì'½ËÁ%¤@Ì$éI¶@Ì"Î(íš@Ì@Yb´e@ÌkëJòä@Ì—ƒá‘^@ÌÃ#&x=@ÌîÉÄ@ÌuºÀ_@ÌF) òR@Ì qã@Ì£±ûÂ@ÌÉk £ï@Ìõ9îÑ@Ì! ÄÄÒ@ËýLé&]@ËúxË4³¶@Ë÷¤³ðG@ËôУY³U@Ëñü™oÞI@Ëï(–3@ËìT™£i@Ë連¿ðh@Ëæ¬´‰‚«@ËãØËÿ³œ@Ëáê"kÉ@ËÞ1ñ“x@ËÛ]:mí@ËØ‰l”Ò“@ËÕµ¥hº÷@ËÒáäè´^@ËÐ+§@ËÍ:wì{r@ËÊfËp@ËÇ“%Ÿk?@ËÄ¿†zWY@ËÁëîÆË@Ë¿\2¡Ü@˼DÑÑ@˹qL˜<É@˶ÎËÍS@˳ÊWªkH@˰öç3þÇ@Ë®#}hpƒ@Ë«PG¨œ@˨|½Ñ¢@Ë¥©h ý@Ë¢Öå @Ë Ðnr[@Ë/Ž¢) @Ëš\S€»@Ë—‰)ô@Ë”µñ:D´@Ë‘âÊQÑ@Ë©œ9“@ËŒ<Ëä<@ˉi|¥:@ˆ–p($¦@˃ÃjT‹@Ë€ðk*V\@Ë~r©nÁ@Ë{J€Ñ¼Ò@Ëxw•£(Ó@Ëu¤±›x@ËrÑÓ@ý@Ëoþü 5ç@Ëm,+‚.„@ËjYaŸÏl@Ëg†žf,@Ëd³áÔ«å@Ëaá+ë¸K@Ë_|«Ç@Ë\;Ô—ž@ËYi2";ƒ@ËV––Ùâº@ËSÄ9uÔ@ËPñt@Ý\@ËNìðš@ËKLlFÊö@ËHyòE"#@ËE§~êï‹@ËBÕ8t@Ë@¬,Žj@Ë=0LÈ1#@Ë:]ô ë¼@Ë7‹¡ô¦ë@Ë4¹V…K@Ë1ç¼ÀÒ@Ë/Óšð]@Ë,BœÂn@Ë)pkKH@Ë&žAïŸ@Ë#Ì•·@Ë ú³ŒD@Ë'êx)°@ËUÚâ܈@˃Ñó@˱Ϫ$@ËßÔ‰¾@Ë ß¦´@Ë ;ð°c”@Ë jý¨É@˘'ð^à@ËÆMˆn @ËôyÅ¿`@Êÿ"¬¨:ä@ÊüPæ/É;@Êù&\Ró@Êö­m-Àw@ÊóÛº£úx@Êñ ¾é`@Êî8i~uš@ÊëfÊâ‡Ø@Êè•2ë„@Êåá—à,@Êâòè÷^@Êà ’Þ6…@ÊÝOw†R@ÊÚ}ž´Ï1@Ê׬.•ù®@ÊÔÚÅî4@ÊÒ bC•u@ÊÏ8Ø@ÊÌf°ž@@ÊÉ•a’Ðå@ÊÆÄIX6@ÊÃò×£ @ÊÁ!œ Ë@ʾPh@ã@Ê»:‚ñ(@ʸ®hÀà@ʵÜòñX¿@ʳ Ù¡Q@ʰ:Åêƒ'@Ê­i¹Zæ¨@ʪ˜³m´ˆ@ʧǴ"ÕV@ʤö»z1 @Ê¢%És±ô@ÊŸTÞ>»@ÊœƒùLÀÎ@Ê™³, •@Ê–âC­F @Ê”rÐ|@Ê‘@¨”‡Ý@ÊŽoäút,@Ê‹Ÿ(É@ʈÎqªo:@Ê…ýÁôO@ʃ-ßQ?@Ê€\vk^B@Ê}‹Ú˜^ö@Êz»Ef;¡@Êwê¶ÔÜõ@Êu.ä+‚@ÊrI­”ù@Êoy2ärÅ@Êl¨¾Õ<½@ÊiØQfVK@Êgê—¨!@Êd7Ši©@Êag0Ú–¼@Ê^–Ýìæ@Ê[Æ‘M’@ÊXöKîY˜@ÊV& ß`@ÊSUÔo]Ã@ÊP…¢Ÿ'*@ÊMµwnVH@ÊJåRÜÓ«@ÊH4ê‡â@ÊEE—[Å@ÊBu ã7à@Ê?¥ÎŸ@Ê<ÔÿWªØ@Ê:€@Ê75 G%ô@Ê4e¬Ì<@Ê1•3°î]@Ê.ÅQSu@Ê+õu”HÎ@Ê)% sR„@Ê&UÑðzº@Ê#† ©Ù@Ê ¶HÄÈÝ@ÊæŽÀ0@ÊÚx„@ÊG,¢Ú@Êw…ÒÎþ@ʧå >@@ÊØL *@Ê ¹0L@Ê 9,¸„|@Êi¦úö$@Êš'Úm÷@ÊʯVÔÍ@Éþû=p@Éü+Ò&•@Éù\mx¹@Éögò@Éó½·ó¥'@Éðîg»'@ÉîàÄ@ÉëOÙ@²Œ@É耜=eY@Éå±eÖ’@Éââ6 Ä@Éà ÛA…@ÉÝCêG~€@ÉÚtÎOcØ@É×¥¸òÚ@ÉÔÖª1Ê#@ÉÒ¢ W@ÉÏ8 ¹³@ÉÌi¥’ŠÆ@ÉÉš±>x@ÉÆËÃ…jº@ÉÃüÜgK$@ÉÁ-ûäì@ɾ_!ûx@É»N­•õ@ɸÁúD›@ɵò»álj@ɳ#übö;@ɰUC~Êå@É­†‘4Òõ@ɪ·å„÷ @ɧé@o @É¥¡ó6±@É¢L #@ÉŸ}xÈÏV@Éœ®î"ë@É™àjï@É—ì‰d@É”Cu§#6@É‘u^,à@ÉŽ¦›®iÄ@É‹Ø8—Âà@ɉ Ü Â@Ɇ;†5l@Ƀm6éÆ@É€žî6nO@É}Ьö²@É{pš}@Éx4;°¡‰@Éuf _•ˆ@Ér—å¦ÔR@ÉoÉĆFt@Élû©ýÔÇ@Éj-– h"@Ég_ˆ´é@Éd‘ô@r@ÉaÃËW@É^õˆ:±@É\'•@dø@ÉYY¨Þ-Á@ÉV‹ÃX¿@ÉS½ãßΦ@ÉPð Cxq@ÉN"9>>®@ÉKTmÐ 5@ÉH†¨øÃÞ@ÉE¸ê¸T\@ÉBë3¤`@É@ûœÄ@É=O×&^@É:‚3™)á@É7´–I@É4æÿA·@É2om'¹@É/Kåà*¹@É,~bé3@É)°æˆ+@É&ãp¼ùô@É$‡‰ @É!H˜çÁ6@É{6Ý‹ @É­ÛhÏ£@Éà†‰w—@É8?k‰@ÉEðŠ”œ@Éx¯jÛ@É «tà(ë@É Þ@êe²@ɉzÒ@ÉCì½PÚ@ÉvÌ…ÐÄ@Èÿ©²âãE@ÈüÜŸÔq4@Èú“Zch@È÷Bt¢¹@ÈôuŽ#ý@Èñ¨•e«é@ÈîÛ£v@È´´É‘!@ȱESAî@È®xøL=Ç@È«¬£èiK@ȨàVY~@ȦÕ÷7@È£GÎ'+M@È {” Þ˜@ȯ`}ú@Èšã3ƒft@Ș  ³@È•JíAÕª@È’~Óúª/@ȲÁDs@@Ȍ浳@ÈŠ¯Š†„@ȇN°†¢B@È„‚¸V2@ȶÆ0Šã@È~êÚÞ)t@È|ö¾@ÈySêGs@Èv‡@H˜Ú@Ès»o6÷~@Èp蘆L_@Èn#àÀv@ÈkX#a|›@ÈhŒl)§@ÈeÀ¼Lp•@Èbõ™:b@È`)ouo¿@È]]Òàùª@ÈZ’<ÛÁB@ÈWÆ­e¯@ÈTû$~¬I@ÈR/¢&¡¯@ÈOd&]xj@ÈL˜±# @ÈIÍBwl«@ÈGÚZ\N@ÈD6xËУ@ÈAk˲Í@È>ŸÉYëÆ@È;Ô{vdA@È9 4!<@È6=óY·±@È3r¹ d@È0§…tôØ@È-ÜXWQ]@È+1Çc(@È(FÅ@È%zøPJ@È"¯åhñ0@ÈäÙñ7@ÈÓB3)@ÈNÔ @ȃÛP ¹@ȸé*ž,@Èíý’y@È#†3R@È X:Ú@È b§ @È®ºâ@È÷ÅÕA@È-ˆ"ß@ÇþbCÇHþ@Çû—Œ’œ³@ÇøÌÛê±@Çö1Íp@Çó7Ž<ÁÁ@Çðlñ7äÌ@Çí¢Z¾Â@Çê×ÊÑBŠ@Çè AoOY@ÇåB¾˜Ñ2@ÇâxBM±~@Çß­ÌØË@ÇÜã]Y0:@ÇÚô¯ ë@Ç×N’‘¶@ÇÔ„6ýq˜@Çѹáô£Œ@ÇÎï“v’Ž@ÇÌ%Kƒ'ã@ÇÉ[ L@ÇÆÏ;èz@ÇÃÆšçåü@ÇÀüm-x@Ǿ2EÞ¨5@Ç»h%)>ä@Ǹž ýÚÌ@ǵÓ÷\dÃ@dz êDÅë@ǰ?ã¶ç@Ç­uã²±r@Ǫ«ê8 î@ǧá÷Få°@Ç¥ ß!Ž@Ç¢N%ªª@”ñIÿU @”ñbÿU¡@”ñ{ÿU @”ñ”ÿU @”ñ­ÿU @”ñÆÿU¡@”ñßÿU @”ñøÿU @”òÿU @”ò*ÿUŸ@”òCÿU @”ò\ÿU @”òuÿU @”òŽÿU @”ò§ÿU @”òÀÿU¡@”òÙÿU @”òòÿU @”ó ÿU¡@”ó$ÿU @”ó=ÿUŸ@”óVÿU @”óoÿU¡@”óˆÿU @”ó¡ÿU @”óºÿU @”óÓÿU¡@”óìÿU @”ôÿU @”ôÿU @”ô7ÿU @”ôPÿU @”ôiÿU @”ô‚ÿU @”ô›ÿU¡@”ô´ÿU @”ôÍÿU¡@”ôæÿU @”ôÿÿU @”õÿU @”õ1ÿU¡@”õJÿUŸ@”õcÿU @”õ|ÿU @”õ•ÿU¡@”õ®ÿU @”õÇÿU @”õàÿU @”õùÿU @”öÿU @”ö+ÿU @”öDÿU @”ö]ÿU¡@”övÿU @”öÿU @”ö¨ÿUŸ@”öÁÿUŸ@”öÚÿU¡@”öóÿU @”÷ ÿU¡@”÷%ÿU @”÷>ÿU @”÷WÿU @”÷pÿU @”÷‰ÿU @”÷¢ÿU @”÷»ÿU @”÷ÔÿUŸ@”÷íÿU¡@”øÿU @”øÿU @”ø8ÿU @”øQÿUŸ@”øjÿU @”øƒÿU @”øœÿU @”øµÿU¡@”øÎÿU @”øçÿU @”ùÿU @”ùÿUŸ@”ù2ÿU @”ùKÿUŸ@”ùdÿU @”ù}ÿUŸ@”ù–ÿU @”ù¯ÿU @”ùÈÿU @”ùáÿU @”ùúÿU @”úÿU @”ú,ÿU @”úEÿU¡@”ú^ÿU @”úwÿU @”úÿU @”ú©ÿU @”úÂÿU @”úÛÿU @”úôÿU @”û ÿU @”û&ÿUŸ@”û?ÿU @”ûXÿU @”ûqÿU @”ûŠÿU @”û£ÿU @”û¼ÿU @”ûÕÿUŸ@”ûîÿU @”üÿU @”ü ÿU @”ü9ÿU @”üRÿU @”ükÿU @”ü„ÿU @”üÿU¡@”ü¶ÿU @”üÏÿU @”üèÿU @”ýÿU @”ýÿU @”ý3ÿU @”ýLÿU @”ýeÿU @”ý~ÿU @”ý—ÿU @”ý°ÿU @”ýÉÿU @”ýâÿU @”ýûÿU @”þÿU @”þ-ÿU¡@”þFÿUŸ@”þ_ÿU @”þxÿU @”þ‘ÿU @”þªÿU @”þÃÿUŸ@”þÜÿU @”þõÿU @”ÿÿU @”ÿ'ÿU @”ÿ@ÿUŸ@”ÿYÿU @”ÿrÿU @”ÿ‹ÿUŸ@”ÿ¤ÿUŸ@”ÿ½ÿU¡@”ÿÖÿU @”ÿïÿU @•ÿU @•!ÿUŸ@•:ÿU @•SÿU @•lÿU @•…ÿUŸ@•žÿU @•·ÿU @•ÐÿU @•éÿU @•ÿU @•ÿU @•4ÿU @•MÿU @•fÿU @•ÿU @•˜ÿU @•±ÿU @•ÊÿU @•ãÿU @•üÿU @•ÿU @•.ÿUŸ@•GÿU @•`ÿU @•yÿUŸ@•’ÿU @•«ÿU @•ÄÿU @•ÝÿU @•öÿU @•ÿU @•(ÿU @•AÿU @•ZÿU¡@•sÿU @•ŒÿU @•¥ÿU @•¾ÿU @•×ÿU @•ðÿU @• ÿU @•"ÿU @•;ÿU @•TÿU @•mÿU @•†ÿU @•ŸÿU @•¸ÿU @•ÑÿU @•êÿU @•ÿU @•ÿUŸ@•5ÿU @•NÿU @•gÿU @•€ÿU @•™ÿU @•²ÿU @•ËÿU @•äÿU @•ýÿU @•ÿU @•/ÿU @•HÿU @•aÿU @•zÿUŸ@•“ÿU¡@•¬ÿU @•ÅÿU @•ÞÿU¡@•÷ÿU @•ÿU @•)ÿUŸ@•BÿU @•[ÿU¡@•tÿU @•ÿU @•¦ÿU @•¿ÿU @•ØÿU @•ñÿU @• ÿU @•#ÿU @•<ÿUŸ@•UÿU @•nÿU @•‡ÿU @• ÿU¡@•¹ÿU @•ÒÿU @•ëÿU @• ÿU @• ÿU @• 6ÿU¡@• OÿU @• hÿUŸ@• ÿU @• šÿU¡@• ³ÿUŸ@• ÌÿU¡@• åÿU @• þÿU @• ÿU¡@• 0ÿU @• IÿU @• bÿU¡@• {ÿU @• ”ÿU @• ­ÿU @• ÆÿU @• ßÿU @• øÿU @• ÿU @• *ÿUŸ@• CÿU @• \ÿU @• uÿU @• ŽÿU @• §ÿU @• ÀÿU @• ÙÿU @• òÿU @• ÿU¡@• $ÿU¡@• =ÿU¡@• VÿU @• oÿU @• ˆÿU @• ¡ÿU¡@• ºÿU @• ÓÿU @• ìÿUŸ@• ÿUŸ@• ÿU @• 7ÿU @• PÿU¡@• iÿU @• ‚ÿUŸ@• ›ÿU @• ´ÿU¡@• ÍÿU @• æÿU @• ÿÿU @•ÿU @•1ÿU @•JÿU @•cÿU @•|ÿU @••ÿU @•®ÿU @•ÇÿU @•àÿU @•ùÿU @•ÿU @•+ÿU @•DÿUŸ@•]ÿU @•vÿU @•ÿU @•¨ÿU @•ÁÿU @•ÚÿU @•óÿU @• ÿU @•%ÿU @•>ÿU @•WÿU @•pÿU @•‰ÿU @•¢ÿU @•»ÿU @•ÔÿU @•íÿU @•ÿU @•ÿU¡@•8ÿUŸ@•QÿU @•jÿU @•ƒÿU @•œÿU @•µÿU @•ÎÿU @•çÿU @•ÿU¡@•ÿU @•2ÿUŸ@•KÿU¡@•dÿU @•}ÿU¡@•–ÿU @•¯ÿU @•ÈÿU @•áÿU @•úÿU @•ÿU @•,ÿUŸ@•EÿUŸ@•^ÿU @•wÿU @•ÿU @•©ÿU @•ÂÿU @•ÛÿU @•ôÿU @• ÿU @•&ÿUŸ@•?ÿU @•XÿU @•qÿU @•ŠÿU @•£ÿU @•¼ÿU @•ÕÿU @•îÿU @•ÿUŸ@• ÿU @•9ÿU¡@•RÿU¡@•kÿUŸ@•„ÿU @•ÿU @•¶ÿU @•ÏÿU @•èÿU @•ÿU @•ÿU @•3ÿU @•LÿUŸ@•eÿUŸ@•~ÿU @•—ÿU¡@•°ÿU @•ÉÿU @•âÿU @•ûÿU¡@•ÿUŸ@•-ÿU @•FÿU @•_ÿU @•xÿU @•‘ÿU @•ªÿU @•ÃÿU @•ÜÿU¡@•õÿU @•ÿU @•'ÿU @•@ÿU¡@•YÿU¡@•rÿU @•‹ÿU @•¤ÿU @•½ÿU @•ÖÿU @•ïÿU @•ÿU @•!ÿU @•:ÿU @•SÿU¡@•lÿU @•…ÿU @•žÿU¡@•·ÿU @•ÐÿU @•éÿU @•ÿU @•ÿU @•4ÿU @•MÿU @•fÿU @•ÿU @•˜ÿU¡@•±ÿUŸ@•ÊÿU @•ãÿU @•üÿU @•ÿU @•.ÿU @•GÿU @•`ÿUŸ@•yÿU¡@•’ÿU @•«ÿU @•ÄÿU @•ÝÿU @•öÿU @•ÿU @•(ÿU @•AÿU @•ZÿU @•sÿU @•ŒÿUŸ@•¥ÿU @•¾ÿU @•×ÿU @•ðÿU¡@• ÿU @•"ÿU¡@•;ÿU @•TÿU @•mÿU @•†ÿU¡@•ŸÿU @•¸ÿU @•ÑÿU @•êÿU @•ÿU @•ÿU @•5ÿU @•NÿU @•gÿU @•€ÿU @•™ÿU @•²ÿUŸ@•ËÿU @•äÿU @•ýÿU @•ÿU @•/ÿU @•HÿU @•aÿU¡@•zÿU @•“ÿU @•¬ÿU @•ÅÿU @•ÞÿU @•÷ÿU @• ÿUŸ@• )ÿU @• BÿU @• [ÿU @• tÿU¡@• ÿU @• ¦ÿUŸ@• ¿ÿU @• ØÿU @• ñÿU @•! ÿU @•!#ÿUŸ@•!<ÿU @•!UÿU @•!nÿU @•!‡ÿU @•! ÿU @•!¹ÿU @•!ÒÿU @•!ëÿU @•"ÿU @•"ÿU @•"6ÿU @•"OÿU @•"hÿU @•"ÿU¡@•"šÿU¡@•"³ÿU¡@•"ÌÿUŸ@•"åÿU @•"þÿU @•#ÿU¡@•#0ÿU @•#IÿUŸ@•#bÿUŸ@•#{ÿU @•#”ÿU @•#­ÿU @•#ÆÿUŸ@•#ßÿU @•#øÿU @•$ÿU @•$*ÿU @•$CÿU @•$\ÿU @•$uÿUŸ@•$ŽÿU @•$§ÿU @•$ÀÿU @•$ÙÿU¡@•$òÿU @•% ÿU @•%$ÿU @•%=ÿU @•%VÿU @•%oÿU @•%ˆÿU @•%¡ÿU @•%ºÿU @•%ÓÿU @•%ìÿU¡@•&ÿUŸ@•&ÿU @•&7ÿU @•&PÿU @•&iÿU @•&‚ÿU @•&›ÿU @•&´ÿU @•&ÍÿU @•&æÿU @•&ÿÿU @•'ÿUŸ@•'1ÿU @•'JÿU @•'cÿUŸ@•'|ÿU @•'•ÿU @•'®ÿU @•'ÇÿU @•'àÿU @•'ùÿU @•(ÿU @•(+ÿUŸ@•(DÿU @•(]ÿUŸ@•(vÿU @•(ÿU @•(¨ÿU @•(ÁÿUŸ@•(ÚÿU @•(óÿU @•) ÿU @•)%ÿU @•)>ÿU¡@•)WÿU @•)pÿU @•)‰ÿU @•)¢ÿU @•)»ÿU @•)ÔÿUŸ@•)íÿU @•*ÿU @•*ÿU @•*8ÿU @•*QÿU @•*jÿU¡@•*ƒÿU @•*œÿU @•*µÿU @•*ÎÿU @•*çÿU @•+ÿU @•+ÿU @•+2ÿU @•+KÿU @•+dÿU¡@•+}ÿU @•+–ÿU @•+¯ÿU @•+ÈÿU @•+áÿU @•+úÿU @•,ÿU @•,,ÿU @•,EÿU¡@•,^ÿUŸ@•,wÿU @•,ÿU @•,©ÿU @•,ÂÿU @•,ÛÿU @•,ôÿUŸ@•- ÿU @•-&ÿU @•-?ÿU @•-XÿU @•-qÿU @•-ŠÿU @•-£ÿU @•-¼ÿU @•-ÕÿU @•-îÿU @•.ÿU @•. ÿU @•.9ÿU @•.RÿU @•.kÿU @•.„ÿU @•.ÿUŸ@•.¶ÿU @•.ÏÿU @•.èÿU @•/ÿU @•/ÿU @•/3ÿU @•/LÿU @•/eÿU @•/~ÿU @•/—ÿU @•/°ÿU @•/ÉÿU @•/âÿUŸ@•/ûÿU @•0ÿU @•0-ÿU @•0FÿU @•0_ÿU @•0xÿU @•0‘ÿU @•0ªÿU @•0ÃÿU @•0ÜÿU @•0õÿU @•1ÿU @•1'ÿUŸ@•1@ÿU @•1YÿU @•1rÿU @•1‹ÿU @•1¤ÿU @•1½ÿU @•1ÖÿU¡@•1ïÿUŸ@•2ÿU @•2!ÿU @•2:ÿU @•2SÿU¡@•2lÿU @•2…ÿU @•2žÿU @•2·ÿU @•2ÐÿU @•2éÿU @•3ÿU @•3ÿU @•34ÿU @•3MÿU @•3fÿU @•3ÿU¡@•3˜ÿU @•3±ÿU @•3ÊÿU @•3ãÿU @•3üÿU @•4ÿU @•4.ÿU @•4GÿU¡@•4`ÿU @•4yÿU @•4’ÿU @•4«ÿU @•4ÄÿUŸ@•4ÝÿU @•4öÿU¡@•5ÿU @•5(ÿU @•5AÿU @•5ZÿU @•5sÿUŸ@•5ŒÿU @•5¥ÿUŸ@•5¾ÿU @•5×ÿU @•5ðÿU¡@•6 ÿU¡@•6"ÿU @•6;ÿU @•6TÿU @•6mÿU @•6†ÿU @•6ŸÿU @•6¸ÿU @•6ÑÿU @•6êÿU @•7ÿU @•7ÿU @•75ÿU @•7NÿU @•7gÿU @•7€ÿU¡@•7™ÿU @•7²ÿU @•7ËÿU @•7äÿU @•7ýÿU @•8ÿU @•8/ÿU @•8HÿU¡@•8aÿU @•8zÿU @•8“ÿU @•8¬ÿU @•8ÅÿU¡@•8ÞÿU @•8÷ÿU @•9ÿU @•9)ÿU @•9BÿU @•9[ÿU @•9tÿU @•9ÿU @•9¦ÿU @•9¿ÿU @•9ØÿU @•9ñÿUŸ@•: ÿU @•:#ÿU @•:<ÿU @•:UÿU @•:nÿUŸ@•:‡ÿU @•: ÿU @•:¹ÿU @•:ÒÿU @•:ëÿU @•;ÿU @•;ÿU @•;6ÿU @•;OÿU @•;hÿU @•;ÿU @•;šÿU¡@•;³ÿU @•;ÌÿUŸ@•;åÿUŸ@•;þÿU @•<ÿU @•<0ÿU @• ÿU @•>$ÿU¡@•>=ÿU @•>VÿU @•>oÿU @•>ˆÿU¡@•>¡ÿU @•>ºÿU @•>ÓÿU¡@•>ìÿU @•?ÿU @•?ÿU @•?7ÿU @•?PÿUŸ@•?iÿU @•?‚ÿU @•?›ÿU @•?´ÿUŸ@•?ÍÿUŸ@•?æÿU @•?ÿÿU @•@ÿU @•@1ÿU @•@JÿU @•@cÿUŸ@•@|ÿU @•@•ÿU¡@•@®ÿU @•@ÇÿU @•@àÿU @•@ùÿU @•AÿU @•A+ÿU @•ADÿU @•A]ÿU @•AvÿU @•AÿU @•A¨ÿU @•AÁÿU @•AÚÿU @•AóÿU¡@•B ÿU @•B%ÿU @•B>ÿU @•BWÿU @•BpÿU @•B‰ÿU @•B¢ÿU @•B»ÿU¡@•BÔÿU @•BíÿU @•CÿU @•CÿU @•C8ÿU @•CQÿU @•CjÿU @•CƒÿU @•CœÿU @•CµÿU @•CÎÿUŸ@•CçÿUŸ@•DÿU @•DÿU @•D2ÿUŸ@•DKÿU @•DdÿUŸ@•D}ÿU @•D–ÿU @•D¯ÿU @•DÈÿU @•DáÿU¡@•DúÿU @•EÿU @•E,ÿU @•EEÿU @•E^ÿU @•EwÿU @•EÿU @•E©ÿU @•EÂÿU @•EÛÿU @•EôÿU @•F ÿU¡@•F&ÿU @•F?ÿU @•FXÿU @•FqÿU @•FŠÿU @•F£ÿU @•F¼ÿU @•FÕÿU @•FîÿU @•GÿU¡@•G ÿU @•G9ÿU @•GRÿU @•GkÿU @•G„ÿU @•GÿU @•G¶ÿU¡@•GÏÿU @•GèÿU @•HÿU @•HÿUŸ@•H3ÿU @•HLÿU @•HeÿU @•H~ÿU @•H—ÿU¡@•H°ÿU @•HÉÿU @•HâÿU @•HûÿU @•IÿU @•I-ÿU @•IFÿU @•I_ÿU @•IxÿU @•I‘ÿU @•IªÿU @•IÃÿU @•IÜÿU @•IõÿU¡@•JÿU @•J'ÿU¡@•J@ÿUŸ@•JYÿU @•JrÿU @•J‹ÿU @•J¤ÿU¡@•J½ÿU @•JÖÿU @•JïÿU @•KÿUŸ@•K!ÿUŸ@•K:ÿU¡@•KSÿU @•KlÿU @•K…ÿUŸ@•KžÿU¡@•K·ÿU @•KÐÿU @•KéÿU¡@•LÿU @•LÿU @•L4ÿU @•LMÿU @•LfÿUŸ@•LÿU @•L˜ÿU @•L±ÿU @•LÊÿU @•LãÿU¡@•LüÿU¡@•MÿU @•M.ÿU @•MGÿU @•M`ÿU @•MyÿU @•M’ÿU @•M«ÿU¡@•MÄÿUŸ@•MÝÿUŸ@•MöÿU @•NÿU @•N(ÿUŸ@•NAÿU @•NZÿU @•NsÿUŸ@•NŒÿU @•N¥ÿU @•N¾ÿUŸ@•N×ÿU @•NðÿU @•O ÿU¡@•O"ÿUŸ@•O;ÿU @•OTÿU @•OmÿU @•O†ÿU @•OŸÿU @•O¸ÿUŸ@•OÑÿUŸ@•OêÿU @•PÿU @•PÿU @•P5ÿU @•PNÿU @•PgÿU @•P€ÿU @•P™ÿU @•P²ÿU @•PËÿU @•PäÿU @•PýÿU @•QÿU @•Q/ÿU @•QHÿU @•QaÿU @•QzÿU¡@•Q“ÿU @•Q¬ÿUŸ@•QÅÿU @•QÞÿU @•Q÷ÿU @•RÿU @•R)ÿU @•RBÿUŸ@•R[ÿU @•RtÿUŸ@•RÿUŸ@•R¦ÿU @•R¿ÿU @•RØÿU¡@•RñÿUŸ@•S ÿU @•S#ÿU @•S<ÿU @•SUÿUŸ@•SnÿUŸ@•S‡ÿU @•S ÿU¡@•S¹ÿUŸ@•SÒÿU @•SëÿU @•TÿU @•TÿU¡@•T6ÿU @•TOÿU @•ThÿU @•TÿU @•TšÿU @•T³ÿU @•TÌÿU @•TåÿU @•TþÿU @•UÿU @•U0ÿU À¼á“]À#“•Íaìh@¥Û”ö/@L €0Dº@®WKFÇÄ?ü§_H¬SX¿²L:Žx(r¿òÆÙCBÚÀ è[À¾À È5«àò"¿èññzoi¿ûUZŒlGÀUNp©òäÀµ -âPí@òÌ2 ¡@òtº-?ö™Kµð¨%¿ì?‘`ÀWÞÄž£À¶•`ň?ÖЋ.~B?ûä­Lž R@›UÑ<¿â¢§fº¿ú ØðA@ý¿ñ“›Cÿ¶9¿¿l¥+¨=@,ÃïêjÖ@\ó0™N@ (ãy˜@Ì­L?"Í@Dà6©ˆ¿þ8É×î<Àv~ÿ£ÀÂ6x€dÀ[(ŒÕX}¿öƒÙ¿ZQ@Ìj/Uú¤@ô *.O@T¶¹Aƒå@ ›dO8ê@)ÐXx#@°nd0½?ú0bKŸl¤À : Ù!@TÀ’õÓŒu@%:È5÷¿éÈ3Ál½z¿ñAî¼+Ö~?í¦¦z¨ñ¿Òc)4émÀÓà|JêXÀ÷L¢(ÀäØBÙŒ˜?ò²8é%@öòš@ {ŒU°@«ûuBÒ?áþ­Àå¡zY?ê_“E EÊ@(„1`µ®@?Ê9U ¿ðïg¹ääÙÀÉRê•7?Ï*>MI™ß'J}ÀÝ“žÎ¢¿ö‚¢¯"‰c?êµjU(?ìâÉ)K]‘?Ñ\QÛ¨×ê¿åùîƒÖ7t¿÷\æe±8K¿ð‹pgSA&¿Ü^6~|J@ ÐŒ”·œ@š©¼n»@ §ßŸè}ÀKÇ@«ÍÀ,äïÌŒ?Èw‚X U @h‹«+^:?€N¡©Û#¿û‘×)¿ï_ žJd¿³ÊCTy1?×Å$æ¾M?æÞvÁ4~?äןo¿×?ºD d½Àº…¡‰j¢ÀkÍòî[¶¿ô²\/ëˆ$?ü¼Ô‹;Žù@ …Ýpˆ?üÚc è@„?ûŠùgû®?ÿwp1;¿ìÊ{î?€ÀSE®‰~9ÀŠ1¬J¤ÀE6ßE|ÀpÏuÏýêÀªí°\?ðsÇa §<í™AŽ¿æþHƒ’À)­œ¿óEšÝdÒ?Û^ê/‘c?ø `"So@ 6â#lê@šŸR.Ob¿ÍØP³êRêÀÔŸ7ãWÀ°mÈjÀøf ͆ÂÀuì §F2¿áêÎ/ð¦?ü"Hò¼Úã?ÛV;I‡7Ÿ¿üoþmÁÀq ˆ&΄@‡r•;de@"Ð|<P¿ÿ "æ?窽vŸ[@ÓSë=Í@4ÖtµÂä?ÒžiæšÄÀ ˜p  ÀÆ—û1¿ð0DãúÆ‚?äH­‡ÈŽ?åÁ0sñµ¿àò°p_£Â¿óî)bÜ?æN¼= "@ ‚SpË@Ó6RNMT?Ö‡ú—ÑýÀ§·z§¾ÀemÄo3«¿í‘ !|~?ñBž{€ÙŸ¿æží-âu¿ìE†) ²?ô ^M™þé@ '³u/šD@ € ËZ‹Ú?þß_æ‘?â—7 .v?­q@ŒŸ'?úõAVÅG@¬­–š5À@^â¶`ó/@¹{½é.@žiÏÝÁk?õwã¤ì)ÅÀ’=½Bú¿áÖæó>?÷àƒ¿w†Ž¿éB ¥H¡XÀ,Îí…[À `ÎQ•ÌPÀ ‡õ]ïÀN#»ÇÀ ¨>¯fG¿ö¢ih2?ÿ¾\TnÎC@ < dÁá?ûÅWr–Y¿Þå™îjM™?å[ÂŒÀåã@ÀÑ'Éj?ÿ *+‹ž\?øæ'E´?õ2ˆ<­v‘?ò_ÝüNA@ 74Ý™Û@К¸é@õau'p†@ röòwV±@Lè p46@ JVgÉ:?×í¶ßñÀ/Eýã×ÀTÙ1åQ”Àa»k$h¿ù-Um l¿ázܽ:줿햦EE´.À$KÜÊ¿ûC¶Ðç7æ?l›¸_âÚG¿äû%´ð鳿â$wk` c@謘¾þ?@ ~•|z©C?ÇgÑ`×qÀ˾hã¤YÀˆ!“! Ÿ¿þŽïœš-²@ :¥WÄí@Ðq½y@F™Ç Ö@—èK“€x@âå ùWË?ù–G—‘ô#¿Ñù¼K–bæ@im)gœ@æ››/ ?õîÆlû°?úxŸø€?þ.7Jp?ð&÷3YY?ýä¤Ó½Ô@Ã)ìõ¿ô-”¢É)À8}ÚGÀbGJ#†ÀÇôé,+ÀŒð‡˜LÖ?›ÿÏÀG:¨¿ü³Á>À'‹Ö2?Ìøl2Ýì¶@¡ëæ’ò?þ<)Œó0«À”DÊ£íh¿ù?i°û Ù?Ùàçñ+ÿ*?Ògy@ ®¡?åûħÂ@šfö÷´‚@Ï;™}[?òáÕípšk¿¤.¹vÆJ@â8zÈ¥@<L&üË@ ß÷€ïi@ Œ)$¿@âÈDǽ?Ô¬Ò:W(›Àé½…ÐÏ¥À!œþß`À‹pÝY¢/@Hq¤! @GªŠßK@ V'žÄ·–@ Ç (?G=@Ž©’lÙà¿Ò“Ç8„ØŽ¿ú—Çht›ÝÀýô4‹¡À"(›/ïjüÀƒ{¡¦»?óW,Ù½ã@ P©{0û@'0¢1s@ Ú›lí@KÔhóF‰¿üŠ„¦¹·À;ïZ )ÀÍý³È{À$ÄKÙZL¿úºg‘y N¿º6Ío±;hÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿøÿø@ <™ýz»I@ Yw)9ì¬@ @VA‰ãŠ@ —š™|æ@ýTx˜Í@-ˆú‹Ádø@žÐË/þÀ¹ >ÈôÀ¶ÅôÍ@²ÚY—·Ü@¨ Öïw¬@ôø¨O@z@ר+?óšY fG@ ãKðƉ@âf¿É Î«BÖ?æ)&P0È;?ù˜H3(|?ÔéiûT”ý?ÛËPò\íÒ@ î_Θ@ù‡»<¯?ú<Í„kÓ¿¶íÔÃ1~@©q§nJn@QŽ×Æð¿Ânâ9px?óÞÒ*Ü´ÀJ1ö[€ÀÞvo¿ø¿ù©šÓcÀé£ =a•?÷Âgîˆ ?ÿü9 @Ì@ :Etí@—$á%?LÿrDšÀƒ€þB„¤ÀºsFbè?ì3ÑÊd–º¿ã4Ÿ!ä®À¼;²vfÀó†@[ÀË Ši&ÓÀóQyZ¿óúF˜ƒ»?ã7Q¾V ¥@ Ì8ù$@xŽæõë[@è½”é[@ Uö½"ðÍÀÞúùAJ¶Àî0 !À ½OÀ -wú·À·2ÝQ4CÀœÚë¿—$¿ü\#_Ê ÀŽâGÂý.ÀY5—C Àæ…[VWÀNþõªÀÅùƒ1UÀ{§~DÀ'_·¬L@:À»””g@Õ·»™‹@™£¼¶d@[µün´ÀÀã‚ÓÅÀ†oCIý ?ñ' &‰8@2'Ð!¹@ÍÊm¤Èò@! ˜iã@^©ÁXü@GØzlf¨@â[@ DéZH­È?à5PÌ ?üÚº6›ÜÁ@ ÕŒU^3 ?ÝÚêI$®À…Âôüè¤?þ-Ÿ £·@ƒx߃JQ@ )·P{ú—¿új©,Š¿é®à B?ô9¾?ûã\9 O?ð‹òSWúÀ!Z[öõ3À Å7‚ÓjÀgæº>5•¿ÕO¼#$øy?ú ™5?ø[r_kH¿Óu4Í(߿˕d¯šý?þÒ¢ôbE?üŒ óFÌ]Àuµ&ÎfÀ D&…€u˜¿òén² ¦Z?­¥¢µÂl_@­ªÑ ¹@…%¬E9¿ö}YŠðÀaë?p4 ¿ð6 Ð ¿ûpd‰æÞ'¿õ%bêé•¿åŽÉ¨‰Lä¿ð™cÙ>•Àñ1ê8„²À@¯ñ3ëÀç<.ƒ?á4×ói@céB?ë?âß#…¾>¿ï$$,ác!À·/31¹”Àÿç`¦Ï?¯ÖÂ¨Ž¹?þÃ{^?cò?ñŽç—XX"?È}I²9’?äŒ$pñ< ¿Ã}ëð8SÅ¿ÿí¹[Éï¿þÛæå8úÀåÂföz¿ò©¥òß»'?ñ q¹„ñ?óú>Fš,¿Ý+.^ʈs¿ã¾ìž˜?õb…ô|¦â?û ;crpË?˜òFvÞ¿ów®O‰¿õóTî3œ?ïø@’Qd?ú‚ã6rß³?ôb“Ó÷x?³F,0¾¥À†ê[ÜĦÀÔì z@ E\¤¦a@‚ 5H›ö@<¯ý¼i¹@-„Äîä,?ú´°ß7ä?ã¾eØäÙè¿åÊJi&`ÀÛV˺T¿ú~¦ƒ×µ¿Ã©@âA¡?àe %ú¹°?É/õLF©?ë8*N'?×oª<ÿÑ¿üdPǯ»©Àûîè²Å¿ôFmx\-£ÀMZèø¥ˆÀ–›¢‹pÀ³¸¡ÜÂYÀßEY~À"…\ƒ?Ô¬û™(8þ@‚½ŒÂ@ëŠvÆÌ?øY“=S`¿åL”ß“?ñÕ?óž@âð]¶M?û~Ç Dv?ÿÐæ"Ά²@ ŸÓ!F ¦@´C«.#Ì?Ý­RjÞ±¿ðly(]¦-¿ï¥ÏS ¿R@Ô2æ òÄ@ Ax@?ØE°!‘º¿õ‰¡¹* ¿§Ü‚¼sBó?ºË Ò¦>?Ù™L–C«?÷±1g¨í?û²Ällqv?úþhhw‚?í³Z9ЦW?ÍÇ4Õ¢ñ²?üA3ïkŠ@ìýçÌ@qÞPº ?çÑf¤bc?ñöðÒsÉ»?פûÙóÀlT~†mÀ$Ǭb¿ôêS ¼~q?¤S‡˜µ0 ¿XJÓ‚½a¿ì(Ì¢uƒÀ¿ÊY(‚ÝÃ@¹ê¯!@+ÃsyŸ@ZÐeiä@¼U«î¹¿@v½±¬c?á/´¿âmŽ?Üj÷S'?ø¡“ë—x™@¨Gÿ~q§@Æ 9±Ø¿õd¬;i÷cÀ ´…#õ¿úh†Œœ@ `b˜Ú÷k@ _6laè@"£¾ƒK@ªˆõÚl?æ=»pv¿¿ÁÃc#v³ýÀ >”ì¹»¨À (fýZ:¿ñk“%ñø¿Ý=¼ê.¶¸¿Â÷e;˜E÷¿êëSïŒñÀ ˆR <À À {û¿å½µƒÊ?ýÂ((„d?Î&$p›¶˜À+˜ÍQ ô¿û!¹7‘?þY‡¾^s@ÒæW)tj?ûÊBïá@°ÕK;~Â@{=ñ@1@2ë·ah?ú~©YÒyº?÷ßj”-©¿ÃÎ ·ÄÀ^ÏmƒÈ?Ä?Ñ„qÑ @÷w”|û?ðî-Kæ´¿ídÉØÕ ÁÀšöþœ¿À©Â\¼•꿾Q\ºôGw@ )t™W’¿ÇºªGxWšÀ¾¶3o6?æã—wŸ?óPEL J?õvì)éu@£À8ÔDB@ÜéV´r˜?÷õþÒÛA?ò‚‰¢†É¿Ù¸«~·M¿ú3; cŸj¿ùûUêhj¿ø±È{?Ì”Ó v‹@ÒÊšÔ@ ÓÝDb£q@в`>@ÀQ»ÎÈ@óÍîÞƒ.@„.Pî&@4Î2½@½A-´-ñ@4?*ç›@˜„Çäg¥?óPCX]U:@ ØÞ‚Ìî@Á—ß0–@jRüJ?õRøO\?üáJ'û/^@U¥ö Y@HrʰI`@&¤Iè‡~@!ñ÷*…@Zø=©C9@›Ýœ¼9Ò@·Q´dM@ëNTÁ@èR¡ÝŸh@?øÄV(@ I@î@¾¤ {v?ÑD†\w@Š-˜?îŽÜ$™i¿ÿ_'6žÅ?®§å²ÕX@ÅAQà Ó@Z€Á’@ %“Yüƒ×@´æ÷Ÿ@Êúé!}@ -—nóî@M¹G­y)?ð&š‡ãúQ@êÉÍÄþ@6.óŽ@=R[Ì /@ Pî™4wŽ@ /Ožm†œ?ÿ‚Ôÿ„/?Ñv¾ãDó?ðë\©ü?óŠ{Ó8{Ž¿ó[O<¶BA?ÊmâÒ™ªK@ÒŽ¿û/ÑÐâƒ@J͑ӈ@&Wš=ô¿Ü,—¿ãÿú4¾z &¿äŽCÊ q@ö߈·G™@‚Ü:Û‘å@cõ‹°š@/àñÓ@ ÁÎWkƒ@ÐA¬ž ?ø†»Ž´Ï¿î©YÓÚw¿éG“9ÆY?ãøøÖ^^@$nóJ?ç¶k¡£“¿ò…~¨§­?ß qWÌ@ ‘* w@s¸¨1N@luÏ)‚?ïw¸e5È?äÔü¤Øé¿”½}¿à ¿ûL!iWW?ô*ýª€êØ@ ƒšG'kj?ñxݯ>µ¤?ªÒªwpc%?ðØÄ2S[èÀ8ñµÒÀðSصfØÀ©ÌV‡zóÀ÷M ¿Ü°`Ü  @ @n¹«ô@ÊùiECì@ êãŠ)tÐ@ 0Ê-–@Š?ù"Ž3Ë¿ïÂQV¢ìi¿ó:D”r0‘?Õ “Üì?üÞo{p„2@,ŽüÑ †@ _PÉŽ‹Ó@”©µXä@à]K.G?×»,JHr¿¸ëK8&?öºRwÐÿ?óugð¿íô]îÁ+¿ÿ”ÎßSÔ¿ò%X$3i•¿ë ðÃHn¿ç8Á¼G¸¿è† x·OÀô½L?<§À[e²naµÀ¿»8o‹Ù¿ñŽÓü‚À¨½š!ÀZ,à((Àƒ#~ F0ÀNÊ,Æ·u¿ù{ëGx,ÀØ$ŠZ ¿úÌJ‘q?ód÷(vÚc@Ò£¸ @­±ÚR8Ñ@˜ TNP?çwÂдNÀæiË/|¿×ïIjo?ôä™É-•?ñÚk„lV@àµOW þ?îw t#ÀÑò3+õÀ¸›—õv¿ö;Ûó$‰b¿ôæ°,¥¿þ±Ì¢óqò¿õ²å‰}Ùþ¿ñ(ÜÍ¿û×x¥õ1k¿ãj¥ædJ?âvCG52¿Ô»G ÔÔÀMÞ÷6ÀÞ5.4‰ÀÑ—Þ}\ ÀCn_áåÀ Sk†‰ æÀ4‹{w`¿þóº29_¾À›o¶`À …a Ð[¿ò—[žKÜü?óC5´_9?ã–FÛ&l?䮨û`¸?ïÓìƒÅŽ?É+âO¯œ ¿è8Ø?ù4=¿â=Ãíœû¿õ”Nëa!¿÷¸sÐb97?ø¶Té6{@ 'HÅøóÐ?ññÞˆÓ?Á¡g'E›?ôpÿ¸¥Ñ‹¿¼ø`‚áY¿ñ|'ªÙÄA?þLIÕxaI?øžÔ¡¤Ð[¿óf>\¡ì¿æÔõøl¿Â*K ¯¥¿óF·[‡Vs¿òËþÊ,=¿÷²üü0G¿ðZ0[®¶©?ðzïœÆyÅ?öJÀ÷D×?æ¼tŠ:Û?ðÉçØiß@yx•|qM@s@›yp&?úÌ%Vço?ì‘ßk®¿¶5š&&£?üÒ“cpÇ›@(¦¸F²Í@0Niw@š@Xåaj@¶aà0¹@\sO;W?ûjð .?ø»9g¿õÍ‘ê'‰Ê¿õ¸Ì<ŸD¿æëá̪b=À<¿gÀ|l«µTÀ½Þk¢ Ü¿úx“cjÆ@$ÚPP@gtß¡@û°»ê,?Ý ;sDsÀ"M&2å¿×)Ä‹~ÒÜ@ 9v~v?üÒê<É]?óßÉOÅ.†?óú>0•>¿¤»_ =(¢¿Ø{|ÝPq/?ôëéß ?òvó@Î?ñ¿«®‰ºÆªk?ô(t¦~ý½?éGÁ(Bµt¿ê"¤é¥ª¿÷—N蜕+¿öÐY´b¿æJŠÓY»¿ô“ÚÄhýòÀ½¿¥7º¿ý§§‰!w¿÷‹\Zaã¿ÙŒxü²Ö¿ÝøšÍž@vÀ¡À6zC¶À ?ÐK§÷À~3›.¿øŠ#ÂÑ\;¿êh <'¦`¿éªq‚$å©@ž$ ªKy@\5Þ ? @ÌЀšP@ÙèKL(Œ@™‡¶ÿ’÷@Yª|w`S@PÛõ@Ûw¹¡“ @!ˆZ@_KOœGb@!ö55Ú@å öÞ@¨ÊZÐÖ@lòÐþ‘­@1™^b_?ÿízÛ|îK?ÿx¼Ø…¹Z?ÿ÷‹þú€?þ’)ÏVA”?þ R|Ù±?ý¯pnKÉ1?ý?‚»Ñ¯?üЇŒ­p?üb~q„Ü^?ûõf > ?û‰=7l§¸?ûÔ<D?ú³µÀo•Ó?úJTÛaëÉ?ùáß¼Ï?ùzSå_Ï?ù°"æð?ø­ô¢xœ?øIÒ6’‚?÷å0yGƒŽ?÷‚%{+ñð?÷ý»ü˜?ö¾¸ ië¸?ö^S¼Å?õþÎéÓn?õ )&‰.?õBaÅ̺?ôåušX ?ô‰e¸\?ô.0Jèh'?óÓÔ<+{)?ózPuëIa?ó!£âÅ™ ?òÉÍmïë®?òrÌ7~?òžH?ñÇCþIý/?ñr»>¦ È?ñ>A±?ðÌëà—î?ðz6ÞšÍ?ð(µ/Ø?ï°jʹǼ?ïU%Ó?îs. è8ž?íÖí’Ô‘7?í<=¯7I?ì£{¨ú?ì …MlÚï?ëuyÝå8]?êàöv¢ò?êMùwârÙ?é¼€ZvÔ?é,‰2;ô?èžR?肱¿Ë?ç…šÝ2éF?æû–ñûB?æs µ_Ã?åëôÇNÎ?åfQt‘ù?ä⮼"‹?ä_]ËipU?ãÞ lwa¥?ã^ S\?âß¡)ŽÌ?âb‰?yûÏ?áæÖÍŒ¼È?ál‡Ó®’—?àóšR÷*?à| M­¨½?àÛÇH§i?ß" ˆÜo?Þ;•çÁ?ÝVÎý@¯?Üu2"ÅÖå?Û–<ÅÉY”?Ú¹êÁ?Ùà8.»/?Ù !&«?Ø4¡Ä;¿b?×b¶'ÕÑ?Ö“ZqãDR?ÕÆŠÅÄj?ÔüCI8€”?Ô4€$]²Æ?Óo=±ï?Ò¬wޏ.?Ñì*x±‚°?Ñ.Rs3W£?Ðrë±N?ÏsäÔ,}Ö?ÎÅ« aw?Ìžr]áØ?Ë:ãg˜âE?ÉÜG×ZÃ?Èôƒö@?Ç,…¢;Cl?ÅÛ½3c«)?Ä“ÉpC?ÃHú¸¯„?Âd[_ü?ÀƇ¦ÙRŽ?¿ Ïdq?¼®&¢÷?ºL& N&?·òÔÀe©?µ¢_ã&??³Z¥àêz?±•µ§:5?­ÊFî à]?©nȇ?¥#¹:^>Ö? éÖ˜ûD*?™v•¼zµ?‘P•“íp{?‚¢Œ®­ ?UËn0¿yñM!&Ø¿ŒT \Ê¿•·² ºÎ¿%ÇÌÌî¿¢9f¸õ¦c¿¥ÐzƈN¿©Wágü%¦¿¬Ï¶e·Þ¿° º”¾æ¿±Èdÿ³mp ç"¿µ ÁƒÎŠå¿¶ ŽüuZ¿¸.æ5ML^¿¹µÔÐ'¥t¿»5heYôD¿¼­®ƒ¾e¿¾´°²-D¿¿ˆˆh±à¿Àu›Ž,0´¿Á#g.#h¿ÁÍ­ŠÉÜ•¿Âtu‡ù-¸¿ÃŸø ò¿Ã·¤¿Dš»¿ÄT7Ÿk¿Äí)º í!¿Å‚ÜÙÉ«G¿Æ9%eӿƤE&¤Û¿Ç0b”(þ¿Ç¸†Y€š¿È=Ȇ÷óü¿È¿ÔaÍ0÷¿É>°\g˜¿Éºbã V¬¿Ê2ò_‹ã¿Ê¨e50˜¿ËÁÃ)$ݿˊcÕaœ¿ËöQlÕJ…¿Ì_‘/ ‚@¿ÌÅÓöœÑR¿Í) ð&>¿Í‰{®®•¨¿ÍæíÃYÍ¿ÎAz—[ӿΙ*Iç‡í¿Îîg$¬¿Ï@ á{œ¿ÏDˆy„Ü¿ÏÛºÔX^޿й &¿¿Ð689 Ýp¿ÐX]÷—›—¿Ðy-P¼4¿Ð˜©G-­;¿Ð¶Ôßšï«¿ÐÓ³nm¿ÐïFòkËŠ¿Ñ “eùÅÈ¿Ñ"›mÓ ¿Ñ:aþ‚Ó>¿ÑPên¹'¿Ñf6ŽÌж¿ÑzJo'`Š¿Ñ(œ«fš¿ÑžÔ%ÛŠ¿Ñ¯Oˆ¿Ñ¾žXkõ¿ÑÌŠÐcοÑٿ̾ƒl¿Ñ嘹hZ¿ÑðP,hÃB¿ÑùéíWµ¿Òfxüv¿Ò Ê*‚šÒ¿Ò("/f¿ÒRØÉÇ¿Ò}¨Œd¿Ò™…䬨¿Ò«asf¿Ò´Š\;®¿Ò¸³sø¿Òº欿Ò»³M6¿ÒÀ3)ð¿ÒÊQî.¿ÒÜÆFg,¿Ò úICuL¿Ò%ŽP Ô¿ÑüaGS0Ú¿Ñó°#Ôý²¿ÑêÐþžˆ¿Ñß‘ùšR•¿ÑÔ*Fkð¿ÑÇà\vOʿѺ¶àpvF¿Ñ¬°sPjj¿ÑÏ´Ê]¿ÑŽ?!G¿Ñ}‰®Ô¤°¿Ñl)šòº¿ÑYù˜ïqm¿ÑFü;ßÇ„¿Ñ34yÌr¿Ñ£±¢ú¿Ñ M¨¿Ðó4cί™¿ÐÜZŠÁŠq¿ÐÄ—\€u¿Ð¬o ƒ¿Ð“biØE¿ÐyŸ, v–¿Ð_'Ѓ©-¿ÐCþÏH=Ë¿Ð(&ŸD¿Ð ¡´#¿ÏÜå¬Ûä¿Ï¡6æ|4¿Ïd=óöi\¿Ï%þþª9:¿Îæ~×h44¿Î¥ÂJC%†¿ÎcÎþ0¿Î §åÕ¿ÍÜQñçt¿Í–ÓfS˜ ¿ÍP0*äoÚ¿Ílîpп̿Ž[Øv¨¿Ìu™AuJ¿Ì*‘È:,¿ËÞ}ð ,¿Ë‘_gÈX¿ËC=ƒÆ°Z¿ÊôçYÍ®¿Ê£ÿ2Ž<¿ÊRë§CöÜ¿ÊæÃ1ü¿É­ò¼'è¿ÉZ8*†Ì¿ÉTîdzˆ¿È¯³M<×Ä¿ÈY5¼ Ü¿ÈàžðΘ¿Ç©¸TõãÌ¿ÇPÁ8_tØ¿Æöÿž¶€¿ÆœwØÄ2¬¿ÆA.2–Ñ`¿Åå&ó|М¿Åˆf^H ¿Å*ð° u”¿ÄÌÊ"˜¼ð¿Ämöê ¨(¿Ä{5þæä¿Ã®[1KN\¿ÃM›Û¿Âì>ɬ­¬¿ÂŠJ¤Ä`¿Â'«:j¤¿ÁĪð6U\¿Áa‚ ˆœ¿ÀüÜj£ãT¿À˜-®­k¿À2ÿNlK¿¿šªŠ£©€¿¾Îg"ý°¿¾<AÎ8¿½31€o À¿¼dO G@¿»”œKà ¿ºÄ!ÀnÔð¿¹òæV‰Ü€¿¹ ñü¡÷¨¿¸NLT@u@¿·züõrí¿¶§ nËF°¿µÒE_²x¿´ý_ôÊ­è¿´'´ï+˜¿³Q…#Ű¿²zÙ]ÜXX¿±£·‡fø¿°Ì'd¿ë`¿¯è`sžU ¿®7²~ÍiÀ¿¬†SJ†ÌпªÔQ#LÒ0¿©!ºBªa ¿§nœÏ2ü`¿¥»Ü‚º ¿¤k>Là¿¢R©iü€¿ ý°¶¨€¿Ò"Ï•@¿šgâRÚâ¿–ýWb.‰¿“’œ_{€¿'ÌB‚ À¿‰zº,‚¤¯¶8¯€¿wŸ£ #¤¿cîw›È?M{kßx?qSð0Ì ?~õäèþ(?†Jr42½?DÈK?‘ò‹²W?•W J…2?˜ºÕLÑ?œdáh€?Ÿ~ŸÊ$º€?¡o6ˆ_  ?£Z1‚`?¤Ì®= ?¦z&îŽÒ€?¨&¸¡ ?©ÒUž+ÍÀ?«|ó®-?­&†d€q ?®ÏùŠÀ?°;-\=¢?±BÝ÷ ?±àº @¦?²²ÿ>à?³ƒ¼é7 ?´T;²tÿ?µ$¹ÉÏð?µóg?ß?¶Ák,]Bp?·Žù„#Ç?¸[½óê?¹'³ß°?¹òÓW¿?º½…æ•0?»†€;ÿ?€?¼O-ñ’€?½š!Eà?½ÝBÄmÄÀ?¾¢÷20?¿g±¦EZà?À¶Ìüç@?Àwäâ¨?À×ê“}˜À?Á8;[+Ú ?Á˜¿ºU8?Á÷>J‡Žè?ÂU뉯ç€?´ ˜ð?Ñu8¸p?Ãn…U‡40?ÃÊáR Õ?Ä&£›<@?ÄÈ;Áæà?ÄÜN‚Î,?Å63™Ë<À?Åu9‚" ?ÅèyÂ?Æ@ öÛ?Æ—NËü ?Æíì%Iµ@?ÇCÚê^5À?Ç™ðu®?Çí¤Š!P?ÈAz,Sg€?È”™$G7à?Èæþá™ °?É8©Q:‹?ɉ–dÚ¹ ?ÉÙÄæÊÐ?Ê)0V‰µ?ÊwÙ/¬J ?Êż¢õ5P?ËعÈû@?Ë_+‚Iü?˪³Xr0?Ëõmx’nÀ?Ì?XÚSá0?̈sU¶`?Ìл’?Í.5|Ð?Í^ÊóÇÐ?ͤ†@?Íéz†vÀ?Î-ˆçU¥P?ÎpºC>_?γ lI<`?Îô}®<®ð?Ï5 YÀ?Ït¶Ã¬]P?ϳ{Fj¿À?ÏñX@–P?Ð& Ôï?Ð5*–ïíà?ÐR¸û²È?ÐoÐp&ßP?ÐŒp1W(?Ш—|@“È?ÐÄEÚÿx?Ðßy±|™P?Ðú3"Ú£x?Ñq, Mx?Ñ.3{³h?ÑGx.ÞÈ?Ñ`?ÀÒÅÈ?Ñx‰xLH?ÑSœãAØ?ѧžŽad¨?ѾiKŸ^h?ÑÔ³.¨ÇX?Ñê{“è#€?ÑÿÁÚ&ä°?Ò…bhè?Ò(Å¢ü0?Ò<ÊMÖØ?ÒO¹wÓ°?ÒblÖæ?Òt˜Û\,¸?Ò†?mÄß0?Ò—_,Ñ×H?Ò§÷Œ¢Ûø?Ò¸¶ p?ÒÇ êÅà?ÒÖ{Ù€?Òå¹V€?Òòð]¤`?ÓQJÀ?Ó 'ÍôP?Ór£ÿfÐ?Ó%1›y‹°?Ó0d?Zl@?Ó; Õýð?ÓE"Ç#à?ÓN­ÏG® ?ÓWªÊ€YÐ?Ó`PØÐp?Ógøü_©?ÓoIi‚i0?Óv 7 à?Ó|;,LP?ÓÛzi`?Ó†ë9­@?Ó‹iì@ƒ ?ÓW<ÊVð?Ó’²ØPšP?Ó•|n89€?Ó—³°E 0?Ó™XR™Ûð?Óšj ¸Yp?Óšè”%0?ÓšÓ¨3Íp?Óš+nË?Ó˜îi/‡?Ó—˜ÒUð?Ó”¸Xwp?Ó‘¾n °?ÓŽ/¤2\ ?ÓŠ ÆcD0?Ó…R¢ÓÆð?Ó€ È?ÓzÏ*?Ós¥ÇXn@?Ól•ÊWz@?Ódï²8Ð?Ó\³[lôà?ÓSà¤ÃWÀ?ÓJwojVà?Ó@wžï<ð?Ó5á>A ?Ó*³Æ¢‰ ?Óï‘Æ& ?Ó”g²@?Ó¢7ÎHð?Òøóá’Ð?Òéøº ?ÒÛAãs€?ÒËòE:^?Ò¼ RY°?Ò«'àæÀ?ÒšzÅÒf@?ÒˆÏ.ŒØ?ÒvŒfÎ~p?Òc²u´† ?ÒPAd» ?Ò<9?½°?Ò'šô™ð?Òcôúz0?Ñü–òÆ…À?Ñæ3#¯xÀ?ÑÏ8Ÿjü ?Ñ·§€ §?ÑŸâ ûÀ?цÁä5j0?Ñmm§¾P@?ÑSƒP5ø`?Ñ9‹™0?Ñìê Wà?ÑA.hD?Ðåÿý¨^Ð?ÐÉ)‡8‘?Ы½üâ´p?н’ÏŽ?Ðo(†ÏÐ?ÐOþûïP?Ð0ACMù`?Ðï“Gæ`?ÏÞWÀ@?Ï›"žòãÀ?ÏW …©HÀ?ÏÌš$À?ÎËioaŽ€?΃á³@?Î;5¿ÒsÀ?Íñfx·€?ͦtm¨€?ÍZ`I§4€?Í *»Öƒ@?̾ÔxÁ€?Ìo^8õÀ?Ìȹ±þ@?Ë;N–?ËzC ŒP?Ë&TsO—@?ÊÑIÀ:¸À?Ê{#É­Ó€?Ê#ãiÆã@?Éˉa¾?ÉrîÀ?ÉŒžAo@?È»ë|ó2À?È_4|Ÿ?Èh‘úÉ?Ç¢ˆº0¥@?ÇB•ô®ÿ€?Æá‘F@}@?Æ{¸mŸ€?ÆVY|¿À?Ÿ"¿¿±R†o`¿²G#\®É€¿³|D _–¿´²°V ¿µêcx²¹¿·#Xù]ŒAÎ…¿¹˜ø®êF¿ºÕ™–]z€¿¼jCÈ6€¿½ReùNÓ¿¾’‡ï™ñ€¿¿ÓËUÖ‡¿À‹¨Ú怿Á,Ѷ§€¿ÁϸÛr€¿ÂqâØèU¿Ã3_¾ƒ€¿Ã¹È`€¿Ä]W‰–j€¿Å&¥I¿Å§nÖ—Ì¿ÆM/7™è¿Æód›´¿Çš _Çt€¿ÈA#ß•Œ€¿Èè¨o¸‡€¿É—`§¿Ê8íþ¿Êá© †¿ËŠÇU»€¿Ì4D¦S¿ÌÞuŽs¿ÍˆR;wm€¿Î2ݧ€¿Îݼ¥€¿ÏˆìŽ;®¿Ð5¾»z@¿ÐpÒŸÀ¿ÐÆ$¥+…€¿ÑQ)/xÀ¿ÑrŸèÝ¿ÑÉ ö(À¿Ò™EÊãÀ¿ÒvB‡-ª@¿ÒÍ7º+€¿Ó#åÒ &€¿ÓzÜаr¿ÓÑê¨\õ¿Ô) ͸©€¿Ô€D²w€¿Ô×Åîñ€¿Õ.çuØ@¿Õ†P*€˜€¿ÕÝÆNjŒ€¿Ö5HF¬€¿ÖŒÔv¿Ñ@¿Öäi?Á4¿×<l퀿ד¦ µ€¿×ëJ×ÛW@¿ØBñ <±¿Øš˜Ã…´€¿Øò>”˜eÀ¿ÙIác÷ÛÀ¿Ù¡È?À¿Ùù3ÎЀ¿ÚP¦ÉqÝÀ¿Ú¨,‡¸É@¿Úÿ¦³L ¿ÛWŽu*@¿Û®qYÄÀ¿Ü¾PÔˆ¿Ü\ø°Ã7¿Ü´±¸¦€¿Ý .Š#¿¿Ýb&nyÀ¿Ý¹;äÀ¿ÞÇì$@¿ÞflDg€¿Þ¼ò/Tø¿ßW×-À¿ßi˜ðuyÀ¿ß¿¶§V€¿à ÖB¬à¿à5½8d“à¿à`Žöæ½`¿à‹J‹GÀ¿àµïS÷à¿àà{c¬p@¿á ü`¿á5HÎ¥`¿á_†lé@¿á‰¨Òð2 ¿á³®H•Ü¿áÝ•Ñ\2`¿â^o•ðÀ¿â1$f[ ¿âZŽïÁ@¿âƒôÐjö`¿â­7Ãøa ¿âÖVÆÎéà¿âÿPÔ$…`¿ã($åÿ° ¿ãPÑõ7rÀ¿ãyVùs] ¿ã¡²é+‰€¿ãÉ乨šà¿ãñë_¿€¿äÅÌ&­@¿äAròˤ€¿ähñÃ}nÀ¿äA-—_ ¿ä·`ER¿äÞM…ƒ®@¿åLb@¿å+]µç ¿åQᣵ@À¿åwþ[ú¿åãl¹(€¿åü¬k¿åéÚåêÀ¿æ>ªæY€¿æ3=þò ¿æWþèQy ¿æ|ƒÐ?@¿æ Èy>À¿æÄÍí.lÀ¿æè’O à¿ç yö«`¿ç/SH €¿çRM’à¿çu/°ê¿ç—o÷e@¿ç¹•¾ro ¿çÛrXðŸÀ¿çý™ÇÞ¿èKR°ì@¿è?ET5€¿è_ñm®%À¿è€NmF@¿è [ù ¿èÀQ‘5À¿èß~̪ø€¿èþ“Z²ÕÀ¿éRÃåÛ¿é;»ÏQ›€¿éYÍBÔ9@¿éw…ã[€¿é”äs©5¿é±ç¶Ê€À¿éÎŽm „€¿éê×X@¿êÁ4þx@¿ê"JÁÙ À¿ê=r»õÀ¿êX7ÛÔj@¿êr˜Þ*|€¿êŒ”zæ4À¿ê¦)i¬$¿ê¿V`ñd€¿êØûš€¿êðs<àó@¿ë`ˆˆ&@¿ëનs¿ë6òSɤÀ¿ëM”3DÀ¿ëcÄ÷@€¿ëyƒL¸‡@¿ëŽÍßuí¿ë££Z7€¿ë¸eûiÀ¿ëËé«j¿ëßWÑkA@¿ëòK}Ûœ@¿ìÃUhI€¿ì½ûŽû€¿ì(:î@¿ì96;³ç@¿ìI±À5@¿ìY©B‚±@¿ìi\‹»€¿ìx ÉÓ¢¿âöaüäK¿â¬ÉÒ™¼€¿âaþ°­Ð€¿âþ´ªê¿áÈÇúëó¿ázXžœc¿á*®¹¸9¿àÙÈe þ¿à‡£¸4¿à4>É $¿ß¿/]Œ¿ßXö±¿Þdöƒä%¿Ý´)õl¿Ý~ D¿ÜJ`@qá¿Û‘¦ëÁt¿ÚÖN%¤¿ÚRöR¿ÙW®†x¿Ø”`Ž¿×ÎbIuQ¿×±zEP¿Ö:I¢¨W¿Õl&Ë鸿ԛDüõÙ¿ÓÇ :Z6¿Òñ4†E\¿Òýà†ê¿Ñ;øF•¿Ð]³q ¿Îöà?¼Æ¿Í-ËVš¿Ë^÷œ™¶¿ÉŠ]ë²@¿Ç¯õÐz¿ÅÏ·#^Ü¿Ã険•ø¿Áý•e芿À ¡ðÍt¿¼'nCûp¿¸+™vé¿´#´ôÞp¿°°.Úx¿§ÞõÀ迟 ­ß€¿ŒQÑdÀ?g^A'€?”2G?4à?¢Õk÷H?«ªÞ¼°È?²LÎÒIH?¶Ðå;û ?»aÉEˆ?¿ÿz±x¸?ÂU Ú±f?İÛϦr?Ç/Á}ö?É|>Ø@?Ëë‹Ûz?Îa¥.K ?Ðo3j­I?Ѱì¸ì?ÒöÕ Å?Ô>z™D?ÕŠVÏz ?ÖÙ_öì?Ø,R"¶!?Ù‚yv½)?ÚܽpY?Ü91Z’ø?ݙʴG3?Þýè3$?à2Ç ãì€?àè`¦Ù¤?áŸÂã7+?âXðúê?ãêdR¿€?ãдœ€?äOzc}?åO¾µes€?æž?æÖ!Å÷,€?çœìÅ?ècïUè„€?é-£´“þ€?éù9}È<?êÆ²÷½€?ë–iy€?ìgZÛÝ€?í:ŒVbÍ?î«fw¢?îæ¹—.?5Q¶€?ðMVGÈ~À?ð»Êú©?ñ+;Û¤@?ñ›ª¬F€?ò ÌI¶€?òƒ/×À?òòðhakÀ?óg_¡äñÀ?óÜÒ¡?ôSHÇdo?ôÊÅ ø Àastroquery-0.3.7/astroquery/alfalfa/tests/setup_package.py0000644000077000000240000000044313067234073024121 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from __future__ import absolute_import import os def get_package_data(): paths = [os.path.join('data', '*.txt'), os.path.join('data', '*.fits'), ] return {'astroquery.alfalfa.tests': paths} astroquery-0.3.7/astroquery/alfalfa/tests/test_alfalfa.py0000644000077000000240000000461213116602135023726 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from contextlib import contextmanager import os import requests from astropy import coordinates import pytest from ...utils import commons from ...utils.testing_tools import MockResponse from ... import alfalfa DATA_FILES = {'catalog': 'alfalfa_cat_small.txt', 'spectrum': 'alfalfa_sp.fits'} class MockResponseAlfalfa(MockResponse): def __init__(self, content, **kwargs): super(MockResponseAlfalfa, self).__init__(content, **kwargs) def iter_lines(self): for l in self.text.split("\n"): yield l def close(self): pass @pytest.fixture def patch_get(request): try: mp = request.getfixturevalue("monkeypatch") except AttributeError: # pytest < 3 mp = request.getfuncargvalue("monkeypatch") mp.setattr(requests, 'get', get_mockreturn) return mp @pytest.fixture def patch_get_readable_fileobj(request): @contextmanager def get_readable_fileobj_mockreturn(filename, **kwargs): file_obj = data_path(DATA_FILES['spectrum']) # TODO: add images option yield open(file_obj, 'rb') # read as bytes, assuming FITS try: mp = request.getfixturevalue("monkeypatch") except AttributeError: # pytest < 3 mp = request.getfuncargvalue("monkeypatch") mp.setattr(commons, 'get_readable_fileobj', get_readable_fileobj_mockreturn) return mp def get_mockreturn(url, params=None, timeout=10): filename = data_path(DATA_FILES['catalog']) content = open(filename, 'rb').read() return MockResponseAlfalfa(content) def data_path(filename): data_dir = os.path.join(os.path.dirname(__file__), 'data') return os.path.join(data_dir, filename) # Test Case: A Seyfert 1 galaxy coords = coordinates.SkyCoord('0h8m05.63s +14d50m23.3s') ALFALFA = alfalfa.core.Alfalfa() def test_alfalfa_catalog(patch_get, patch_get_readable_fileobj, coords=coords): cat = ALFALFA.get_catalog() assert len(cat) > 0 def test_alfalfa_crossID(patch_get, patch_get_readable_fileobj, coords=coords): agc = ALFALFA.query_region(coords, optical_counterpart=True) assert agc == 100051 def test_alfalfa_spectrum(patch_get, patch_get_readable_fileobj, coords=coords): agc = ALFALFA.query_region(coords, optical_counterpart=True) sp = ALFALFA.get_spectrum(agc) assert len(sp) == 3 astroquery-0.3.7/astroquery/alma/0000755000077000000240000000000013232443301017103 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/__init__.py0000644000077000000240000000153713067234073021234 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst """ ALMA Archive service. """ from astropy import config as _config class Conf(_config.ConfigNamespace): """ Configuration parameters for `astroquery.alma`. """ timeout = _config.ConfigItem(60, "Timeout in seconds.") archive_url = _config.ConfigItem( ['http://almascience.org', 'https://almascience.eso.org', 'https://almascience.nrao.edu', 'https://almascience.nao.ac.jp', 'https://beta.cadc-ccda.hia-iha.nrc-cnrc.gc.ca'], 'The ALMA Archive mirror to use.') username = _config.ConfigItem( "", 'Optional default username for ALMA archive.') conf = Conf() from .core import Alma, AlmaClass from .utils import make_finder_chart __all__ = ['Alma', 'AlmaClass', 'Conf', 'conf', ] astroquery-0.3.7/astroquery/alma/core.py0000644000077000000240000012744213232443033020421 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from __future__ import print_function import time import os.path import getpass import keyring import numpy as np import re import tarfile import string import requests from requests import HTTPError import sys from pkg_resources import resource_filename from bs4 import BeautifulSoup from astropy.extern.six.moves.urllib_parse import urljoin, urlparse from astropy.extern.six import iteritems, StringIO from astropy.extern import six from astropy.table import Table, Column from astropy import log from astropy.utils.console import ProgressBar from astropy import units as u import astropy.coordinates as coord import astropy.io.votable as votable from ..exceptions import (RemoteServiceError, TableParseError, InvalidQueryError, LoginError) from ..utils import commons, system_tools, url_helpers from ..utils.process_asyncs import async_to_sync from ..query import QueryWithLogin from . import conf __doctest_skip__ = ['AlmaClass.*'] @async_to_sync class AlmaClass(QueryWithLogin): TIMEOUT = conf.timeout archive_url = conf.archive_url USERNAME = conf.username def __init__(self): super(AlmaClass, self).__init__() def query_object_async(self, object_name, cache=True, public=True, science=True, payload=None, **kwargs): """ Query the archive with a source name Parameters ---------- object_name : str The object name. Will be parsed by SESAME on the ALMA servers. cache : bool Cache the query? public : bool Return only publicly available datasets? science : bool Return only data marked as "science" in the archive? payload : dict Dictionary of additional keywords. See `help`. kwargs : dict Passed to `query_async` """ if payload is None: payload = {} payload.update({'source_name_resolver': object_name, }) return self.query_async(payload, cache=cache, public=public, science=science, **kwargs) def query_region_async(self, coordinate, radius, cache=True, public=True, science=True, payload=None, **kwargs): """ Query the ALMA archive with a source name and radius Parameters ---------- coordinates : str / `astropy.coordinates` the identifier or coordinates around which to query. radius : str / `~astropy.units.Quantity`, optional the radius of the region cache : bool Cache the query? public : bool Return only publicly available datasets? science : bool Return only data marked as "science" in the archive? payload : dict Dictionary of additional keywords. See `help`. kwargs : dict Passed to `query_async` """ coordinate = commons.parse_coordinates(coordinate) cstr = coordinate.fk5.to_string(style='hmsdms', sep=':') rdc = "{cstr}, {rad}".format(cstr=cstr, rad=coord.Angle(radius).deg) if payload is None: payload = {} payload.update({'ra_dec': rdc}) return self.query_async(payload, cache=cache, public=public, science=science, **kwargs) def query_async(self, payload, cache=True, public=True, science=True, max_retries=5, get_html_version=False, get_query_payload=False, **kwargs): """ Perform a generic query with user-specified payload Parameters ---------- payload : dict A dictionary of payload keywords that are accepted by the ALMA archive system. You can look these up by examining the forms at http://almascience.org/aq or using the `help` method cache : bool Cache the query? (note: HTML queries *cannot* be cached using the standard caching mechanism because the URLs are different each time public : bool Return only publicly available datasets? science : bool Return only data marked as "science" in the archive? """ url = urljoin(self._get_dataarchive_url(), 'aq/') payload.update(kwargs) if get_html_version: payload.update({'result_view': 'observation', 'format': 'URL', 'download': 'true'}) else: payload.update({'result_view': 'raw', 'format': 'VOTABLE', 'download': 'true'}) if public: payload['public_data'] = 'public' if science: payload['science_observations'] = '=%TARGET%' self.validate_query(payload) if get_query_payload: return payload response = self._request('GET', url, params=payload, timeout=self.TIMEOUT, cache=cache and not get_html_version) self._last_response = response response.raise_for_status() if get_html_version: if 'run' not in response.text: if max_retries > 0: log.info("Failed query. Retrying up to {0} more times" .format(max_retries)) return self.query_async(payload=payload, cache=False, public=public, science=science, max_retries=max_retries-1, get_html_version=get_html_version, get_query_payload=get_query_payload, **kwargs) raise RemoteServiceError("Incorrect return from HTML table query.") response2 = self._request('GET', "{0}/{1}/{2}".format( self._get_dataarchive_url(), 'aq', response.text), params={'query_url': response.url.split("?")[-1]}, timeout=self.TIMEOUT, cache=False, ) self._last_response = response2 response2.raise_for_status() if len(response2.text) == 0: if max_retries > 0: log.info("Failed (empty) query. Retrying up to {0} more times" .format(max_retries)) return self.query_async(payload=payload, cache=cache, public=public, science=science, max_retries=max_retries-1, get_html_version=get_html_version, get_query_payload=get_query_payload, **kwargs) raise RemoteServiceError("Empty return.") return response2 else: return response def validate_query(self, payload, cache=True): """ Use the ALMA query validator service to check whether the keywords are valid """ # Check that the keywords specified are allowed self._validate_payload(payload) vurl = self._get_dataarchive_url() + '/aq/validate' bad_kws = {} for kw in payload: vpayload = {'field': kw, kw: payload[kw]} response = self._request('GET', vurl, params=vpayload, cache=cache, timeout=self.TIMEOUT) if response.content: bad_kws[kw] = response.content if bad_kws: raise InvalidQueryError("Invalid query parameters: " "{0}".format(bad_kws)) def _get_dataarchive_url(self): """ If the generic ALMA URL is used, query it to determine which mirror to access for querying data """ if not hasattr(self, 'dataarchive_url'): if self.archive_url in ('http://almascience.org', 'https://almascience.org'): response = self._request('GET', self.archive_url + "/aq", cache=False) response.raise_for_status() # Jan 2017: we have to force https because the archive doesn't # tell us it needs https. self.dataarchive_url = response.url.replace("/aq/", "").replace("http://", "https://") else: self.dataarchive_url = self.archive_url return self.dataarchive_url def stage_data(self, uids): """ Stage ALMA data Parameters ---------- uids : list or str A list of valid UIDs or a single UID. UIDs should have the form: 'uid://A002/X391d0b/X7b' Returns ------- data_file_table : Table A table containing 3 columns: the UID, the file URL (for future downloading), and the file size """ """ With log.set_level(10) INFO: Staging files... [astroquery.alma.core] DEBUG: First request URL: https://almascience.eso.org/rh/submission [astroquery.alma.core] DEBUG: First request payload: {'dataset': [u'ALMA+uid___A002_X3b3400_X90f']} [astroquery.alma.core] DEBUG: First response URL: https://almascience.eso.org/rh/checkAuthenticationStatus/3f98de33-197e-4692-9afa-496842032ea9/submission [astroquery.alma.core] DEBUG: Request ID: 3f98de33-197e-4692-9afa-496842032ea9 [astroquery.alma.core] DEBUG: Submission URL: https://almascience.eso.org/rh/submission/3f98de33-197e-4692-9afa-496842032ea9 [astroquery.alma.core] .DEBUG: Data list URL: https://almascience.eso.org/rh/requests/anonymous/786823226 [astroquery.alma.core] """ if isinstance(uids, six.string_types + (np.bytes_,)): uids = [uids] if not isinstance(uids, (list, tuple, np.ndarray)): raise TypeError("Datasets must be given as a list of strings.") log.info("Staging files...") self._get_dataarchive_url() url = urljoin(self.dataarchive_url, 'rh/submission') log.debug("First request URL: {0}".format(url)) # 'ALMA+uid___A002_X391d0b_X7b' payload = {'dataset': ['ALMA+' + clean_uid(uid) for uid in uids]} log.debug("First request payload: {0}".format(payload)) self._staging_log = {'first_post_url': url} # Request staging for the UIDs # This component cannot be cached, since the returned data can change # if new data are uploaded response = self._request('POST', url, data=payload, timeout=self.TIMEOUT, cache=False) self._staging_log['initial_response'] = response log.debug("First response URL: {0}".format(response.url)) if 'login' in response.url: raise ValueError("You must login before downloading this data set.") if response.status_code == 405: if hasattr(self, '_last_successful_staging_log'): log.warning("Error 405 received. If you have previously staged " "the same UIDs, the result returned is probably " "correct, otherwise you may need to create a fresh " "astroquery.Alma instance.") return self._last_successful_staging_log['result'] else: raise HTTPError("Received an error 405: this may indicate you " "have already staged the data. Try downloading " "the file URLs directly with download_files.") response.raise_for_status() if 'j_spring_cas_security_check' in response.url: time.sleep(1) # CANNOT cache this stage: it not a real data page! results in # infinite loops response = self._request('POST', url, data=payload, timeout=self.TIMEOUT, cache=False) self._staging_log['initial_response'] = response if 'j_spring_cas_security_check' in response.url: log.warning("Staging request was not successful. Try again?") response.raise_for_status() if 'j_spring_cas_security_check' in response.url: raise RemoteServiceError("Could not access data. This error " "can arise if the data are private and " "you do not have access rights or are " "not logged in.") request_id = response.url.split("/")[-2] self._staging_log['request_id'] = request_id log.debug("Request ID: {0}".format(request_id)) # Submit a request for the specific request ID identified above submission_url = urljoin(self.dataarchive_url, url_helpers.join('rh/submission', request_id)) log.debug("Submission URL: {0}".format(submission_url)) self._staging_log['submission_url'] = submission_url staging_submission = self._request('GET', submission_url, cache=True) self._staging_log['staging_submission'] = staging_submission staging_submission.raise_for_status() data_page_url = staging_submission.url self._staging_log['data_page_url'] = data_page_url dpid = data_page_url.split("/")[-1] self._staging_log['staging_page_id'] = dpid # CANNOT cache this step: please_wait will happen infinitely data_page = self._request('GET', data_page_url, cache=False) self._staging_log['data_page'] = data_page data_page.raise_for_status() has_completed = False while not has_completed: time.sleep(1) summary = self._request('GET', url_helpers.join(data_page_url, 'summary'), cache=False) summary.raise_for_status() print(".", end='') sys.stdout.flush() has_completed = summary.json()['complete'] self._staging_log['summary'] = summary summary.raise_for_status() self._staging_log['json_data'] = json_data = summary.json() username = self.USERNAME if self.USERNAME else 'anonymous' # templates: # https://almascience.eso.org/dataPortal/requests/keflavich/946895898/ALMA/ # 2013.1.00308.S_uid___A001_X196_X93_001_of_001.tar/2013.1.00308.S_uid___A001_X196_X93_001_of_001.tar # uid___A002_X9ee74a_X26f0/2013.1.00308.S_uid___A002_X9ee74a_X26f0.asdm.sdm.tar url_decomposed = urlparse(data_page_url) base_url = ('{uri.scheme}://{uri.netloc}/' 'dataPortal/requests/{username}/' '{staging_page_id}/ALMA'.format(uri=url_decomposed, staging_page_id=dpid, username=username, )) tbl = self._json_summary_to_table(json_data, base_url=base_url) self._staging_log['result'] = tbl self._staging_log['file_urls'] = tbl['URL'] self._last_successful_staging_log = self._staging_log return tbl def _HEADER_data_size(self, files): """ Given a list of file URLs, return the data size. This is useful for assessing how much data you might be downloading! (This is discouraged by the ALMA archive, as it puts unnecessary load on their system) """ totalsize = 0 * u.B data_sizes = {} pb = ProgressBar(len(files)) for ii, fileLink in enumerate(files): response = self._request('HEAD', fileLink, stream=False, cache=False, timeout=self.TIMEOUT) filesize = (int(response.headers['content-length']) * u.B).to(u.GB) totalsize += filesize data_sizes[fileLink] = filesize log.debug("File {0}: size {1}".format(fileLink, filesize)) pb.update(ii + 1) response.raise_for_status() return data_sizes, totalsize.to(u.GB) def download_files(self, files, savedir=None, cache=True, continuation=True): """ Given a list of file URLs, download them Note: Given a list with repeated URLs, each will only be downloaded once, so the return may have a different length than the input list """ downloaded_files = [] if savedir is None: savedir = self.cache_location for fileLink in unique(files): filename = self._request("GET", fileLink, save=True, savedir=savedir, timeout=self.TIMEOUT, cache=cache, continuation=continuation) downloaded_files.append(filename) return downloaded_files def retrieve_data_from_uid(self, uids, cache=True): """ Stage & Download ALMA data. Will print out the expected file size before attempting the download. Parameters ---------- uids : list or str A list of valid UIDs or a single UID. UIDs should have the form: 'uid://A002/X391d0b/X7b' cache : bool Whether to cache the downloads. Returns ------- downloaded_files : list A list of the downloaded file paths """ if isinstance(uids, six.string_types + (np.bytes_,)): uids = [uids] if not isinstance(uids, (list, tuple, np.ndarray)): raise TypeError("Datasets must be given as a list of strings.") files = self.stage_data(uids) file_urls = files['URL'] totalsize = files['size'].sum() * files['size'].unit # each_size, totalsize = self.data_size(files) log.info("Downloading files of size {0}...".format(totalsize.to(u.GB))) # TODO: Add cache=cache keyword here. Currently would have no effect. downloaded_files = self.download_files(file_urls) return downloaded_files def _parse_result(self, response, verbose=False): """ Parse a VOtable response """ if not verbose: commons.suppress_vo_warnings() if 'run?' in response.url: if response.text == "": raise RemoteServiceError("Empty return.") # this is a CSV-like table returned via a direct browser request import pandas table = Table.from_pandas(pandas.read_csv(StringIO(response.text))) else: fixed_content = self._hack_bad_arraysize_vofix(response.content) tf = six.BytesIO(fixed_content) vo_tree = votable.parse(tf, pedantic=False, invalid='mask') first_table = vo_tree.get_first_table() table = first_table.to_table(use_names_over_ids=True) return table def _hack_bad_arraysize_vofix(self, text): """ Hack to fix an error in the ALMA votables present in most 2016 and 2017 queries. The problem is that this entry: ' \r', has an invalid ``arraysize`` entry. Also, it returns a char, but it should be an int. Since that problem was discovered and fixed, many other entries have the same error. According to the IVOA, the tables are wrong, not astropy.io.votable: http://www.ivoa.net/documents/VOTable/20130315/PR-VOTable-1.3-20130315.html#ToC11 """ lines = text.split(b"\n") newlines = [] for ln in lines: if b'FIELD name="Band"' in ln: ln = ln.replace(b'arraysize="0*"', b'arraysize="1*"') ln = ln.replace(b'datatype="char"', b'datatype="int"') elif b'arraysize="0*"' in ln: ln = ln.replace(b'arraysize="0*"', b'arraysize="*"') newlines.append(ln) return b"\n".join(newlines) def _login(self, username=None, store_password=False, reenter_password=False): """ Login to the ALMA Science Portal. Parameters ---------- username : str, optional Username to the ALMA Science Portal. If not given, it should be specified in the config file. store_password : bool, optional Stores the password securely in your keyring. Default is False. reenter_password : bool, optional Asks for the password even if it is already stored in the keyring. This is the way to overwrite an already stored passwork on the keyring. Default is False. """ if username is None: if not self.USERNAME: raise LoginError("If you do not pass a username to login(), " "you should configure a default one!") else: username = self.USERNAME # Check if already logged in loginpage = self._request("GET", "https://asa.alma.cl/cas/login", cache=False) root = BeautifulSoup(loginpage.content, 'html5lib') if root.find('div', class_='success'): log.info("Already logged in.") return True # Get password from keyring or prompt if reenter_password is False: password_from_keyring = keyring.get_password( "astroquery:asa.alma.cl", username) else: password_from_keyring = None if password_from_keyring is None: if system_tools.in_ipynb(): log.warning("You may be using an ipython notebook:" " the password form will appear in your terminal.") password = getpass.getpass("{0}, enter your ALMA password:" "\n".format(username)) else: password = password_from_keyring # Authenticate log.info("Authenticating {0} on asa.alma.cl ...".format(username)) # Do not cache pieces of the login process data = {kw: root.find('input', {'name': kw})['value'] for kw in ('lt', '_eventId', 'execution')} data['username'] = username data['password'] = password login_response = self._request("POST", "https://asa.alma.cl/cas/login", params={'service': urljoin(self.archive_url, 'rh/login')}, data=data, cache=False) authenticated = ('You have successfully logged in' in login_response.text) if authenticated: log.info("Authentication successful!") self.USERNAME = username else: log.exception("Authentication failed!") # When authenticated, save password in keyring if needed if authenticated and password_from_keyring is None and store_password: keyring.set_password("astroquery:asa.alma.cl", username, password) return authenticated def get_cycle0_uid_contents(self, uid): """ List the file contents of a UID from Cycle 0. Will raise an error if the UID is from cycle 1+, since those data have been released in a different and more consistent format. See http://almascience.org/documents-and-tools/cycle-2/ALMAQA2Productsv1.01.pdf for details. """ # First, check if UID is in the Cycle 0 listing if uid in self.cycle0_table['uid']: cycle0id = self.cycle0_table[ self.cycle0_table['uid'] == uid][0]['ID'] contents = [row['Files'] for row in self._cycle0_tarfile_content if cycle0id in row['ID']] return contents else: info_url = urljoin( self._get_dataarchive_url(), 'documents-and-tools/cycle-2/ALMAQA2Productsv1.01.pdf') raise ValueError("Not a Cycle 0 UID. See {0} for details about " "cycle 1+ data release formats.".format(info_url)) @property def _cycle0_tarfile_content(self): """ In principle, this is a static file, but we'll retrieve it just in case """ if not hasattr(self, '_cycle0_tarfile_content_table'): url = urljoin(self._get_dataarchive_url(), 'alma-data/archive/cycle-0-tarfile-content') response = self._request('GET', url, cache=True) # html.parser is needed because some 's have form: # which the default parser does not pick up root = BeautifulSoup(response.content, 'html.parser') html_table = root.find('table', class_='grid listing') data = list(zip(*[(x.findAll('td')[0].text, x.findAll('td')[1].text) for x in html_table.findAll('tr')])) columns = [Column(data=data[0], name='ID'), Column(data=data[1], name='Files')] tbl = Table(columns) assert len(tbl) == 8497 self._cycle0_tarfile_content_table = tbl else: tbl = self._cycle0_tarfile_content_table return tbl @property def cycle0_table(self): """ Return a table of Cycle 0 Project IDs and associated UIDs. The table is distributed with astroquery and was provided by Felix Stoehr. """ if not hasattr(self, '_cycle0_table'): filename = resource_filename( 'astroquery.alma', 'data/cycle0_delivery_asdm_mapping.txt') self._cycle0_table = Table.read(filename, format='ascii.no_header') self._cycle0_table.rename_column('col1', 'ID') self._cycle0_table.rename_column('col2', 'uid') return self._cycle0_table def get_files_from_tarballs(self, downloaded_files, regex=r'.*\.fits$', path='cache_path', verbose=True): """ Given a list of successfully downloaded tarballs, extract files with names matching a specified regular expression. The default is to extract all FITS files Parameters ---------- downloaded_files : list A list of downloaded files. These should be paths on your local machine. regex : str A valid regular expression path : 'cache_path' or str If 'cache_path', will use the astroquery.Alma cache directory (``Alma.cache_location``), otherwise will use the specified path. Note that the subdirectory structure of the tarball will be maintained. Returns ------- filelist : list A list of the extracted file locations on disk """ if path == 'cache_path': path = self.cache_location elif not os.path.isdir(path): raise OSError("Specified an invalid path {0}.".format(path)) fitsre = re.compile(regex) filelist = [] for fn in downloaded_files: tf = tarfile.open(fn) for member in tf.getmembers(): if fitsre.match(member.name): if verbose: log.info("Extracting {0} to {1}".format(member.name, path)) tf.extract(member, path) filelist.append(os.path.join(path, member.name)) return filelist def download_and_extract_files(self, urls, delete=True, regex=r'.*\.fits$', include_asdm=False, path='cache_path', verbose=True): """ Given a list of tarball URLs: 1. Download the tarball 2. Extract all FITS files (or whatever matches the regex) 3. Delete the downloaded tarball See ``Alma.get_files_from_tarballs`` for details Parameters ---------- urls : str or list A single URL or a list of URLs include_asdm : bool Only affects cycle 1+ data. If set, the ASDM files will be downloaded in addition to the script and log files. By default, though, this file will be downloaded and deleted without extracting any information: you must change the regex if you want to extract data from an ASDM tarball """ if isinstance(urls, six.string_types): urls = [urls] if not isinstance(urls, (list, tuple, np.ndarray)): raise TypeError("Datasets must be given as a list of strings.") all_files = [] for url in urls: if url[-4:] != '.tar': raise ValueError("URLs should be links to tarballs.") tarfile_name = os.path.split(url)[-1] if tarfile_name in self._cycle0_tarfile_content['ID']: # It is a cycle 0 file: need to check if it contains FITS match = (self._cycle0_tarfile_content['ID'] == tarfile_name) if not any(re.match(regex, x) for x in self._cycle0_tarfile_content['Files'][match]): log.info("No FITS files found in {0}".format(tarfile_name)) continue else: if 'asdm' in tarfile_name and not include_asdm: log.info("ASDM tarballs do not contain FITS files; " "skipping.") continue try: tarball_name = self._request('GET', url, save=True, timeout=self.TIMEOUT) except requests.ConnectionError as ex: self.partial_file_list = all_files log.error("There was an error downloading the file. " "A partially completed download list is " "in Alma.partial_file_list") raise ex except requests.HTTPError as ex: if ex.response.status_code == 401: log.info("Access denied to {url}. Skipping to" " next file".format(url=url)) continue else: raise ex fitsfilelist = self.get_files_from_tarballs([tarball_name], regex=regex, path=path, verbose=verbose) if delete: log.info("Deleting {0}".format(tarball_name)) os.remove(tarball_name) all_files += fitsfilelist return all_files def help(self, cache=True): """ Return the valid query parameters """ help_list = self._get_help_page(cache=cache) print("Valid ALMA keywords:") for title, section in help_list: print() print(title) for row in section: if len(row) == 2: # text value name, payload_keyword = row print(" {0:33s}: {1:35s}".format(name, payload_keyword)) # elif len(row) == 3: # radio button # name,payload_keyword,value = row # print(" {0:33s}: {1:20s} = {2:15s}".format(name, # payload_keyword, # value)) elif len(row) == 4: # radio button or checkbox name, payload_keyword, checkbox, value = row print(" {2} {0:29s}: {1:20s} = {3:15s}" .format(name, payload_keyword, checkbox, value)) else: raise ValueError("Wrong number of rows - ALMA query page" " did not parse properly.") def _get_help_page(self, cache=True): if not hasattr(self, '_help_list') or not self._help_list: querypage = self._request( 'GET', self._get_dataarchive_url() + "/aq/", cache=cache, timeout=self.TIMEOUT) root = BeautifulSoup(querypage.content, "html5lib") sections = root.findAll('td', class_='category') whitespace = re.compile(r"\s+") help_list = [] for section in sections: title = section.find( 'div', class_='categorytitle').text.lstrip() help_section = (title, []) for inp in section.findAll('div', class_='inputdiv'): sp = inp.find('span') buttons = inp.findAll('input') for b in buttons: # old version:for=id=rawView; name=viewFormat # new version:for=id=rawView; name=result_view payload_keyword = b.attrs['name'] bid = b.attrs['id'] label = inp.find('label') if sp is not None: name = whitespace.sub(" ", sp.text) elif label.attrs['for'] == bid: name = whitespace.sub(" ", label.text) else: raise TableParseError("ALMA query page has" " an unrecognized entry") if b.attrs['type'] == 'text': help_section[1].append((name, payload_keyword)) elif b.attrs['type'] == 'radio': value = b.attrs['value'] if 'checked' in b.attrs: checked = b.attrs['checked'] == 'checked' checkbox = "(x)" if checked else "( )" else: checkbox = "( )" help_section[1].append((name, payload_keyword, checkbox, value)) elif b.attrs['type'] == 'checkbox': if 'checked' in b.attrs: checked = b.attrs['checked'] == 'checked' else: checked = False value = b.attrs['value'] checkbox = "[x]" if checked else "[ ]" help_section[1].append((name, payload_keyword, checkbox, value)) select = inp.find('select') if select is not None: options = [(filter_printable(option.text), option.attrs['value']) for option in select.findAll('option')] if sp is not None: name = whitespace.sub(" ", sp.text) else: name = select.attrs['name'] option_str = " , ".join(["{0} = {1}".format(o[0], o[1]) for o in options]) help_section[1].append((name, option_str)) help_list.append(help_section) self._help_list = help_list return self._help_list def _validate_payload(self, payload): if not hasattr(self, '_valid_params'): help_list = self._get_help_page(cache=False) self._valid_params = [row[1] for title, section in help_list for row in section] if len(self._valid_params) == 0: raise ValueError("The query validation failed for unknown " "reasons. Try again?") # These parameters are entirely hidden, but Felix says they are # allowed self._valid_params.append('download') self._valid_params.append('format') invalid_params = [k for k in payload if k not in self._valid_params] if len(invalid_params) > 0: raise InvalidQueryError("The following parameters are not accepted" " by the ALMA query service:" " {0}".format(invalid_params)) def _parse_staging_request_page(self, data_list_page): """ Parse pages like this one: https://almascience.eso.org/rh/requests/anonymous/786572566 that include links to data sets that have been requested and staged Parameters ---------- data_list_page : requests.Response object """ root = BeautifulSoup(data_list_page.content, 'html5lib') data_table = root.findAll('table', class_='list', id='report')[0] columns = {'uid': [], 'URL': [], 'size': []} for tr in data_table.findAll('tr'): tds = tr.findAll('td') # Cannot check class if it is not defined cl = 'class' in tr.attrs if (len(tds) > 1 and 'uid' in tds[0].text and (cl and 'Level' in tr['class'][0])): # New Style text = tds[0].text.strip().split() if text[0] in ('Asdm', 'Member'): uid = text[-1] elif len(tds) > 1 and 'uid' in tds[1].text: # Old Style uid = tds[1].text.strip() elif cl and tr['class'] == 'Level_1': raise ValueError("Heading was found when parsing the download " "page but it was not parsed correctly") if len(tds) > 3 and (cl and tr['class'][0] == 'fileRow'): # New Style size, unit = re.search(r'(-|[0-9\.]*)([A-Za-z]*)', tds[2].text).groups() href = tds[1].find('a') if size == '': # this is a header row continue authorized = ('access_authorized.png' in tds[3].findChild('img')['src']) if authorized: columns['uid'].append(uid) if href and 'href' in href.attrs: columns['URL'].append(href.attrs['href']) else: columns['URL'].append('None_Found') unit = (u.Unit(unit) if unit in ('GB', 'MB') else u.Unit('kB') if 'kb' in unit.lower() else 1) try: columns['size'].append(float(size) * u.Unit(unit)) except ValueError: # size is probably a string? columns['size'].append(-1 * u.byte) log.log(level=5, msg="Found a new-style entry. " "size={0} uid={1} url={2}" .format(size, uid, columns['URL'][-1])) else: log.warning("Access to {0} is not authorized.".format(uid)) elif len(tds) > 3 and tds[2].find('a'): # Old Style href = tds[2].find('a') size, unit = re.search(r'([0-9\.]*)([A-Za-z]*)', tds[3].text).groups() columns['uid'].append(uid) columns['URL'].append(href.attrs['href']) unit = (u.Unit(unit) if unit in ('GB', 'MB') else u.Unit('kB') if 'kb' in unit.lower() else 1) columns['size'].append(float(size) * u.Unit(unit)) log.log(level=5, msg="Found an old-style entry. " "size={0} uid={1} url={2}".format(size, uid, columns['URL'][-1])) columns['size'] = u.Quantity(columns['size'], u.Gbyte) if len(columns['uid']) == 0: raise RemoteServiceError( "No valid UIDs were found in the staged data table. " "Please include {0} in a bug report." .format(self._staging_log['data_list_url'])) tbl = Table([Column(name=k, data=v) for k, v in iteritems(columns)]) return tbl def _json_summary_to_table(self, data, base_url): """ """ columns = {'uid': [], 'URL': [], 'size': []} for entry in data['node_data']: # de_type can be useful (e.g., MOUS), but it is not necessarily # specified # file_name and file_key *must* be specified. is_file = (entry['file_name'] != 'null' and entry['file_key'] != 'null') if is_file: # "de_name": "ALMA+uid://A001/X122/X35e", columns['uid'].append(entry['de_name'][5:]) if entry['file_size'] == 'null': columns['size'].append(np.nan * u.Gbyte) else: columns['size'].append( (int(entry['file_size']) * u.B).to(u.Gbyte)) # example template for constructing url: # https://almascience.eso.org/dataPortal/requests/keflavich/940238268/ALMA/ # uid___A002_X9d6f4c_X154/2013.1.00546.S_uid___A002_X9d6f4c_X154.asdm.sdm.tar # above is WRONG... except for ASDMs, when it's right # should be: # 2013.1.00546.S_uid___A002_X9d6f4c_X154.asdm.sdm.tar/2013.1.00546.S_uid___A002_X9d6f4c_X154.asdm.sdm.tar # # apparently ASDMs are different from others: # templates: # https://almascience.eso.org/dataPortal/requests/keflavich/946895898/ALMA/ # 2013.1.00308.S_uid___A001_X196_X93_001_of_001.tar/2013.1.00308.S_uid___A001_X196_X93_001_of_001.tar # uid___A002_X9ee74a_X26f0/2013.1.00308.S_uid___A002_X9ee74a_X26f0.asdm.sdm.tar url = url_helpers.join(base_url, entry['file_key'], entry['file_name']) if 'null' in url: raise ValueError("The URL {0} was created containing " "'null', which is invalid.".format(url)) columns['URL'].append(url) columns['size'] = u.Quantity(columns['size'], u.Gbyte) tbl = Table([Column(name=k, data=v) for k, v in iteritems(columns)]) return tbl Alma = AlmaClass() def clean_uid(uid): """ Return a uid with all unacceptable characters replaced with underscores """ if not hasattr(uid, 'replace'): return clean_uid(str(uid.astype('S'))) try: return uid.decode('utf-8').replace(u"/", u"_").replace(u":", u"_") except AttributeError: return uid.replace("/", "_").replace(":", "_") def reform_uid(uid): """ Convert a uid with underscores to the original format """ return uid[:3] + "://" + "/".join(uid[6:].split("_")) def unique(seq): """ Return unique elements of a list, preserving order """ seen = set() seen_add = seen.add return [x for x in seq if not (x in seen or seen_add(x))] def filter_printable(s): """ extract printable characters from a string """ return filter(lambda x: x in string.printable, s) astroquery-0.3.7/astroquery/alma/data/0000755000077000000240000000000013232443301020014 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/data/cycle0_delivery_asdm_mapping.txt0000644000077000000240000010724113067234073026375 0ustar adamstaff000000000000002011.0.00170.S_2013-07-22 uid://A002/X5784d5/X15c 2011.0.00629.S_2013-02-21 uid://A002/X51d696/X315 2011.0.00170.S_2013-03-01 uid://A002/X5578f1/X1b8 2011.0.00175.S_2013-03-05 uid://A002/X40e374/X6cb 2011.0.00020.S_2012-12-01 uid://A002/X518d2b/Xbde 2011.0.00199.S_2013-03-01 uid://A002/X590461/X620 2011.0.00611.S_2013-03-01 uid://A002/X36a70f/X4ce 2011.0.00611.S_2013-03-01 uid://A002/X36a70f/X77a 2011.0.00611.S_2013-03-01 uid://A002/X535168/X435 2011.0.00611.S_2013-03-01 uid://A002/X535168/X66e 2011.0.00611.S_2013-03-01 uid://A002/X537777/X326 2011.0.00777.S_2013-03-01 uid://A002/X590461/Xc05 2011.0.00210.S_2013-02-27 uid://A002/X537777/X1de 2011.0.00210.S_2013-02-27 uid://A002/X537777/X426 2011.0.00772.S_2012-12-01 uid://A002/X4b29af/X24c 2011.0.00772.S_2012-12-01 uid://A002/X4b29af/X5c 2011.0.00175.S_2013-03-05 uid://A002/X40e374/X88e 2011.0.00232.S_2013-02-28 uid://A002/X54face/X1b5 2011.0.00735.S_2012-01-13 uid://A002/X36e26f/X22 2011.0.00647.S_2013-02-11 uid://A002/X52f1e2/X4af 2011.0.00367.S_2013-02-28 uid://A002/X54face/X623 2011.0.00367.S_2013-02-28 uid://A002/X5552a3/X7d0 2011.0.00367.S_2013-02-28 uid://A002/X56a957/Xa82 2011.0.00367.S_2013-02-28 uid://A002/X574c40/X263 2011.0.00367.S_2013-02-28 uid://A002/X579ce0/X36 2011.0.00367.S_2013-02-28 uid://A002/X383b50/X7b4 2011.0.00469.S_2013-02-28 uid://A002/X2eea47/X464 2011.0.00469.S_2013-02-28 uid://A002/X307fb7/X343 2011.0.00469.S_2013-02-28 uid://A002/X307fb7/X4a9 2011.0.00469.S_2013-02-28 uid://A002/X307fb7/X60f 2011.0.00469.S_2013-02-28 uid://A002/X4ba082/X36f 2011.0.00469.S_2013-02-28 uid://A002/X535168/X166 2011.0.00469.S_2013-02-28 uid://A002/X54d35d/X1f7 2011.0.00469.S_2013-02-28 uid://A002/X54d35d/X3be 2011.0.00469.S_2013-02-28 uid://A002/X2eea47/X322 2011.0.00629.S_2013-02-21 uid://A002/X51d696/Xef 2011.0.00170.S_2013-03-16 uid://A002/X56a957/X25b 2011.0.00777.S_2012-03-11 uid://A002/X590461/Xda3 2011.0.00808.S_2012-03-12 uid://A002/X36ffba/X1bb 2011.0.00131.S_2012-01-23 uid://A002/X2c75ca/X7ce 2011.0.00175.S_2013-03-05 uid://A002/X41e287/X591 2011.0.00020.S_2013-03-06 uid://A002/X32d5f1/X832 2011.0.00020.S_2013-03-06 uid://A002/X41ac1f/X21f 2011.0.00020.S_2013-03-06 uid://A002/X518d2b/X36e 2011.0.00020.S_2013-03-06 uid://A002/X535168/Xb6c 2011.0.00020.S_2013-03-06 uid://A002/X539bb9/X99 2011.0.00419.S_2013-03-06 uid://A002/X3dc0e7/Xbbc 2011.0.00419.S_2013-03-06 uid://A002/X4b1170/X226 2011.0.00419.S_2013-02-28 uid://A002/X3fa880/X52d 2011.0.00419.S_2013-02-28 uid://A002/X3fbe56/Xa24 2011.0.00419.S_2013-02-28 uid://A002/X40f691/X70e 2011.0.00419.S_2013-02-28 uid://A002/X4b1170/X57 2011.0.00319.S_2012-08-30 uid://A002/X435875/X371 2011.0.00131.S_2011-12-06 uid://A002/X2eaf7f/X43 2011.0.00647.S_2013-01-02 uid://A002/X52f1e2/X309 2011.0.00647.S_2013-01-02 uid://A002/X532128/X214 2011.0.00647.S_2013-01-02 uid://A002/X52f1e2/X182 2011.0.00647.S_2013-01-02 uid://A002/X532128/X8d 2011.0.00150.S_2013-03-21 uid://A002/X54d35d/X761 2011.0.00526.S_2012-09-14 uid://A002/X4b483b/X1ce 2011.0.00399.S_2012-12-17 uid://A002/X40e374/X366 2011.0.00399.S_2012-12-17 uid://A002/X5552a3/X9ef 2011.0.00150.S_2013-01-26 uid://A002/X54face/X434 2011.0.00150.S_2013-01-26 uid://A002/X3df8fa/Xf6 2011.0.00199.S_2013-04-05 uid://A002/X4fed6b/X1 2011.0.00199.S_2013-04-01 uid://A002/X518d2b/X8c8 2011.0.00199.S_2013-04-02 uid://A002/X4afc39/Xac8 2011.0.00199.S_2013-04-04 uid://A002/X460fc9/Xb16 2011.0.00199.S_2013-04-03 uid://A002/X463144/Xb67 2011.0.00780.S_2011-12-19 uid://A002/X305ca0/X637 2011.0.00780.S_2011-12-19 uid://A002/X305ca0/X33b 2011.0.00780.S_2011-12-19 uid://A002/X305ca0/X4b9 2011.0.00780.S_2011-12-19 uid://A002/X307fb7/X7a7 2011.0.00780.S_2011-12-19 uid://A002/X307fb7/X925 2011.0.00780.S_2011-12-19 uid://A002/X307fb7/Xa8b 2011.0.00780.S_2011-12-19 uid://A002/X307fb7/Xc2f 2011.0.00780.S_2011-12-19 uid://A002/X307fb7/Xd62 2011.0.00780.S_2011-12-19 uid://A002/X2f146f/X700 2011.0.00526.S_2013-02-14 uid://A002/X4b483b/X1ce 2011.0.00034.S_2013-05-06 uid://A002/X57d273/X230 2011.0.00034.S_2013-05-06 uid://A002/X57d273/X8e 2011.0.00034.S_2013-05-06 uid://A002/X590461/X11e1 2011.0.00064.S_2013-01-29 uid://A002/X3fa880/X4f 2011.0.00064.S_2013-01-29 uid://A002/X3cb0a0/X56e 2011.0.00064.S_2013-01-29 uid://A002/X40cb9e/X58 2011.0.00064.S_2013-01-29 uid://A002/X3cb0a0/X867 2011.0.00064.S_2013-01-29 uid://A002/X3e007f/X1f8 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X30d 2011.0.00727.S_2013-05-03 uid://A002/X4320bd/X4b2 2011.0.00727.S_2013-05-03 uid://A002/X433c46/X19c 2011.0.00727.S_2013-05-03 uid://A002/X4785e0/X284 2011.0.00727.S_2013-05-03 uid://A002/X4b483b/X5c 2011.0.00656.S_2013-05-03 uid://A002/X497d07/X354 2011.0.00656.S_2013-05-03 uid://A002/X49b5dd/X23d 2011.0.00064.S_2013-01-29 uid://A002/X3df8fa/X30e 2011.0.00470.S_2013-06-17 uid://A002/X5784d5/X4f9 2011.0.00470.S_2013-06-17 uid://A002/X36a70f/Xab6 2011.0.00470.S_2013-06-17 uid://A002/X388522/X341 2011.0.00470.S_2013-06-17 uid://A002/X388522/X483 2011.0.00470.S_2013-06-17 uid://A002/X590461/X1853 2011.0.00863.S_2013-05-24 uid://A002/X574c40/X58c 2011.0.00863.S_2013-05-24 uid://A002/X574c40/X6f2 2011.0.00661.S_2013-06-13 uid://A002/X579ce0/X23b 2011.0.00820.S_2013-06-24 uid://A002/X590461/X1b27 2011.0.00777.S_2013-08-06 uid://A002/X579ce0/X4ba 2011.0.00777.S_2013-08-06 uid://A002/X57b9e2/X609 2011.0.00777.S_2013-08-06 uid://A002/X57b9e2/X739 2011.0.00767.S_2013-02-07 uid://A002/X43036c/X20a 2011.0.00767.S_2013-02-07 uid://A002/X460fc9/X113 2011.0.00767.S_2013-02-07 uid://A002/X479db5/X64 2011.0.00767.S_2013-02-07 uid://A002/X5673e2/X4f 2011.0.00320.S_2013-05-02 uid://A002/X496ee3/X4be 2011.0.00320.S_2013-05-02 uid://A002/X49be16/X3d1 2011.0.00320.S_2013-05-02 uid://A002/X515b5c/X616 2011.0.00524.S_2012-05-30 uid://A002/X36bf6c/X70e 2011.0.00273.S_2012-05-30 uid://A002/X3c7a84/X1c 2011.0.00467.S_2012-05-29 uid://A002/X30cca6/X254 2011.0.00229.S_2012-06-10 uid://A002/X3c9295/X1e0 2011.0.00229.S_2012-06-10 uid://A002/X3c9295/X8c 2011.0.00229.S_2012-06-10 uid://A002/X3ca066/X549 2011.0.00229.S_2012-06-10 uid://A002/X3ca066/X67f 2011.0.00229.S_2012-06-10 uid://A002/X3ca066/X7dc 2011.0.00229.S_2012-06-10 uid://A002/X3dc0e7/X3f2 2011.0.00229.S_2012-06-10 uid://A002/X3dc0e7/X528 2011.0.00229.S_2012-06-10 uid://A002/X3df8fa/X20b 2011.0.00229.S_2012-06-10 uid://A002/X3e007f/X54 2011.0.00531.S_2012-06-22 uid://A002/X3f6a86/X5da 2011.0.00531.S_2012-06-22 uid://A002/X3b3400/Xcd7 2011.0.00206.S_2012-06-22 uid://A002/X411025/X6d7 2011.0.00958.S_2012-06-21 uid://A002/X411025/X568 2011.0.00097.S_2012-06-05 uid://A002/X3dc0e7/X6ce 2011.0.00097.S_2012-06-05 uid://A002/X3ddbb0/X54 2011.0.00097.S_2012-06-05 uid://A002/X3ddbb0/Xc2 2011.0.00097.S_2012-06-05 uid://A002/X3ddbb0/X2e3 2011.0.00750.S_2012-06-05 uid://A002/X3c9295/X40f 2011.0.00750.S_2012-06-05 uid://A002/X3c9295/X539 2011.0.00750.S_2012-06-05 uid://A002/X3c9295/X820 2011.0.00750.S_2012-06-05 uid://A002/X3daf0c/X541 2011.0.00957.S_2012-06-28 uid://A002/X36e957/X604 2011.0.00259.S_2012-06-18 uid://A002/X307fb7/X224 2011.0.00259.S_2012-06-18 uid://A002/X3fce56/X626 2011.0.00259.S_2012-06-18 uid://A002/X4122f3/X258 2011.0.00628.S_2012-06-29 uid://A002/X3f6a86/Xb99 2011.0.00628.S_2012-06-29 uid://A002/X3fa880/X9aa 2011.0.00628.S_2012-06-29 uid://A002/X3fdb4f/X91c 2011.0.00628.S_2012-06-29 uid://A002/X3fdb4f/Xae8 2011.0.00628.S_2012-06-29 uid://A002/X3fdb4f/Xcb4 2011.0.00010.S_2012-05-07 uid://A002/X3fbe56/X48f 2011.0.00010.S_2012-05-07 uid://A002/X3fce56/X69 2011.0.00010.S_2012-06-28 uid://A002/X3fce56/X1e1 2011.0.00010.S_2012-06-28 uid://A002/X3fce56/X4ba 2011.0.00465.S_2012-06-28 uid://A002/X41c27b/X2fc 2011.0.00061.S_2012-03-12 uid://A002/X32d5f1/X937 2011.0.00061.S_2012-03-12 uid://A002/X32f7a3/X34 2011.0.00061.S_2012-03-12 uid://A002/X369097/X1e9 2011.0.00061.S_2012-03-12 uid://A002/X369097/X419 2011.0.00061.S_2012-03-12 uid://A002/X3302c8/Xe 2011.0.00099.S_2012-02-24 uid://A002/X30cca6/Xc0 2011.0.00099.S_2012-02-24 uid://A002/X305ca0/X792 2011.0.00099.S_2012-05-16 uid://A002/X3c7a84/X164 2011.0.00101.S_2012-04-17 uid://A002/X31d189/Xa50 2011.0.00101.S_2012-04-17 uid://A002/X36bf6c/X58a 2011.0.00108.S_2012-04-17 uid://A002/X30a93d/Xba7 2011.0.00108.S_2012-04-17 uid://A002/X30cca6/X342 2011.0.00525.S_2012-04-17 uid://A002/X35be16/Xeb 2011.0.00525.S_2012-04-17 uid://A002/X35e007/Xfd 2011.0.00525.S_2012-04-17 uid://A002/X388522/X1f3 2011.0.00525.S_2012-04-17 uid://A002/X388522/Xa5 2011.0.00525.S_2012-04-17 uid://A002/X383b50/Xdb7 2011.0.00199.S_2012-06-15 uid://A002/X3ca066/X114 2011.0.00206.S_2012-07-30 uid://A002/X41f8d2/X9e9 2011.0.00476.S_2012-07-30 uid://A002/X3e007f/X3ab 2011.0.00465.S_2012-08-03 uid://A002/X3daf0c/X34c 2011.0.00465.S_2012-08-03 uid://A002/X43036c/X410 2011.0.00275.S_2012-07-13 uid://A002/X3fce56/X7b5 2011.0.00275.S_2012-07-13 uid://A002/X40e374/Xa31 2011.0.00275.S_2012-07-13 uid://A002/X41065b/X1c2 2011.0.00275.S_2012-07-13 uid://A002/X41065b/X50 2011.0.00275.S_2012-07-13 uid://A002/X41c27b/X622 2011.0.00275.S_2012-07-13 uid://A002/X41d520/X97a 2011.0.00511.S_2013-01-03 uid://A002/X436934/X48c 2011.0.00511.S_2013-01-03 uid://A002/X4785e0/Xab0 2011.0.00010.S_2012-08-17 uid://A002/X3fce56/X34d 2011.0.00010.S_2012-08-17 uid://A002/X3fdb4f/X2f7 2011.0.00121.S_2012-07-30 uid://A002/X41e287/Xd1 2011.0.00121.S_2012-08-16 uid://A002/X41e287/X1da 2011.0.00467.S_2012-08-24 uid://A002/X44a295/X888 2011.0.00099.S_2012-08-23 uid://A002/X3f99b1/X3ec 2011.0.00958.S_2012-08-27 uid://A002/X43036c/X9c6 2011.0.00172.S_2013-01-14 uid://A002/X449249/X247 2011.0.00172.S_2013-01-14 uid://A002/X44a295/X94f 2011.0.00172.S_2013-01-14 uid://A002/X3fbe56/Xece 2011.0.00772.S_2012-09-12 uid://A002/X3fbe56/X607 2011.0.00772.S_2012-09-12 uid://A002/X3b3400/X90f 2011.0.00772.S_2012-09-12 uid://A002/X3b3400/Xaf3 2011.0.00539.S_2012-08-31 uid://A002/X45c06b/Xabf 2011.0.00175.S_2012-09-06 uid://A002/X460fc9/X2ef 2011.0.00175.S_2012-09-06 uid://A002/X44c3c1/X2b4 2011.0.00175.S_2012-09-06 uid://A002/X4320bd/X621 2011.0.00175.S_2012-09-06 uid://A002/X3ddbb0/X866 2011.0.00217.S_2012-09-06 uid://A002/X47aefc/X369 2011.0.00217.S_2012-09-06 uid://A002/X47bd4d/X4c7 2011.0.00217.S_2012-09-06 uid://A002/X47d651/X15d 2011.0.00217.S_2012-09-06 uid://A002/X47d651/X2fc 2011.0.00217.S_2012-09-06 uid://A002/X47ed8e/X533 2011.0.00217.S_2012-09-06 uid://A002/X47ed8e/X6c 2011.0.00273.S_2012-09-07 uid://A002/X3c8f66/X352 2011.0.00273.S_2012-09-07 uid://A002/X494155/X8be 2011.0.00273.S_2012-09-07 uid://A002/X45f1dd/Xd13 2011.0.00958.S_2012-09-10 uid://A002/X49990a/X1f 2011.0.00243.S_2012-09-12 uid://A002/X44f2b6/X201 2011.0.00243.S_2012-09-12 uid://A002/X45c06b/X78b 2011.0.00243.S_2012-09-12 uid://A002/X494155/X674 2011.0.00243.S_2012-09-18 uid://A002/X44f2b6/X4c 2011.0.00243.S_2012-09-18 uid://A002/X44c3c1/X85c 2011.0.00243.S_2012-09-18 uid://A002/X4320bd/Xc78 2011.0.00010.S_2012-09-20 uid://A002/X3c7a84/X866 2011.0.00010.S_2012-09-20 uid://A002/X3c7a84/X9de 2011.0.00539.S_2012-09-20 uid://A002/X41d520/Xb0b 2011.0.00319.S_2012-08-30 uid://A002/X435875/X204 2011.0.00319.S_2012-08-30 uid://A002/X435875/X9d 2011.0.00319.S_2012-08-30 uid://A002/X44ddb2/X238 2011.0.00319.S_2012-08-30 uid://A002/X44ddb2/Xdb 2011.0.00133.S_2012-07-31 uid://A002/X3dc0e7/X2b5 2011.0.00133.S_2012-07-31 uid://A002/X3ddbb0/X195 2011.0.00133.S_2012-07-31 uid://A002/X4210d0/X136 2011.0.00307.S_2012-09-27 uid://A002/X45f1dd/X1ce 2011.0.00887.S_2012-09-22 uid://A002/X40d164/X1b3 2011.0.00887.S_2012-09-22 uid://A002/X40d164/X32 2011.0.00887.S_2012-09-22 uid://A002/X40d164/X334 2011.0.00887.S_2012-09-22 uid://A002/X40d164/X4b5 2011.0.00727.S_2012-09-24 uid://A002/X4320bd/X19d 2011.0.00727.S_2012-09-24 uid://A002/X4320bd/X346 2011.0.00208.S_2012-09-03 uid://A002/X41d520/Xd2d 2011.0.00208.S_2012-09-03 uid://A002/X45e2af/X139 2011.0.00208.S_2012-09-03 uid://A002/X45e2af/X2b1 2011.0.00724.S_2012-10-01 uid://A002/X41f8d2/X50f 2011.0.00405.S_2012-06-29 uid://A002/X4122f3/X133 2011.0.00405.S_2012-06-29 uid://A002/X412638/X12d 2011.0.00405.S_2012-06-29 uid://A002/X412638/X9 2011.0.00405.S_2012-06-29 uid://A002/X41e287/X788 2011.0.00405.S_2012-06-29 uid://A002/X41e287/X8ac 2011.0.00652.S_2012-10-04 uid://A002/X3fdb4f/X463 2011.0.00652.S_2012-10-04 uid://A002/X47bd4d/X37c 2011.0.00142.S_2012-10-04 uid://A002/X4320bd/X77f 2011.0.00142.S_2012-10-04 uid://A002/X3e007f/X53b 2011.0.00142.S_2012-10-04 uid://A002/X3e007f/X9c2 2011.0.00142.S_2012-10-04 uid://A002/X3e17df/Xa88 2011.0.00099.S_2012-10-03 uid://A002/X44c3c1/Xafb 2011.0.00467.S_2012-09-12 uid://A002/X30a93d/X772 2011.0.00467.S_2012-09-12 uid://A002/X30a93d/Xa32 2011.0.00467.S_2012-09-12 uid://A002/X30a93d/X603 2011.0.00467.S_2012-09-12 uid://A002/X41c27b/X838 2011.0.00467.S_2012-09-12 uid://A002/X41d520/Xbf0 2011.0.00467.S_2012-09-12 uid://A002/X41b513/X24e 2011.0.00083.S_2012-09-19 uid://A002/X4320bd/Xf38 2011.0.00083.S_2012-09-19 uid://A002/X433c46/X96b 2011.0.00083.S_2012-09-19 uid://A002/X4b29af/X8b8 2011.0.00083.S_2012-09-19 uid://A002/X4b71b4/X25a 2011.0.00476.S_2012-06-20 uid://A002/X3fdb4f/X78c 2011.0.00476.S_2012-06-20 uid://A002/X47aefc/X109 2011.0.00724.S_2012-10-10 uid://A002/X46457e/X2ec 2011.0.00124.S_2012-10-10 uid://A002/X46457e/X979 2011.0.00124.S_2012-10-10 uid://A002/X46457e/Xadc 2011.0.00124.S_2012-10-10 uid://A002/X4785e0/X7e1 2011.0.00124.S_2012-10-10 uid://A002/X4785e0/X953 2011.0.00099.S_2012-10-11 uid://A002/X44f2b6/X398 2011.0.00099.S_2012-10-10 uid://A002/X47bd4d/X1e8 2011.0.00307.S_2012-10-03 uid://A002/X4b29af/X5fc 2011.0.00307.S_2012-10-03 uid://A002/X4b29af/X6ba 2011.0.00768.S_2012-10-10 uid://A002/X47d651/Xa81 2011.0.00768.S_2012-10-10 uid://A002/X49a70a/X782 2011.0.00768.S_2012-10-10 uid://A002/X49a70a/X9a7 2011.0.00645.S_2012-10-15 uid://A002/X3da7b0/X1a5 2011.0.00645.S_2012-10-15 uid://A002/X3da7b0/X6c 2011.0.00645.S_2012-10-15 uid://A002/X44c3c1/X9f2 2011.0.00397.S_2012-10-17 uid://A002/X4b6a0b/X12f 2011.0.00405.S_2012-10-18 uid://A002/X3ca066/Xa6f 2011.0.00405.S_2012-10-18 uid://A002/X3ca066/Xb94 2011.0.00405.S_2012-10-18 uid://A002/X4122f3/Xf 2011.0.00405.S_2012-10-18 uid://A002/X43036c/X5f1 2011.0.00747.S_2012-10-18 uid://A002/X4b58a4/X31 2011.0.00612.S_2012-11-07 uid://A002/X460fc9/X7a8 2011.0.00612.S_2012-11-07 uid://A002/X463144/X609 2011.0.00612.S_2012-11-07 uid://A002/X4b483b/X5c3 2011.0.00511.S_2012-10-18 uid://A002/X4b1170/X8bf 2011.0.00511.S_2012-10-19 uid://A002/X4ae797/X8e2 2011.0.00733.S_2012-10-17 uid://A002/X44ddb2/X3df 2011.0.00733.S_2012-10-17 uid://A002/X44a295/X5b8 2011.0.00733.S_2012-10-17 uid://A002/X435875/X4df 2011.0.00733.S_2012-10-17 uid://A002/X44c3c1/X460 2011.0.00733.S_2012-10-18 uid://A002/X433c46/X4d2 2011.0.00318.S_2012-10-18 uid://A002/X41c27b/X53 2011.0.00318.S_2012-10-18 uid://A002/X41ac1f/X4b0 2011.0.00318.S_2012-10-18 uid://A002/X496160/X60 2011.0.00318.S_2012-10-18 uid://A002/X47d651/X4ba 2011.0.00318.S_2012-10-18 uid://A002/X4785e0/X3cc 2011.0.00318.S_2012-10-18 uid://A002/X433c46/X348 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X18c 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X21d 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X2cd 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X36d 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X5c 2011.0.00754.S_2012-10-25 uid://A002/X41d520/Xf3 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X401 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X4a7 2011.0.00754.S_2012-10-25 uid://A002/X41d520/X541 2011.0.00182.S_2012-10-29 uid://A002/X40e374/Xba3 2011.0.00182.S_2012-10-29 uid://A002/X40e374/Xd36 2011.0.00182.S_2012-10-29 uid://A002/X40e374/Xec9 2011.0.00182.S_2012-10-29 uid://A002/X41065b/X334 2011.0.00182.S_2012-10-29 uid://A002/X41065b/X4c7 2011.0.00182.S_2012-10-29 uid://A002/X4afc39/X43b 2011.0.00039.S_2012-10-20 uid://A002/X47bd4d/Xbd4 2011.0.00039.S_2012-10-20 uid://A002/X47bd4d/Xd2c 2011.0.00039.S_2012-10-20 uid://A002/X47ed8e/X804 2011.0.00039.S_2012-10-20 uid://A002/X497d07/X538 2011.0.00039.S_2012-10-20 uid://A002/X49990a/X197 2011.0.00039.S_2012-10-20 uid://A002/X49a70a/X5c0 2011.0.00957.S_2012-03-12 uid://A002/X30cca6/X9b4 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X1bb 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X451 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X589 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X671 2011.0.00957.S_2012-03-12 uid://A002/X32041d/X759 2011.0.00957.S_2012-03-12 uid://A002/X321719/X1e8 2011.0.00957.S_2012-03-12 uid://A002/X321719/X2c1 2011.0.00957.S_2012-03-12 uid://A002/X321719/X424 2011.0.00957.S_2012-03-12 uid://A002/X321719/X4fd 2011.0.00957.S_2012-03-12 uid://A002/X321719/X600 2011.0.00957.S_2012-03-12 uid://A002/X321719/X723 2011.0.00957.S_2012-03-12 uid://A002/X321719/X826 2011.0.00957.S_2012-03-12 uid://A002/X321719/X929 2011.0.00957.S_2012-03-12 uid://A002/X321719/Xa2c 2011.0.00957.S_2012-03-12 uid://A002/X321719/Xb2f 2011.0.00957.S_2012-03-12 uid://A002/X321719/Xc32 2011.0.00957.S_2012-03-12 uid://A002/X321719/Xe5 2011.0.00957.S_2012-03-12 uid://A002/X369097/X316 2011.0.00957.S_2012-03-12 uid://A002/X36d011/X29b 2011.0.00957.S_2012-03-12 uid://A002/X36d011/X393 2011.0.00957.S_2012-03-12 uid://A002/X36e957/X316 2011.0.00957.S_2012-03-12 uid://A002/X36e957/X419 2011.0.00957.S_2012-03-12 uid://A002/X36e957/X501 2011.0.00957.S_2012-03-12 uid://A002/X3854ab/Xaa 2011.0.00808.S_2012-03-12 uid://A002/X368c03/X12 2011.0.00808.S_2012-03-12 uid://A002/X36ffba/X1f 2011.0.00808.S_2012-03-12 uid://A002/X37f559/X764 2011.0.00635.S_2012-10-05 uid://A002/X4210d0/X4e0 2011.0.00635.S_2012-10-05 uid://A002/X460fc9/X4ce 2011.0.00635.S_2012-10-05 uid://A002/X463144/X307 2011.0.00635.S_2012-10-05 uid://A002/X463144/X473 2011.0.00405.S_2012-10-05 uid://A002/X411025/X441 2011.0.00405.S_2012-10-05 uid://A002/X41e287/X9d0 2011.0.00405.S_2012-10-05 uid://A002/X43036c/X734 2011.0.00121.S_2012-11-02 uid://A002/X41ac1f/X3f8 2011.0.00121.S_2012-11-02 uid://A002/X41c27b/X9c5 2011.0.00121.S_2012-11-02 uid://A002/X41d520/X800 2011.0.00121.S_2012-11-02 uid://A002/X41e287/Xc94 2011.0.00121.S_2012-11-02 uid://A002/X4210d0/Xb31 2011.0.00902.S_2012-05-15 uid://A002/X3c9295/X2eb 2011.0.00307.S_2012-11-06 uid://A002/X31ab3d/X404 2011.0.00307.S_2012-11-06 uid://A002/X31ab3d/X555 2011.0.00307.S_2012-11-06 uid://A002/X4ae797/X465 2011.0.00525.S_2012-10-31 uid://A002/X47aefc/X18 2011.0.00525.S_2012-10-31 uid://A002/X3b3400/X395 2011.0.00083.S_2012-10-30 uid://A002/X460fc9/X8cc 2011.0.00083.S_2012-10-30 uid://A002/X463144/X7f5 2011.0.00083.S_2012-10-30 uid://A002/X463144/X922 2011.0.00083.S_2012-10-30 uid://A002/X4b71b4/X616 2011.0.00210.S_2012-11-05 uid://A002/X4b1170/Xa3a 2011.0.00273.S_2012-11-05 uid://A002/X4ae797/X776 2011.0.00273.S_2012-11-05 uid://A002/X45e2af/X458 2011.0.00208.S_2012-11-12 uid://A002/X51ac2a/X35f 2011.0.00208.S_2012-11-12 uid://A002/X51ac2a/X4dc 2011.0.00539.S_2012-11-11 uid://A002/X47bd4d/X98b 2011.0.00539.S_2012-11-11 uid://A002/X496ee3/X28f 2011.0.00121.S_2012-11-06 uid://A002/X41f8d2/Xbf5 2011.0.00121.S_2012-11-06 uid://A002/X4ae797/X5ca 2011.0.00656.S_2012-11-06 uid://A002/X496160/X2d4 2011.0.00656.S_2012-11-06 uid://A002/X4b1170/X447 2011.0.00210.S_2012-11-15 uid://A002/X4927e8/X455 2011.0.00210.S_2012-11-15 uid://A002/X4927e8/X634 2011.0.00511.S_2012-11-06 uid://A002/X4b29af/X818 2011.0.00097.S_2012-11-14 uid://A002/X52f1e2/X6cd 2011.0.00136.S_2012-11-06 uid://A002/X31ab3d/X257 2011.0.00136.S_2012-11-06 uid://A002/X31ceee/Xe8 2011.0.00136.S_2012-11-06 uid://A002/X32d5f1/X2f0 2011.0.00136.S_2012-11-06 uid://A002/X32f196/X170 2011.0.00259.S_2012-11-06 uid://A002/X4b29af/Xab7 2011.0.00017.S_2012-11-20 uid://A002/X44ddb2/X64a 2011.0.00017.S_2012-11-20 uid://A002/X47ed8e/X3cd 2011.0.00017.S_2012-11-20 uid://A002/X494155/X23a 2011.0.00017.S_2012-11-20 uid://A002/X4b29af/X403 2011.0.00396.S_2012-11-20 uid://A002/X497d07/X1b2 2011.0.00396.S_2012-11-20 uid://A002/X4afc39/X72 2011.0.00396.S_2012-11-20 uid://A002/X4afc39/X25f 2011.0.00097.S_2012-11-18 uid://A002/X517008/X438 2011.0.00223.S_2012-11-22 uid://A002/X518d2b/X71a 2011.0.00223.S_2012-11-22 uid://A002/X51ac2a/X62a 2011.0.00097.S_2012-11-19 uid://A002/X517008/X617 2011.0.00097.S_2012-11-20 uid://A002/X51ac2a/Xb0f 2011.0.00525.S_2012-10-03 uid://A002/X41f8d2/X4f 2011.0.00525.S_2012-10-03 uid://A002/X40f691/X4e6 2011.0.00108.S_2012-11-28 uid://A002/X47b743/X130 2011.0.00108.S_2012-11-28 uid://A002/X515b5c/X279 2011.0.00120.S_2012-11-21 uid://A002/X4ae797/X90 2011.0.00120.S_2012-11-21 uid://A002/X4b483b/X3c1 2011.0.00120.S_2012-11-21 uid://A002/X4b71b4/X1f 2011.0.00120.S_2012-11-21 uid://A002/X4ba082/X18a 2011.0.00716.S_2012-11-28 uid://A002/X518d2b/X4b7 2011.0.00199.S_2012-11-20 uid://A002/X460fc9/Xa91 2011.0.00199.S_2012-11-20 uid://A002/X4afc39/Xa3a 2011.0.00199.S_2012-11-20 uid://A002/X518d2b/Xb3a 2011.0.00648.S_2012-11-28 uid://A002/X4927e8/X2da 2011.0.00648.S_2012-11-28 uid://A002/X496ee3/X5 2011.0.00648.S_2012-11-28 uid://A002/X49be16/X9c 2011.0.00648.S_2012-11-28 uid://A002/X4b1170/X584 2011.0.00539.S_2012-12-03 uid://A002/X535168/Xa18 2011.0.00017.S_2012-12-03 uid://A002/X4210d0/X815 2011.0.00017.S_2012-12-03 uid://A002/X436934/X28 2011.0.00259.S_2012-12-04 uid://A002/X552607/X24d 2011.0.00656.S_2012-12-01 uid://A002/X496160/X410 2011.0.00656.S_2012-12-01 uid://A002/X49b5dd/X39d 2011.0.00340.S_2012-12-05 uid://A002/X554543/X207 2011.0.00340.S_2012-12-05 uid://A002/X554543/X3d0 2011.0.00340.S_2012-12-05 uid://A002/X554543/X667 2011.0.00150.S_2012-12-05 uid://A002/X54d35d/X664 2011.0.00175.S_2012-12-07 uid://A002/X411025/X53 2011.0.00175.S_2012-12-07 uid://A002/X3fdb4f/X5e4 2011.0.00175.S_2012-12-07 uid://A002/X3ddbb0/X6be 2011.0.00175.S_2012-12-07 uid://A002/X49b5dd/Xfd 2011.0.00150.S_2012-12-06 uid://A002/X54d35d/X567 2011.0.00820.S_2012-12-01 uid://A002/X4bb4dd/X5d 2011.0.00725.S_2012-12-09 uid://A002/X5552a3/X159 2011.0.00511.S_2012-12-10 uid://A002/X518d2b/X571 2011.0.00511.S_2012-12-10 uid://A002/X51ac2a/X851 2011.0.00017.S_2012-12-10 uid://A002/X41f8d2/X8e0 2011.0.00017.S_2012-12-10 uid://A002/X449249/Xde 2011.0.00017.S_2012-12-10 uid://A002/X44c3c1/X6cc 2011.0.00150.S_2012-12-12 uid://A002/X54face/X340 2011.0.00175.S_2012-12-17 uid://A002/X46457e/X71 2011.0.00259.S_2012-12-19 uid://A002/X554543/Xdd 2011.0.00259.S_2012-12-19 uid://A002/X5552a3/X695 2011.0.00182.S_2012-12-20 uid://A002/X49990a/X505 2011.0.00182.S_2012-12-20 uid://A002/X4b58a4/X1ee 2011.0.00223.S_2012-12-20 uid://A002/X532128/X39b 2011.0.00223.S_2012-12-20 uid://A002/X533e2c/X288 2011.0.00223.S_2012-12-20 uid://A002/X533e2c/X39a 2011.0.00223.S_2012-12-20 uid://A002/X533e2c/X9a 2011.0.00921.S_2012-12-17 uid://A002/X44a295/X62 2011.0.00921.S_2012-12-17 uid://A002/X4785e0/X61 2011.0.00921.S_2012-12-17 uid://A002/X532128/X610 2011.0.00820.S_2012-12-21 uid://A002/X5552a3/Xd88 2011.0.00820.S_2012-12-21 uid://A002/X5552a3/Xdfb 2011.0.00820.S_2012-12-21 uid://A002/X5578f1/X878 2011.0.00820.S_2012-12-21 uid://A002/X5578f1/X958 2011.0.00876.S_2012-12-28 uid://A002/X3dc0e7/X7ae 2011.0.00876.S_2012-12-28 uid://A002/X3dc0e7/X983 2011.0.00876.S_2012-12-28 uid://A002/X3ddbb0/X447 2011.0.00876.S_2012-12-28 uid://A002/X3f8662/X1e7 2011.0.00876.S_2012-12-28 uid://A002/X3fa880/X1cd 2011.0.00876.S_2012-12-28 uid://A002/X44875a/X2c4 2011.0.00876.S_2012-12-28 uid://A002/X44a295/X261 2011.0.00876.S_2012-12-28 uid://A002/X44c3c1/Xdf 2011.0.00876.S_2012-12-28 uid://A002/X537777/X7f5 2011.0.00876.S_2012-12-28 uid://A002/X53a723/X20d 2011.0.00028.S_2013-01-02 uid://A002/X51ee7e/X44 2011.0.00028.S_2013-01-02 uid://A002/X51ee7e/X1c2 2011.0.00028.S_2013-01-02 uid://A002/X51ee7e/X35f 2011.0.00028.S_2013-01-02 uid://A002/X51ee7e/X4dd 2011.0.00028.S_2013-01-02 uid://A002/X51ee7e/X67a 2011.0.00150.S_2012-12-19 uid://A002/X54face/X434 2011.0.00150.S_2012-12-19 uid://A002/X3df8fa/Xf6 2011.0.00150.S_2012-12-20 uid://A002/X54face/X528 2011.0.00061.S_2012-12-25 uid://A002/X494155/X4e9 2011.0.00061.S_2012-12-25 uid://A002/X496160/X56e 2011.0.00526.S_2012-01-04 uid://A002/X5784d5/X7ae 2011.0.00724.S_2013-01-02 uid://A002/X4b58a4/X373 2011.0.00724.S_2013-01-04 uid://A002/X49a70a/Xd6 2011.0.00733.S_2013-01-10 uid://A002/X47ed8e/X311 2011.0.00307.S_2012-12-19 uid://A002/X31bf7f/X7a 2011.0.00307.S_2012-12-19 uid://A002/X54d35d/Xb61 2011.0.00497.S_2012-12-20 uid://A002/X535168/Xd17 2011.0.00097.S_2012-11-15 uid://A002/X52f1e2/X7a9 2011.0.00097.S_2012-11-16 uid://A002/X532128/X56a 2011.0.00348.S_2013-01-09 uid://A002/X3f837d/Xbe 2011.0.00348.S_2013-01-09 uid://A002/X3f8662/Xa8 2011.0.00348.S_2013-01-09 uid://A002/X3fbe56/X211 2011.0.00348.S_2013-01-09 uid://A002/X3fbe56/X350 2011.0.00348.S_2013-01-09 uid://A002/X5552a3/Xbd6 2011.0.00348.S_2013-01-09 uid://A002/X5784d5/X32d 2011.0.00348.S_2013-01-09 uid://A002/X57b9e2/X22a 2011.0.00777.S_2012-12-01 uid://A002/X32d5f1/X18c 2011.0.00777.S_2012-12-01 uid://A002/X388522/X5c5 2011.0.00777.S_2012-12-01 uid://A002/X4bb4dd/X16d 2011.0.00604.S_2012-11-20 uid://A002/X494155/Xa21 2011.0.00604.S_2012-11-20 uid://A002/X4b1170/Xbaf 2011.0.00020.S_2012-10-03 uid://A002/X32d5f1/X570 2011.0.00020.S_2012-10-03 uid://A002/X331413/X60 2011.0.00020.S_2012-10-03 uid://A002/X36a70f/X1c7 2011.0.00020.S_2012-10-03 uid://A002/X36e957/X1b8 2011.0.00020.S_2012-10-03 uid://A002/X41b513/X121 2011.0.00020.S_2012-10-03 uid://A002/X41c27b/X4f5 2011.0.00020.S_2012-10-03 uid://A002/X47701c/X166 2011.0.00020.S_2012-10-03 uid://A002/X47701c/X29c 2011.0.00652.S_2013-01-15 uid://A002/X383b50/X1007 2011.0.00652.S_2013-01-15 uid://A002/X5784d5/X689 2011.0.00863.S_2013-01-15 uid://A002/X552607/X95a 2011.0.00863.S_2013-01-15 uid://A002/X552607/Xa39 2011.0.00820.S_2013-01-18 uid://A002/X590461/X1b94 2011.0.00820.S_2013-01-17 uid://A002/X590461/X17e6 2011.0.00628.S_2012-09-30 uid://A002/X3b55d6/Xbbc 2011.0.00628.S_2012-09-30 uid://A002/X3c9295/X663 2011.0.00628.S_2012-09-30 uid://A002/X3ca066/Xcb8 2011.0.00628.S_2012-09-30 uid://A002/X3cb0a0/Xd10 2011.0.00628.S_2012-09-30 uid://A002/X44875a/X499 2011.0.00229.S_2013-01-18 uid://A002/X40e374/X62 2011.0.00403.S_2013-01-23 uid://A002/X590461/X9db 2011.0.00403.S_2013-01-23 uid://A002/X590461/Xb0a 2011.0.00199.S_2013-01-23 uid://A002/X51d696/X64 2011.0.00319.S_2013-01-20 uid://A002/X45f1dd/X7a 2011.0.00319.S_2013-01-20 uid://A002/X479db5/X21e 2011.0.00319.S_2013-01-20 uid://A002/X494155/X40 2011.0.00319.S_2013-01-20 uid://A002/X590461/X19b4 2011.0.00497.S_2013-01-29 uid://A002/X533e2c/X648 2011.0.00497.S_2013-01-29 uid://A002/X533e2c/X785 2011.0.00059.S_2013-01-23 uid://A002/X49990a/X32a 2011.0.00020.S_2013-01-23 uid://A002/X32d5f1/X832 2011.0.00020.S_2013-01-23 uid://A002/X41ac1f/X21f 2011.0.00020.S_2013-01-23 uid://A002/X518d2b/X36e 2011.0.00020.S_2013-01-23 uid://A002/X535168/Xb6c 2011.0.00020.S_2013-01-23 uid://A002/X539bb9/X99 2011.0.00307.S_2012-09-27 uid://A002/X45c06b/X3c4 2011.0.00307.S_2012-04-17 uid://A002/X31bf7f/X2d7 2011.0.00307.S_2012-04-17 uid://A002/X31bf7f/X1f8 2011.0.00467.S_2012-05-10 uid://A002/X3b55d6/Xa0 2011.0.00733.S_2012-02-07 uid://A002/X47ed8e/X20b 2011.0.00087.S_2013-01-23 uid://A002/X54d35d/X868 2011.0.00087.S_2013-01-23 uid://A002/X54d35d/X9d4 2011.0.00273.S_2013-02-05 uid://A002/X4b29af/Xd21 2011.0.00273.S_2013-02-05 uid://A002/X4afc39/X8ce 2011.0.00273.S_2013-02-05 uid://A002/X535168/X796 2011.0.00206.S_2013-02-07 uid://A002/X518d2b/X170 2011.0.00206.S_2013-02-07 uid://A002/X3f6a86/X9cd 2011.0.00206.S_2013-02-07 uid://A002/X3ca066/Xe84 2011.0.00099.S_2013-02-08 uid://A002/X3cb0a0/X417 2011.0.00351.S_2013-01-23 uid://A002/X3c7a84/Xb56 2011.0.00351.S_2013-01-23 uid://A002/X45c06b/X49b 2011.0.00351.S_2013-01-23 uid://A002/X479db5/X586 2011.0.00351.S_2013-01-23 uid://A002/X47bd4d/X6a9 2011.0.00351.S_2013-01-23 uid://A002/X47d651/X5b1 2011.0.00747.S_2013-01-28 uid://A002/X41f8d2/X2ed 2011.0.00747.S_2013-01-28 uid://A002/X463144/Xda 2011.0.00747.S_2013-01-28 uid://A002/X58ec89/X25c 2011.0.00747.S_2013-01-28 uid://A002/X40e374/X53e 2011.0.00277.S_2012-02-07 uid://A002/X569422/X742 2011.0.00742.S_2013-02-08 uid://A002/X569422/X50d 2011.0.00779.S_2013-02-08 uid://A002/X513d18/X261 2011.0.00779.S_2013-02-08 uid://A002/X515b5c/X9b0 2011.0.00742.S_2013-02-11 uid://A002/X590461/X708 2011.0.00742.S_2013-02-11 uid://A002/X590461/X886 2011.0.00046.S_2013-02-11 uid://A002/X4bb4dd/X323 2011.0.00958.S_2012-09-11 uid://A002/X49a70a/X4d8 2011.0.00130.S_2013-02-11 uid://A002/X590461/X482 2011.0.00539.S_2013-02-15 uid://A002/X433c46/X7ab 2011.0.00526.S_2013-02-14 uid://A002/X2f0ad3/X71 2011.0.00131.S_2011-12-06 uid://A002/X2cbea7/X5ce 2011.0.00131.S_2011-12-06 uid://A002/X2cbea7/X733 2011.0.00131.S_2011-12-06 uid://A002/X2cd715/X7a 2011.0.00131.S_2011-12-06 uid://A002/X2ce37c/X12 2011.0.00131.S_2011-12-06 uid://A002/X2e7826/X3e6 2011.0.00131.S_2011-12-06 uid://A002/X2eaf7f/X167 2011.0.00191.S_2011-12-06 uid://A002/X2b8998/X192 2011.0.00191.S_2011-12-06 uid://A002/X2b8998/X2bf 2011.0.00191.S_2011-12-06 uid://A002/X2b8998/X65 2011.0.00191.S_2011-12-06 uid://A002/X2e7826/X576 2011.0.00191.S_2011-12-06 uid://A002/X2e7826/X6c8 2011.0.00191.S_2011-12-06 uid://A002/X2e7826/X7d4 2011.0.00397.S_2011-12-19 uid://A002/X31d189/X81d 2011.0.00397.S_2011-12-19 uid://A002/X31d189/X44e 2011.0.00510.S_2011-12-19 uid://A002/X3302c8/X436 2011.0.00020.S_2011-12-26 uid://A002/X31ab3d/X6a6 2011.0.00020.S_2011-12-26 uid://A002/X31ab3d/X7d3 2011.0.00236.S_2011-12-26 uid://A002/X2c75ca/X3ec 2011.0.00236.S_2011-12-26 uid://A002/X2c75ca/X5ec 2011.0.00236.S_2011-12-26 uid://A002/X2c75ca/X51c 2011.0.00236.S_2011-12-26 uid://A002/X30a93d/X6e 2011.0.00236.S_2011-12-26 uid://A002/X30a93d/X1b3 2011.0.00236.S_2011-12-26 uid://A002/X30a93d/X2f9 2011.0.00268.S_2012-02-02 uid://A002/X36a70f/X318 2011.0.00268.S_2012-02-02 uid://A002/X36d011/X4d5 2011.0.00268.S_2012-02-02 uid://A002/X36d011/X63b 2011.0.00958.S_2012-01-23 uid://A002/X31d189/X66a 2011.0.00958.S_2012-01-23 uid://A002/X3302c8/X17a 2011.0.00780.S_2012-01-23 uid://A002/X331413/X491 2011.0.00780.S_2012-01-23 uid://A002/X331413/X60f 2011.0.00780.S_2012-02-02 uid://A002/X35edea/X441 2011.0.00780.S_2012-02-02 uid://A002/X35edea/Xac 2011.0.00454.S_2012-02-08 uid://A002/X36a70f/Xc87 2011.0.00131.S_2012-01-23 uid://A002/X331413/X325 2011.0.00851.S_2012-02-08 uid://A002/X30cca6/X4a5 2011.0.00851.S_2012-02-08 uid://A002/X31ab3d/X121 2011.0.00851.S_2012-02-08 uid://A002/X31d189/X1ab 2011.0.00851.S_2012-02-08 uid://A002/X31d189/X2e1 2011.0.00851.S_2012-02-08 uid://A002/X31d189/X75 2011.0.00851.S_2012-02-08 uid://A002/X32041d/Xb5 2011.0.00851.S_2012-02-08 uid://A002/X32d5f1/X46a 2011.0.00474.S_2012-02-09 uid://A002/X2c1301/Xa2 2011.0.00474.S_2012-02-09 uid://A002/X2c54bd/X1cc 2011.0.00474.S_2012-02-09 uid://A002/X2c54bd/X3cb 2011.0.00474.S_2012-02-09 uid://A002/X2c54bd/X52b 2011.0.00474.S_2012-02-09 uid://A002/X2c54bd/X75 2011.0.00474.S_2012-02-09 uid://A002/X2c75ca/X20f 2011.0.00474.S_2012-02-09 uid://A002/X2c75ca/Xaf 2011.0.00474.S_2012-02-09 uid://A002/X3237b1/Xc9 2011.0.00294.S_2012-02-09 uid://A002/X2e7826/X95c 2011.0.00294.S_2012-02-09 uid://A002/X2e7826/Xbc4 2011.0.00294.S_2012-02-09 uid://A002/X2ec530/X9fe 2011.0.00294.S_2012-02-09 uid://A002/X2ec530/Xcc4 2011.0.00294.S_2012-02-09 uid://A002/X2ec530/Xf0b 2011.0.00294.S_2012-02-09 uid://A002/X2eea47/Xa3a 2011.0.00294.S_2012-02-09 uid://A002/X2eea47/Xcc9 2011.0.00294.S_2012-02-09 uid://A002/X305ca0/X8b 2011.0.00471.S_2012-02-24 uid://A002/X35edea/X228 2011.0.00471.S_2012-02-24 uid://A002/X35edea/X5ad 2011.0.00471.S_2012-02-24 uid://A002/X36a70f/X895 2011.0.00471.S_2012-02-24 uid://A002/X35edea/X77d 2011.0.00510.S_2012-02-24 uid://A002/X331413/X83f 2011.0.00510.S_2012-02-24 uid://A002/X35edea/X970 2011.0.00510.S_2012-02-24 uid://A002/X35edea/Xac4 2011.0.00131.S_2012-02-24 uid://A002/X38570d/X17b 2011.0.00131.S_2012-02-24 uid://A002/X383b50/X359 2011.0.00367.S_2012-03-12 uid://A002/X35abb2/X26f 2011.0.00367.S_2012-03-12 uid://A002/X35cca0/X3f5 2011.0.00367.S_2012-03-12 uid://A002/X369097/X584 2011.0.00367.S_2012-03-12 uid://A002/X369097/X780 2011.0.00367.S_2012-03-12 uid://A002/X369097/X9f0 2011.0.00367.S_2012-03-12 uid://A002/X369097/Xbfe 2011.0.00367.S_2012-03-12 uid://A002/X36bf6c/X2d0 2011.0.00367.S_2012-03-12 uid://A002/X36bf6c/X9e 2011.0.00367.S_2012-03-12 uid://A002/X36d011/X77d 2011.0.00367.S_2012-03-12 uid://A002/X36e957/X826 2011.0.00367.S_2012-03-12 uid://A002/X386355/X3ef 2011.0.00010.S_2012-04-13 uid://A002/X383b50/Xc45 2011.0.00307.S_2012-04-20 uid://A002/X36a70f/Xe0e 2011.0.00101.S_2011-12-06 uid://A002/X2f146f/X6f 2011.0.00101.S_2011-12-06 uid://A002/X30a93d/X43e 2011.0.00206.S_2012-05-14 uid://A002/X3b3400/X7df 2011.0.00206.S_2012-05-14 uid://A002/X3ca066/X93e 2011.0.00206.S_2012-05-14 uid://A002/X3daf0c/X1f8 2011.0.00206.S_2012-05-15 uid://A002/X3b55d6/X727 2011.0.00206.S_2012-05-15 uid://A002/X3e17df/X1cd 2011.0.00191.S_2012-05-15 uid://A002/X3dc0e7/Xf32 2011.0.00191.S_2012-05-15 uid://A002/X3dc0e7/Xdce 2011.0.00405.S_2012-05-15 uid://A002/X3cb0a0/Xb7d 2011.0.00405.S_2012-05-15 uid://A002/X3cb0a0/X9e8 2011.0.00958.S_2012-05-29 uid://A002/X3fa880/X8c2 2011.0.00471.S_2012-05-29 uid://A002/X3c7a84/X1fb 2011.0.00471.S_2012-05-29 uid://A002/X3c7a84/X31f 2011.0.00471.S_2012-05-29 uid://A002/X3c7a84/X443 2011.0.00020.S_2012-05-29 uid://A002/X331413/X1bc 2011.0.00020.S_2012-05-29 uid://A002/X36e957/X4f 2011.0.00020.S_2012-05-29 uid://A002/X383b50/X69 2011.0.00020.S_2012-05-29 uid://A002/X383b50/X1e1 2011.0.00374.S_2012-05-29 uid://A002/X3c7a84/X567 2011.0.00374.S_2012-05-29 uid://A002/X3b3400/X4e0 2011.0.00374.S_2012-05-29 uid://A002/X3b55d6/X4c6 2011.0.00374.S_2012-05-29 uid://A002/X3b55d6/X9ff 2011.0.00374.S_2012-05-29 uid://A002/X3b3400/X64c 2011.0.00374.S_2012-05-29 uid://A002/X3c7a84/X6d3 2011.0.00374.S_2012-05-29 uid://A002/X3b55d6/X875 2011.0.00374.S_2012-05-29 uid://A002/X3e17df/X3fd 2011.0.00064.S_2013-02-19 uid://A002/X55186e/X64 2011.0.00232.S_2013-02-16 uid://A002/X5578f1/X4f 2011.0.00232.S_2013-02-16 uid://A002/X56a957/X64 2011.0.00170.S_2013-02-19 uid://A002/X5578f1/X42a 2011.0.00170.S_2013-02-19 uid://A002/X5578f1/X5b4 2011.0.00429.S_2013-02-11 uid://A002/X54d35d/X64 2011.0.00526.S_2013-02-14 uid://A002/X4ae797/X247 2011.0.00526.S_2013-02-14 uid://A002/X2f0ad3/X279 2011.0.00539.S_2013-02-15 uid://A002/X436934/X2f9 2011.0.00539.S_2013-02-15 uid://A002/X449249/X3ce 2011.0.00539.S_2013-02-15 uid://A002/X44a295/Xaf5 2011.0.00539.S_2013-02-15 uid://A002/X590461/X5f 2011.0.00539.S_2013-02-15 uid://A002/X590461/X288 2011.0.00064.S_2013-02-19 uid://A002/X552607/X607 2011.0.00115.S_2013-02-19 uid://A002/X45f1dd/X9a2 2011.0.00115.S_2013-02-19 uid://A002/X45f1dd/Xb62 2011.0.00115.S_2013-02-19 uid://A002/X46457e/X6cd 2011.0.00115.S_2013-02-19 uid://A002/X479db5/X77f 2011.0.00115.S_2013-02-19 uid://A002/X479db5/X890 2011.0.00115.S_2013-02-19 uid://A002/X47d651/X7cd 2011.0.00397.S_2012-07-05 uid://A002/X411025/X1fb 2011.0.00397.S_2012-07-05 uid://A002/X411025/X301 2011.0.00548.S_2013-02-19 uid://A002/X56a957/X63a 2011.0.00465.S_2013-02-11 uid://A002/X41e287/X2f0 2011.0.00465.S_2013-02-11 uid://A002/X41d520/X5f7 2011.0.00259.S_2012-12-04 uid://A002/X3e33cb/X2fd 2011.0.00470.S_2013-02-26 uid://A002/X5784d5/X4f9 2011.0.00470.S_2013-02-26 uid://A002/X36a70f/Xab6 2011.0.00470.S_2013-02-26 uid://A002/X590461/X1853 2011.0.00820.S_2013-02-27 uid://A002/X5578f1/X8e8 2011.0.00497.S_2013-02-15 uid://A002/X533e2c/X53c 2011.0.00172.S_2013-02-11 uid://A002/X36a70f/X63 2011.0.00172.S_2013-02-11 uid://A002/X38570d/X10 2011.0.00172.S_2013-02-11 uid://A002/X35cca0/X27e 2011.0.00172.S_2013-02-11 uid://A002/X369097/X85 2011.0.00084.S_2013-02-28 uid://A002/X49a70a/X2de 2011.0.00084.S_2013-02-28 uid://A002/X2eea47/X1e0 2011.0.00820.S_2012-06-12 uid://A002/X3e3a61/X28d 2011.0.00820.S_2012-06-12 uid://A002/X3e3a61/Xce 2011.0.00958.S_2012-09-12 uid://A002/X41e287/Xb16 2011.0.00604.S_2013-02-11 uid://A002/X4b71b4/X459 2011.0.00604.S_2013-02-11 uid://A002/X515b5c/X459 2011.0.00619.S_2013-02-26 uid://A002/X552607/X4b 2011.0.00467.S_2012-06-28 uid://A002/X3f6a86/Xd65 2011.0.00099.S_2012-08-23 uid://A002/X3f6a86/X7fb 2011.0.00099.S_2012-08-24 uid://A002/X3f6a86/X7fb astroquery-0.3.7/astroquery/alma/setup_package.py0000644000077000000240000000041013067234073022275 0ustar adamstaff00000000000000# Licensed under a 3-clause BSD style license - see LICENSE.rst from __future__ import absolute_import import os def get_package_data(): paths = [os.path.join('data', 'cycle0_delivery_asdm_mapping.txt'), ] return {'astroquery.alma': paths} astroquery-0.3.7/astroquery/alma/tests/0000755000077000000240000000000013232443301020245 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/tests/__init__.py0000644000077000000240000000000013067234073022356 0ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/tests/data/0000755000077000000240000000000013232443301021156 5ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/tests/data/data_list_page.html0000644000077000000240000002716313067234073025027 0ustar adamstaff00000000000000 Alma Request Handler - Request Details

Request #519752156 by Anonymous User COMPLETE

ALMA
Include raw

Requested Projects / OUSets / Executionblocks

UNIX/Linux Shell script if you prefer command line download of complete request: downloadRequest519752156script.sh
Data entities 1-1 of 1
Select Project / OUSet / Executionblock File Size Access
Data entities 1-1 of 1 4.9GB
astroquery-0.3.7/astroquery/alma/tests/data/downloadRequest519752156script.sh0000644000077000000240000000064213067234073027064 0ustar adamstaff00000000000000#!/bin/bash #Please use the current script to download the whole content of request 519752156 wget "https://almascience.eso.org/dataPortal/requests/anonymous/519752156/ALMA/2011.0.00121.S_2012-07-30_001_of_002.tar/2011.0.00121.S_2012-07-30_001_of_002.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/519752156/ALMA/2011.0.00121.S_2012-07-30_002_of_002.tar/2011.0.00121.S_2012-07-30_002_of_002.tar" astroquery-0.3.7/astroquery/alma/tests/data/downloadRequest786572566script.sh0000644000077000000240000000057013067234073027077 0ustar adamstaff00000000000000#!/bin/bash #Please use the current script to download the whole content of request 786572566 wget "https://almascience.eso.org/dataPortal/requests/anonymous/786572566/ALMA/uid___A002_X3b3400_X90f/uid___A002_X3b3400_X90f.asdm.sdm.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786572566/ALMA/uid___A002_X3b3400_Xaf3/uid___A002_X3b3400_Xaf3.asdm.sdm.tar" astroquery-0.3.7/astroquery/alma/tests/data/downloadRequest786978956script.sh0000644000077000000240000001032213067234073027110 0ustar adamstaff00000000000000#!/bin/bash #Please use the current script to download the whole content of request 786978956 wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_006_of_011.tar/2011.0.00772.S_2012-12-01_006_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_011_of_015.tar/2011.0.00772.S_2012-09-12_011_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_010_of_015.tar/2011.0.00772.S_2012-09-12_010_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_008_of_015.tar/2011.0.00772.S_2012-09-12_008_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_002_of_015.tar/2011.0.00772.S_2012-09-12_002_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_007_of_011.tar/2011.0.00772.S_2012-12-01_007_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_007_of_015.tar/2011.0.00772.S_2012-09-12_007_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_013_of_015.tar/2011.0.00772.S_2012-09-12_013_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_008_of_011.tar/2011.0.00772.S_2012-12-01_008_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_010_of_011.tar/2011.0.00772.S_2012-12-01_010_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_014_of_015.tar/2011.0.00772.S_2012-09-12_014_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_003_of_015.tar/2011.0.00772.S_2012-09-12_003_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_006_of_015.tar/2011.0.00772.S_2012-09-12_006_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_012_of_015.tar/2011.0.00772.S_2012-09-12_012_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_015_of_015.tar/2011.0.00772.S_2012-09-12_015_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_001_of_011.tar/2011.0.00772.S_2012-12-01_001_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_005_of_011.tar/2011.0.00772.S_2012-12-01_005_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_001_of_015.tar/2011.0.00772.S_2012-09-12_001_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_004_of_015.tar/2011.0.00772.S_2012-09-12_004_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_011_of_011.tar/2011.0.00772.S_2012-12-01_011_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_002_of_011.tar/2011.0.00772.S_2012-12-01_002_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_005_of_015.tar/2011.0.00772.S_2012-09-12_005_of_015.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_009_of_011.tar/2011.0.00772.S_2012-12-01_009_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_004_of_011.tar/2011.0.00772.S_2012-12-01_004_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-12-01_003_of_011.tar/2011.0.00772.S_2012-12-01_003_of_011.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/786978956/ALMA/2011.0.00772.S_2012-09-12_009_of_015.tar/2011.0.00772.S_2012-09-12_009_of_015.tar" astroquery-0.3.7/astroquery/alma/tests/data/downloadRequest787632764script.sh0000644000077000000240000000517613067234073027104 0ustar adamstaff00000000000000#!/bin/bash #Please use the current script to download the whole content of request 787632764 wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-06_003_of_004.tar/2011.0.00121.S_2012-11-06_003_of_004.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_001_of_008.tar/2011.0.00121.S_2012-11-02_001_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-08-16_001_of_002.tar/2011.0.00121.S_2012-08-16_001_of_002.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_007_of_008.tar/2011.0.00121.S_2012-11-02_007_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-08-16_002_of_002.tar/2011.0.00121.S_2012-08-16_002_of_002.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_008_of_008.tar/2011.0.00121.S_2012-11-02_008_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-06_004_of_004.tar/2011.0.00121.S_2012-11-06_004_of_004.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_004_of_008.tar/2011.0.00121.S_2012-11-02_004_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_006_of_008.tar/2011.0.00121.S_2012-11-02_006_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-07-30_001_of_002.tar/2011.0.00121.S_2012-07-30_001_of_002.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_002_of_008.tar/2011.0.00121.S_2012-11-02_002_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_005_of_008.tar/2011.0.00121.S_2012-11-02_005_of_008.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-07-30_002_of_002.tar/2011.0.00121.S_2012-07-30_002_of_002.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-06_001_of_004.tar/2011.0.00121.S_2012-11-06_001_of_004.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-06_002_of_004.tar/2011.0.00121.S_2012-11-06_002_of_004.tar" wget "https://almascience.eso.org/dataPortal/requests/anonymous/787632764/ALMA/2011.0.00121.S_2012-11-02_003_of_008.tar/2011.0.00121.S_2012-11-02_003_of_008.tar" astroquery-0.3.7/astroquery/alma/tests/data/empty.html0000644000077000000240000000000013067234073023202 0ustar adamstaff00000000000000astroquery-0.3.7/astroquery/alma/tests/data/initial_response.html0000644000077000000240000000530713067234073025432 0ustar adamstaff00000000000000 Alma Request Handler - Logout


Your request is being handled

In a few seconds you will be redirected to the confirmation page.

Please wait.....