Skip to content

Commit db74b2a

Browse files
committed
CLN: Better exceptions and tests for core/frame
CLN: Big simplification of test_frame TST: Add test cases for bad input, etc. CLN: Exceptions that shouldn't happen should be assertions (mostly _apply*) CLN/TST: Right Exceptions + remove duplicate tests A few tests were duplicating the same thing or actually just the same test, those have been refactored or removed. Many tests were changed to specify the Exception they were looking for (and also to use the new `with_statement` format for assertRaises, etc.) CLN: Harmonize SparseDF and DF Exceptions ENH: SparseDF apply now accepts axis='columns'
1 parent 3c2e71d commit db74b2a

File tree

15 files changed

+391
-427
lines changed

15 files changed

+391
-427
lines changed

doc/source/release.rst

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,8 +71,9 @@ pandas 0.13
7171
when the key is a column
7272
- Support for using a ``DatetimeIndex/PeriodsIndex`` directly in a datelike calculation
7373
e.g. s-s.index (:issue:`4629`)
74-
- Better/cleaned up exceptions in core/common, io/excel and core/format.
75-
(:issue:`4721`, :issue:`3954`)
74+
- Better/cleaned up exceptions in core/common, io/excel and core/format
75+
(:issue:`4721`, :issue:`3954`), as well as cleaned up test cases in
76+
tests/test_frame, tests/test_multilevel (:issue:`4732`).
7677

7778
**API Changes**
7879

@@ -143,9 +144,10 @@ pandas 0.13
143144
now returns a ``MultiIndex`` rather than an ``Index``. (:issue:`4039`)
144145

145146
- Infer and downcast dtype if ``downcast='infer'`` is passed to ``fillna/ffill/bfill`` (:issue:`4604`)
146-
- Factored out excel_value_to_python_value from ExcelFile::_parse_excel (:issue:`4589`)
147147
- ``__nonzero__`` for all NDFrame objects, will now raise a ``ValueError``, this reverts back to (:issue:`1073`, :issue:`4633`)
148148
behavior.
149+
- ``DataFrame.update()`` no longer raises a ``DataConflictError``, it now
150+
will raise a ``ValueError`` instead (if necessary) (:issue:`4732`)
149151

150152
**Internal Refactoring**
151153

