Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 18 additions & 32 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,49 +11,35 @@ jobs:
runs-on: ubuntu-latest

steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install poetry
run: pipx install poetry

- name: Set up Python
uses: actions/setup-python@v4
- uses: actions/setup-python@v4
with:
python-version: '3.8'
cache: 'poetry'
python-version: "3.8"

- name: Install dependencies
run: poetry install
- uses: astral-sh/setup-uv@v6
with:
version: "latest"

- name: Check formatting
run: |
source $(poetry env info --path)/bin/activate
make format-check
run: make format-check

test:
runs-on: ubuntu-latest
strategy:
matrix:
os: [ubuntu-latest, windows-latest, macos-latest]
runs-on: ${{ matrix.os }}

steps:
- name: Checkout
uses: actions/checkout@v3
- uses: actions/checkout@v4

- name: Install poetry
run: pipx install poetry

- name: Set up Python
uses: actions/setup-python@v4
- uses: actions/setup-python@v4
with:
python-version: '3.8'
cache: 'poetry'

- name: Install dependencies
run: poetry install
python-version: "3.8"

- name: Run main
run: make run
- uses: astral-sh/setup-uv@v6
with:
version: "latest"

- name: Test
run: |
source $(poetry env info --path)/bin/activate
make test
run: make test
8 changes: 8 additions & 0 deletions .idea/.gitignore

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/inspectionProfiles/profiles_settings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 4 additions & 0 deletions .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions .idea/modules.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 0 additions & 19 deletions .replit

This file was deleted.

5 changes: 5 additions & 0 deletions .vscode/extensions.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"recommendations": [
"ms-python.python",
]
}
15 changes: 15 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "Python Debugger: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}
]
}
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"python.testing.pytestArgs": [
"."
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true
}
23 changes: 23 additions & 0 deletions .vscode/tasks.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "Run Tests",
"type": "shell",
"command": "make test",
"group": {
"kind": "test",
"isDefault": true
},
},
{
"label": "Format",
"type": "shell",
"command": "make format",
"presentation": {
"reveal": "silent"
},
"problemMatcher": []
},
]
}
19 changes: 13 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,24 +1,31 @@
all: test

UV := $(shell command -v uv 2> /dev/null)
SRCS := $(shell git ls-files *.py)

.PHONY: run
run:
./main.py
ifdef UV
RUNNER := uv run
else
RUNNER :=
endif

.PHONY: test
test:
pytest test_*.py
$(RUNNER) pytest test_*.py

.PHONY: format
format:
yapf -i $(SRCS)
$(RUNNER) ruff format $(SRCS)

.PHONY: format-check
format-check:
yapf --diff $(SRCS) \
$(RUNNER) ruff format --check $(SRCS) \
|| (echo "Some files require formatting. Run 'make format' to fix." && exit 1)

.PHONY: clean
clean:
git clean -Xfd

ifndef VERBOSE
.SILENT:
endif
66 changes: 28 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
# Media Player Refactoring Python Kata

[![CI](https://github.com/Coding-Cuddles/media-player-refactoring-python-kata/actions/workflows/main.yml/badge.svg)](https://github.com/Coding-Cuddles/media-player-refactoring-python-kata/actions/workflows/main.yml)
[![Replit](https://img.shields.io/badge/Try%20with%20Replit-black?logo=replit)](https://replit.com/new/github/Coding-Cuddles/media-player-refactoring-python-kata)

## Overview

Expand Down Expand Up @@ -43,44 +42,44 @@ We have the `MediaFile` class to represent a media file, your task is to:

1. Update the player interfaces to take `MediaFile` objects, e.g.:

```python
class IMediaPlayer(ABC):
```python
class IMediaPlayer(ABC):

@abstractmethod
def play_audio(self, file):
pass
```
@abstractmethod
def play_audio(self, file):
pass
```

2. Create specialized players that can only handle certain formats (i.e.,
`Mp3Player`, `FlacPlayer`, `WavPlayer`).

```python
class Mp3Player(IAudioPlayer):
```python
class Mp3Player(IAudioPlayer):

def play_audio(file):
if file.format != "mp3":
raise ValueError("Invalid file format for Mp3Player!")
def play_audio(file):
if file.format != "mp3":
raise ValueError("Invalid file format for Mp3Player!")

# Implementation...
```
# Implementation...
```

The same kind of specialization will be done for `FlacPlayer`, `WavPlayer`,
and respective video and image players.

3. Add corresponding unit tests, e.g.:

```python
def test_mp3_player_handles_mp3():
mp3_player = Mp3Player()
mp3_file = MediaFile(format="mp3", filename="")
mp3_player.play_audio(mp3_file)
```python
def test_mp3_player_handles_mp3():
mp3_player = Mp3Player()
mp3_file = MediaFile(format="mp3", filename="")
mp3_player.play_audio(mp3_file)

def test_mp3_player_rejects_non_mp3():
mp3_player = Mp3Player()
flac_file = MediaFile(format="flac", filename="")
with pytest.raises(ValueError):
mp3_player.play_audio(flac_file)
```
def test_mp3_player_rejects_non_mp3():
mp3_player = Mp3Player()
flac_file = MediaFile(format="flac", filename="")
with pytest.raises(ValueError):
mp3_player.play_audio(flac_file)
```

### Exercise 3

Expand All @@ -101,21 +100,12 @@ Your task is to refactor the code to segregate interfaces based on the
different file formats and adapt the `MediaListPlayer` to work with the new
classes and interfaces.

## Usage

You can import this project into [Replit](https://replit.com), and it will
handle all dependencies automatically.

### Prerequisites

* [Python 3.8+](https://www.python.org/)
* [pytest](https://pytest.org)
## Prerequisites

### Run main
- [Python 3.8+](https://www.python.org/)
- [pytest](https://pytest.org)

```console
make run
```
## Usage

### Run tests

Expand Down
4 changes: 0 additions & 4 deletions main.py

This file was deleted.

5 changes: 0 additions & 5 deletions media_player.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ class MediaFile:


class IMediaPlayer(ABC):

@abstractmethod
def play_audio(self):
raise NotImplementedError
Expand All @@ -24,7 +23,6 @@ def view_image(self):


class AudioPlayer(IMediaPlayer):

def play_audio(self):
# Implementation...
pass
Expand All @@ -37,7 +35,6 @@ def view_image(self):


class VideoPlayer(IMediaPlayer):

def play_audio(self):
raise NotImplementedError

Expand All @@ -50,7 +47,6 @@ def view_image(self):


class ImagePlayer(IMediaPlayer):

def play_audio(self):
raise NotImplementedError

Expand All @@ -63,7 +59,6 @@ def view_image(self):


class MediaListPlayer:

def play_list(self, media_list, players):
for media in media_list:
# Implementation...
Expand Down
Loading
Loading