Skip to content

Commit

Permalink
Python 3.5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
mdboom committed Aug 24, 2015
1 parent 5e1e978 commit d5b1f43
Show file tree
Hide file tree
Showing 22 changed files with 3,476 additions and 3,256 deletions.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ matrix:
env: PYTHON_VERSION=3.3 SETUP_CMD='test --open-files'
- os: linux
env: PYTHON_VERSION=3.4 SETUP_CMD='test --open-files'
- os: linux
env: PYTHON_VERSION=3.5.0b4 SETUP_CMD='test --open-files'
python: 3.5.0b4

# Now try with all optional dependencies on 2.7 and an appropriate 3.x
# build (with latest numpy). We also note the code coverage on Python
Expand Down
12 changes: 5 additions & 7 deletions astropy/coordinates/transformations.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import numpy as np

from ..utils.compat import ignored
from ..utils.compat.funcsigs import signature
from ..extern import six


Expand Down Expand Up @@ -686,17 +687,14 @@ class FunctionTransform(CoordinateTransform):
"""
def __init__(self, func, fromsys, tosys, priority=1, register_graph=None):
from inspect import getargspec

if not six.callable(func):
raise TypeError('func must be callable')

with ignored(TypeError):
# TypeError raised for things getargspec can't process. We'll trust
# the transform designer knows what they're doing, though, because
# sometimes this is fine..
argspec = getargspec(func)
if (len(argspec[0]) - len(argspec[3]) != 2) and not argspec[1]:
sig = signature(func)
kinds = [x.kind for x in sig.parameters.values()]
if (len(x for x in kinds if x == sig.POSITIONAL_ONLY) != 2
and not sig.VAR_POSITIONAL in kinds):
raise ValueError('provided function does not accept two arguments')

self.func = func
Expand Down
6 changes: 3 additions & 3 deletions astropy/cosmology/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
from .. import constants as const
from .. import units as u
from ..utils import isiterable, deprecated
from ..utils.compat.funcsigs import signature
from ..utils.state import ScienceState, ScienceStateAlias

from . import parameters
Expand Down Expand Up @@ -437,16 +438,15 @@ def clone(self, **kwargs):
return self

# Get constructor arguments
import inspect
arglist = inspect.getargspec(self.__init__).args
arglist = signature(self.__init__).parameters.keys()

# Build the dictionary of values used to construct this
# object. This -assumes- every argument to __init__ has a
# property. This is true of all the classes we provide, but
# maybe a user won't do that. So at least try to have a useful
# error message.
argdict = {}
for arg in arglist[1:]: # Skip self, which should always be first
for arg in arglist:
try:
val = getattr(self, arg)
argdict[arg] = val
Expand Down
6,480 changes: 3,333 additions & 3,147 deletions astropy/extern/pytest.py

Large diffs are not rendered by default.

6 changes: 3 additions & 3 deletions astropy/io/fits/diff.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@
import fnmatch
import functools
import glob
import inspect
import io
import textwrap
import os.path
Expand All @@ -26,6 +25,7 @@
from ...extern.six import u, string_types
from ...extern.six.moves import zip, xrange, reduce
from ...utils import indent
from ...utils.compat.funcsigs import signature
from .card import Card, BLANK_CARD
from .header import Header
# HDUList is used in one of the doctests
Expand Down Expand Up @@ -108,10 +108,10 @@ def fromdiff(cls, other, a, b):
['*']
"""

args, _, _, _ = inspect.getargspec(cls.__init__)
sig = signature(cls.__init__)
# The first 3 arguments of any Diff initializer are self, a, and b.
kwargs = {}
for arg in args[3:]:
for arg in list(sig.parameters.keys())[3:]:
if hasattr(other, arg):
kwargs[arg] = getattr(other, arg)

Expand Down
8 changes: 4 additions & 4 deletions astropy/io/fits/hdu/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


import datetime
import inspect
import os
import warnings

Expand All @@ -21,6 +20,7 @@
from ....extern.six import string_types
from ....utils import lazyproperty, deprecated
from ....utils.compat import ignored
from ....utils.compat.funcsigs import signature, Parameter
from ....utils.exceptions import AstropyUserWarning