pandas/core/format.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -825,9 +825,8 @@ def __init__(self, obj, path_or_buf, sep=",", na_rep='', float_format=None,
825825

826826
# validate mi options
827827
if self.has_mi_columns:
828-
# guarded against in to_csv itself
829-
if cols is not None: # pragma: no cover
830-
raise AssertionError("cannot specify cols with a multi_index on the columns")
828+
if cols is not None:
829+
raise TypeError("cannot specify cols with a MultiIndex on the columns")
831830

832831
if cols is not None:
833832
if isinstance(cols,Index):

pandas/core/frame.py

Lines changed: 67 additions & 85 deletions
Large diffs are not rendered by default.

pandas/core/generic.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -417,7 +417,7 @@ def rename(self, *args, **kwargs):
417417
inplace = kwargs.get('inplace', False)
418418

419419
if (com._count_not_none(*axes.values()) == 0):
420-
raise Exception('must pass an index to rename')
420+
raise TypeError('must pass an index to rename')
421421

422422
# renamer function if passed a dict
423423
def _get_rename_function(mapper):
@@ -1242,7 +1242,7 @@ def filter(self, items=None, like=None, regex=None, axis=None):
12421242
matcher = re.compile(regex)
12431243
return self.select(lambda x: matcher.search(x) is not None, axis=axis_name)
12441244
else:
1245-
raise ValueError('items was None!')
1245+
raise TypeError('Must pass either `items`, `like`, or `regex`')
12461246

12471247
#----------------------------------------------------------------------
12481248
# Attribute access

pandas/core/indexing.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ def __setitem__(self, key, value):
8484

8585
if isinstance(key, tuple):
8686
if len(key) > self.ndim:
87-
raise IndexingError('only tuples of length <= %d supported',
87+
raise IndexingError('only tuples of length <= %d supported' %
8888
self.ndim)
8989
indexer = self._convert_tuple(key, is_setter=True)
9090
else:

pandas/core/internals.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1625,7 +1625,7 @@ def set_axis(self, axis, value, maybe_rename=True, check_axis=True):
16251625
value = _ensure_index(value)
16261626

16271627
if check_axis and len(value) != len(cur_axis):
1628-
raise Exception('Length mismatch (%d vs %d)'
1628+
raise ValueError('Length mismatch (%d vs %d)'
16291629
% (len(value), len(cur_axis)))
16301630

16311631
self.axes[axis] = value
@@ -2297,7 +2297,7 @@ def fast_2d_xs(self, loc, copy=False):
22972297
return result
22982298

22992299
if not copy:
2300-
raise Exception('cannot get view of mixed-type or '
2300+
raise TypeError('cannot get view of mixed-type or '
23012301
'non-consolidated DataFrame')
23022302

23032303
items = self.items
@@ -2483,7 +2483,8 @@ def _set_item(item, arr):
24832483
def insert(self, loc, item, value, allow_duplicates=False):
24842484

24852485
if not allow_duplicates and item in self.items:
2486-
raise Exception('cannot insert %s, already exists' % item)
2486+
# Should this be a different kind of error??
2487+
raise ValueError('cannot insert %s, already exists' % item)
24872488

24882489
try:
24892490
new_items = self.items.insert(loc, item)
@@ -2826,7 +2827,8 @@ def _maybe_rename_join(self, other, lsuffix, rsuffix, copydata=True):
28262827
to_rename = self.items.intersection(other.items)
28272828
if len(to_rename) > 0:
28282829
if not lsuffix and not rsuffix:
2829-
raise Exception('columns overlap: %s' % to_rename)
2830+
raise ValueError('columns overlap but no suffix specified: %s'
2831+
% to_rename)
28302832

28312833
def lrenamer(x):
28322834
if x in to_rename:

pandas/core/reshape.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@
2121
from pandas.core.index import Index, MultiIndex
2222

2323

24-
class ReshapeError(Exception):
25-
pass
26-
27-
2824
class _Unstacker(object):
2925
"""
3026
Helper class to unstack data / pivot with multi-level index
@@ -129,8 +125,8 @@ def _make_selectors(self):
129125
mask.put(selector, True)
130126

131127
if mask.sum() < len(self.index):
132-
raise ReshapeError('Index contains duplicate entries, '
133-
'cannot reshape')
128+
raise ValueError('Index contains duplicate entries, '
129+
'cannot reshape')
134130

135131
self.group_index = comp_index
136132
self.mask = mask

pandas/core/series.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2377,7 +2377,7 @@ def sort(self, axis=0, kind='quicksort', order=None, ascending=True):
23772377

23782378
if (true_base is not None and
23792379
(true_base.ndim != 1 or true_base.shape != self.shape)):
2380-
raise Exception('This Series is a view of some other array, to '
2380+
raise TypeError('This Series is a view of some other array, to '
23812381
'sort in-place you must create a copy')
23822382

23832383
self[:] = sortedSeries
@@ -2542,7 +2542,7 @@ def sortlevel(self, level=0, ascending=True):
25422542
sorted : Series
25432543
"""
25442544
if not isinstance(self.index, MultiIndex):
2545-
raise Exception('can only sort by level with a hierarchical index')
2545+
raise TypeError('can only sort by level with a hierarchical index')
25462546

25472547
new_index, indexer = self.index.sortlevel(level, ascending=ascending)
25482548
new_values = self.values.take(indexer)

pandas/sparse/frame.py

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ def _reindex_with_indexers(self, reindexers, method=None, fill_value=np.nan, lim
600600
def _join_compat(self, other, on=None, how='left', lsuffix='', rsuffix='',
601601
sort=False):
602602
if isinstance(other, Series):
603-
assert(other.name is not None)
603+
if other.name is None:
604+
raise ValueError('Other Series must have a name')
604605
other = SparseDataFrame({other.name: other},
605606
default_fill_value=self._default_fill_value)
606607
if on is not None:
@@ -627,19 +628,19 @@ def _join_index(self, other, how, lsuffix, rsuffix):
627628
return concat([this, other], axis=1, verify_integrity=True)
628629

629630
def _maybe_rename_join(self, other, lsuffix, rsuffix):
630-
intersection = self.columns.intersection(other.columns)
631-
632-
if len(intersection) > 0:
631+
to_rename = self.columns.intersection(other.columns)
632+
if len(to_rename) > 0:
633633
if not lsuffix and not rsuffix:
634-
raise Exception('columns overlap: %s' % intersection)
634+
raise ValueError('columns overlap but no suffix specified: %s'
635+
% to_rename)
635636

636637
def lrenamer(x):
637-
if x in intersection:
638+
if x in to_rename:
638639
return '%s%s' % (x, lsuffix)
639640
return x
640641

641642
def rrenamer(x):
642-
if x in intersection:
643+
if x in to_rename:
643644
return '%s%s' % (x, rsuffix)
644645
return x
645646

@@ -687,7 +688,7 @@ def apply(self, func, axis=0, broadcast=False, reduce=False):
687688
----------
688689
func : function
689690
Function to apply to each column
690-
axis : {0, 1}
691+
axis : {0, 1, 'index', 'columns'}
691692
broadcast : bool, default False
692693
For aggregation functions, return object of same size with values
693694
propagated
@@ -698,6 +699,7 @@ def apply(self, func, axis=0, broadcast=False, reduce=False):
698699
"""
699700
if not len(self.columns):
700701
return self
702+
axis = self._get_axis_number(axis)
701703

702704
if isinstance(func, np.ufunc):
703705
new_series = {}

0 commit comments

Comments
 (0)