@@ -21,18 +21,25 @@ def test__convert_pixel_scales_1d__widens_any_real_scalar(pixel_scales):
2121 """
2222 Any concrete real scalar widens, not just an exact `float`. `int` is what a user types by
2323 hand; `np.floating` is what indexing an array or reading a FITS header returns.
24+
25+ The tuple-ness is asserted before the value: `np.float64(1.0) == (1.0,)` NumPy-broadcasts
26+ to `array([True])`, which is truthy, so a value-only assertion passes on the unwidened
27+ scalar and tests nothing.
2428 """
25- assert aa .util .geometry .convert_pixel_scales_1d (pixel_scales = pixel_scales ) == (1.0 ,)
29+ pixel_scales = aa .util .geometry .convert_pixel_scales_1d (pixel_scales = pixel_scales )
30+
31+ assert type (pixel_scales ) is tuple
32+ assert pixel_scales == (1.0 ,)
2633
2734
2835@pytest .mark .parametrize (
2936 "pixel_scales" , [1 , 1.0 , np .float64 (1.0 ), np .int32 (1 ), np .float32 (1.0 )]
3037)
3138def test__convert_pixel_scales_2d__widens_any_real_scalar (pixel_scales ):
32- assert aa .util .geometry .convert_pixel_scales_2d (pixel_scales = pixel_scales ) == (
33- 1.0 ,
34- 1.0 ,
35- )
39+ pixel_scales = aa .util .geometry .convert_pixel_scales_2d (pixel_scales = pixel_scales )
40+
41+ assert type ( pixel_scales ) is tuple
42+ assert pixel_scales == ( 1.0 , 1.0 )
3643
3744
3845@pytest .mark .parametrize ("pixel_scales" , [1 , np .float64 (1.0 ), np .int32 (1 )])
@@ -86,6 +93,64 @@ def test__convert_pixel_scales__a_bool_is_not_treated_as_a_scalar():
8693 assert aa .util .geometry .convert_pixel_scales_2d (pixel_scales = True ) is True
8794
8895
96+ @pytest .mark .parametrize ("shape_native" , [5 , np .int32 (5 ), np .int64 (5 )])
97+ def test__convert_shape_native_1d__widens_any_integer_scalar (shape_native ):
98+ """
99+ Any concrete integer scalar widens, not just an exact `int`. An `np.integer` is what
100+ indexing a shape tuple or reading a FITS header returns, and `Array1D.full` then does
101+ `shape_native[0]` on whatever comes back — a bare scalar raised `IndexError` there.
102+
103+ The tuple-ness is asserted before the value: `np.int32(5) == (5,)` NumPy-broadcasts to
104+ `array([True])`, which is truthy, so a value-only assertion passes on the unwidened
105+ scalar and tests nothing.
106+ """
107+ shape_native = aa .util .geometry .convert_shape_native_1d (shape_native = shape_native )
108+
109+ assert type (shape_native ) is tuple
110+ assert shape_native == (5 ,)
111+
112+
113+ @pytest .mark .parametrize ("shape_native" , [5 , np .int32 (5 ), np .int64 (5 )])
114+ def test__convert_shape_native_1d__widened_entry_is_a_python_int (shape_native ):
115+ """
116+ The widened value is cast, so a NumPy scalar never reaches the shape stored on a
117+ structure. `5 == np.int32(5)` in Python, so the cast has to be asserted on the type.
118+ """
119+ (entry ,) = aa .util .geometry .convert_shape_native_1d (shape_native = shape_native )
120+ assert type (entry ) is int
121+
122+
123+ def test__convert_shape_native_1d__a_float_is_not_widened ():
124+ """
125+ Unlike `pixel_scales`, `shape_native` counts pixels rather than measuring them, so a
126+ `float` is a mistake worth surfacing rather than one to normalise away — the predicate
127+ here is `is_concrete_integer`, not `is_concrete_scalar`.
128+ """
129+ assert aa .util .geometry .convert_shape_native_1d (shape_native = 5.0 ) == 5.0
130+
131+
132+ def test__convert_shape_native_1d__a_bool_is_not_treated_as_a_scalar ():
133+ """`bool` is a subclass of `int`, but `True` reaching a pixel count is a different mistake."""
134+ assert aa .util .geometry .convert_shape_native_1d (shape_native = True ) is True
135+
136+
137+ def test__convert_shape_native_1d__tuple_input_is_returned_unchanged ():
138+ shape_native = (5 ,)
139+ assert (
140+ aa .util .geometry .convert_shape_native_1d (shape_native = shape_native )
141+ is shape_native
142+ )
143+
144+
145+ def test__convert_shape_native_1d__a_tracer_passes_through_untouched ():
146+ """Inside a `jax.jit` the value is traced; widening it would resolve it to a bool."""
147+ tracer_like = _NotAConcreteScalar ()
148+
149+ assert (
150+ aa .util .geometry .convert_shape_native_1d (shape_native = tracer_like ) is tracer_like
151+ )
152+
153+
89154def test__central_pixel_coordinates_1d_from ():
90155 central_pixel_coordinates = aa .util .geometry .central_pixel_coordinates_1d_from (
91156 shape_slim = (3 ,)
0 commit comments