Repository: postlund/pyatv
Pull request #1329 (2021-09-23 17:34:25)

convert: Add model_str method

codecov[bot]: # [Codecov](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) Report
> Merging [#1329](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) (2c445dc) into [master](https://codecov.io/gh/postlund/pyatv/commit/974f89b907bf3b9ae11f38394a298598186d9c27?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) (974f89b) will **decrease** coverage by `0.02%`.
> The diff coverage is `100.00%`.

[![Impacted file tree graph](https://codecov.io/gh/postlund/pyatv/pull/1329/graphs/tree.svg?width=650&height=150&src=pr&token=wb6azJjRSY&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl)](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl)

```diff
@@            Coverage Diff             @@
##           master    #1329      +/-   ##
==========================================
- Coverage   92.48%   92.45%   -0.03%     
==========================================
  Files         149      149              
  Lines        9164     9133      -31     
==========================================
- Hits         8475     8444      -31     
  Misses        689      689              
```


| [Impacted Files](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) | Coverage Δ | |
|---|---|---|
| [pyatv/convert.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvY29udmVydC5weQ==) | `100.00% <100.00%> (ø)` | |
| [pyatv/protocols/raop/raop.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL3Jhb3AvcmFvcC5weQ==) | `87.79% <0.00%> (-0.70%)` | :arrow_down: |
| [pyatv/protocols/mrp/pairing.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL21ycC9wYWlyaW5nLnB5) | `97.61% <0.00%> (-0.11%)` | :arrow_down: |
| [pyatv/protocols/companion/connection.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2NvbXBhbmlvbi9jb25uZWN0aW9uLnB5) | `89.09% <0.00%> (-0.10%)` | :arrow_down: |
| [pyatv/protocols/dmap/pairing.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2RtYXAvcGFpcmluZy5weQ==) | `96.59% <0.00%> (-0.08%)` | :arrow_down: |
| [pyatv/protocols/raop/\_\_init\_\_.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL3Jhb3AvX19pbml0X18ucHk=) | `93.03% <0.00%> (-0.06%)` | :arrow_down: |
| [pyatv/protocols/mrp/player\_state.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL21ycC9wbGF5ZXJfc3RhdGUucHk=) | `98.96% <0.00%> (-0.04%)` | :arrow_down: |
| [pyatv/protocols/dmap/\_\_init\_\_.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2RtYXAvX19pbml0X18ucHk=) | `97.33% <0.00%> (-0.03%)` | :arrow_down: |
| [pyatv/protocols/dmap/daap.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvcHJvdG9jb2xzL2RtYXAvZGFhcC5weQ==) | `97.19% <0.00%> (-0.03%)` | :arrow_down: |
| [pyatv/support/http.py](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl#diff-cHlhdHYvc3VwcG9ydC9odHRwLnB5) | `93.37% <0.00%> (-0.03%)` | :arrow_down: |
| ... and [7 more](https://codecov.io/gh/postlund/pyatv/pull/1329/diff?src=pr&el=tree-more&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl) | |

------

[Continue to review full report at Codecov](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl). Last update [974f89b...2c445dc](https://codecov.io/gh/postlund/pyatv/pull/1329?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=Pierre+St%C3%A5hl).


Patch:
diff --git a/docs/api/pyatv/convert.html b/docs/api/pyatv/convert.html
index 24890a26..df90f050 100644
--- a/docs/api/pyatv/convert.html
+++ b/docs/api/pyatv/convert.html
@@ -16,9 +16,10 @@ link_group: api
 </ul>
 </li>
 <li><h3><a href="#header-functions">Functions</a></h3>
-<ul class="">
+<ul class="two-column">
 <li><code><a title="pyatv.convert.device_state_str" href="#pyatv.convert.device_state_str">device_state_str</a></code></li>
 <li><code><a title="pyatv.convert.media_type_str" href="#pyatv.convert.media_type_str">media_type_str</a></code></li>
+<li><code><a title="pyatv.convert.model_str" href="#pyatv.convert.model_str">model_str</a></code></li>
 <li><code><a title="pyatv.convert.protocol_str" href="#pyatv.convert.protocol_str">protocol_str</a></code></li>
 <li><code><a title="pyatv.convert.repeat_str" href="#pyatv.convert.repeat_str">repeat_str</a></code></li>
 <li><code><a title="pyatv.convert.shuffle_str" href="#pyatv.convert.shuffle_str">shuffle_str</a></code></li>
@@ -32,7 +33,7 @@ link_group: api
 </header>
 <section id="section-intro">
 <p>Various types of extraction and conversion functions.</p>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L1-L55" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L1-L77" class="git-link">Browse git</a></div>
 </section>
 <section>
 </section>
@@ -48,7 +49,7 @@ link_group: api
 </dt>
 <dd>
 <section class="desc"><p>Convert internal API device state to string.</p></section>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L6-L16" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L13-L23" class="git-link">Browse git</a></div>
 </dd>
 <dt id="pyatv.convert.media_type_str">
 <code class="name flex">
@@ -57,7 +58,16 @@ link_group: api
 </dt>
 <dd>
 <section class="desc"><p>Convert internal API media type to string.</p></section>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L19-L26" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L26-L33" class="git-link">Browse git</a></div>
+</dd>
+<dt id="pyatv.convert.model_str">
+<code class="name flex">
+<span>def <span class="ident">model_str</span></span>(<span>device_model: <a title="pyatv.const.DeviceModel" href="const#pyatv.const.DeviceModel">DeviceModel</a>) -> str</span>
+</code>
+</dt>
+<dd>
+<section class="desc"><p>Convert device model to string.</p></section>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L65-L77" class="git-link">Browse git</a></div>
 </dd>
 <dt id="pyatv.convert.protocol_str">
 <code class="name flex">
@@ -66,7 +76,7 @@ link_group: api
 </dt>
 <dd>
 <section class="desc"><p>Convert internal API protocol to string.</p></section>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L47-L55" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L54-L62" class="git-link">Browse git</a></div>
 </dd>
 <dt id="pyatv.convert.repeat_str">
 <code class="name flex">
@@ -75,7 +85,7 @@ link_group: api
 </dt>
 <dd>
 <section class="desc"><p>Convert internal API repeat state to string.</p></section>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L29-L35" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L36-L42" class="git-link">Browse git</a></div>
 </dd>
 <dt id="pyatv.convert.shuffle_str">
 <code class="name flex">
@@ -84,7 +94,7 @@ link_group: api
 </dt>
 <dd>
 <section class="desc"><p>Convert internal API shuffle state to string.</p></section>
-<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L38-L44" class="git-link">Browse git</a></div>
+<div class="git-link-div"><a href="https://github.com/postlund/pyatv/blob/master/pyatv/convert.py#L45-L51" class="git-link">Browse git</a></div>
 </dd>
 </dl>
 </section>
diff --git a/pyatv/convert.py b/pyatv/convert.py
index 48e15314..8e51f745 100644
--- a/pyatv/convert.py
+++ b/pyatv/convert.py
@@ -1,6 +1,13 @@
 """Various types of extraction and conversion functions."""
 
-from pyatv.const import DeviceState, MediaType, Protocol, RepeatState, ShuffleState
+from pyatv.const import (
+    DeviceModel,
+    DeviceState,
+    MediaType,
+    Protocol,
+    RepeatState,
+    ShuffleState,
+)
 
 
 def device_state_str(state: DeviceState) -> str:
@@ -53,3 +60,18 @@ def protocol_str(protocol: Protocol) -> str:
         Protocol.Companion: "Companion",
         Protocol.RAOP: "RAOP",
     }.get(protocol, "Unknown")
+
+
+def model_str(device_model: DeviceModel) -> str:
+    """Convert device model to string."""
+    return {
+        DeviceModel.Gen2: "Apple TV 2",
+        DeviceModel.Gen3: "Apple TV 3",
+        DeviceModel.Gen4: "Apple TV 4",
+        DeviceModel.Gen4K: "Apple TV 4K",
+        DeviceModel.HomePod: "HomePod",
+        DeviceModel.HomePodMini: "HomePod Mini",
+        DeviceModel.AirPortExpress: "AirPort Express (gen 1)",
+        DeviceModel.AirPortExpressGen2: "AirPort Express (gen 2)",
+        DeviceModel.AppleTV4KGen2: "Apple TV 4K (gen2)",
+    }.get(device_model, "Unknown")


Test patch:
diff --git a/tests/test_convert.py b/tests/test_convert.py
index 757a7c90..ea18fc33 100644
--- a/tests/test_convert.py
+++ b/tests/test_convert.py
@@ -1,60 +1,103 @@
 """Unit tests for pyatv.convert."""
 
-from pyatv import convert
-from pyatv.const import DeviceState, MediaType, Protocol, RepeatState, ShuffleState
-
-
-def test_media_type_to_string():
-    assert "Unknown" == convert.media_type_str(MediaType.Unknown)
-    assert "Video" == convert.media_type_str(MediaType.Video)
-    assert "Music" == convert.media_type_str(MediaType.Music)
-    assert "TV" == convert.media_type_str(MediaType.TV)
-
-
-def test_unknown_media_type_to_str():
-    assert "Unsupported" == convert.media_type_str(999)
-
-
-def test_device_state_str():
-    assert "Idle" == convert.device_state_str(DeviceState.Idle)
-    assert "Loading" == convert.device_state_str(DeviceState.Loading)
-    assert "Stopped" == convert.device_state_str(DeviceState.Stopped)
-    assert "Paused" == convert.device_state_str(DeviceState.Paused)
-    assert "Playing" == convert.device_state_str(DeviceState.Playing)
-    assert "Seeking" == convert.device_state_str(DeviceState.Seeking)
-
-
-def test_unsupported_device_state_str():
-    assert "Unsupported" == convert.device_state_str(999)
-
-
-def test_repeat_str():
-    assert "Off" == convert.repeat_str(RepeatState.Off)
-    assert "Track" == convert.repeat_str(RepeatState.Track)
-    assert "All" == convert.repeat_str(RepeatState.All)
+import pytest
 
-
-def test_unknown_repeat_to_str():
-    assert "Unsupported" == convert.repeat_str(1234)
-
-
-def test_shuffle_str():
-    assert "Off" == convert.shuffle_str(ShuffleState.Off)
-    assert "Albums" == convert.shuffle_str(ShuffleState.Albums)
-    assert "Songs" == convert.shuffle_str(ShuffleState.Songs)
-
-
-def test_unknown_shuffle_to_str():
-    assert "Unsupported" == convert.shuffle_str(1234)
-
-
-def test_protocol_str():
-    assert "MRP" == convert.protocol_str(Protocol.MRP)
-    assert "DMAP" == convert.protocol_str(Protocol.DMAP)
-    assert "AirPlay" == convert.protocol_str(Protocol.AirPlay)
-    assert "Companion" == convert.protocol_str(Protocol.Companion)
-    assert "RAOP" == convert.protocol_str(Protocol.RAOP)
-
-
-def test_unknown_protocol_str():
-    assert "Unknown" == convert.protocol_str("invalid")
+from pyatv import convert
+from pyatv.const import (
+    DeviceModel,
+    DeviceState,
+    MediaType,
+    Protocol,
+    RepeatState,
+    ShuffleState,
+)
+
+
+@pytest.mark.parametrize(
+    "media_type,output",
+    [
+        (MediaType.Unknown, "Unknown"),
+        (MediaType.Video, "Video"),
+        (MediaType.Music, "Music"),
+        (MediaType.TV, "TV"),
+        (99, "Unsupported"),
+    ],
+)
+def test_media_type_to_string(media_type, output):
+    assert convert.media_type_str(media_type) == output
+
+
+@pytest.mark.parametrize(
+    "device_state,output",
+    [
+        (DeviceState.Idle, "Idle"),
+        (DeviceState.Loading, "Loading"),
+        (DeviceState.Stopped, "Stopped"),
+        (DeviceState.Paused, "Paused"),
+        (DeviceState.Playing, "Playing"),
+        (DeviceState.Seeking, "Seeking"),
+        (999, "Unsupported"),
+    ],
+)
+def test_device_state_str(device_state, output):
+    assert convert.device_state_str(device_state) == output
+
+
+@pytest.mark.parametrize(
+    "repeat,output",
+    [
+        (RepeatState.Off, "Off"),
+        (RepeatState.Track, "Track"),
+        (RepeatState.All, "All"),
+        (1234, "Unsupported"),
+    ],
+)
+def test_repeat_str(repeat, output):
+    assert convert.repeat_str(repeat) == output
+
+
+@pytest.mark.parametrize(
+    "shuffle,output",
+    [
+        (ShuffleState.Off, "Off"),
+        (ShuffleState.Albums, "Albums"),
+        (ShuffleState.Songs, "Songs"),
+        (1234, "Unsupported"),
+    ],
+)
+def test_shuffle_str(shuffle, output):
+    assert convert.shuffle_str(shuffle) == output
+
+
+@pytest.mark.parametrize(
+    "protocol,output",
+    [
+        (Protocol.MRP, "MRP"),
+        (Protocol.DMAP, "DMAP"),
+        (Protocol.AirPlay, "AirPlay"),
+        (Protocol.Companion, "Companion"),
+        (Protocol.RAOP, "RAOP"),
+        (1234, "Unknown"),
+    ],
+)
+def test_protocol_str(protocol, output):
+    assert convert.protocol_str(protocol) == output
+
+
+@pytest.mark.parametrize(
+    "model,output",
+    [
+        (DeviceModel.Gen2, "Apple TV 2"),
+        (DeviceModel.Gen3, "Apple TV 3"),
+        (DeviceModel.Gen4, "Apple TV 4"),
+        (DeviceModel.Gen4K, "Apple TV 4K"),
+        (DeviceModel.HomePod, "HomePod"),
+        (DeviceModel.HomePodMini, "HomePod Mini"),
+        (DeviceModel.AirPortExpress, "AirPort Express (gen 1)"),
+        (DeviceModel.AirPortExpressGen2, "AirPort Express (gen 2)"),
+        (DeviceModel.AppleTV4KGen2, "Apple TV 4K (gen2)"),
+        (1234, "Unknown"),
+    ],
+)
+def test_model_str(model, output):
+    assert convert.model_str(model) == output