initial commit
This commit is contained in:
parent
67f3dbd39c
commit
c6cac9cc06
7
.gitignore
vendored
7
.gitignore
vendored
@ -1,3 +1,8 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
.env
|
||||
.env
|
||||
.python-version
|
||||
dist/
|
||||
build/
|
||||
movietimes.egg-info/
|
||||
.pytest_cache/
|
23
README.md
Normal file
23
README.md
Normal 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
3
requirements-dev.txt
Normal file
@ -0,0 +1,3 @@
|
||||
pytest
|
||||
setuptools
|
||||
build
|
3
requirements.txt
Normal file
3
requirements.txt
Normal file
@ -0,0 +1,3 @@
|
||||
requests
|
||||
beautifulsoup4
|
||||
rich
|
17
setup.py
Normal file
17
setup.py
Normal 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",
|
||||
],
|
||||
},
|
||||
)
|
1
src/movietimes/__init__.py
Normal file
1
src/movietimes/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# src/__init__.py
|
4
src/movietimes/cli.py
Normal file
4
src/movietimes/cli.py
Normal file
@ -0,0 +1,4 @@
|
||||
from .movie_showtimes import main
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
55
src/movietimes/movie_showtimes.py
Normal file
55
src/movietimes/movie_showtimes.py
Normal 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
1
tests/__init__.py
Normal file
@ -0,0 +1 @@
|
||||
# Make tests a package
|
69
tests/test_movie_showtimes.py
Normal file
69
tests/test_movie_showtimes.py
Normal 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
|
||||
|
Loading…
x
Reference in New Issue
Block a user