diff --git a/scrapers/__init__.py b/scrapers/__init__.py index 01e594c..4749123 100644 --- a/scrapers/__init__.py +++ b/scrapers/__init__.py @@ -1,55 +1,5 @@ -def __getattr__(name): - if name == "AtCoderScraper": - from .atcoder import AtCoderScraper +from .atcoder import AtCoderScraper +from .codeforces import CodeforcesScraper +from .cses import CSESScraper - return AtCoderScraper - elif name == "BaseScraper": - from .base import BaseScraper - - return BaseScraper - elif name == "ScraperConfig": - from .base import ScraperConfig - - return ScraperConfig - elif name == "CodeforcesScraper": - from .codeforces import CodeforcesScraper - - return CodeforcesScraper - elif name == "CSESScraper": - from .cses import CSESScraper - - return CSESScraper - elif name in [ - "ContestListResult", - "ContestSummary", - "MetadataResult", - "ProblemSummary", - "TestCase", - "TestsResult", - ]: - from .models import ( - ContestListResult, # noqa: F401 - ContestSummary, # noqa: F401 - MetadataResult, # noqa: F401 - ProblemSummary, # noqa: F401 - TestCase, # noqa: F401 - TestsResult, # noqa: F401 - ) - - return locals()[name] - raise AttributeError(f"module 'scrapers' has no attribute '{name}'") - - -__all__ = [ - "AtCoderScraper", - "BaseScraper", - "CodeforcesScraper", - "CSESScraper", - "ScraperConfig", - "ContestListResult", - "ContestSummary", - "MetadataResult", - "ProblemSummary", - "TestCase", - "TestsResult", -] +__all__ = ["CodeforcesScraper", "CSESScraper", "AtCoderScraper"] diff --git a/scrapers/cses.py b/scrapers/cses.py old mode 100755 new mode 100644 diff --git a/tests/scrapers/test_interface_compliance.py b/tests/scrapers/test_interface_compliance.py deleted file mode 100644 index ab07ff2..0000000 --- a/tests/scrapers/test_interface_compliance.py +++ /dev/null @@ -1,167 +0,0 @@ -from unittest.mock import Mock - -import pytest - -import scrapers -from scrapers.base import BaseScraper -from scrapers.models import ContestListResult, MetadataResult, TestsResult - -SCRAPERS = [ - scrapers.AtCoderScraper, - scrapers.CodeforcesScraper, - scrapers.CSESScraper, -] - - -class TestScraperInterfaceCompliance: - @pytest.mark.parametrize("scraper_class", SCRAPERS) - def test_implements_base_interface(self, scraper_class): - scraper = scraper_class() - - assert isinstance(scraper, BaseScraper) - assert hasattr(scraper, "platform_name") - assert hasattr(scraper, "scrape_contest_metadata") - assert hasattr(scraper, "scrape_problem_tests") - assert hasattr(scraper, "scrape_contest_list") - - @pytest.mark.parametrize("scraper_class", SCRAPERS) - def test_platform_name_is_string(self, scraper_class): - scraper = scraper_class() - platform_name = scraper.platform_name - - assert isinstance(platform_name, str) - assert len(platform_name) > 0 - assert platform_name.islower() # Convention: lowercase platform names - - @pytest.mark.parametrize("scraper_class", SCRAPERS) - def test_metadata_method_signature(self, scraper_class, mocker): - scraper = scraper_class() - - # Mock the underlying HTTP calls to avoid network requests - if scraper.platform_name == "codeforces": - mock_scraper = Mock() - mock_response = Mock() - mock_response.text = "A. Test" - mock_scraper.get.return_value = mock_response - mocker.patch( - "scrapers.codeforces.cloudscraper.create_scraper", - return_value=mock_scraper, - ) - - result = scraper.scrape_contest_metadata("test_contest") - - assert isinstance(result, MetadataResult) - assert hasattr(result, "success") - assert hasattr(result, "error") - assert hasattr(result, "problems") - assert hasattr(result, "contest_id") - assert isinstance(result.success, bool) - assert isinstance(result.error, str) - - @pytest.mark.parametrize("scraper_class", SCRAPERS) - def test_problem_tests_method_signature(self, scraper_class, mocker): - scraper = scraper_class() - - if scraper.platform_name == "codeforces": - mock_scraper = Mock() - mock_response = Mock() - mock_response.text = """ -
3
6