Expand Down Expand Up @@ -490,14 +490,14 @@ def block_iter(nbytes):
# self._kwargs. self._kwargs contains any number of optional arguments
# that may or may not be valid depending on the HDU type
cls = _hdu_class_from_header(cls, header)
args, varargs, varkwargs, defaults = inspect.getargspec(cls.__init__)
sig = signature(cls.__init__)
new_kwargs = kwargs.copy()
if not varkwargs:
if Parameter.VAR_KEYWORD not in (x.kind for x in sig.parameters.values()):
# If __init__ accepts arbitrary keyword arguments, then we can go
# ahead and pass all keyword arguments; otherwise we need to delete
# any that are invalid
for key in kwargs:
if key not in args:
if key not in sig.parameters:
del new_kwargs[key]

hdu = cls(data=DELAYED, header=header, **new_kwargs)
Expand Down
52 changes: 22 additions & 30 deletions astropy/modeling/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,19 @@

import numpy as np

from ..utils import indent, isiterable, isinstancemethod, metadata
from ..utils import indent, isinstancemethod, metadata
from ..extern import six
from ..extern.six.moves import copyreg
from ..table import Table
from ..utils import (deprecated, sharedmethod, find_current_module,
InheritDocstrings, OrderedDescriptorContainer)
from ..utils.codegen import make_function_with_signature
from ..utils.compat import ignored
from ..utils.compat.odict import OrderedDict
from ..utils.compat import ignored
from ..utils.exceptions import AstropyDeprecationWarning
from .utils import (array_repr_oneline, check_broadcast, combine_labels,
make_binary_operator_eval, ExpressionTree,
IncompatibleShapeError, AliasDict)
IncompatibleShapeError, AliasDict, get_inputs_and_params)
from ..nddata.utils import add_array, extract_array

from .parameters import Parameter, InputParameterError
Expand Down Expand Up @@ -551,7 +551,7 @@ class Model(object):
_custom_inverse = None

# If a bounding_box_default function is defined in the model,
# then the _bounding_box attribute should be set to 'auto' in the model.
# then the _bounding_box attribute should be set to 'auto' in the model.
# Otherwise, the default is None for no bounding box.
_bounding_box = None

