feat: Add Ruff linting, pre-commit hooks, and build scripts

- Configure Ruff for linting and formatting with pre-commit hooks
- Add Makefile with convenient commands for development workflow
- Create build and upload scripts for Gitea package registry
- Update README with documentation for new features
- Fix code quality issues identified by Ruff
- Add development dependencies (ruff, pre-commit) to pyproject.toml
- Update Python version requirement to >=3.9
- Add template for Gitea PyPI configuration
- Bump version to 0.3.0
- All tests passing and code properly formatted
This commit is contained in:
2025-08-11 14:49:17 +02:00
parent 2f58c5bd3a
commit a60f5274b2
16 changed files with 725 additions and 125 deletions
+36 -17
View File
@@ -2,13 +2,14 @@
Test suite for paroles_net_scraper package
"""
import sys
import os
import sys
from unittest.mock import Mock, patch
import pytest
from unittest.mock import patch, Mock
# Add the parent directory to the path so we can import the scraper
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..')))
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
# Import from the package
from paroles_net_scraper import get_song_lyrics
@@ -31,14 +32,17 @@ def test_get_song_lyrics_success():
</body>
</html>
"""
# Mock response object
mock_response = Mock()
mock_response.content = mock_html
mock_response.raise_for_status.return_value = None
# Mock BeautifulSoup parsing
with patch('paroles_net_scraper.paroles_net_scraper.requests.get', return_value=mock_response):
with patch(
"paroles_net_scraper.paroles_net_scraper.requests.get",
return_value=mock_response,
):
lyrics = get_song_lyrics("Test Artist", "Test Song")
assert "This is the first line of the song" in lyrics
assert "This is the second line of the song" in lyrics
@@ -59,20 +63,26 @@ def test_get_song_lyrics_not_found():
</body>
</html>
"""
# Mock response object
mock_response = Mock()
mock_response.content = mock_html
mock_response.raise_for_status.return_value = None
with patch('paroles_net_scraper.paroles_net_scraper.requests.get', return_value=mock_response):
with patch(
"paroles_net_scraper.paroles_net_scraper.requests.get",
return_value=mock_response,
):
lyrics = get_song_lyrics("Non Existent", "Non Existent Song")
assert lyrics == "Lyrics not found on the page"
def test_get_song_lyrics_request_exception():
"""Test handling of request exceptions"""
with patch('paroles_net_scraper.paroles_net_scraper.requests.get', side_effect=Exception("Network error")):
with patch(
"paroles_net_scraper.paroles_net_scraper.requests.get",
side_effect=Exception("Network error"),
):
lyrics = get_song_lyrics("Test Artist", "Test Song")
assert "Error parsing lyrics" in lyrics
@@ -81,19 +91,28 @@ def test_url_formatting():
"""Test URL formatting with special characters"""
# This test will check that the URL is properly formatted
# We'll test this by checking the requests.get call arguments
mock_response = Mock()
mock_response.content = "<div class='song-text'></div>"
mock_response.raise_for_status.return_value = None
with patch('paroles_net_scraper.paroles_net_scraper.requests.get', return_value=mock_response) as mock_get:
with patch(
"paroles_net_scraper.paroles_net_scraper.requests.get",
return_value=mock_response,
) as mock_get:
# Test with artist and song containing spaces and special characters
get_song_lyrics("Ed Sheeran", "Shape of You")
expected_url = "https://www.paroles.net/ed-sheeran/paroles-shape-of-you"
mock_get.assert_called_once_with(expected_url, headers={
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
})
mock_get.assert_called_once_with(
expected_url,
headers={
"User-Agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36"
)
},
)
if __name__ == "__main__":
pytest.main([__file__])
pytest.main([__file__])