Skip to content

Commit 21d505c

Browse files
Apply TR feedback
Co-authored-by: Bartosz <[email protected]>
1 parent d17eb80 commit 21d505c

File tree

4 files changed

+61
-40
lines changed

4 files changed

+61
-40
lines changed

python-selenium/README.md

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,27 @@ Type: play [<track_number>] | pause | tracks | more | exit
3232
>
3333
```
3434

35-
Type one of the available commands to interact with Bandcamp's Discover section through your headless browser. Listen to songs with `play`, list available tracks with `tracks`, and load more songs using `more`. You can exit the music player by typing `exit`.
35+
Type one of the available commands to interact with Bandcamp's Discover section through your headless browser. Listen to songs with `play`, pause the current song with `pause` and restart it with `play`. List available tracks with `tracks`, and load more songs using `more`. You can exit the music player by typing `exit`.
36+
37+
## Troubleshooting
38+
39+
If the music player seems to hang when you run the script, confirm whether you've correctly set up your webdriver based on the following points.
40+
41+
### Version Compatibility
42+
43+
Confirm that your browser and corresponding webdriver are in sync. If you followed the previous suggestion, then you should be using Firefox and geckodriver. If that doesn't work for any reason, you may need to switch browser _and_ webdriver.
44+
45+
For example, if you're using Chrome, then you need to install ChromeDriver and it must match your Chrome version. Otherwise, you may run into errors like `SessionNotCreatedException`.
46+
For more details, refer to the official [ChromeDriver documentation](https://sites.google.com/chromium.org/driver/) or [geckodriver releases](https://github.com/mozilla/geckodriver/releases).
47+
48+
### Driver Installation and Path Issues
49+
50+
Once you've confirmed that your browser and driver match, make sure that the webdriver executable is properly installed:
51+
52+
- **Path Configuration:** The driver must be in your system's PATH, or you need to specify its full path in your code.
53+
- **Permissions:** Ensure the driver file has the necessary execution permissions.
54+
55+
If you're still running into issues executing the script, then consult the [Selenium Documentation](https://www.selenium.dev/documentation/) for additional troubleshooting tips or leave a comment on the tutorial.
3656

3757
## About the Authors
3858

python-selenium/src/bandcamp/app/tui.py

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,7 @@ def interact():
88
"""Control the player through user interactions."""
99
with Player() as player:
1010
while True:
11-
print(
12-
"\nType: play [<track number>] | pause | tracks | more | exit"
13-
)
11+
print("\nType: play [<track number>] | pause | tracks | more | exit")
1412
match input("> ").strip().lower().split():
1513
case ["play"]:
1614
play(player)
@@ -24,12 +22,8 @@ def interact():
2422
pause(player)
2523
case ["tracks"]:
2624
display_tracks(player)
27-
case ["more"] if len(
28-
player.tracklist.available_tracks
29-
) >= MAX_TRACKS:
30-
print(
31-
"Can't load more tracks. Pick one from the track list."
32-
)
25+
case ["more"] if len(player.tracklist.available_tracks) >= MAX_TRACKS:
26+
print("Can't load more tracks. Pick one from the track list.")
3327
case ["more"]:
3428
player.tracklist.load_more()
3529
display_tracks(player)
@@ -41,9 +35,15 @@ def interact():
4135

4236

4337
def play(player, track_number=None):
44-
"""Play a track and shows info about the track."""
45-
player.play(track_number)
46-
print(player._current_track._get_track_info())
38+
"""Play a track and show info about the track."""
39+
try:
40+
player.play(track_number)
41+
print(player._current_track._get_track_info())
42+
except IndexError:
43+
print(
44+
"Please provide a valid track number. "
45+
"You can list available tracks with `tracks`."
46+
)
4747

4848

4949
def pause(player):
@@ -56,17 +56,13 @@ def display_tracks(player):
5656
header = f"{'#':<5} {'Album':<{CW}} {'Artist':<{CW}} {'Genre':<{CW}}"
5757
print(header)
5858
print("-" * 100)
59-
for track_number, track in enumerate(
60-
player.tracklist.available_tracks, start=1
61-
):
59+
for track_number, track in enumerate(player.tracklist.available_tracks, start=1):
6260
if track.text:
6361
album, artist, *genre = track.text.split("\n")
6462
album = _truncate(album, CW)
6563
artist = _truncate(artist, CW)
6664
genre = _truncate(genre[0], CW) if genre else ""
67-
print(
68-
f"{track_number:<5} {album:<{CW}} {artist:<{CW}} {genre:<{CW}}"
69-
)
65+
print(f"{track_number:<5} {album:<{CW}} {artist:<{CW}} {genre:<{CW}}")
7066

7167

7268
def _truncate(text, width):

python-selenium/src/bandcamp/web/element.py

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
from bandcamp.web.locators import DiscoverPageLocator, TrackLocator
88

99

10-
class TrackElement(WebComponent, TrackLocator):
10+
class TrackElement(WebComponent):
1111
"""Model a playable track in Bandcamp's Discover section."""
1212

1313
def play(self) -> None:
@@ -26,26 +26,26 @@ def is_playing(self) -> bool:
2626

2727
def _get_track_info(self) -> Track:
2828
"""Create a representation of the track's relevant information."""
29-
full_url = self._parent.find_element(*self.URL).get_attribute("href")
29+
full_url = self._parent.find_element(*TrackLocator.URL).get_attribute("href")
3030
# Cut off the referrer query parameter
3131
clean_url = full_url.split("?")[0] if full_url else ""
3232
# Some tracks don't have a genre
3333
try:
34-
genre = self._parent.find_element(*self.GENRE).text
34+
genre = self._parent.find_element(*TrackLocator.GENRE).text
3535
except NoSuchElementException:
3636
genre = ""
3737
return Track(
38-
album=self._parent.find_element(*self.ALBUM).text,
39-
artist=self._parent.find_element(*self.ARTIST).text,
38+
album=self._parent.find_element(*TrackLocator.ALBUM).text,
39+
artist=self._parent.find_element(*TrackLocator.ARTIST).text,
4040
genre=genre,
4141
url=clean_url,
4242
)
4343

4444
def _get_play_button(self):
45-
return self._parent.find_element(*self.PLAY_BUTTON)
45+
return self._parent.find_element(*TrackLocator.PLAY_BUTTON)
4646

4747

48-
class DiscoverTrackList(WebComponent, DiscoverPageLocator, TrackLocator):
48+
class DiscoverTrackList(WebComponent):
4949
"""Model the track list in Bandcamp's Discover section."""
5050

5151
def __init__(self, parent: WebElement, driver: WebDriver = None) -> None:
@@ -54,31 +54,35 @@ def __init__(self, parent: WebElement, driver: WebDriver = None) -> None:
5454

5555
def load_more(self) -> None:
5656
"""Load additional tracks in the Discover section."""
57-
view_more_button = self._driver.find_element(*self.PAGINATION_BUTTON)
57+
view_more_button = self._driver.find_element(
58+
*DiscoverPageLocator.PAGINATION_BUTTON
59+
)
5860
view_more_button.click()
5961
# The button is disabled until all new tracks are loaded.
60-
self._wait.until(EC.element_to_be_clickable(self.PAGINATION_BUTTON))
62+
self._wait.until(EC.element_to_be_clickable(DiscoverPageLocator.PAGINATION_BUTTON))
6163
self.available_tracks = self._get_available_tracks()
6264

6365
def _get_available_tracks(self) -> list:
6466
"""Find all currently available tracks in the Discover section."""
6567
self._wait.until(
66-
lambda driver: any(
67-
e.is_displayed() and e.text.strip()
68-
for e in driver.find_elements(*self.ITEM)
69-
),
68+
self._track_text_loaded,
7069
message="Timeout waiting for track text to load",
7170
)
7271

73-
all_items = self._driver.find_elements(*self.ITEM)
72+
all_items = self._driver.find_elements(*DiscoverPageLocator.ITEM)
7473
all_tracks = []
7574
for item in all_items:
76-
if item.find_element(*self.PLAY_BUTTON):
75+
if item.find_element(*TrackLocator.PLAY_BUTTON):
7776
all_tracks.append(item)
7877

7978
# Filter tracks that are displayed and have text.
8079
return [
81-
track
82-
for track in all_tracks
83-
if track.is_displayed() and track.text.strip()
80+
track for track in all_tracks if track.is_displayed() and track.text.strip()
8481
]
82+
83+
def _track_text_loaded(self, driver):
84+
"""Check if the track text has loaded."""
85+
return any(
86+
e.is_displayed() and e.text.strip()
87+
for e in driver.find_elements(*DiscoverPageLocator.ITEM)
88+
)

python-selenium/src/bandcamp/web/page.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@
55
from bandcamp.web.locators import DiscoverPageLocator
66

77

8-
class DiscoverPage(WebPage, DiscoverPageLocator):
8+
class DiscoverPage(WebPage):
99
"""Model the relevant parts of the Bandcamp Discover page."""
1010

1111
def __init__(self, driver: WebDriver) -> None:
1212
super().__init__(driver)
1313
self._accept_cookie_consent()
1414
self.discover_tracklist = DiscoverTrackList(
15-
self._driver.find_element(*self.DISCOVER_RESULTS), self._driver
15+
self._driver.find_element(*DiscoverPageLocator.DISCOVER_RESULTS),
16+
self._driver,
1617
)
1718

1819
def _accept_cookie_consent(self) -> None:
1920
"""Accept the necessary cookie consent."""
20-
self._driver.find_element(*self.COOKIE_ACCEPT_NECESSARY).click()
21+
self._driver.find_element(*DiscoverPageLocator.COOKIE_ACCEPT_NECESSARY).click()

0 commit comments

Comments
 (0)