implement astype portion of #24024
State: closed

and accompanying tests

Uses _eadata like #24394

Constitutes ~10% of the diff of #24024, more after that gets rebased.

Labels:
name: Dtype Conversions
description: Unexpected or buggy dtype conversions
name: Clean
name: ExtensionArray
description: Extending pandas with custom dtypes or arrays.

Comments:
# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=h1) Report
> Merging [#24405](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/fc7bc3f74d1f5702bf66c519ad190126538a8f5b?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `98.57%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/24405/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #24405      +/-   ##
==========================================
+ Coverage    92.3%   92.31%   +0.01%     
==========================================
  Files         163      163              
  Lines       51943    51965      +22     
==========================================
+ Hits        47946    47972      +26     
+ Misses       3997     3993       -4
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.72% <98.57%> (+0.01%)` | :arrow_up: |
| #single | `43.01% <57.14%> (+0.01%)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/dtypes/missing.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZHR5cGVzL21pc3NpbmcucHk=) | `93.1% <ø> (ø)` | :arrow_up: |
| [pandas/core/arrays/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lbGlrZS5weQ==) | `96.48% <100%> (+0.12%)` | :arrow_up: |
| [pandas/core/indexes/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZWxpa2UucHk=) | `97.57% <100%> (-0.01%)` | :arrow_down: |
| [pandas/core/arrays/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lcy5weQ==) | `98.56% <100%> (+0.78%)` | :arrow_up: |
| [pandas/core/indexes/timedeltas.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy90aW1lZGVsdGFzLnB5) | `90.44% <100%> (+0.02%)` | :arrow_up: |
| [pandas/core/arrays/period.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL3BlcmlvZC5weQ==) | `98.41% <100%> (-0.06%)` | :arrow_down: |
| [pandas/core/indexes/period.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9wZXJpb2QucHk=) | `93.09% <100%> (+0.01%)` | :arrow_up: |
| [pandas/core/indexes/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZXMucHk=) | `96.28% <100%> (-0.05%)` | :arrow_down: |
| [pandas/core/arrays/timedeltas.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL3RpbWVkZWx0YXMucHk=) | `87.22% <92.3%> (+0.36%)` | :arrow_up: |
| ... and [1 more](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=footer). Last update [fc7bc3f...6a5c216](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

# [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=h1) Report
> Merging [#24405](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=desc) into [master](https://codecov.io/gh/pandas-dev/pandas/commit/d1b2a52a59b11bd66458289920612b88d80cab73?src=pr&el=desc) will **increase** coverage by `0.01%`.
> The diff coverage is `98.59%`.

[![Impacted file tree graph](https://codecov.io/gh/pandas-dev/pandas/pull/24405/graphs/tree.svg?width=650&token=eZ4WkYLtcO&height=150&src=pr)](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=tree)

```diff
@@            Coverage Diff             @@
##           master   #24405      +/-   ##
==========================================
+ Coverage    92.3%   92.31%   +0.01%     
==========================================
  Files         165      165              
  Lines       52176    52194      +18     
==========================================
+ Hits        48161    48183      +22     
+ Misses       4015     4011       -4
```

| Flag | Coverage Δ | |
|---|---|---|
| #multiple | `90.73% <98.59%> (+0.01%)` | :arrow_up: |
| #single | `42.96% <50.7%> (ø)` | :arrow_up: |

| [Impacted Files](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=tree) | Coverage Δ | |
|---|---|---|
| [pandas/core/dtypes/missing.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvZHR5cGVzL21pc3NpbmcucHk=) | `93.1% <ø> (ø)` | :arrow_up: |
| [pandas/core/indexes/base.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9iYXNlLnB5) | `96.28% <ø> (ø)` | :arrow_up: |
| [pandas/core/arrays/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lbGlrZS5weQ==) | `96.08% <100%> (+0.15%)` | :arrow_up: |
| [pandas/core/indexes/datetimelike.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZWxpa2UucHk=) | `97.53% <100%> (-0.04%)` | :arrow_down: |
| [pandas/core/arrays/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL2RhdGV0aW1lcy5weQ==) | `98.39% <100%> (+0.78%)` | :arrow_up: |
| [pandas/core/indexes/timedeltas.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy90aW1lZGVsdGFzLnB5) | `90.25% <100%> (-0.03%)` | :arrow_down: |
| [pandas/core/arrays/period.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL3BlcmlvZC5weQ==) | `98.42% <100%> (-0.06%)` | :arrow_down: |
| [pandas/core/indexes/period.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9wZXJpb2QucHk=) | `92.69% <100%> (-0.02%)` | :arrow_down: |
| [pandas/core/indexes/datetimes.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvaW5kZXhlcy9kYXRldGltZXMucHk=) | `96.14% <100%> (-0.07%)` | :arrow_down: |
| [pandas/core/arrays/timedeltas.py](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree#diff-cGFuZGFzL2NvcmUvYXJyYXlzL3RpbWVkZWx0YXMucHk=) | `87.36% <94.44%> (+0.44%)` | :arrow_up: |
| ... and [1 more](https://codecov.io/gh/pandas-dev/pandas/pull/24405/diff?src=pr&el=tree-more) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=continue).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=footer). Last update [d1b2a52...eac662b](https://codecov.io/gh/pandas-dev/pandas/pull/24405?src=pr&el=lastupdated). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments).

is this contingent on #24394 ? should that be first?
> is this contingent on #24394 ? should that be first?

No, they are independent.  They just both implement+use `_eadata`.
added requested assertion in test_period and passed copy=copy to numpy copy in the DatetimeLikeArrayMixin.astype case where it was obvious.  For the rest I'm going to leave that to Tom in #24024 post-rebase (and if this goes through I'll make a PR on his branch to help rebase)
What are the new parts that was discovered in this PR?
> What are the new parts that was discovered in this PR?

Primarily the int32 casting stuff and some `copy`-related topics that I think have been resolved.
I think 
https://github.com/pandas-dev/pandas/pull/24405/commits/04efd450a9ef6fd92029d99044cc10a5ebf33914 broke `TimedeltaIndex.astype(str)`. Looking into it now
Though now that I think about it, this is some pretty strange behavior

```python
In [3]: pd.timedelta_range('2000', periods=2)._data.astype(str)[0]
Out[3]: Timedelta('0 days 00:00:00.000002')
```

Looks like we need to bring in the `_format_native_types` changes for TimedeltaArray. That should clear all this up.
5d718e66d86ab8fc6707ece5bb062086cc36424b (hopefully) fixed TImedeltaArray._format_native_types to return an array of strings.

Py2 failure: https://travis-ci.org/pandas-dev/pandas/jobs/473068039#L2035. Also have some linting failures.

I'll assume you have other things to work on @jbrockmendel, and continue to push changes here if that's OK. 
e29d8984897c665051c0cc5b62929a43f219dd9e hopefully fixes the Py2 failure. At some point, the type for the `na_rep` parameter of the datetimelike `_format_native_types` became unicode. On the base class it's `str` (on whatever version of Python), and the underlying formatter seems to expect `str` (again, on whatever version of Python).
lgtm. assume you just rebased? and if you want to add TODO have at it. ping on green.
By "just" rebased do you mean recently? If so I think the last one was 
https://github.com/pandas-dev/pandas/pull/24405/commits/207ffb91f348353070440cd3e0b9878f2eec61a4.

I'll merge master again when I fix this last py2 error.

If you meant "is rebasing the only thing you did?" then no, there are some real changes here.

---

It looks like the period tests aren't happy with my changes to format arrays. On 0.23.4 we were inconsistent

```python
In [5]: type(pd.period_range('2000', periods=2).astype(str)[0])
Out[5]: numpy.unicode_

In [6]: type(pd.date_range('2000', periods=2).astype(str)[0])
Out[6]: str
```

I'll revert the period change here and open an issue.
Merged master and fixed the py2 issue (
https://github.com/pandas-dev/pandas/pull/24405/commits/a3c42f0f696b29f7f2aac1344dc7195210815a24).

I decided not to open an issue because the behavior is correct for Python 3 and we're not going to change this for 0.24, so who cares :)
>  and continue to push changes here if that's OK.

Extremely happy to hand this one off, thanks for figuring it out.
ok lgtm. ping on green.
All green.
thanks! nice @jbrockmendel and @TomAugspurger