Expand Down Expand Up @@ -773,18 +773,18 @@ def inverse(self):
@property
def bounding_box(self):
"""
A `tuple` of length `n_inputs` defining the bounding box limits, or
`None` for no bounding box.
A `tuple` of length `n_inputs` defining the bounding box limits, or
`None` for no bounding box.
The default is `None`, unless ``bounding_box_default`` is defined.
`bounding_box` can be set manually to an array-like object of shape
`bounding_box` can be set manually to an array-like object of shape
``(model.n_inputs, 2)``. For further usage, including how to set the
``bounding_box_default``, see :ref:`bounding-boxes`
The limits are ordered according to the `numpy` indexing
convention, and are the reverse of the model input order,
e.g. for inputs ``('x', 'y', 'z')`` the ``bounding_box`` is defined:
* for 1D: ``(x_low, x_high)``
* for 2D: ``((y_low, y_high), (x_low, x_high))``
* for 3D: ``((z_low, z_high), (y_low, y_high), (x_low, x_high))``
Expand Down Expand Up @@ -830,7 +830,7 @@ def bounding_box(self):
@bounding_box.setter
def bounding_box(self, limits):
"""
Assigns the bounding box limits.
Assigns the bounding box limits.
"""

if limits == 'auto':
Expand Down Expand Up @@ -2325,30 +2325,22 @@ def _custom_model_wrapper(func, fit_deriv=None):
"callable object")

model_name = func.__name__
argspec = inspect.getargspec(func)
param_values = argspec.defaults or ()

nparams = len(param_values)
param_names = argspec.args[-nparams:]
inputs, params = get_inputs_and_params(func)

if (fit_deriv is not None and
len(six.get_function_defaults(fit_deriv)) != nparams):
len(six.get_function_defaults(fit_deriv)) != len(params)):
raise ModelDefinitionError("derivative function should accept "
"same number of parameters as func.")

if nparams:
input_names = argspec.args[:-nparams]
else:
input_names = argspec.args

# TODO: Maybe have a clever scheme for default output name?
if input_names:
output_names = (input_names[0],)
if inputs:
output_names = (inputs[0].name,)
else:
output_names = ('x',)

params = dict((name, Parameter(name, default=default))
for name, default in zip(param_names, param_values))
params = dict((param.name, Parameter(param.name, default=param.default))
for param in params)

mod = find_current_module(2)
if mod:
Expand All @@ -2359,7 +2351,7 @@ def _custom_model_wrapper(func, fit_deriv=None):
members = {
'__module__': str(modname),
'__doc__': func.__doc__,
'inputs': tuple(input_names),
'inputs': tuple(x.name for x in inputs),
'outputs': output_names,
'evaluate': staticmethod(func),
}
Expand All @@ -2384,15 +2376,15 @@ def render_model(model, arr=None, coords=None):
arr : `numpy.ndarray`, optional
Array on which the model is evaluated.
coords : array-like, optional
Coordinate arrays mapping to ``arr``, such that
Coordinate arrays mapping to ``arr``, such that
``arr[coords] == arr``.
Returns
-------
array : `numpy.ndarray`
The model evaluated on the input ``arr`` or a new array from ``coords``.
If ``arr`` and ``coords`` are both `None`, the returned array is
limited to the `Model.bounding_box` limits. If
The model evaluated on the input ``arr`` or a new array from ``coords``.
If ``arr`` and ``coords`` are both `None`, the returned array is
limited to the `Model.bounding_box` limits. If
`Model.bounding_box` is `None`, ``arr`` or ``coords`` must be passed.
Examples
Expand Down Expand Up @@ -2428,15 +2420,15 @@ def render_model(model, arr=None, coords=None):

if bbox is not None:
# assures position is at center pixel, important when using add_array
pd = pos, delta = np.array([(np.mean(bb), np.ceil((bb[1] - bb[0]) / 2))
pd = pos, delta = np.array([(np.mean(bb), np.ceil((bb[1] - bb[0]) / 2))
for bb in bbox]).astype(int).T

if coords is not None:
sub_shape = tuple(delta * 2 + 1)
sub_coords = np.array([extract_array(c, sub_shape, pos) for c in coords])
else:
limits = [slice(p - d, p + d + 1, 1) for p, d in pd.T]
sub_coords = np.mgrid[limits]
sub_coords = np.mgrid[limits]

sub_coords = sub_coords[::-1]

Expand Down
12 changes: 6 additions & 6 deletions astropy/modeling/functional_models.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,12 @@
from .parameters import Parameter, InputParameterError
from .utils import ellipse_extent
from ..utils import deprecated
from ..utils.compat.funcsigs import signature
from ..extern import six

from .utils import get_inputs_and_params


__all__ = sorted([
'AiryDisk2D', 'Moffat1D', 'Moffat2D', 'Box1D',
'Box2D', 'Const1D', 'Const2D', 'Ellipse2D', 'Disk2D',
Expand Down Expand Up @@ -1739,13 +1743,9 @@ def evaluate(cls, x, y, amplitude, r_eff, n, x_0, y_0, ellip, theta):
@deprecated('1.0', alternative='astropy.modeling.models.custom_model',
pending=True)
def custom_model_1d(func, func_fit_deriv=None):
argspec = inspect.getargspec(func)
param_values = argspec.defaults
nparams = len(param_values)
inputs, params = get_inputs_and_params(func)

if len(argspec.args) == nparams + 1:
param_names = argspec.args[-nparams:]
else:
if len(inputs) != 1:
raise ModelDefinitionError(
"All parameters must be keyword arguments")

Expand Down
9 changes: 5 additions & 4 deletions astropy/modeling/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@
from __future__ import (absolute_import, unicode_literals, division,
print_function)

import inspect
import functools
import numbers
import types
Expand All @@ -20,6 +19,8 @@
from ..utils import isiterable, OrderedDescriptor
from ..extern import six

from .utils import get_inputs_and_params

__all__ = ['Parameter', 'InputParameterError']


Expand Down Expand Up @@ -662,16 +663,16 @@ def _create_value_wrapper(wrapper, model):
# Just allow non-wrappers to fall through silently, for convenience
return None
else:
wrapper_args = inspect.getargspec(wrapper)
nargs = len(wrapper_args.args)
inputs, params = get_inputs_and_params(wrapper)
nargs = len(inputs)

if nargs == 1:
pass
elif nargs == 2:
if model is not None:
# Don't make a partial function unless we're tied to a
# specific model instance
model_arg = wrapper_args.args[1]
model_arg = inputs.args[1].name
wrapper = functools.partial(wrapper, **{model_arg: model})
else:
raise TypeError("Parameter getter/setter must be a function "
Expand Down
Loading

0 comments on commit d5b1f43

Please sign in to comment.