Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 1 addition & 3 deletions instaparser/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
A Python client library for the Instaparser API.
"""

from .article import Article
from .client import InstaparserClient
from .exceptions import (
InstaparserAPIError,
Expand All @@ -13,8 +12,7 @@
InstaparserRateLimitError,
InstaparserValidationError,
)
from .pdf import PDF
from .summary import Summary
from .models import PDF, Article, Summary

__version__ = "1.0.1"

Expand Down
4 changes: 1 addition & 3 deletions instaparser/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
42 changes: 39 additions & 3 deletions instaparser/article.py → instaparser/models.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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"<PDF url={self.url!r} title={self.title!r}>"


@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"<Summary overview={overview!r} key_sentences={len(self.key_sentences)}>"

def __str__(self) -> str:
return self.overview
24 changes: 0 additions & 24 deletions instaparser/pdf.py

This file was deleted.

30 changes: 0 additions & 30 deletions instaparser/summary.py

This file was deleted.

2 changes: 1 addition & 1 deletion tests/test_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,14 @@
import pytest

from instaparser import InstaparserClient
from instaparser.article import Article
from instaparser.client import _encode_multipart_formdata
from instaparser.exceptions import (
InstaparserAPIError,
InstaparserAuthenticationError,
InstaparserRateLimitError,
InstaparserValidationError,
)
from instaparser.models import Article

API_KEY = "test-api-key-12345"
BASE_URL = "https://api.test.instaparser.com"
Expand Down
61 changes: 59 additions & 2 deletions tests/test_article.py → tests/test_models.py
Original file line number Diff line number Diff line change
@@ -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:
Expand Down Expand Up @@ -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="<p>Content</p>")
assert str(pdf) == "<p>Content</p>"


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"
37 changes: 0 additions & 37 deletions tests/test_pdf.py

This file was deleted.

31 changes: 0 additions & 31 deletions tests/test_summary.py

This file was deleted.