initial commit

This commit is contained in:
Phil 2025-03-14 11:43:11 -06:00
parent 67f3dbd39c
commit c6cac9cc06
10 changed files with 182 additions and 1 deletions

7
.gitignore vendored
View File

@ -1,3 +1,8 @@
__pycache__/
*.pyc
.env
.env
.python-version
dist/
build/
movietimes.egg-info/
.pytest_cache/

23
README.md Normal file
View File

@ -0,0 +1,23 @@
# MovieTimes
MovieTimes is a Python-based scraper that fetches movie showtimes for a given ZIP code using Google search results.
## Installation
```bash
git clone https://github.com/yourusername/movietimes.git
cd movietimes
pip install -r requirements.txt
```
## Usage
```bash
python src/showtimes_scraper.py 90210
```
## Testing
```bash
pytest
```

3
requirements-dev.txt Normal file
View File

@ -0,0 +1,3 @@
pytest
setuptools
build

3
requirements.txt Normal file
View File

@ -0,0 +1,3 @@
requests
beautifulsoup4
rich

17
setup.py Normal file
View File

@ -0,0 +1,17 @@
from setuptools import setup, find_packages
setup(
name="movietimes",
version="1.0",
packages=find_packages(where="src"),
package_dir={"": "src"},
install_requires=[
"requests",
"rich"
],
entry_points={
"console_scripts": [
"movietimes=movietimes.cli:main",
],
},
)

View File

@ -0,0 +1 @@
# src/__init__.py

4
src/movietimes/cli.py Normal file
View File

@ -0,0 +1,4 @@
from .movie_showtimes import main
if __name__ == "__main__":
main()

View File

@ -0,0 +1,55 @@
import requests
import time
import os
from rich.console import Console
from rich.table import Table
SERPAPI_SHOWTIMES_URL = "https://serpapi.com/search"
SERPAPI_API_KEY = os.getenv("SERPAPI_API_KEY", "your_serpapi_api_key")
default_theater_query = "cinemark century boulder"
default_location = "boulder, colorado, united states"
console = Console()
def get_movie_showtimes():
params = {
'q': default_theater_query,
'hl': 'en',
'gl': 'us',
'location': default_location,
'api_key': SERPAPI_API_KEY
}
response = requests.get(SERPAPI_SHOWTIMES_URL, params=params)
if response.status_code == 200:
data = response.json()
return data.get('showtimes', [])
else:
raise ValueError("Could not fetch movie showtimes from SerpApi.")
def display_showtimes(showtimes):
if not showtimes:
console.print("[bold red]No showtimes available.[/bold red]")
return
for day_data in showtimes:
day = day_data.get("day", "Unknown Day")
console.print(f"\n[bold cyan]{day}[/bold cyan]")
for movie in day_data.get("movies", []):
table = Table(title=f"{movie['name']}", show_header=True, header_style="bold magenta")
table.add_column("Type", style="dim")
table.add_column("Times", justify="right")
for showing in movie.get("showing", []):
table.add_row(showing["type"], ", ".join(showing["time"]))
console.print(table)
def main():
showtimes = get_movie_showtimes()
display_showtimes(showtimes)
time.sleep(1)
if __name__ == '__main__':
main()

1
tests/__init__.py Normal file
View File

@ -0,0 +1 @@
# Make tests a package

View File

@ -0,0 +1,69 @@
import pytest
import requests
from unittest.mock import patch
from src.movie_showtimes import get_movie_showtimes, display_showtimes
from io import StringIO
from rich.console import Console
@pytest.fixture
def mock_successful_response():
"""Mock a successful API response."""
return {
"showtimes": [
{
"day": "Today",
"movies": [
{
"name": "Dune",
"showing": [
{"time": ["12:30pm", "4:00pm"], "type": "Standard"},
{"time": ["1:30pm", "5:30pm"], "type": "IMAX"}
]
}
]
}
]
}
@pytest.fixture
def mock_failed_response():
"""Mock a failed API response."""
return {}
@patch("requests.get")
def test_get_movie_showtimes_success(mock_get, mock_successful_response):
"""Test fetching movie showtimes successfully from SerpApi."""
mock_get.return_value.status_code = 200
mock_get.return_value.json.return_value = mock_successful_response
showtimes = get_movie_showtimes()
assert len(showtimes) == 1
assert showtimes[0]["day"] == "Today"
assert showtimes[0]["movies"][0]["name"] == "Dune"
assert showtimes[0]["movies"][0]["showing"][0]["type"] == "Standard"
@patch("requests.get")
def test_get_movie_showtimes_failure(mock_get, mock_failed_response):
"""Test handling of API failure (non-200 response)."""
mock_get.return_value.status_code = 500
mock_get.return_value.json.return_value = mock_failed_response
with pytest.raises(ValueError, match="Could not fetch movie showtimes from SerpApi."):
get_movie_showtimes()
@patch("sys.stdout", new_callable=StringIO)
def test_display_showtimes_output(mock_stdout, mock_successful_response):
"""Test console output formatting of display_showtimes."""
console = Console(file=mock_stdout)
display_showtimes(mock_successful_response["showtimes"])
output = mock_stdout.getvalue()
assert "Today" in output
assert "Dune" in output
assert "Standard" in output
assert "12:30pm, 4:00pm" in output
assert "IMAX" in output
assert "1:30pm, 5:30pm" in output