diff --git a/instaparser/__init__.py b/instaparser/__init__.py index 5c06a2c..5137e83 100644 --- a/instaparser/__init__.py +++ b/instaparser/__init__.py @@ -4,7 +4,6 @@ A Python client library for the Instaparser API. """ -from .article import Article from .client import InstaparserClient from .exceptions import ( InstaparserAPIError, @@ -13,8 +12,7 @@ InstaparserRateLimitError, InstaparserValidationError, ) -from .pdf import PDF -from .summary import Summary +from .models import PDF, Article, Summary __version__ = "1.0.1" diff --git a/instaparser/client.py b/instaparser/client.py index babc0f8..6ea9a98 100644 --- a/instaparser/client.py +++ b/instaparser/client.py @@ -12,15 +12,13 @@ from urllib.parse import urlencode, urljoin from urllib.request import Request, urlopen -from .article import Article from .exceptions import ( InstaparserAPIError, InstaparserAuthenticationError, InstaparserRateLimitError, InstaparserValidationError, ) -from .pdf import PDF -from .summary import Summary +from .models import PDF, Article, Summary def _encode_multipart_formdata( diff --git a/instaparser/article.py b/instaparser/models.py similarity index 62% rename from instaparser/article.py rename to instaparser/models.py index 983b618..b609d6c 100644 --- a/instaparser/article.py +++ b/instaparser/models.py @@ -1,6 +1,4 @@ -""" -Article class representing a parsed article from Instaparser. -""" +"""Model classes representing parsed results from Instaparser.""" from dataclasses import dataclass, field from typing import Any @@ -54,3 +52,41 @@ def __repr__(self) -> str: def __str__(self) -> str: return self.body or "" + + +@dataclass(repr=False) +class PDF(Article): + """ + Represents a parsed PDF from Instaparser. + + Inherits from Article since most fields are the same. + PDFs always have is_rtl=False and videos=[]. + """ + + def __post_init__(self) -> None: + self.is_rtl = False + self.videos = [] + + def __repr__(self) -> str: + return f"" + + +@dataclass(repr=False) +class Summary: + """ + Represents a summary result from Instaparser. + + Attributes: + key_sentences: List of key sentences extracted from the article + overview: Concise summary of the article + """ + + key_sentences: list[str] + overview: str + + def __repr__(self) -> str: + overview = self.overview[:50] + "..." if len(self.overview) > 50 else self.overview + return f"" + + def __str__(self) -> str: + return self.overview diff --git a/instaparser/pdf.py b/instaparser/pdf.py deleted file mode 100644 index 2d277c9..0000000 --- a/instaparser/pdf.py +++ /dev/null @@ -1,24 +0,0 @@ -""" -PDF class representing a parsed PDF from Instaparser. -""" - -from dataclasses import dataclass - -from .article import Article - - -@dataclass(repr=False) -class PDF(Article): - """ - Represents a parsed PDF from Instaparser. - - Inherits from Article since most fields are the same. - PDFs always have is_rtl=False and videos=[]. - """ - - def __post_init__(self) -> None: - self.is_rtl = False - self.videos = [] - - def __repr__(self) -> str: - return f"" diff --git a/instaparser/summary.py b/instaparser/summary.py deleted file mode 100644 index 288818e..0000000 --- a/instaparser/summary.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Summary class representing a summary result from Instaparser. -""" - - -class Summary: - """ - Represents a summary result from Instaparser. - - Attributes: - key_sentences: List of key sentences extracted from the article - overview: Concise summary of the article - """ - - def __init__(self, key_sentences: list[str], overview: str): - """ - Initialize a Summary from API response data. - - Args: - key_sentences: List of key sentences extracted from the article - overview: Concise summary of the article - """ - self.key_sentences = key_sentences - self.overview = overview - - def __repr__(self) -> str: - return f"" - - def __str__(self) -> str: - return self.overview diff --git a/tests/test_client.py b/tests/test_client.py index 677d7ee..cb37a39 100644 --- a/tests/test_client.py +++ b/tests/test_client.py @@ -6,7 +6,6 @@ import pytest from instaparser import InstaparserClient -from instaparser.article import Article from instaparser.client import _encode_multipart_formdata from instaparser.exceptions import ( InstaparserAPIError, @@ -14,6 +13,7 @@ InstaparserRateLimitError, InstaparserValidationError, ) +from instaparser.models import Article API_KEY = "test-api-key-12345" BASE_URL = "https://api.test.instaparser.com" diff --git a/tests/test_article.py b/tests/test_models.py similarity index 50% rename from tests/test_article.py rename to tests/test_models.py index 6cff6ae..0991fba 100644 --- a/tests/test_article.py +++ b/tests/test_models.py @@ -1,8 +1,8 @@ """ -Tests for Article class. +Tests for model classes. """ -from instaparser.article import Article +from instaparser.models import PDF, Article, Summary class TestArticle: @@ -60,3 +60,60 @@ def test_str_returns_empty_when_no_body(self): """Test __str__ returns empty string when body is None.""" article = Article() assert str(article) == "" + + +class TestPDF: + """Tests for PDF class.""" + + def test_inherits_from_article(self): + """Test that PDF inherits from Article.""" + assert issubclass(PDF, Article) + + def test_forces_is_rtl_false(self): + """Test that PDF always sets is_rtl to False, even if True is passed.""" + pdf = PDF(is_rtl=True) + assert pdf.is_rtl is False + + def test_forces_videos_empty(self): + """Test that PDF always sets videos to [], even if videos are passed.""" + pdf = PDF(videos=["https://example.com/video.mp4"]) + assert pdf.videos == [] + + def test_repr(self): + """Test __repr__ includes class name, url, and title.""" + pdf = PDF(url="https://example.com/doc.pdf", title="Test PDF") + repr_str = repr(pdf) + assert "PDF" in repr_str + assert "https://example.com/doc.pdf" in repr_str + assert "Test PDF" in repr_str + + def test_str_returns_body(self): + """Test that __str__ is inherited from Article and returns body.""" + pdf = PDF(html="

Content

") + assert str(pdf) == "

Content

" + + +class TestSummary: + """Tests for Summary class.""" + + def test_repr_truncates_long_overview(self): + """Test __repr__ truncates overview longer than 50 characters.""" + summary = Summary( + key_sentences=["Sentence 1", "Sentence 2"], + overview="This is a test overview that is longer than 50 characters for truncation", + ) + repr_str = repr(summary) + assert "..." in repr_str + assert "key_sentences=2" in repr_str + + def test_repr_does_not_truncate_short_overview(self): + """Test __repr__ does not add ellipsis for short overview.""" + summary = Summary(key_sentences=["Sentence"], overview="Short") + repr_str = repr(summary) + assert "..." not in repr_str + assert "key_sentences=1" in repr_str + + def test_str_returns_overview(self): + """Test __str__ returns the overview.""" + summary = Summary(key_sentences=["Sentence"], overview="The overview") + assert str(summary) == "The overview" diff --git a/tests/test_pdf.py b/tests/test_pdf.py deleted file mode 100644 index 8a62d4b..0000000 --- a/tests/test_pdf.py +++ /dev/null @@ -1,37 +0,0 @@ -""" -Tests for PDF class. -""" - -from instaparser.article import Article -from instaparser.pdf import PDF - - -class TestPDF: - """Tests for PDF class.""" - - def test_inherits_from_article(self): - """Test that PDF inherits from Article.""" - assert issubclass(PDF, Article) - - def test_forces_is_rtl_false(self): - """Test that PDF always sets is_rtl to False, even if True is passed.""" - pdf = PDF(is_rtl=True) - assert pdf.is_rtl is False - - def test_forces_videos_empty(self): - """Test that PDF always sets videos to [], even if videos are passed.""" - pdf = PDF(videos=["https://example.com/video.mp4"]) - assert pdf.videos == [] - - def test_repr(self): - """Test __repr__ includes class name, url, and title.""" - pdf = PDF(url="https://example.com/doc.pdf", title="Test PDF") - repr_str = repr(pdf) - assert "PDF" in repr_str - assert "https://example.com/doc.pdf" in repr_str - assert "Test PDF" in repr_str - - def test_str_returns_body(self): - """Test that __str__ is inherited from Article and returns body.""" - pdf = PDF(html="

Content

") - assert str(pdf) == "

Content

" diff --git a/tests/test_summary.py b/tests/test_summary.py deleted file mode 100644 index 97b060f..0000000 --- a/tests/test_summary.py +++ /dev/null @@ -1,31 +0,0 @@ -""" -Tests for Summary class. -""" - -from instaparser.summary import Summary - - -class TestSummary: - """Tests for Summary class.""" - - def test_repr(self): - """Test __repr__ includes class name, truncated overview, and sentence count.""" - summary = Summary( - key_sentences=["Sentence 1", "Sentence 2"], - overview="This is a test overview that is longer than 50 characters for truncation", - ) - repr_str = repr(summary) - assert "Summary" in repr_str - assert "key_sentences=2" in repr_str - - def test_repr_with_short_overview(self): - """Test __repr__ with short overview.""" - summary = Summary(key_sentences=["Sentence"], overview="Short") - repr_str = repr(summary) - assert "Summary" in repr_str - assert "key_sentences=1" in repr_str - - def test_str_returns_overview(self): - """Test __str__ returns the overview.""" - summary = Summary(key_sentences=["Sentence"], overview="The overview") - assert str(summary) == "The overview"