From 8e2fffe5c295a380a59ca6537800bf4c6ac43429 Mon Sep 17 00:00:00 2001 From: Islem Maboud Date: Tue, 22 Jul 2025 19:52:28 +0100 Subject: [PATCH 1/2] feat: add wikipedia endpoints from the OpenAPI spec --- .openapi-generator/FILES | 19 +- .openapi-generator/VERSION | 2 +- README.md | 5 - examples/advanced.py | 3 +- examples/basic.py | 1 + perigon/__init__.py | 27 +- perigon/api/__init__.py | 1 + perigon/api/supplemental_endpoints_api.py | 873 ++++++++++++++++++ perigon/api/v1_api.py | 483 +++++++++- perigon/models/__init__.py | 26 +- .../models/articles_vector_search_result.py | 103 +++ perigon/models/auth_exception.py | 24 +- perigon/models/auth_exception_cause.py | 114 +++ .../auth_exception_cause_stack_trace_inner.py | 113 +++ .../models/auth_exception_suppressed_inner.py | 114 +++ perigon/models/illegal_parameter_exception.py | 24 +- perigon/models/internal_error_exception.py | 24 +- perigon/models/not_found_exception.py | 24 +- perigon/models/scored_data_article.py | 104 +++ perigon/models/scored_data_wiki_data.py | 104 +++ perigon/models/too_many_requests_exception.py | 24 +- perigon/models/wiki_data.py | 236 +++++ perigon/models/wiki_page.py | 285 ++++++ perigon/models/wiki_page_section_holder.py | 135 +++ perigon/models/wikipedia_search_filter.py | 277 ++++++ perigon/models/wikipedia_search_params.py | 179 ++++ perigon/models/wikipedia_search_result.py | 105 +++ .../models/wikipedia_vector_search_result.py | 103 +++ poetry.lock | 19 +- 29 files changed, 3433 insertions(+), 118 deletions(-) create mode 100644 perigon/api/supplemental_endpoints_api.py create mode 100644 perigon/models/articles_vector_search_result.py create mode 100644 perigon/models/auth_exception_cause.py create mode 100644 perigon/models/auth_exception_cause_stack_trace_inner.py create mode 100644 perigon/models/auth_exception_suppressed_inner.py create mode 100644 perigon/models/scored_data_article.py create mode 100644 perigon/models/scored_data_wiki_data.py create mode 100644 perigon/models/wiki_data.py create mode 100644 perigon/models/wiki_page.py create mode 100644 perigon/models/wiki_page_section_holder.py create mode 100644 perigon/models/wikipedia_search_filter.py create mode 100644 perigon/models/wikipedia_search_params.py create mode 100644 perigon/models/wikipedia_search_result.py create mode 100644 perigon/models/wikipedia_vector_search_result.py diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES index 8565d10..cc20fbc 100644 --- a/.openapi-generator/FILES +++ b/.openapi-generator/FILES @@ -2,6 +2,7 @@ README.md perigon/__init__.py perigon/api/__init__.py +perigon/api/supplemental_endpoints_api.py perigon/api/v1_api.py perigon/api_client.py perigon/api_response.py @@ -11,7 +12,11 @@ perigon/models/all_endpoint_sort_by.py perigon/models/article.py perigon/models/article_search_filter.py perigon/models/article_search_params.py +perigon/models/articles_vector_search_result.py perigon/models/auth_exception.py +perigon/models/auth_exception_cause.py +perigon/models/auth_exception_cause_stack_trace_inner.py +perigon/models/auth_exception_suppressed_inner.py perigon/models/category_holder.py perigon/models/category_with_score_holder.py perigon/models/company.py @@ -44,7 +49,8 @@ perigon/models/place.py perigon/models/query_search_result.py perigon/models/question.py perigon/models/record_stat_holder.py -perigon/models/scored_article.py +perigon/models/scored_data_article.py +perigon/models/scored_data_wiki_data.py perigon/models/sentiment_holder.py perigon/models/sort_by.py perigon/models/source.py @@ -57,18 +63,21 @@ perigon/models/summary_body.py perigon/models/summary_search_result.py perigon/models/symbol_holder.py perigon/models/too_many_requests_exception.py -perigon/models/too_many_requests_exception_cause.py -perigon/models/too_many_requests_exception_cause_stack_trace_inner.py -perigon/models/too_many_requests_exception_suppressed_inner.py perigon/models/topic_dto.py perigon/models/topic_holder.py perigon/models/topic_labels.py perigon/models/topic_search_result.py -perigon/models/vector_search_result.py perigon/models/web_resources.py +perigon/models/wiki_data.py +perigon/models/wiki_page.py +perigon/models/wiki_page_section_holder.py perigon/models/wikidata_date_holder.py perigon/models/wikidata_label_holder.py perigon/models/wikidata_political_party_holder.py perigon/models/wikidata_position_holder.py +perigon/models/wikipedia_search_filter.py +perigon/models/wikipedia_search_params.py +perigon/models/wikipedia_search_result.py +perigon/models/wikipedia_vector_search_result.py perigon/py.typed pyproject.toml diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION index eb1dc6a..e465da4 100644 --- a/.openapi-generator/VERSION +++ b/.openapi-generator/VERSION @@ -1 +1 @@ -7.13.0 +7.14.0 diff --git a/README.md b/README.md index bf61c6c..fb1174e 100644 --- a/README.md +++ b/README.md @@ -229,11 +229,6 @@ articles, journalist = asyncio.run(main()) --- -## Usage Examples -We have put together basic and advanced examples of accessing and using the Perigon API using the python SDK inside the **examples/** folder. - ---- - ## 🪪 License MIT Ā© Perigon \ No newline at end of file diff --git a/examples/advanced.py b/examples/advanced.py index 4af578a..f1ad711 100644 --- a/examples/advanced.py +++ b/examples/advanced.py @@ -15,9 +15,10 @@ 3. Run: python examples/advanced.py """ -import os import asyncio +import os from datetime import datetime, timedelta, timezone + from perigon import ApiClient, V1Api from perigon.models import ArticleSearchParams, SummaryBody diff --git a/examples/basic.py b/examples/basic.py index 973d5c8..2a5d1f1 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -12,6 +12,7 @@ """ import os + from perigon import ApiClient, V1Api diff --git a/perigon/__init__.py b/perigon/__init__.py index ca00b71..7d1f7f1 100644 --- a/perigon/__init__.py +++ b/perigon/__init__.py @@ -18,6 +18,7 @@ __version__ = "1.0.0" # import apis into sdk package +from perigon.api.supplemental_endpoints_api import SupplementalEndpointsApi from perigon.api.v1_api import V1Api from perigon.api_client import ApiClient @@ -37,7 +38,13 @@ from perigon.models.article import Article from perigon.models.article_search_filter import ArticleSearchFilter from perigon.models.article_search_params import ArticleSearchParams +from perigon.models.articles_vector_search_result import ArticlesVectorSearchResult from perigon.models.auth_exception import AuthException +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, +) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner from perigon.models.category_holder import CategoryHolder from perigon.models.category_with_score_holder import CategoryWithScoreHolder from perigon.models.company import Company @@ -70,7 +77,8 @@ from perigon.models.query_search_result import QuerySearchResult from perigon.models.question import Question from perigon.models.record_stat_holder import RecordStatHolder -from perigon.models.scored_article import ScoredArticle +from perigon.models.scored_data_article import ScoredDataArticle +from perigon.models.scored_data_wiki_data import ScoredDataWikiData from perigon.models.sentiment_holder import SentimentHolder from perigon.models.sort_by import SortBy from perigon.models.source import Source @@ -83,22 +91,19 @@ from perigon.models.summary_search_result import SummarySearchResult from perigon.models.symbol_holder import SymbolHolder from perigon.models.too_many_requests_exception import TooManyRequestsException -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, -) from perigon.models.topic_dto import TopicDto from perigon.models.topic_holder import TopicHolder from perigon.models.topic_labels import TopicLabels from perigon.models.topic_search_result import TopicSearchResult -from perigon.models.vector_search_result import VectorSearchResult from perigon.models.web_resources import WebResources +from perigon.models.wiki_data import WikiData +from perigon.models.wiki_page import WikiPage +from perigon.models.wiki_page_section_holder import WikiPageSectionHolder from perigon.models.wikidata_date_holder import WikidataDateHolder from perigon.models.wikidata_label_holder import WikidataLabelHolder from perigon.models.wikidata_political_party_holder import WikidataPoliticalPartyHolder from perigon.models.wikidata_position_holder import WikidataPositionHolder +from perigon.models.wikipedia_search_filter import WikipediaSearchFilter +from perigon.models.wikipedia_search_params import WikipediaSearchParams +from perigon.models.wikipedia_search_result import WikipediaSearchResult +from perigon.models.wikipedia_vector_search_result import WikipediaVectorSearchResult diff --git a/perigon/api/__init__.py b/perigon/api/__init__.py index ff6d0ad..358b5a3 100644 --- a/perigon/api/__init__.py +++ b/perigon/api/__init__.py @@ -1,4 +1,5 @@ # flake8: noqa # import apis into api package +from perigon.api.supplemental_endpoints_api import SupplementalEndpointsApi from perigon.api.v1_api import V1Api diff --git a/perigon/api/supplemental_endpoints_api.py b/perigon/api/supplemental_endpoints_api.py new file mode 100644 index 0000000..9ea085f --- /dev/null +++ b/perigon/api/supplemental_endpoints_api.py @@ -0,0 +1,873 @@ +from datetime import datetime +from enum import Enum +from typing import Any, Dict, Iterable, List, Mapping, Optional, Union + +from pydantic import Field, StrictBool, StrictInt, StrictStr +from typing_extensions import Annotated + +from perigon.api_client import ApiClient +from perigon.models.company_search_result import CompanySearchResult +from perigon.models.journalist import Journalist +from perigon.models.journalist_search_result import JournalistSearchResult +from perigon.models.people_search_result import PeopleSearchResult +from perigon.models.sort_by import SortBy +from perigon.models.source_search_result import SourceSearchResult +from perigon.models.topic_search_result import TopicSearchResult + +# Define API paths +PATH_GET_JOURNALIST_BY_ID = "/v1/journalists/{id}" +PATH_SEARCH_COMPANIES = "/v1/companies/all" +PATH_SEARCH_JOURNALISTS = "/v1/journalists/all" +PATH_SEARCH_PEOPLE = "/v1/people/all" +PATH_SEARCH_SOURCES = "/v1/sources/all" +PATH_SEARCH_TOPICS = "/v1/topics/all" + + +def _normalise_query(params: Mapping[str, Any]) -> Dict[str, Any]: + """ + • Convert Enum → Enum.value + • Convert list/tuple/set → CSV string (after Enum handling) + • Skip None values + """ + out: Dict[str, Any] = {} + for key, value in params.items(): + if value is None: # ignore "unset" + continue + + # Unwrap single Enum + if isinstance(value, Enum): # Enum → str + value = value.value + + # Handle datetime objects properly + from datetime import datetime + + if isinstance(value, datetime): + value = value.isoformat().split("+")[0] + + # Handle collection (after possible Enum unwrap) + elif isinstance(value, (list, tuple, set)): + # unwrap Enum members inside the collection + items: Iterable[str] = ( + ( + item.isoformat().replace(" ", "+") + if isinstance(item, datetime) + else str(item.value if isinstance(item, Enum) else item) + ) + for item in value + ) + value = ",".join(items) # CSV join + else: + value = str(value) + + out[key] = value + + return out + + +class SupplementalEndpointsApi: + """""" + + def __init__(self, api_client: Optional[ApiClient] = None): + self.api_client = api_client or ApiClient() + + # ----------------- get_journalist_by_id (sync) ----------------- # + def get_journalist_by_id(self, id: str) -> Journalist: + """ + Find additional details on a journalist by using the journalist ID found in an article response object. + + Args: + id (str): Parameter id (required) + + Returns: + Journalist: The response + """ + # Get path template from class attribute + path = PATH_GET_JOURNALIST_BY_ID + + # Replace path parameters + path = path.format(id=str(id)) + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return Journalist.model_validate(resp.json()) + + # ----------------- get_journalist_by_id (async) ----------------- # + async def get_journalist_by_id_async(self, id: str) -> Journalist: + """ + Async variant of get_journalist_by_id. Find additional details on a journalist by using the journalist ID found in an article response object. + + Args: + id (str): Parameter id (required) + + Returns: + Journalist: The response + """ + # Get path template from class attribute + path = PATH_GET_JOURNALIST_BY_ID + + # Replace path parameters + path = path.format(id=str(id)) + + params: Dict[str, Any] = {} + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return Journalist.model_validate(resp.json()) + + # ----------------- search_companies (sync) ----------------- # + def search_companies( + self, + id: Optional[List[str]] = None, + symbol: Optional[List[str]] = None, + domain: Optional[List[str]] = None, + country: Optional[List[str]] = None, + exchange: Optional[List[str]] = None, + num_employees_from: Optional[int] = None, + num_employees_to: Optional[int] = None, + ipo_from: Optional[datetime] = None, + ipo_to: Optional[datetime] = None, + q: Optional[str] = None, + name: Optional[str] = None, + industry: Optional[str] = None, + sector: Optional[str] = None, + size: Optional[int] = None, + page: Optional[int] = None, + ) -> CompanySearchResult: + """ + Browse or search for companies Perigon tracks using name, domain, ticker symbol, industry, and more. Supports Boolean search logic and filtering by metadata such as country, exchange, employee count, and IPO date. + + Args: + id (Optional[List[str]]): Filter by unique company identifiers. Multiple values create an OR filter. + symbol (Optional[List[str]]): Filter by company stock ticker symbols (e.g., AAPL, MSFT, GOOGL). Multiple values create an OR filter. + domain (Optional[List[str]]): Filter by company domains or websites (e.g., apple.com, microsoft.com). Multiple values create an OR filter. + country (Optional[List[str]]): Filter by company headquarters country. Multiple values create an OR filter. + exchange (Optional[List[str]]): Filter by stock exchange where companies are listed (e.g., NASDAQ, NYSE). Multiple values create an OR filter. + num_employees_from (Optional[int]): Filter for companies with at least this many employees. + num_employees_to (Optional[int]): Filter for companies with no more than this many employees. + ipo_from (Optional[datetime]): Filter for companies that went public on or after this date. Accepts ISO 8601 format (e.g., 2023-01-01T00:00:00) or yyyy-mm-dd format. + ipo_to (Optional[datetime]): Filter for companies that went public on or before this date. Accepts ISO 8601 format (e.g., 2023-12-31T23:59:59) or yyyy-mm-dd format. + q (Optional[str]): Primary search query for filtering companies across name, alternative names, domains, and ticker symbols. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + name (Optional[str]): Search within company names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + industry (Optional[str]): Filter by company industry classifications. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + sector (Optional[str]): Filter by company sector classifications. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + size (Optional[int]): The number of companies to return per page in the paginated response. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + + Returns: + CompanySearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_COMPANIES + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if id is not None: + params["id"] = id + if symbol is not None: + params["symbol"] = symbol + if domain is not None: + params["domain"] = domain + if country is not None: + params["country"] = country + if exchange is not None: + params["exchange"] = exchange + if num_employees_from is not None: + params["numEmployeesFrom"] = num_employees_from + if num_employees_to is not None: + params["numEmployeesTo"] = num_employees_to + if ipo_from is not None: + params["ipoFrom"] = ipo_from + if ipo_to is not None: + params["ipoTo"] = ipo_to + if q is not None: + params["q"] = q + if name is not None: + params["name"] = name + if industry is not None: + params["industry"] = industry + if sector is not None: + params["sector"] = sector + if size is not None: + params["size"] = size + if page is not None: + params["page"] = page + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return CompanySearchResult.model_validate(resp.json()) + + # ----------------- search_companies (async) ----------------- # + async def search_companies_async( + self, + id: Optional[List[str]] = None, + symbol: Optional[List[str]] = None, + domain: Optional[List[str]] = None, + country: Optional[List[str]] = None, + exchange: Optional[List[str]] = None, + num_employees_from: Optional[int] = None, + num_employees_to: Optional[int] = None, + ipo_from: Optional[datetime] = None, + ipo_to: Optional[datetime] = None, + q: Optional[str] = None, + name: Optional[str] = None, + industry: Optional[str] = None, + sector: Optional[str] = None, + size: Optional[int] = None, + page: Optional[int] = None, + ) -> CompanySearchResult: + """ + Async variant of search_companies. Browse or search for companies Perigon tracks using name, domain, ticker symbol, industry, and more. Supports Boolean search logic and filtering by metadata such as country, exchange, employee count, and IPO date. + + Args: + id (Optional[List[str]]): Filter by unique company identifiers. Multiple values create an OR filter. + symbol (Optional[List[str]]): Filter by company stock ticker symbols (e.g., AAPL, MSFT, GOOGL). Multiple values create an OR filter. + domain (Optional[List[str]]): Filter by company domains or websites (e.g., apple.com, microsoft.com). Multiple values create an OR filter. + country (Optional[List[str]]): Filter by company headquarters country. Multiple values create an OR filter. + exchange (Optional[List[str]]): Filter by stock exchange where companies are listed (e.g., NASDAQ, NYSE). Multiple values create an OR filter. + num_employees_from (Optional[int]): Filter for companies with at least this many employees. + num_employees_to (Optional[int]): Filter for companies with no more than this many employees. + ipo_from (Optional[datetime]): Filter for companies that went public on or after this date. Accepts ISO 8601 format (e.g., 2023-01-01T00:00:00) or yyyy-mm-dd format. + ipo_to (Optional[datetime]): Filter for companies that went public on or before this date. Accepts ISO 8601 format (e.g., 2023-12-31T23:59:59) or yyyy-mm-dd format. + q (Optional[str]): Primary search query for filtering companies across name, alternative names, domains, and ticker symbols. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + name (Optional[str]): Search within company names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + industry (Optional[str]): Filter by company industry classifications. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + sector (Optional[str]): Filter by company sector classifications. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + size (Optional[int]): The number of companies to return per page in the paginated response. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + + Returns: + CompanySearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_COMPANIES + + params: Dict[str, Any] = {} + if id is not None: + params["id"] = id + if symbol is not None: + params["symbol"] = symbol + if domain is not None: + params["domain"] = domain + if country is not None: + params["country"] = country + if exchange is not None: + params["exchange"] = exchange + if num_employees_from is not None: + params["numEmployeesFrom"] = num_employees_from + if num_employees_to is not None: + params["numEmployeesTo"] = num_employees_to + if ipo_from is not None: + params["ipoFrom"] = ipo_from + if ipo_to is not None: + params["ipoTo"] = ipo_to + if q is not None: + params["q"] = q + if name is not None: + params["name"] = name + if industry is not None: + params["industry"] = industry + if sector is not None: + params["sector"] = sector + if size is not None: + params["size"] = size + if page is not None: + params["page"] = page + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return CompanySearchResult.model_validate(resp.json()) + + # ----------------- search_journalists (sync) ----------------- # + def search_journalists( + self, + id: Optional[List[str]] = None, + q: Optional[str] = None, + name: Optional[str] = None, + twitter: Optional[str] = None, + size: Optional[int] = None, + page: Optional[int] = None, + source: Optional[List[str]] = None, + topic: Optional[List[str]] = None, + category: Optional[List[str]] = None, + label: Optional[List[str]] = None, + min_monthly_posts: Optional[int] = None, + max_monthly_posts: Optional[int] = None, + country: Optional[List[str]] = None, + updated_at_from: Optional[datetime] = None, + updated_at_to: Optional[datetime] = None, + show_num_results: Optional[bool] = None, + ) -> JournalistSearchResult: + """ + Search journalists using broad search attributes. Our database contains over 230,000 journalists from around the world and is refreshed frequently. + + Args: + id (Optional[List[str]]): Filter by unique journalist identifiers. Multiple values create an OR filter to find journalists matching any of the specified IDs. + q (Optional[str]): Primary search query for filtering journalists based on their name, title, and Twitter bio. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + name (Optional[str]): Search specifically within journalist names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + twitter (Optional[str]): Filter journalists by their exact Twitter handle, without the @ symbol. + size (Optional[int]): The number of journalists to return per page in the paginated response. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + source (Optional[List[str]]): Filter journalists by the publisher domains they write for. Supports wildcards (* and ?) for pattern matching (e.g., *.cnn.com). Multiple values create an OR filter. + topic (Optional[List[str]]): Filter journalists by the topics they frequently cover. Multiple values create an OR filter to find journalists covering any of the specified topics. + category (Optional[List[str]]): Filter journalists by the content categories they typically write about (e.g., Politics, Tech, Sports, Business). Multiple values create an OR filter. + label (Optional[List[str]]): Filter journalists by the type of content they typically produce (e.g., Opinion, Paid-news, Non-news). Multiple values create an OR filter. + min_monthly_posts (Optional[int]): Filter for journalists who publish at least this many articles per month. Used to identify more active journalists. + max_monthly_posts (Optional[int]): Filter for journalists who publish no more than this many articles per month. + country (Optional[List[str]]): Filter journalists by countries they commonly cover in their reporting. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). Multiple values create an OR filter. + updated_at_from (Optional[datetime]): Filter for journalist profiles updated on or after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + updated_at_to (Optional[datetime]): Filter for journalist profiles updated on or before this date. Accepts ISO 8601 format (e.g., 2023-03-01T23:59:59) or yyyy-mm-dd format. + show_num_results (Optional[bool]): Controls whether to return the exact result count. When false (default), counts are capped at 10,000 for performance reasons. Set to true for precise counts in smaller result sets. + + Returns: + JournalistSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_JOURNALISTS + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if id is not None: + params["id"] = id + if q is not None: + params["q"] = q + if name is not None: + params["name"] = name + if twitter is not None: + params["twitter"] = twitter + if size is not None: + params["size"] = size + if page is not None: + params["page"] = page + if source is not None: + params["source"] = source + if topic is not None: + params["topic"] = topic + if category is not None: + params["category"] = category + if label is not None: + params["label"] = label + if min_monthly_posts is not None: + params["minMonthlyPosts"] = min_monthly_posts + if max_monthly_posts is not None: + params["maxMonthlyPosts"] = max_monthly_posts + if country is not None: + params["country"] = country + if updated_at_from is not None: + params["updatedAtFrom"] = updated_at_from + if updated_at_to is not None: + params["updatedAtTo"] = updated_at_to + if show_num_results is not None: + params["showNumResults"] = show_num_results + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return JournalistSearchResult.model_validate(resp.json()) + + # ----------------- search_journalists (async) ----------------- # + async def search_journalists_async( + self, + id: Optional[List[str]] = None, + q: Optional[str] = None, + name: Optional[str] = None, + twitter: Optional[str] = None, + size: Optional[int] = None, + page: Optional[int] = None, + source: Optional[List[str]] = None, + topic: Optional[List[str]] = None, + category: Optional[List[str]] = None, + label: Optional[List[str]] = None, + min_monthly_posts: Optional[int] = None, + max_monthly_posts: Optional[int] = None, + country: Optional[List[str]] = None, + updated_at_from: Optional[datetime] = None, + updated_at_to: Optional[datetime] = None, + show_num_results: Optional[bool] = None, + ) -> JournalistSearchResult: + """ + Async variant of search_journalists. Search journalists using broad search attributes. Our database contains over 230,000 journalists from around the world and is refreshed frequently. + + Args: + id (Optional[List[str]]): Filter by unique journalist identifiers. Multiple values create an OR filter to find journalists matching any of the specified IDs. + q (Optional[str]): Primary search query for filtering journalists based on their name, title, and Twitter bio. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + name (Optional[str]): Search specifically within journalist names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + twitter (Optional[str]): Filter journalists by their exact Twitter handle, without the @ symbol. + size (Optional[int]): The number of journalists to return per page in the paginated response. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + source (Optional[List[str]]): Filter journalists by the publisher domains they write for. Supports wildcards (* and ?) for pattern matching (e.g., *.cnn.com). Multiple values create an OR filter. + topic (Optional[List[str]]): Filter journalists by the topics they frequently cover. Multiple values create an OR filter to find journalists covering any of the specified topics. + category (Optional[List[str]]): Filter journalists by the content categories they typically write about (e.g., Politics, Tech, Sports, Business). Multiple values create an OR filter. + label (Optional[List[str]]): Filter journalists by the type of content they typically produce (e.g., Opinion, Paid-news, Non-news). Multiple values create an OR filter. + min_monthly_posts (Optional[int]): Filter for journalists who publish at least this many articles per month. Used to identify more active journalists. + max_monthly_posts (Optional[int]): Filter for journalists who publish no more than this many articles per month. + country (Optional[List[str]]): Filter journalists by countries they commonly cover in their reporting. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). Multiple values create an OR filter. + updated_at_from (Optional[datetime]): Filter for journalist profiles updated on or after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + updated_at_to (Optional[datetime]): Filter for journalist profiles updated on or before this date. Accepts ISO 8601 format (e.g., 2023-03-01T23:59:59) or yyyy-mm-dd format. + show_num_results (Optional[bool]): Controls whether to return the exact result count. When false (default), counts are capped at 10,000 for performance reasons. Set to true for precise counts in smaller result sets. + + Returns: + JournalistSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_JOURNALISTS + + params: Dict[str, Any] = {} + if id is not None: + params["id"] = id + if q is not None: + params["q"] = q + if name is not None: + params["name"] = name + if twitter is not None: + params["twitter"] = twitter + if size is not None: + params["size"] = size + if page is not None: + params["page"] = page + if source is not None: + params["source"] = source + if topic is not None: + params["topic"] = topic + if category is not None: + params["category"] = category + if label is not None: + params["label"] = label + if min_monthly_posts is not None: + params["minMonthlyPosts"] = min_monthly_posts + if max_monthly_posts is not None: + params["maxMonthlyPosts"] = max_monthly_posts + if country is not None: + params["country"] = country + if updated_at_from is not None: + params["updatedAtFrom"] = updated_at_from + if updated_at_to is not None: + params["updatedAtTo"] = updated_at_to + if show_num_results is not None: + params["showNumResults"] = show_num_results + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return JournalistSearchResult.model_validate(resp.json()) + + # ----------------- search_people (sync) ----------------- # + def search_people( + self, + name: Optional[str] = None, + wikidata_id: Optional[List[str]] = None, + occupation_id: Optional[List[str]] = None, + occupation_label: Optional[str] = None, + page: Optional[int] = None, + size: Optional[int] = None, + ) -> PeopleSearchResult: + """ + Search and retrieve additional information on known persons that exist within Perigon's entity database and as referenced in any article response object. Our database contains over 650,000 people from around the world and is refreshed frequently. People data is derived from Wikidata and includes a wikidataId field that can be used to lookup even more information on Wikidata's website. + + Args: + name (Optional[str]): Search by person's name. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + wikidata_id (Optional[List[str]]): Filter by Wikidata entity IDs (e.g., Q7747, Q937). These are unique identifiers from Wikidata.org that precisely identify public figures and eliminate name ambiguity. Multiple values create an OR filter. + occupation_id (Optional[List[str]]): Filter by Wikidata occupation IDs (e.g., Q82955 for politician, Q33999 for actor, Q19546 for businessman). Finds people with specific professions. Multiple values create an OR filter. + occupation_label (Optional[str]): Search by occupation name (e.g., politician, actor, CEO, athlete). Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of people to return per page in the paginated response. + + Returns: + PeopleSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_PEOPLE + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if name is not None: + params["name"] = name + if wikidata_id is not None: + params["wikidataId"] = wikidata_id + if occupation_id is not None: + params["occupationId"] = occupation_id + if occupation_label is not None: + params["occupationLabel"] = occupation_label + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return PeopleSearchResult.model_validate(resp.json()) + + # ----------------- search_people (async) ----------------- # + async def search_people_async( + self, + name: Optional[str] = None, + wikidata_id: Optional[List[str]] = None, + occupation_id: Optional[List[str]] = None, + occupation_label: Optional[str] = None, + page: Optional[int] = None, + size: Optional[int] = None, + ) -> PeopleSearchResult: + """ + Async variant of search_people. Search and retrieve additional information on known persons that exist within Perigon's entity database and as referenced in any article response object. Our database contains over 650,000 people from around the world and is refreshed frequently. People data is derived from Wikidata and includes a wikidataId field that can be used to lookup even more information on Wikidata's website. + + Args: + name (Optional[str]): Search by person's name. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + wikidata_id (Optional[List[str]]): Filter by Wikidata entity IDs (e.g., Q7747, Q937). These are unique identifiers from Wikidata.org that precisely identify public figures and eliminate name ambiguity. Multiple values create an OR filter. + occupation_id (Optional[List[str]]): Filter by Wikidata occupation IDs (e.g., Q82955 for politician, Q33999 for actor, Q19546 for businessman). Finds people with specific professions. Multiple values create an OR filter. + occupation_label (Optional[str]): Search by occupation name (e.g., politician, actor, CEO, athlete). Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of people to return per page in the paginated response. + + Returns: + PeopleSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_PEOPLE + + params: Dict[str, Any] = {} + if name is not None: + params["name"] = name + if wikidata_id is not None: + params["wikidataId"] = wikidata_id + if occupation_id is not None: + params["occupationId"] = occupation_id + if occupation_label is not None: + params["occupationLabel"] = occupation_label + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return PeopleSearchResult.model_validate(resp.json()) + + # ----------------- search_sources (sync) ----------------- # + def search_sources( + self, + domain: Optional[List[str]] = None, + name: Optional[str] = None, + source_group: Optional[str] = None, + sort_by: Optional[SortBy] = None, + page: Optional[int] = None, + size: Optional[int] = None, + min_monthly_visits: Optional[int] = None, + max_monthly_visits: Optional[int] = None, + min_monthly_posts: Optional[int] = None, + max_monthly_posts: Optional[int] = None, + country: Optional[List[str]] = None, + source_country: Optional[List[str]] = None, + source_state: Optional[List[str]] = None, + source_county: Optional[List[str]] = None, + source_city: Optional[List[str]] = None, + source_lat: Optional[float] = None, + source_lon: Optional[float] = None, + source_max_distance: Optional[float] = None, + category: Optional[List[str]] = None, + topic: Optional[List[str]] = None, + label: Optional[List[str]] = None, + paywall: Optional[bool] = None, + show_subdomains: Optional[bool] = None, + show_num_results: Optional[bool] = None, + ) -> SourceSearchResult: + """ + Search and filter the 142,000+ media sources available via the Perigon API. The result includes a list of individual media sources that were matched to your specific criteria. + + Args: + domain (Optional[List[str]]): Filter by specific publisher domains or subdomains. Supports wildcards (* and ?) for pattern matching (e.g., *.cnn.com, us?.nytimes.com). Multiple values create an OR filter. + name (Optional[str]): Search by source name or alternative names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + source_group (Optional[str]): Filter by predefined publisher bundles (e.g., top100, top50tech). Returns all sources within the specified group. See documentation for available source groups. + sort_by (Optional[SortBy]): Determines the source sorting order. Options include relevance (default, best match to query), globalRank (by overall traffic and popularity), monthlyVisits (by total monthly visitor count), and avgMonthlyPosts (by number of articles published monthly). + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of sources to return per page in the paginated response. + min_monthly_visits (Optional[int]): Filter for sources with at least this many monthly visitors. Used to target publishers by audience size. + max_monthly_visits (Optional[int]): Filter for sources with no more than this many monthly visitors. Used to target publishers by audience size. + min_monthly_posts (Optional[int]): Filter for sources that publish at least this many articles per month. Used to target publishers by content volume. + max_monthly_posts (Optional[int]): Filter for sources that publish no more than this many articles per month. Used to target publishers by content volume. + country (Optional[List[str]]): Filter sources by countries they commonly cover in their reporting. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). See documentation for supported country codes. Multiple values create an OR filter. + source_country (Optional[List[str]]): Filter for local publications based in specific countries. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). See documentation for supported country codes. Multiple values create an OR filter. + source_state (Optional[List[str]]): Filter for local publications based in specific states or regions. Uses standard two-letter state codes in lowercase (e.g., ca, ny, tx). See documentation for supported state codes. Multiple values create an OR filter. + source_county (Optional[List[str]]): Filter for local publications based in specific counties. Multiple values create an OR filter. + source_city (Optional[List[str]]): Filter for local publications based in specific cities. Multiple values create an OR filter. + source_lat (Optional[float]): Latitude coordinate for filtering local publications by geographic proximity. Used with sourceLon and sourceMaxDistance for radius search. + source_lon (Optional[float]): Longitude coordinate for filtering local publications by geographic proximity. Used with sourceLat and sourceMaxDistance for radius search. + source_max_distance (Optional[float]): Maximum distance in kilometers from the coordinates defined by sourceLat and sourceLon. Defines the radius for local publication searches. + category (Optional[List[str]]): Filter sources by their primary content categories such as Politics, Tech, Sports, Business, or Finance. Returns sources that frequently cover these topics. Multiple values create an OR filter. + topic (Optional[List[str]]): Filter sources by their frequently covered topics (e.g., Markets, Cryptocurrency, Climate Change). Returns sources where the specified topic is among their top 10 covered areas. Multiple values create an OR filter. + label (Optional[List[str]]): Filter sources by their content label patterns (e.g., Opinion, Paid-news, Non-news). Returns sources where the specified label is common in their published content. See documentation for all available labels. Multiple values create an OR filter. + paywall (Optional[bool]): Filter by paywall status. Set to true to find sources with paywalls, or false to find sources without paywalls. + show_subdomains (Optional[bool]): Controls whether subdomains are included as separate results. When true (default), subdomains appear as distinct sources. When false, results are consolidated to parent domains only. + show_num_results (Optional[bool]): Controls whether to return the exact result count. When false (default), counts are capped at 10,000 for performance reasons. Set to true for precise counts in smaller result sets. + + Returns: + SourceSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_SOURCES + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if domain is not None: + params["domain"] = domain + if name is not None: + params["name"] = name + if source_group is not None: + params["sourceGroup"] = source_group + if sort_by is not None: + params["sortBy"] = sort_by + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + if min_monthly_visits is not None: + params["minMonthlyVisits"] = min_monthly_visits + if max_monthly_visits is not None: + params["maxMonthlyVisits"] = max_monthly_visits + if min_monthly_posts is not None: + params["minMonthlyPosts"] = min_monthly_posts + if max_monthly_posts is not None: + params["maxMonthlyPosts"] = max_monthly_posts + if country is not None: + params["country"] = country + if source_country is not None: + params["sourceCountry"] = source_country + if source_state is not None: + params["sourceState"] = source_state + if source_county is not None: + params["sourceCounty"] = source_county + if source_city is not None: + params["sourceCity"] = source_city + if source_lat is not None: + params["sourceLat"] = source_lat + if source_lon is not None: + params["sourceLon"] = source_lon + if source_max_distance is not None: + params["sourceMaxDistance"] = source_max_distance + if category is not None: + params["category"] = category + if topic is not None: + params["topic"] = topic + if label is not None: + params["label"] = label + if paywall is not None: + params["paywall"] = paywall + if show_subdomains is not None: + params["showSubdomains"] = show_subdomains + if show_num_results is not None: + params["showNumResults"] = show_num_results + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return SourceSearchResult.model_validate(resp.json()) + + # ----------------- search_sources (async) ----------------- # + async def search_sources_async( + self, + domain: Optional[List[str]] = None, + name: Optional[str] = None, + source_group: Optional[str] = None, + sort_by: Optional[SortBy] = None, + page: Optional[int] = None, + size: Optional[int] = None, + min_monthly_visits: Optional[int] = None, + max_monthly_visits: Optional[int] = None, + min_monthly_posts: Optional[int] = None, + max_monthly_posts: Optional[int] = None, + country: Optional[List[str]] = None, + source_country: Optional[List[str]] = None, + source_state: Optional[List[str]] = None, + source_county: Optional[List[str]] = None, + source_city: Optional[List[str]] = None, + source_lat: Optional[float] = None, + source_lon: Optional[float] = None, + source_max_distance: Optional[float] = None, + category: Optional[List[str]] = None, + topic: Optional[List[str]] = None, + label: Optional[List[str]] = None, + paywall: Optional[bool] = None, + show_subdomains: Optional[bool] = None, + show_num_results: Optional[bool] = None, + ) -> SourceSearchResult: + """ + Async variant of search_sources. Search and filter the 142,000+ media sources available via the Perigon API. The result includes a list of individual media sources that were matched to your specific criteria. + + Args: + domain (Optional[List[str]]): Filter by specific publisher domains or subdomains. Supports wildcards (* and ?) for pattern matching (e.g., *.cnn.com, us?.nytimes.com). Multiple values create an OR filter. + name (Optional[str]): Search by source name or alternative names. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + source_group (Optional[str]): Filter by predefined publisher bundles (e.g., top100, top50tech). Returns all sources within the specified group. See documentation for available source groups. + sort_by (Optional[SortBy]): Determines the source sorting order. Options include relevance (default, best match to query), globalRank (by overall traffic and popularity), monthlyVisits (by total monthly visitor count), and avgMonthlyPosts (by number of articles published monthly). + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of sources to return per page in the paginated response. + min_monthly_visits (Optional[int]): Filter for sources with at least this many monthly visitors. Used to target publishers by audience size. + max_monthly_visits (Optional[int]): Filter for sources with no more than this many monthly visitors. Used to target publishers by audience size. + min_monthly_posts (Optional[int]): Filter for sources that publish at least this many articles per month. Used to target publishers by content volume. + max_monthly_posts (Optional[int]): Filter for sources that publish no more than this many articles per month. Used to target publishers by content volume. + country (Optional[List[str]]): Filter sources by countries they commonly cover in their reporting. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). See documentation for supported country codes. Multiple values create an OR filter. + source_country (Optional[List[str]]): Filter for local publications based in specific countries. Uses ISO 3166-1 alpha-2 two-letter country codes in lowercase (e.g., us, gb, jp). See documentation for supported country codes. Multiple values create an OR filter. + source_state (Optional[List[str]]): Filter for local publications based in specific states or regions. Uses standard two-letter state codes in lowercase (e.g., ca, ny, tx). See documentation for supported state codes. Multiple values create an OR filter. + source_county (Optional[List[str]]): Filter for local publications based in specific counties. Multiple values create an OR filter. + source_city (Optional[List[str]]): Filter for local publications based in specific cities. Multiple values create an OR filter. + source_lat (Optional[float]): Latitude coordinate for filtering local publications by geographic proximity. Used with sourceLon and sourceMaxDistance for radius search. + source_lon (Optional[float]): Longitude coordinate for filtering local publications by geographic proximity. Used with sourceLat and sourceMaxDistance for radius search. + source_max_distance (Optional[float]): Maximum distance in kilometers from the coordinates defined by sourceLat and sourceLon. Defines the radius for local publication searches. + category (Optional[List[str]]): Filter sources by their primary content categories such as Politics, Tech, Sports, Business, or Finance. Returns sources that frequently cover these topics. Multiple values create an OR filter. + topic (Optional[List[str]]): Filter sources by their frequently covered topics (e.g., Markets, Cryptocurrency, Climate Change). Returns sources where the specified topic is among their top 10 covered areas. Multiple values create an OR filter. + label (Optional[List[str]]): Filter sources by their content label patterns (e.g., Opinion, Paid-news, Non-news). Returns sources where the specified label is common in their published content. See documentation for all available labels. Multiple values create an OR filter. + paywall (Optional[bool]): Filter by paywall status. Set to true to find sources with paywalls, or false to find sources without paywalls. + show_subdomains (Optional[bool]): Controls whether subdomains are included as separate results. When true (default), subdomains appear as distinct sources. When false, results are consolidated to parent domains only. + show_num_results (Optional[bool]): Controls whether to return the exact result count. When false (default), counts are capped at 10,000 for performance reasons. Set to true for precise counts in smaller result sets. + + Returns: + SourceSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_SOURCES + + params: Dict[str, Any] = {} + if domain is not None: + params["domain"] = domain + if name is not None: + params["name"] = name + if source_group is not None: + params["sourceGroup"] = source_group + if sort_by is not None: + params["sortBy"] = sort_by + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + if min_monthly_visits is not None: + params["minMonthlyVisits"] = min_monthly_visits + if max_monthly_visits is not None: + params["maxMonthlyVisits"] = max_monthly_visits + if min_monthly_posts is not None: + params["minMonthlyPosts"] = min_monthly_posts + if max_monthly_posts is not None: + params["maxMonthlyPosts"] = max_monthly_posts + if country is not None: + params["country"] = country + if source_country is not None: + params["sourceCountry"] = source_country + if source_state is not None: + params["sourceState"] = source_state + if source_county is not None: + params["sourceCounty"] = source_county + if source_city is not None: + params["sourceCity"] = source_city + if source_lat is not None: + params["sourceLat"] = source_lat + if source_lon is not None: + params["sourceLon"] = source_lon + if source_max_distance is not None: + params["sourceMaxDistance"] = source_max_distance + if category is not None: + params["category"] = category + if topic is not None: + params["topic"] = topic + if label is not None: + params["label"] = label + if paywall is not None: + params["paywall"] = paywall + if show_subdomains is not None: + params["showSubdomains"] = show_subdomains + if show_num_results is not None: + params["showNumResults"] = show_num_results + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return SourceSearchResult.model_validate(resp.json()) + + # ----------------- search_topics (sync) ----------------- # + def search_topics( + self, + name: Optional[str] = None, + category: Optional[str] = None, + subcategory: Optional[str] = None, + page: Optional[int] = None, + size: Optional[int] = None, + ) -> TopicSearchResult: + """ + Search through all available Topics that exist within the Perigon Database. + + Args: + name (Optional[str]): Search for topics by exact name or partial text match. Does not support wildcards. Examples include Markets, Cryptocurrency, Climate Change, etc. + category (Optional[str]): Filter topics by broad article categories such as Politics, Tech, Sports, Business, Finance, Entertainment, etc. + subcategory (Optional[str]): Filter topics by their specific subcategory. Subcategories provide more granular classification beyond the main category, such as TV or Event. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of topics to return per page in the paginated response. + + Returns: + TopicSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_TOPICS + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if name is not None: + params["name"] = name + if category is not None: + params["category"] = category + if subcategory is not None: + params["subcategory"] = subcategory + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return TopicSearchResult.model_validate(resp.json()) + + # ----------------- search_topics (async) ----------------- # + async def search_topics_async( + self, + name: Optional[str] = None, + category: Optional[str] = None, + subcategory: Optional[str] = None, + page: Optional[int] = None, + size: Optional[int] = None, + ) -> TopicSearchResult: + """ + Async variant of search_topics. Search through all available Topics that exist within the Perigon Database. + + Args: + name (Optional[str]): Search for topics by exact name or partial text match. Does not support wildcards. Examples include Markets, Cryptocurrency, Climate Change, etc. + category (Optional[str]): Filter topics by broad article categories such as Politics, Tech, Sports, Business, Finance, Entertainment, etc. + subcategory (Optional[str]): Filter topics by their specific subcategory. Subcategories provide more granular classification beyond the main category, such as TV or Event. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of topics to return per page in the paginated response. + + Returns: + TopicSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_TOPICS + + params: Dict[str, Any] = {} + if name is not None: + params["name"] = name + if category is not None: + params["category"] = category + if subcategory is not None: + params["subcategory"] = subcategory + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return TopicSearchResult.model_validate(resp.json()) diff --git a/perigon/api/v1_api.py b/perigon/api/v1_api.py index 2b3160e..905ea99 100644 --- a/perigon/api/v1_api.py +++ b/perigon/api/v1_api.py @@ -8,6 +8,7 @@ from perigon.api_client import ApiClient from perigon.models.all_endpoint_sort_by import AllEndpointSortBy from perigon.models.article_search_params import ArticleSearchParams +from perigon.models.articles_vector_search_result import ArticlesVectorSearchResult from perigon.models.company_search_result import CompanySearchResult from perigon.models.journalist import Journalist from perigon.models.journalist_search_result import JournalistSearchResult @@ -19,11 +20,13 @@ from perigon.models.summary_body import SummaryBody from perigon.models.summary_search_result import SummarySearchResult from perigon.models.topic_search_result import TopicSearchResult -from perigon.models.vector_search_result import VectorSearchResult +from perigon.models.wikipedia_search_params import WikipediaSearchParams +from perigon.models.wikipedia_search_result import WikipediaSearchResult +from perigon.models.wikipedia_vector_search_result import WikipediaVectorSearchResult # Define API paths PATH_GET_JOURNALIST_BY_ID = "/v1/journalists/{id}" -PATH_SEARCH_ARTICLES = "/v1/all" +PATH_SEARCH_ARTICLES = "/v1/articles/all" PATH_SEARCH_COMPANIES = "/v1/companies/all" PATH_SEARCH_JOURNALISTS = "/v1/journalists/all" PATH_SEARCH_PEOPLE = "/v1/people/all" @@ -31,7 +34,9 @@ PATH_SEARCH_STORIES = "/v1/stories/all" PATH_SEARCH_SUMMARIZER = "/v1/summarize" PATH_SEARCH_TOPICS = "/v1/topics/all" +PATH_SEARCH_WIKIPEDIA = "/v1/wikipedia/all" PATH_VECTOR_SEARCH_ARTICLES = "/v1/vector/news/all" +PATH_VECTOR_SEARCH_WIKIPEDIA = "/v1/vector/wikipedia/all" def _normalise_query(params: Mapping[str, Any]) -> Dict[str, Any]: @@ -213,6 +218,12 @@ def search_articles( negative_sentiment_to: Optional[float] = None, taxonomy: Optional[List[str]] = None, prefix_taxonomy: Optional[str] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> QuerySearchResult: """ Search and filter all news articles available via the Perigon API. The result includes a list of individual articles that were matched to your specific criteria. @@ -263,7 +274,7 @@ def search_articles( state (Optional[List[str]]): Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations. exclude_state (Optional[List[str]]): A list of states to exclude. Articles that include, or are associated with, any of the states provided here will be filtered out. This is especially useful if you want to ignore news tied to certain geographical areas (e.g., US states). county (Optional[List[str]]): A list of counties to include (or specify) in the search results. This field filters the returned articles based on the county associated with the event or news. Only articles tagged with one of these counties will be included. - exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the vector search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter + exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter locations_country (Optional[List[str]]): Filters articles where a specified country plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the country in question. If multiple parameters are passed, they will be applied as OR operations. country (Optional[List[str]]): Country code to filter by country. If multiple parameters are passed, they will be applied as OR operations. exclude_locations_country (Optional[List[str]]): Excludes articles where a specified country plays a central role in the content, ensuring results are not deeply relevant to the country in question. If multiple parameters are passed, they will be applied as AND operations, excluding articles relevant to any of the specified countries. @@ -298,6 +309,12 @@ def search_articles( negative_sentiment_to (Optional[float]): Filter articles with a negative sentiment score less than or equal to the specified value. Scores range from 0 to 1, with higher values indicating stronger negative tone. taxonomy (Optional[List[str]]): Filters by Google Content Categories. This field will accept 1 or more categories, must pass the full name of the category. Example: taxonomy=/Finance/Banking/Other, /Finance/Investing/Funds. [Full list](https://cloud.google.com/natural-language/docs/categories) prefix_taxonomy (Optional[str]): Filters by Google Content Categories. This field will filter by the category prefix only. Example: prefixTaxonomy=/Finance + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: QuerySearchResult: The response @@ -467,6 +484,18 @@ def search_articles( params["taxonomy"] = taxonomy if prefix_taxonomy is not None: params["prefixTaxonomy"] = prefix_taxonomy + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = self.api_client.request("GET", path, params=params) @@ -556,6 +585,12 @@ async def search_articles_async( negative_sentiment_to: Optional[float] = None, taxonomy: Optional[List[str]] = None, prefix_taxonomy: Optional[str] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> QuerySearchResult: """ Async variant of search_articles. Search and filter all news articles available via the Perigon API. The result includes a list of individual articles that were matched to your specific criteria. @@ -606,7 +641,7 @@ async def search_articles_async( state (Optional[List[str]]): Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations. exclude_state (Optional[List[str]]): A list of states to exclude. Articles that include, or are associated with, any of the states provided here will be filtered out. This is especially useful if you want to ignore news tied to certain geographical areas (e.g., US states). county (Optional[List[str]]): A list of counties to include (or specify) in the search results. This field filters the returned articles based on the county associated with the event or news. Only articles tagged with one of these counties will be included. - exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the vector search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter + exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter locations_country (Optional[List[str]]): Filters articles where a specified country plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the country in question. If multiple parameters are passed, they will be applied as OR operations. country (Optional[List[str]]): Country code to filter by country. If multiple parameters are passed, they will be applied as OR operations. exclude_locations_country (Optional[List[str]]): Excludes articles where a specified country plays a central role in the content, ensuring results are not deeply relevant to the country in question. If multiple parameters are passed, they will be applied as AND operations, excluding articles relevant to any of the specified countries. @@ -641,6 +676,12 @@ async def search_articles_async( negative_sentiment_to (Optional[float]): Filter articles with a negative sentiment score less than or equal to the specified value. Scores range from 0 to 1, with higher values indicating stronger negative tone. taxonomy (Optional[List[str]]): Filters by Google Content Categories. This field will accept 1 or more categories, must pass the full name of the category. Example: taxonomy=/Finance/Banking/Other, /Finance/Investing/Funds. [Full list](https://cloud.google.com/natural-language/docs/categories) prefix_taxonomy (Optional[str]): Filters by Google Content Categories. This field will filter by the category prefix only. Example: prefixTaxonomy=/Finance + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: QuerySearchResult: The response @@ -809,6 +850,18 @@ async def search_articles_async( params["taxonomy"] = taxonomy if prefix_taxonomy is not None: params["prefixTaxonomy"] = prefix_taxonomy + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = await self.api_client.request_async("GET", path, params=params) @@ -1527,6 +1580,12 @@ def search_stories( show_story_page_info: Optional[bool] = None, show_num_results: Optional[bool] = None, show_duplicates: Optional[bool] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> StorySearchResult: """ Search and filter all news stories available via the Perigon API. Each story aggregates key information across related articles, including AI-generated names, summaries, and key points. @@ -1573,6 +1632,12 @@ def search_stories( show_story_page_info (Optional[bool]): Parameter show_story_page_info show_num_results (Optional[bool]): Show total number of results. By default set to false, will cap result count at 10000. show_duplicates (Optional[bool]): Stories are deduplicated by default. If a story is deduplicated, all future articles are merged into the original story. duplicateOf field contains the original cluster Id. When showDuplicates=true, all stories are shown. + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: StorySearchResult: The response @@ -1664,6 +1729,18 @@ def search_stories( params["showNumResults"] = show_num_results if show_duplicates is not None: params["showDuplicates"] = show_duplicates + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = self.api_client.request("GET", path, params=params) @@ -1714,6 +1791,12 @@ async def search_stories_async( show_story_page_info: Optional[bool] = None, show_num_results: Optional[bool] = None, show_duplicates: Optional[bool] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> StorySearchResult: """ Async variant of search_stories. Search and filter all news stories available via the Perigon API. Each story aggregates key information across related articles, including AI-generated names, summaries, and key points. @@ -1760,6 +1843,12 @@ async def search_stories_async( show_story_page_info (Optional[bool]): Parameter show_story_page_info show_num_results (Optional[bool]): Show total number of results. By default set to false, will cap result count at 10000. show_duplicates (Optional[bool]): Stories are deduplicated by default. If a story is deduplicated, all future articles are merged into the original story. duplicateOf field contains the original cluster Id. When showDuplicates=true, all stories are shown. + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: StorySearchResult: The response @@ -1850,6 +1939,18 @@ async def search_stories_async( params["showNumResults"] = show_num_results if show_duplicates is not None: params["showDuplicates"] = show_duplicates + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = await self.api_client.request_async("GET", path, params=params) @@ -1940,6 +2041,12 @@ def search_summarizer( negative_sentiment_to: Optional[float] = None, taxonomy: Optional[List[str]] = None, prefix_taxonomy: Optional[str] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> SummarySearchResult: """ Produce a single, concise summary over the full corpus of articles matching your filters, using your prompt to guide which insights to highlight. @@ -1991,7 +2098,7 @@ def search_summarizer( state (Optional[List[str]]): Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations. exclude_state (Optional[List[str]]): A list of states to exclude. Articles that include, or are associated with, any of the states provided here will be filtered out. This is especially useful if you want to ignore news tied to certain geographical areas (e.g., US states). county (Optional[List[str]]): A list of counties to include (or specify) in the search results. This field filters the returned articles based on the county associated with the event or news. Only articles tagged with one of these counties will be included. - exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the vector search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter + exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter locations_country (Optional[List[str]]): Filters articles where a specified country plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the country in question. If multiple parameters are passed, they will be applied as OR operations. country (Optional[List[str]]): Country code to filter by country. If multiple parameters are passed, they will be applied as OR operations. exclude_locations_country (Optional[List[str]]): Excludes articles where a specified country plays a central role in the content, ensuring results are not deeply relevant to the country in question. If multiple parameters are passed, they will be applied as AND operations, excluding articles relevant to any of the specified countries. @@ -2026,6 +2133,12 @@ def search_summarizer( negative_sentiment_to (Optional[float]): Filter articles with a negative sentiment score less than or equal to the specified value. Scores range from 0 to 1, with higher values indicating stronger negative tone. taxonomy (Optional[List[str]]): Filters by Google Content Categories. This field will accept 1 or more categories, must pass the full name of the category. Example: taxonomy=/Finance/Banking/Other, /Finance/Investing/Funds. [Full list](https://cloud.google.com/natural-language/docs/categories) prefix_taxonomy (Optional[str]): Filters by Google Content Categories. This field will filter by the category prefix only. Example: prefixTaxonomy=/Finance + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: SummarySearchResult: The response @@ -2195,6 +2308,18 @@ def search_summarizer( params["taxonomy"] = taxonomy if prefix_taxonomy is not None: params["prefixTaxonomy"] = prefix_taxonomy + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = self.api_client.request( @@ -2287,6 +2412,12 @@ async def search_summarizer_async( negative_sentiment_to: Optional[float] = None, taxonomy: Optional[List[str]] = None, prefix_taxonomy: Optional[str] = None, + show_highlighting: Optional[bool] = None, + highlight_fragment_size: Optional[int] = None, + highlight_num_fragments: Optional[int] = None, + highlight_pre_tag: Optional[str] = None, + highlight_post_tag: Optional[str] = None, + highlight_q: Optional[str] = None, ) -> SummarySearchResult: """ Async variant of search_summarizer. Produce a single, concise summary over the full corpus of articles matching your filters, using your prompt to guide which insights to highlight. @@ -2338,7 +2469,7 @@ async def search_summarizer_async( state (Optional[List[str]]): Filters articles where a specified state plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the state in question. If multiple parameters are passed, they will be applied as OR operations. exclude_state (Optional[List[str]]): A list of states to exclude. Articles that include, or are associated with, any of the states provided here will be filtered out. This is especially useful if you want to ignore news tied to certain geographical areas (e.g., US states). county (Optional[List[str]]): A list of counties to include (or specify) in the search results. This field filters the returned articles based on the county associated with the event or news. Only articles tagged with one of these counties will be included. - exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the vector search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter + exclude_county (Optional[List[str]]): Excludes articles from specific counties or administrative divisions in the search results. Accepts either a single county name or a list of county names. County names should match the format used in article metadata (e.g., 'Los Angeles County', 'Cook County'). This parameter allows for more granular geographic filter locations_country (Optional[List[str]]): Filters articles where a specified country plays a central role in the content, beyond mere mentions, to ensure the results are deeply relevant to the country in question. If multiple parameters are passed, they will be applied as OR operations. country (Optional[List[str]]): Country code to filter by country. If multiple parameters are passed, they will be applied as OR operations. exclude_locations_country (Optional[List[str]]): Excludes articles where a specified country plays a central role in the content, ensuring results are not deeply relevant to the country in question. If multiple parameters are passed, they will be applied as AND operations, excluding articles relevant to any of the specified countries. @@ -2373,6 +2504,12 @@ async def search_summarizer_async( negative_sentiment_to (Optional[float]): Filter articles with a negative sentiment score less than or equal to the specified value. Scores range from 0 to 1, with higher values indicating stronger negative tone. taxonomy (Optional[List[str]]): Filters by Google Content Categories. This field will accept 1 or more categories, must pass the full name of the category. Example: taxonomy=/Finance/Banking/Other, /Finance/Investing/Funds. [Full list](https://cloud.google.com/natural-language/docs/categories) prefix_taxonomy (Optional[str]): Filters by Google Content Categories. This field will filter by the category prefix only. Example: prefixTaxonomy=/Finance + show_highlighting (Optional[bool]): When set to true, enables text highlighting in search results. + highlight_fragment_size (Optional[int]): Specifies the size in characters of each highlighted text fragment. Defaults to 100 if not specified. + highlight_num_fragments (Optional[int]): Controls the maximum number of highlighted fragments to return per field. + highlight_pre_tag (Optional[str]): Defines the HTML tag that appears before highlighted text. Defaults to '' if not specified. + highlight_post_tag (Optional[str]): Defines the HTML tag that appears after highlighted text. Defaults to '' if not specified. + highlight_q (Optional[str]): Specifies a separate query for highlighting, allowing highlights based on terms different from the main search query. Example: main query 'q=climate change' with 'highlightQ=renewable OR solar' will highlight terms 'renewable' and 'solar' in results about climate change. Returns: SummarySearchResult: The response @@ -2541,6 +2678,18 @@ async def search_summarizer_async( params["taxonomy"] = taxonomy if prefix_taxonomy is not None: params["prefixTaxonomy"] = prefix_taxonomy + if show_highlighting is not None: + params["showHighlighting"] = show_highlighting + if highlight_fragment_size is not None: + params["highlightFragmentSize"] = highlight_fragment_size + if highlight_num_fragments is not None: + params["highlightNumFragments"] = highlight_num_fragments + if highlight_pre_tag is not None: + params["highlightPreTag"] = highlight_pre_tag + if highlight_post_tag is not None: + params["highlightPostTag"] = highlight_post_tag + if highlight_q is not None: + params["highlightQ"] = highlight_q params = _normalise_query(params) resp = await self.api_client.request_async( @@ -2634,10 +2783,263 @@ async def search_topics_async( resp.raise_for_status() return TopicSearchResult.model_validate(resp.json()) + # ----------------- search_wikipedia (sync) ----------------- # + def search_wikipedia( + self, + q: Optional[str] = None, + title: Optional[str] = None, + summary: Optional[str] = None, + text: Optional[str] = None, + reference: Optional[str] = None, + id: Optional[List[str]] = None, + wiki_page_id: Optional[List[int]] = None, + wiki_revision_id: Optional[List[int]] = None, + wiki_code: Optional[List[str]] = None, + wiki_namespace: Optional[List[int]] = None, + wikidata_id: Optional[List[str]] = None, + wikidata_instance_of_id: Optional[List[str]] = None, + wikidata_instance_of_label: Optional[List[str]] = None, + category: Optional[List[str]] = None, + section_id: Optional[List[str]] = None, + wiki_revision_from: Optional[datetime] = None, + wiki_revision_to: Optional[datetime] = None, + scraped_at_from: Optional[datetime] = None, + scraped_at_to: Optional[datetime] = None, + pageviews_from: Optional[int] = None, + pageviews_to: Optional[int] = None, + with_pageviews: Optional[bool] = None, + show_num_results: Optional[bool] = None, + page: Optional[int] = None, + size: Optional[int] = None, + sort_by: Optional[SortBy] = None, + ) -> WikipediaSearchResult: + """ + Search and filter all Wikipedia pages available via the Perigon API. The result includes a list of individual pages that were matched to your specific criteria. + + Args: + q (Optional[str]): Primary search query for filtering pages based on their title, summary, and content. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + title (Optional[str]): Search specifically within page titles. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + summary (Optional[str]): Search specifically within page summary. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + text (Optional[str]): Search specifically within the page's content (across all sections). Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + reference (Optional[str]): Search specifically across page's references. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + id (Optional[List[str]]): Retrieve specific pages by their unique Perigon identifiers. Multiple IDs can be provided to return a collection of specific pages. + wiki_page_id (Optional[List[int]]): Retrieve specific pages by their Wikipedia identifiers. These are unique only in a combination with `wikiCode` parameter. Multiple IDs can be provided to return a collection of specific pages. + wiki_revision_id (Optional[List[int]]): Retrieve specific pages by their Wikipedia revision identifiers. These are unique only in a combination with `wikiCode` parameter. Multiple IDs can be provided to return a collection of specific pages. This ID changes each time a page is edited. + wiki_code (Optional[List[str]]): Retrieve pages only from specified wiki projects. Currently, the only accepted value is `enwiki`. + wiki_namespace (Optional[List[int]]): Retrieve pages only from specified wiki namespace. Currently, only the main namespace (0) is available. + wikidata_id (Optional[List[str]]): Retrieve pages by the ids corresponding to their Wikidata entities. + wikidata_instance_of_id (Optional[List[str]]): Retrieve all pages whose Wikidata entities are instances of these provided ids. + wikidata_instance_of_label (Optional[List[str]]): Retrieve all pages whose Wikidata entities are instances of these ids (provided as labels). + category (Optional[List[str]]): Retrieve all pages for specified categories. + section_id (Optional[List[str]]): Retrieve pages containing provided section ids. Each section ID is unique. + wiki_revision_from (Optional[datetime]): Retrieve pages modified after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + wiki_revision_to (Optional[datetime]): Retrieve pages modified before this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + scraped_at_from (Optional[datetime]): Retrieve pages scraped after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + scraped_at_to (Optional[datetime]): Retrieve pages scraped before this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + pageviews_from (Optional[int]): Retrieve pages with the average number of views per day higher than the provided value. + pageviews_to (Optional[int]): Retrieve pages with the average number of views per day lower than the provided value. + with_pageviews (Optional[bool]): Retrieve pages that have any viewership statistics available for them. If `false` (the default) - return all pages. + show_num_results (Optional[bool]): Whether to show the total number of all matched pages. Default value is false which makes queries a bit more efficient but also counts up to 10000 pages. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of articles to return per page in the paginated response. + sort_by (Optional[SortBy]): Determines the Wikipedia page sorting order. Options include relevance (default), revisionTsDesc (recently edited first), revisionTsAsc (recently edited last), pageViewsDesc (highest viewership first), pageViewsAsc (highest viewership last), scrapedAtDesc (recently scraped first), scrapedAtAsc (recently scraped last). + + Returns: + WikipediaSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_WIKIPEDIA + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + if q is not None: + params["q"] = q + if title is not None: + params["title"] = title + if summary is not None: + params["summary"] = summary + if text is not None: + params["text"] = text + if reference is not None: + params["reference"] = reference + if id is not None: + params["id"] = id + if wiki_page_id is not None: + params["wikiPageId"] = wiki_page_id + if wiki_revision_id is not None: + params["wikiRevisionId"] = wiki_revision_id + if wiki_code is not None: + params["wikiCode"] = wiki_code + if wiki_namespace is not None: + params["wikiNamespace"] = wiki_namespace + if wikidata_id is not None: + params["wikidataId"] = wikidata_id + if wikidata_instance_of_id is not None: + params["wikidataInstanceOfId"] = wikidata_instance_of_id + if wikidata_instance_of_label is not None: + params["wikidataInstanceOfLabel"] = wikidata_instance_of_label + if category is not None: + params["category"] = category + if section_id is not None: + params["sectionId"] = section_id + if wiki_revision_from is not None: + params["wikiRevisionFrom"] = wiki_revision_from + if wiki_revision_to is not None: + params["wikiRevisionTo"] = wiki_revision_to + if scraped_at_from is not None: + params["scrapedAtFrom"] = scraped_at_from + if scraped_at_to is not None: + params["scrapedAtTo"] = scraped_at_to + if pageviews_from is not None: + params["pageviewsFrom"] = pageviews_from + if pageviews_to is not None: + params["pageviewsTo"] = pageviews_to + if with_pageviews is not None: + params["withPageviews"] = with_pageviews + if show_num_results is not None: + params["showNumResults"] = show_num_results + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + if sort_by is not None: + params["sortBy"] = sort_by + params = _normalise_query(params) + + resp = self.api_client.request("GET", path, params=params) + resp.raise_for_status() + return WikipediaSearchResult.model_validate(resp.json()) + + # ----------------- search_wikipedia (async) ----------------- # + async def search_wikipedia_async( + self, + q: Optional[str] = None, + title: Optional[str] = None, + summary: Optional[str] = None, + text: Optional[str] = None, + reference: Optional[str] = None, + id: Optional[List[str]] = None, + wiki_page_id: Optional[List[int]] = None, + wiki_revision_id: Optional[List[int]] = None, + wiki_code: Optional[List[str]] = None, + wiki_namespace: Optional[List[int]] = None, + wikidata_id: Optional[List[str]] = None, + wikidata_instance_of_id: Optional[List[str]] = None, + wikidata_instance_of_label: Optional[List[str]] = None, + category: Optional[List[str]] = None, + section_id: Optional[List[str]] = None, + wiki_revision_from: Optional[datetime] = None, + wiki_revision_to: Optional[datetime] = None, + scraped_at_from: Optional[datetime] = None, + scraped_at_to: Optional[datetime] = None, + pageviews_from: Optional[int] = None, + pageviews_to: Optional[int] = None, + with_pageviews: Optional[bool] = None, + show_num_results: Optional[bool] = None, + page: Optional[int] = None, + size: Optional[int] = None, + sort_by: Optional[SortBy] = None, + ) -> WikipediaSearchResult: + """ + Async variant of search_wikipedia. Search and filter all Wikipedia pages available via the Perigon API. The result includes a list of individual pages that were matched to your specific criteria. + + Args: + q (Optional[str]): Primary search query for filtering pages based on their title, summary, and content. Supports Boolean operators (AND, OR, NOT), exact phrases with quotes, and wildcards (* and ?) for flexible searching. + title (Optional[str]): Search specifically within page titles. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + summary (Optional[str]): Search specifically within page summary. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + text (Optional[str]): Search specifically within the page's content (across all sections). Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + reference (Optional[str]): Search specifically across page's references. Supports Boolean operators, exact phrases with quotes, and wildcards for matching title variations. + id (Optional[List[str]]): Retrieve specific pages by their unique Perigon identifiers. Multiple IDs can be provided to return a collection of specific pages. + wiki_page_id (Optional[List[int]]): Retrieve specific pages by their Wikipedia identifiers. These are unique only in a combination with `wikiCode` parameter. Multiple IDs can be provided to return a collection of specific pages. + wiki_revision_id (Optional[List[int]]): Retrieve specific pages by their Wikipedia revision identifiers. These are unique only in a combination with `wikiCode` parameter. Multiple IDs can be provided to return a collection of specific pages. This ID changes each time a page is edited. + wiki_code (Optional[List[str]]): Retrieve pages only from specified wiki projects. Currently, the only accepted value is `enwiki`. + wiki_namespace (Optional[List[int]]): Retrieve pages only from specified wiki namespace. Currently, only the main namespace (0) is available. + wikidata_id (Optional[List[str]]): Retrieve pages by the ids corresponding to their Wikidata entities. + wikidata_instance_of_id (Optional[List[str]]): Retrieve all pages whose Wikidata entities are instances of these provided ids. + wikidata_instance_of_label (Optional[List[str]]): Retrieve all pages whose Wikidata entities are instances of these ids (provided as labels). + category (Optional[List[str]]): Retrieve all pages for specified categories. + section_id (Optional[List[str]]): Retrieve pages containing provided section ids. Each section ID is unique. + wiki_revision_from (Optional[datetime]): Retrieve pages modified after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + wiki_revision_to (Optional[datetime]): Retrieve pages modified before this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + scraped_at_from (Optional[datetime]): Retrieve pages scraped after this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + scraped_at_to (Optional[datetime]): Retrieve pages scraped before this date. Accepts ISO 8601 format (e.g., 2023-03-01T00:00:00) or yyyy-mm-dd format. + pageviews_from (Optional[int]): Retrieve pages with the average number of views per day higher than the provided value. + pageviews_to (Optional[int]): Retrieve pages with the average number of views per day lower than the provided value. + with_pageviews (Optional[bool]): Retrieve pages that have any viewership statistics available for them. If `false` (the default) - return all pages. + show_num_results (Optional[bool]): Whether to show the total number of all matched pages. Default value is false which makes queries a bit more efficient but also counts up to 10000 pages. + page (Optional[int]): The specific page of results to retrieve in the paginated response. Starts at 0. + size (Optional[int]): The number of articles to return per page in the paginated response. + sort_by (Optional[SortBy]): Determines the Wikipedia page sorting order. Options include relevance (default), revisionTsDesc (recently edited first), revisionTsAsc (recently edited last), pageViewsDesc (highest viewership first), pageViewsAsc (highest viewership last), scrapedAtDesc (recently scraped first), scrapedAtAsc (recently scraped last). + + Returns: + WikipediaSearchResult: The response + """ + # Get path template from class attribute + path = PATH_SEARCH_WIKIPEDIA + + params: Dict[str, Any] = {} + if q is not None: + params["q"] = q + if title is not None: + params["title"] = title + if summary is not None: + params["summary"] = summary + if text is not None: + params["text"] = text + if reference is not None: + params["reference"] = reference + if id is not None: + params["id"] = id + if wiki_page_id is not None: + params["wikiPageId"] = wiki_page_id + if wiki_revision_id is not None: + params["wikiRevisionId"] = wiki_revision_id + if wiki_code is not None: + params["wikiCode"] = wiki_code + if wiki_namespace is not None: + params["wikiNamespace"] = wiki_namespace + if wikidata_id is not None: + params["wikidataId"] = wikidata_id + if wikidata_instance_of_id is not None: + params["wikidataInstanceOfId"] = wikidata_instance_of_id + if wikidata_instance_of_label is not None: + params["wikidataInstanceOfLabel"] = wikidata_instance_of_label + if category is not None: + params["category"] = category + if section_id is not None: + params["sectionId"] = section_id + if wiki_revision_from is not None: + params["wikiRevisionFrom"] = wiki_revision_from + if wiki_revision_to is not None: + params["wikiRevisionTo"] = wiki_revision_to + if scraped_at_from is not None: + params["scrapedAtFrom"] = scraped_at_from + if scraped_at_to is not None: + params["scrapedAtTo"] = scraped_at_to + if pageviews_from is not None: + params["pageviewsFrom"] = pageviews_from + if pageviews_to is not None: + params["pageviewsTo"] = pageviews_to + if with_pageviews is not None: + params["withPageviews"] = with_pageviews + if show_num_results is not None: + params["showNumResults"] = show_num_results + if page is not None: + params["page"] = page + if size is not None: + params["size"] = size + if sort_by is not None: + params["sortBy"] = sort_by + params = _normalise_query(params) + + resp = await self.api_client.request_async("GET", path, params=params) + resp.raise_for_status() + return WikipediaSearchResult.model_validate(resp.json()) + # ----------------- vector_search_articles (sync) ----------------- # def vector_search_articles( self, article_search_params: ArticleSearchParams - ) -> VectorSearchResult: + ) -> ArticlesVectorSearchResult: """ Perform a natural language search over news articles from the past 6 months using semantic relevance. The result includes a list of articles most closely matched to your query intent. @@ -2645,7 +3047,7 @@ def vector_search_articles( article_search_params (ArticleSearchParams): Parameter article_search_params (required) Returns: - VectorSearchResult: The response + ArticlesVectorSearchResult: The response """ # Get path template from class attribute path = PATH_VECTOR_SEARCH_ARTICLES @@ -2661,12 +3063,12 @@ def vector_search_articles( json=article_search_params.model_dump(by_alias=True), ) resp.raise_for_status() - return VectorSearchResult.model_validate(resp.json()) + return ArticlesVectorSearchResult.model_validate(resp.json()) # ----------------- vector_search_articles (async) ----------------- # async def vector_search_articles_async( self, article_search_params: ArticleSearchParams - ) -> VectorSearchResult: + ) -> ArticlesVectorSearchResult: """ Async variant of vector_search_articles. Perform a natural language search over news articles from the past 6 months using semantic relevance. The result includes a list of articles most closely matched to your query intent. @@ -2674,7 +3076,7 @@ async def vector_search_articles_async( article_search_params (ArticleSearchParams): Parameter article_search_params (required) Returns: - VectorSearchResult: The response + ArticlesVectorSearchResult: The response """ # Get path template from class attribute path = PATH_VECTOR_SEARCH_ARTICLES @@ -2689,4 +3091,61 @@ async def vector_search_articles_async( json=article_search_params.model_dump(by_alias=True), ) resp.raise_for_status() - return VectorSearchResult.model_validate(resp.json()) + return ArticlesVectorSearchResult.model_validate(resp.json()) + + # ----------------- vector_search_wikipedia (sync) ----------------- # + def vector_search_wikipedia( + self, wikipedia_search_params: WikipediaSearchParams + ) -> WikipediaVectorSearchResult: + """ + Perform a natural language search over Wikipedia pages using semantic relevance. The result includes a list of page sections most closely matched to your query intent. + + Args: + wikipedia_search_params (WikipediaSearchParams): Parameter wikipedia_search_params (required) + + Returns: + WikipediaVectorSearchResult: The response + """ + # Get path template from class attribute + path = PATH_VECTOR_SEARCH_WIKIPEDIA + + # --- build query dict on the fly --- + params: Dict[str, Any] = {} + params = _normalise_query(params) + + resp = self.api_client.request( + "POST", + path, + params=params, + json=wikipedia_search_params.model_dump(by_alias=True), + ) + resp.raise_for_status() + return WikipediaVectorSearchResult.model_validate(resp.json()) + + # ----------------- vector_search_wikipedia (async) ----------------- # + async def vector_search_wikipedia_async( + self, wikipedia_search_params: WikipediaSearchParams + ) -> WikipediaVectorSearchResult: + """ + Async variant of vector_search_wikipedia. Perform a natural language search over Wikipedia pages using semantic relevance. The result includes a list of page sections most closely matched to your query intent. + + Args: + wikipedia_search_params (WikipediaSearchParams): Parameter wikipedia_search_params (required) + + Returns: + WikipediaVectorSearchResult: The response + """ + # Get path template from class attribute + path = PATH_VECTOR_SEARCH_WIKIPEDIA + + params: Dict[str, Any] = {} + params = _normalise_query(params) + + resp = await self.api_client.request_async( + "POST", + path, + params=params, + json=wikipedia_search_params.model_dump(by_alias=True), + ) + resp.raise_for_status() + return WikipediaVectorSearchResult.model_validate(resp.json()) diff --git a/perigon/models/__init__.py b/perigon/models/__init__.py index 6f5843b..09d200b 100644 --- a/perigon/models/__init__.py +++ b/perigon/models/__init__.py @@ -19,7 +19,13 @@ from perigon.models.article import Article from perigon.models.article_search_filter import ArticleSearchFilter from perigon.models.article_search_params import ArticleSearchParams +from perigon.models.articles_vector_search_result import ArticlesVectorSearchResult from perigon.models.auth_exception import AuthException +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, +) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner from perigon.models.category_holder import CategoryHolder from perigon.models.category_with_score_holder import CategoryWithScoreHolder from perigon.models.company import Company @@ -52,7 +58,8 @@ from perigon.models.query_search_result import QuerySearchResult from perigon.models.question import Question from perigon.models.record_stat_holder import RecordStatHolder -from perigon.models.scored_article import ScoredArticle +from perigon.models.scored_data_article import ScoredDataArticle +from perigon.models.scored_data_wiki_data import ScoredDataWikiData from perigon.models.sentiment_holder import SentimentHolder from perigon.models.sort_by import SortBy from perigon.models.source import Source @@ -65,22 +72,19 @@ from perigon.models.summary_search_result import SummarySearchResult from perigon.models.symbol_holder import SymbolHolder from perigon.models.too_many_requests_exception import TooManyRequestsException -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, -) from perigon.models.topic_dto import TopicDto from perigon.models.topic_holder import TopicHolder from perigon.models.topic_labels import TopicLabels from perigon.models.topic_search_result import TopicSearchResult -from perigon.models.vector_search_result import VectorSearchResult from perigon.models.web_resources import WebResources +from perigon.models.wiki_data import WikiData +from perigon.models.wiki_page import WikiPage +from perigon.models.wiki_page_section_holder import WikiPageSectionHolder from perigon.models.wikidata_date_holder import WikidataDateHolder from perigon.models.wikidata_label_holder import WikidataLabelHolder from perigon.models.wikidata_political_party_holder import WikidataPoliticalPartyHolder from perigon.models.wikidata_position_holder import WikidataPositionHolder +from perigon.models.wikipedia_search_filter import WikipediaSearchFilter +from perigon.models.wikipedia_search_params import WikipediaSearchParams +from perigon.models.wikipedia_search_result import WikipediaSearchResult +from perigon.models.wikipedia_vector_search_result import WikipediaVectorSearchResult diff --git a/perigon/models/articles_vector_search_result.py b/perigon/models/articles_vector_search_result.py new file mode 100644 index 0000000..434af66 --- /dev/null +++ b/perigon/models/articles_vector_search_result.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing_extensions import Self + +from perigon.models.scored_data_article import ScoredDataArticle + + +class ArticlesVectorSearchResult(BaseModel): + """ + Articles vector search result + """ # noqa: E501 + + status: StrictInt + results: List[ScoredDataArticle] + __properties: ClassVar[List[str]] = ["status", "results"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ArticlesVectorSearchResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ArticlesVectorSearchResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "status": obj.get("status"), + "results": ( + [ScoredDataArticle.from_dict(_item) for _item in obj["results"]] + if obj.get("results") is not None + else None + ), + } + ) + return _obj diff --git a/perigon/models/auth_exception.py b/perigon/models/auth_exception.py index a1759ff..aaa08a3 100644 --- a/perigon/models/auth_exception.py +++ b/perigon/models/auth_exception.py @@ -23,15 +23,11 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing_extensions import Self -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, ) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner class AuthException(BaseModel): @@ -39,13 +35,13 @@ class AuthException(BaseModel): AuthException """ # noqa: E501 - cause: Optional[TooManyRequestsExceptionCause] = None - stack_trace: Optional[List[TooManyRequestsExceptionCauseStackTraceInner]] = Field( + cause: Optional[AuthExceptionCause] = None + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( default=None, alias="stackTrace" ) status_code: Optional[StrictStr] = Field(default=None, alias="statusCode") message: Optional[StrictStr] = None - suppressed: Optional[List[TooManyRequestsExceptionSuppressedInner]] = None + suppressed: Optional[List[AuthExceptionSuppressedInner]] = None localized_message: Optional[StrictStr] = Field( default=None, alias="localizedMessage" ) @@ -242,13 +238,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "cause": ( - TooManyRequestsExceptionCause.from_dict(obj["cause"]) + AuthExceptionCause.from_dict(obj["cause"]) if obj.get("cause") is not None else None ), "stackTrace": ( [ - TooManyRequestsExceptionCauseStackTraceInner.from_dict(_item) + AuthExceptionCauseStackTraceInner.from_dict(_item) for _item in obj["stackTrace"] ] if obj.get("stackTrace") is not None @@ -258,7 +254,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "message": obj.get("message"), "suppressed": ( [ - TooManyRequestsExceptionSuppressedInner.from_dict(_item) + AuthExceptionSuppressedInner.from_dict(_item) for _item in obj["suppressed"] ] if obj.get("suppressed") is not None diff --git a/perigon/models/auth_exception_cause.py b/perigon/models/auth_exception_cause.py new file mode 100644 index 0000000..11a7d2f --- /dev/null +++ b/perigon/models/auth_exception_cause.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing_extensions import Self + +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, +) + + +class AuthExceptionCause(BaseModel): + """ + AuthExceptionCause + """ # noqa: E501 + + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( + default=None, alias="stackTrace" + ) + message: Optional[StrictStr] = None + localized_message: Optional[StrictStr] = Field( + default=None, alias="localizedMessage" + ) + __properties: ClassVar[List[str]] = ["stackTrace", "message", "localizedMessage"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AuthExceptionCause from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in stack_trace (list) + _items = [] + if self.stack_trace: + for _item_stack_trace in self.stack_trace: + if _item_stack_trace: + _items.append(_item_stack_trace.to_dict()) + _dict["stackTrace"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AuthExceptionCause from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "stackTrace": ( + [ + AuthExceptionCauseStackTraceInner.from_dict(_item) + for _item in obj["stackTrace"] + ] + if obj.get("stackTrace") is not None + else None + ), + "message": obj.get("message"), + "localizedMessage": obj.get("localizedMessage"), + } + ) + return _obj diff --git a/perigon/models/auth_exception_cause_stack_trace_inner.py b/perigon/models/auth_exception_cause_stack_trace_inner.py new file mode 100644 index 0000000..a6b1034 --- /dev/null +++ b/perigon/models/auth_exception_cause_stack_trace_inner.py @@ -0,0 +1,113 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictBool, StrictInt, StrictStr +from typing_extensions import Self + + +class AuthExceptionCauseStackTraceInner(BaseModel): + """ + AuthExceptionCauseStackTraceInner + """ # noqa: E501 + + class_loader_name: Optional[StrictStr] = Field( + default=None, alias="classLoaderName" + ) + module_name: Optional[StrictStr] = Field(default=None, alias="moduleName") + module_version: Optional[StrictStr] = Field(default=None, alias="moduleVersion") + method_name: Optional[StrictStr] = Field(default=None, alias="methodName") + file_name: Optional[StrictStr] = Field(default=None, alias="fileName") + line_number: Optional[StrictInt] = Field(default=None, alias="lineNumber") + native_method: Optional[StrictBool] = Field(default=None, alias="nativeMethod") + class_name: Optional[StrictStr] = Field(default=None, alias="className") + __properties: ClassVar[List[str]] = [ + "classLoaderName", + "moduleName", + "moduleVersion", + "methodName", + "fileName", + "lineNumber", + "nativeMethod", + "className", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AuthExceptionCauseStackTraceInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AuthExceptionCauseStackTraceInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "classLoaderName": obj.get("classLoaderName"), + "moduleName": obj.get("moduleName"), + "moduleVersion": obj.get("moduleVersion"), + "methodName": obj.get("methodName"), + "fileName": obj.get("fileName"), + "lineNumber": obj.get("lineNumber"), + "nativeMethod": obj.get("nativeMethod"), + "className": obj.get("className"), + } + ) + return _obj diff --git a/perigon/models/auth_exception_suppressed_inner.py b/perigon/models/auth_exception_suppressed_inner.py new file mode 100644 index 0000000..bacbf86 --- /dev/null +++ b/perigon/models/auth_exception_suppressed_inner.py @@ -0,0 +1,114 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictStr +from typing_extensions import Self + +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, +) + + +class AuthExceptionSuppressedInner(BaseModel): + """ + AuthExceptionSuppressedInner + """ # noqa: E501 + + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( + default=None, alias="stackTrace" + ) + message: Optional[StrictStr] = None + localized_message: Optional[StrictStr] = Field( + default=None, alias="localizedMessage" + ) + __properties: ClassVar[List[str]] = ["stackTrace", "message", "localizedMessage"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of AuthExceptionSuppressedInner from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in stack_trace (list) + _items = [] + if self.stack_trace: + for _item_stack_trace in self.stack_trace: + if _item_stack_trace: + _items.append(_item_stack_trace.to_dict()) + _dict["stackTrace"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of AuthExceptionSuppressedInner from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "stackTrace": ( + [ + AuthExceptionCauseStackTraceInner.from_dict(_item) + for _item in obj["stackTrace"] + ] + if obj.get("stackTrace") is not None + else None + ), + "message": obj.get("message"), + "localizedMessage": obj.get("localizedMessage"), + } + ) + return _obj diff --git a/perigon/models/illegal_parameter_exception.py b/perigon/models/illegal_parameter_exception.py index 38163f8..eff900d 100644 --- a/perigon/models/illegal_parameter_exception.py +++ b/perigon/models/illegal_parameter_exception.py @@ -23,15 +23,11 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing_extensions import Self -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, ) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner class IllegalParameterException(BaseModel): @@ -39,12 +35,12 @@ class IllegalParameterException(BaseModel): IllegalParameterException """ # noqa: E501 - cause: Optional[TooManyRequestsExceptionCause] = None - stack_trace: Optional[List[TooManyRequestsExceptionCauseStackTraceInner]] = Field( + cause: Optional[AuthExceptionCause] = None + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( default=None, alias="stackTrace" ) message: Optional[StrictStr] = None - suppressed: Optional[List[TooManyRequestsExceptionSuppressedInner]] = None + suppressed: Optional[List[AuthExceptionSuppressedInner]] = None localized_message: Optional[StrictStr] = Field( default=None, alias="localizedMessage" ) @@ -152,13 +148,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "cause": ( - TooManyRequestsExceptionCause.from_dict(obj["cause"]) + AuthExceptionCause.from_dict(obj["cause"]) if obj.get("cause") is not None else None ), "stackTrace": ( [ - TooManyRequestsExceptionCauseStackTraceInner.from_dict(_item) + AuthExceptionCauseStackTraceInner.from_dict(_item) for _item in obj["stackTrace"] ] if obj.get("stackTrace") is not None @@ -167,7 +163,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "message": obj.get("message"), "suppressed": ( [ - TooManyRequestsExceptionSuppressedInner.from_dict(_item) + AuthExceptionSuppressedInner.from_dict(_item) for _item in obj["suppressed"] ] if obj.get("suppressed") is not None diff --git a/perigon/models/internal_error_exception.py b/perigon/models/internal_error_exception.py index 33aaf38..adda545 100644 --- a/perigon/models/internal_error_exception.py +++ b/perigon/models/internal_error_exception.py @@ -23,15 +23,11 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing_extensions import Self -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, ) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner class InternalErrorException(BaseModel): @@ -39,12 +35,12 @@ class InternalErrorException(BaseModel): InternalErrorException """ # noqa: E501 - cause: Optional[TooManyRequestsExceptionCause] = None - stack_trace: Optional[List[TooManyRequestsExceptionCauseStackTraceInner]] = Field( + cause: Optional[AuthExceptionCause] = None + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( default=None, alias="stackTrace" ) message: Optional[StrictStr] = None - suppressed: Optional[List[TooManyRequestsExceptionSuppressedInner]] = None + suppressed: Optional[List[AuthExceptionSuppressedInner]] = None localized_message: Optional[StrictStr] = Field( default=None, alias="localizedMessage" ) @@ -152,13 +148,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "cause": ( - TooManyRequestsExceptionCause.from_dict(obj["cause"]) + AuthExceptionCause.from_dict(obj["cause"]) if obj.get("cause") is not None else None ), "stackTrace": ( [ - TooManyRequestsExceptionCauseStackTraceInner.from_dict(_item) + AuthExceptionCauseStackTraceInner.from_dict(_item) for _item in obj["stackTrace"] ] if obj.get("stackTrace") is not None @@ -167,7 +163,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "message": obj.get("message"), "suppressed": ( [ - TooManyRequestsExceptionSuppressedInner.from_dict(_item) + AuthExceptionSuppressedInner.from_dict(_item) for _item in obj["suppressed"] ] if obj.get("suppressed") is not None diff --git a/perigon/models/not_found_exception.py b/perigon/models/not_found_exception.py index 6e7c62a..1d89987 100644 --- a/perigon/models/not_found_exception.py +++ b/perigon/models/not_found_exception.py @@ -23,15 +23,11 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr from typing_extensions import Self -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, ) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner class NotFoundException(BaseModel): @@ -39,12 +35,12 @@ class NotFoundException(BaseModel): NotFoundException """ # noqa: E501 - cause: Optional[TooManyRequestsExceptionCause] = None - stack_trace: Optional[List[TooManyRequestsExceptionCauseStackTraceInner]] = Field( + cause: Optional[AuthExceptionCause] = None + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( default=None, alias="stackTrace" ) message: Optional[StrictStr] = None - suppressed: Optional[List[TooManyRequestsExceptionSuppressedInner]] = None + suppressed: Optional[List[AuthExceptionSuppressedInner]] = None localized_message: Optional[StrictStr] = Field( default=None, alias="localizedMessage" ) @@ -152,13 +148,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "cause": ( - TooManyRequestsExceptionCause.from_dict(obj["cause"]) + AuthExceptionCause.from_dict(obj["cause"]) if obj.get("cause") is not None else None ), "stackTrace": ( [ - TooManyRequestsExceptionCauseStackTraceInner.from_dict(_item) + AuthExceptionCauseStackTraceInner.from_dict(_item) for _item in obj["stackTrace"] ] if obj.get("stackTrace") is not None @@ -167,7 +163,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "message": obj.get("message"), "suppressed": ( [ - TooManyRequestsExceptionSuppressedInner.from_dict(_item) + AuthExceptionSuppressedInner.from_dict(_item) for _item in obj["suppressed"] ] if obj.get("suppressed") is not None diff --git a/perigon/models/scored_data_article.py b/perigon/models/scored_data_article.py new file mode 100644 index 0000000..857c180 --- /dev/null +++ b/perigon/models/scored_data_article.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set, Union + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt +from typing_extensions import Self + +from perigon.models.article import Article + + +class ScoredDataArticle(BaseModel): + """ + ScoredDataArticle + """ # noqa: E501 + + score: Optional[Union[StrictFloat, StrictInt]] = None + data: Optional[Article] = None + __properties: ClassVar[List[str]] = ["score", "data"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ScoredDataArticle from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of data + if self.data: + _dict["data"] = self.data.to_dict() + # set to None if score (nullable) is None + # and model_fields_set contains the field + if self.score is None and "score" in self.model_fields_set: + _dict["score"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ScoredDataArticle from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "score": obj.get("score"), + "data": ( + Article.from_dict(obj["data"]) + if obj.get("data") is not None + else None + ), + } + ) + return _obj diff --git a/perigon/models/scored_data_wiki_data.py b/perigon/models/scored_data_wiki_data.py new file mode 100644 index 0000000..421932f --- /dev/null +++ b/perigon/models/scored_data_wiki_data.py @@ -0,0 +1,104 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set, Union + +from pydantic import BaseModel, ConfigDict, StrictFloat, StrictInt +from typing_extensions import Self + +from perigon.models.wiki_data import WikiData + + +class ScoredDataWikiData(BaseModel): + """ + ScoredDataWikiData + """ # noqa: E501 + + score: Optional[Union[StrictFloat, StrictInt]] = None + data: Optional[WikiData] = None + __properties: ClassVar[List[str]] = ["score", "data"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of ScoredDataWikiData from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of data + if self.data: + _dict["data"] = self.data.to_dict() + # set to None if score (nullable) is None + # and model_fields_set contains the field + if self.score is None and "score" in self.model_fields_set: + _dict["score"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of ScoredDataWikiData from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "score": obj.get("score"), + "data": ( + WikiData.from_dict(obj["data"]) + if obj.get("data") is not None + else None + ), + } + ) + return _obj diff --git a/perigon/models/too_many_requests_exception.py b/perigon/models/too_many_requests_exception.py index a9e3c03..f0cb994 100644 --- a/perigon/models/too_many_requests_exception.py +++ b/perigon/models/too_many_requests_exception.py @@ -23,15 +23,11 @@ from pydantic import BaseModel, ConfigDict, Field, StrictStr, field_validator from typing_extensions import Self -from perigon.models.too_many_requests_exception_cause import ( - TooManyRequestsExceptionCause, -) -from perigon.models.too_many_requests_exception_cause_stack_trace_inner import ( - TooManyRequestsExceptionCauseStackTraceInner, -) -from perigon.models.too_many_requests_exception_suppressed_inner import ( - TooManyRequestsExceptionSuppressedInner, +from perigon.models.auth_exception_cause import AuthExceptionCause +from perigon.models.auth_exception_cause_stack_trace_inner import ( + AuthExceptionCauseStackTraceInner, ) +from perigon.models.auth_exception_suppressed_inner import AuthExceptionSuppressedInner class TooManyRequestsException(BaseModel): @@ -39,13 +35,13 @@ class TooManyRequestsException(BaseModel): TooManyRequestsException """ # noqa: E501 - cause: Optional[TooManyRequestsExceptionCause] = None - stack_trace: Optional[List[TooManyRequestsExceptionCauseStackTraceInner]] = Field( + cause: Optional[AuthExceptionCause] = None + stack_trace: Optional[List[AuthExceptionCauseStackTraceInner]] = Field( default=None, alias="stackTrace" ) status: Optional[StrictStr] = None message: Optional[StrictStr] = None - suppressed: Optional[List[TooManyRequestsExceptionSuppressedInner]] = None + suppressed: Optional[List[AuthExceptionSuppressedInner]] = None localized_message: Optional[StrictStr] = Field( default=None, alias="localizedMessage" ) @@ -242,13 +238,13 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: _obj = cls.model_validate( { "cause": ( - TooManyRequestsExceptionCause.from_dict(obj["cause"]) + AuthExceptionCause.from_dict(obj["cause"]) if obj.get("cause") is not None else None ), "stackTrace": ( [ - TooManyRequestsExceptionCauseStackTraceInner.from_dict(_item) + AuthExceptionCauseStackTraceInner.from_dict(_item) for _item in obj["stackTrace"] ] if obj.get("stackTrace") is not None @@ -258,7 +254,7 @@ def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: "message": obj.get("message"), "suppressed": ( [ - TooManyRequestsExceptionSuppressedInner.from_dict(_item) + AuthExceptionSuppressedInner.from_dict(_item) for _item in obj["suppressed"] ] if obj.get("suppressed") is not None diff --git a/perigon/models/wiki_data.py b/perigon/models/wiki_data.py new file mode 100644 index 0000000..5429d68 --- /dev/null +++ b/perigon/models/wiki_data.py @@ -0,0 +1,236 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing_extensions import Self + +from perigon.models.wikidata_label_holder import WikidataLabelHolder + + +class WikiData(BaseModel): + """ + WikiData + """ # noqa: E501 + + page_id: Optional[StrictStr] = Field(default=None, alias="pageId") + section_id: Optional[StrictStr] = Field(default=None, alias="sectionId") + wiki_page_id: Optional[StrictInt] = Field(default=None, alias="wikiPageId") + wiki_revision_id: Optional[StrictInt] = Field(default=None, alias="wikiRevisionId") + wiki_revision_ts: Optional[StrictStr] = Field(default=None, alias="wikiRevisionTs") + wiki_code: Optional[StrictStr] = Field(default=None, alias="wikiCode") + wiki_namespace: Optional[StrictInt] = Field(default=None, alias="wikiNamespace") + wiki_title: Optional[StrictStr] = Field(default=None, alias="wikiTitle") + wikidata_id: Optional[StrictStr] = Field(default=None, alias="wikidataId") + wikidata_instance_of: Optional[List[WikidataLabelHolder]] = Field( + default=None, alias="wikidataInstanceOf" + ) + redirect_titles: Optional[List[StrictStr]] = Field( + default=None, alias="redirectTitles" + ) + pageviews: Optional[StrictInt] = None + title: Optional[StrictStr] = None + style_level: Optional[StrictInt] = Field(default=None, alias="styleLevel") + content: Optional[StrictStr] = None + __properties: ClassVar[List[str]] = [ + "pageId", + "sectionId", + "wikiPageId", + "wikiRevisionId", + "wikiRevisionTs", + "wikiCode", + "wikiNamespace", + "wikiTitle", + "wikidataId", + "wikidataInstanceOf", + "redirectTitles", + "pageviews", + "title", + "styleLevel", + "content", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikiData from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in wikidata_instance_of (list) + _items = [] + if self.wikidata_instance_of: + for _item_wikidata_instance_of in self.wikidata_instance_of: + if _item_wikidata_instance_of: + _items.append(_item_wikidata_instance_of.to_dict()) + _dict["wikidataInstanceOf"] = _items + # set to None if page_id (nullable) is None + # and model_fields_set contains the field + if self.page_id is None and "page_id" in self.model_fields_set: + _dict["pageId"] = None + + # set to None if section_id (nullable) is None + # and model_fields_set contains the field + if self.section_id is None and "section_id" in self.model_fields_set: + _dict["sectionId"] = None + + # set to None if wiki_page_id (nullable) is None + # and model_fields_set contains the field + if self.wiki_page_id is None and "wiki_page_id" in self.model_fields_set: + _dict["wikiPageId"] = None + + # set to None if wiki_revision_id (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_id is None + and "wiki_revision_id" in self.model_fields_set + ): + _dict["wikiRevisionId"] = None + + # set to None if wiki_revision_ts (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_ts is None + and "wiki_revision_ts" in self.model_fields_set + ): + _dict["wikiRevisionTs"] = None + + # set to None if wiki_code (nullable) is None + # and model_fields_set contains the field + if self.wiki_code is None and "wiki_code" in self.model_fields_set: + _dict["wikiCode"] = None + + # set to None if wiki_namespace (nullable) is None + # and model_fields_set contains the field + if self.wiki_namespace is None and "wiki_namespace" in self.model_fields_set: + _dict["wikiNamespace"] = None + + # set to None if wiki_title (nullable) is None + # and model_fields_set contains the field + if self.wiki_title is None and "wiki_title" in self.model_fields_set: + _dict["wikiTitle"] = None + + # set to None if wikidata_id (nullable) is None + # and model_fields_set contains the field + if self.wikidata_id is None and "wikidata_id" in self.model_fields_set: + _dict["wikidataId"] = None + + # set to None if wikidata_instance_of (nullable) is None + # and model_fields_set contains the field + if ( + self.wikidata_instance_of is None + and "wikidata_instance_of" in self.model_fields_set + ): + _dict["wikidataInstanceOf"] = None + + # set to None if redirect_titles (nullable) is None + # and model_fields_set contains the field + if self.redirect_titles is None and "redirect_titles" in self.model_fields_set: + _dict["redirectTitles"] = None + + # set to None if pageviews (nullable) is None + # and model_fields_set contains the field + if self.pageviews is None and "pageviews" in self.model_fields_set: + _dict["pageviews"] = None + + # set to None if title (nullable) is None + # and model_fields_set contains the field + if self.title is None and "title" in self.model_fields_set: + _dict["title"] = None + + # set to None if style_level (nullable) is None + # and model_fields_set contains the field + if self.style_level is None and "style_level" in self.model_fields_set: + _dict["styleLevel"] = None + + # set to None if content (nullable) is None + # and model_fields_set contains the field + if self.content is None and "content" in self.model_fields_set: + _dict["content"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikiData from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "pageId": obj.get("pageId"), + "sectionId": obj.get("sectionId"), + "wikiPageId": obj.get("wikiPageId"), + "wikiRevisionId": obj.get("wikiRevisionId"), + "wikiRevisionTs": obj.get("wikiRevisionTs"), + "wikiCode": obj.get("wikiCode"), + "wikiNamespace": obj.get("wikiNamespace"), + "wikiTitle": obj.get("wikiTitle"), + "wikidataId": obj.get("wikidataId"), + "wikidataInstanceOf": ( + [ + WikidataLabelHolder.from_dict(_item) + for _item in obj["wikidataInstanceOf"] + ] + if obj.get("wikidataInstanceOf") is not None + else None + ), + "redirectTitles": obj.get("redirectTitles"), + "pageviews": obj.get("pageviews"), + "title": obj.get("title"), + "styleLevel": obj.get("styleLevel"), + "content": obj.get("content"), + } + ) + return _obj diff --git a/perigon/models/wiki_page.py b/perigon/models/wiki_page.py new file mode 100644 index 0000000..5a82382 --- /dev/null +++ b/perigon/models/wiki_page.py @@ -0,0 +1,285 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing_extensions import Self + +from perigon.models.wiki_page_section_holder import WikiPageSectionHolder +from perigon.models.wikidata_label_holder import WikidataLabelHolder + + +class WikiPage(BaseModel): + """ + WikiPage + """ # noqa: E501 + + id: Optional[StrictStr] = None + scraped_at: Optional[StrictStr] = Field(default=None, alias="scrapedAt") + wiki_page_id: Optional[StrictInt] = Field(default=None, alias="wikiPageId") + wiki_revision_id: Optional[StrictInt] = Field(default=None, alias="wikiRevisionId") + wiki_revision_ts: Optional[StrictStr] = Field(default=None, alias="wikiRevisionTs") + wiki_code: Optional[StrictStr] = Field(default=None, alias="wikiCode") + wiki_namespace: Optional[StrictInt] = Field(default=None, alias="wikiNamespace") + wiki_title: Optional[StrictStr] = Field(default=None, alias="wikiTitle") + url: Optional[StrictStr] = None + top_image: Optional[StrictStr] = Field(default=None, alias="topImage") + wikidata_id: Optional[StrictStr] = Field(default=None, alias="wikidataId") + wikidata_instance_of: Optional[List[WikidataLabelHolder]] = Field( + default=None, alias="wikidataInstanceOf" + ) + redirect_titles: Optional[List[StrictStr]] = Field( + default=None, alias="redirectTitles" + ) + summary: Optional[StrictStr] = None + sections: Optional[List[WikiPageSectionHolder]] = None + categories: Optional[List[StrictStr]] = None + external_links: Optional[List[StrictStr]] = Field( + default=None, alias="externalLinks" + ) + references: Optional[List[StrictStr]] = None + pageviews: Optional[StrictInt] = None + __properties: ClassVar[List[str]] = [ + "id", + "scrapedAt", + "wikiPageId", + "wikiRevisionId", + "wikiRevisionTs", + "wikiCode", + "wikiNamespace", + "wikiTitle", + "url", + "topImage", + "wikidataId", + "wikidataInstanceOf", + "redirectTitles", + "summary", + "sections", + "categories", + "externalLinks", + "references", + "pageviews", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikiPage from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in wikidata_instance_of (list) + _items = [] + if self.wikidata_instance_of: + for _item_wikidata_instance_of in self.wikidata_instance_of: + if _item_wikidata_instance_of: + _items.append(_item_wikidata_instance_of.to_dict()) + _dict["wikidataInstanceOf"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in sections (list) + _items = [] + if self.sections: + for _item_sections in self.sections: + if _item_sections: + _items.append(_item_sections.to_dict()) + _dict["sections"] = _items + # set to None if id (nullable) is None + # and model_fields_set contains the field + if self.id is None and "id" in self.model_fields_set: + _dict["id"] = None + + # set to None if scraped_at (nullable) is None + # and model_fields_set contains the field + if self.scraped_at is None and "scraped_at" in self.model_fields_set: + _dict["scrapedAt"] = None + + # set to None if wiki_page_id (nullable) is None + # and model_fields_set contains the field + if self.wiki_page_id is None and "wiki_page_id" in self.model_fields_set: + _dict["wikiPageId"] = None + + # set to None if wiki_revision_id (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_id is None + and "wiki_revision_id" in self.model_fields_set + ): + _dict["wikiRevisionId"] = None + + # set to None if wiki_revision_ts (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_ts is None + and "wiki_revision_ts" in self.model_fields_set + ): + _dict["wikiRevisionTs"] = None + + # set to None if wiki_code (nullable) is None + # and model_fields_set contains the field + if self.wiki_code is None and "wiki_code" in self.model_fields_set: + _dict["wikiCode"] = None + + # set to None if wiki_namespace (nullable) is None + # and model_fields_set contains the field + if self.wiki_namespace is None and "wiki_namespace" in self.model_fields_set: + _dict["wikiNamespace"] = None + + # set to None if wiki_title (nullable) is None + # and model_fields_set contains the field + if self.wiki_title is None and "wiki_title" in self.model_fields_set: + _dict["wikiTitle"] = None + + # set to None if url (nullable) is None + # and model_fields_set contains the field + if self.url is None and "url" in self.model_fields_set: + _dict["url"] = None + + # set to None if top_image (nullable) is None + # and model_fields_set contains the field + if self.top_image is None and "top_image" in self.model_fields_set: + _dict["topImage"] = None + + # set to None if wikidata_id (nullable) is None + # and model_fields_set contains the field + if self.wikidata_id is None and "wikidata_id" in self.model_fields_set: + _dict["wikidataId"] = None + + # set to None if wikidata_instance_of (nullable) is None + # and model_fields_set contains the field + if ( + self.wikidata_instance_of is None + and "wikidata_instance_of" in self.model_fields_set + ): + _dict["wikidataInstanceOf"] = None + + # set to None if redirect_titles (nullable) is None + # and model_fields_set contains the field + if self.redirect_titles is None and "redirect_titles" in self.model_fields_set: + _dict["redirectTitles"] = None + + # set to None if summary (nullable) is None + # and model_fields_set contains the field + if self.summary is None and "summary" in self.model_fields_set: + _dict["summary"] = None + + # set to None if sections (nullable) is None + # and model_fields_set contains the field + if self.sections is None and "sections" in self.model_fields_set: + _dict["sections"] = None + + # set to None if categories (nullable) is None + # and model_fields_set contains the field + if self.categories is None and "categories" in self.model_fields_set: + _dict["categories"] = None + + # set to None if external_links (nullable) is None + # and model_fields_set contains the field + if self.external_links is None and "external_links" in self.model_fields_set: + _dict["externalLinks"] = None + + # set to None if references (nullable) is None + # and model_fields_set contains the field + if self.references is None and "references" in self.model_fields_set: + _dict["references"] = None + + # set to None if pageviews (nullable) is None + # and model_fields_set contains the field + if self.pageviews is None and "pageviews" in self.model_fields_set: + _dict["pageviews"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikiPage from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "id": obj.get("id"), + "scrapedAt": obj.get("scrapedAt"), + "wikiPageId": obj.get("wikiPageId"), + "wikiRevisionId": obj.get("wikiRevisionId"), + "wikiRevisionTs": obj.get("wikiRevisionTs"), + "wikiCode": obj.get("wikiCode"), + "wikiNamespace": obj.get("wikiNamespace"), + "wikiTitle": obj.get("wikiTitle"), + "url": obj.get("url"), + "topImage": obj.get("topImage"), + "wikidataId": obj.get("wikidataId"), + "wikidataInstanceOf": ( + [ + WikidataLabelHolder.from_dict(_item) + for _item in obj["wikidataInstanceOf"] + ] + if obj.get("wikidataInstanceOf") is not None + else None + ), + "redirectTitles": obj.get("redirectTitles"), + "summary": obj.get("summary"), + "sections": ( + [ + WikiPageSectionHolder.from_dict(_item) + for _item in obj["sections"] + ] + if obj.get("sections") is not None + else None + ), + "categories": obj.get("categories"), + "externalLinks": obj.get("externalLinks"), + "references": obj.get("references"), + "pageviews": obj.get("pageviews"), + } + ) + return _obj diff --git a/perigon/models/wiki_page_section_holder.py b/perigon/models/wiki_page_section_holder.py new file mode 100644 index 0000000..cf0fab7 --- /dev/null +++ b/perigon/models/wiki_page_section_holder.py @@ -0,0 +1,135 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing_extensions import Self + + +class WikiPageSectionHolder(BaseModel): + """ + WikiPageSectionHolder + """ # noqa: E501 + + id: Optional[StrictStr] = None + title: Optional[StrictStr] = None + style_level: Optional[StrictInt] = Field(default=None, alias="styleLevel") + loc: Optional[List[StrictInt]] = None + text_raw: Optional[StrictStr] = Field(default=None, alias="textRaw") + text_rich: Optional[StrictStr] = Field(default=None, alias="textRich") + __properties: ClassVar[List[str]] = [ + "id", + "title", + "styleLevel", + "loc", + "textRaw", + "textRich", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikiPageSectionHolder from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # set to None if id (nullable) is None + # and model_fields_set contains the field + if self.id is None and "id" in self.model_fields_set: + _dict["id"] = None + + # set to None if title (nullable) is None + # and model_fields_set contains the field + if self.title is None and "title" in self.model_fields_set: + _dict["title"] = None + + # set to None if style_level (nullable) is None + # and model_fields_set contains the field + if self.style_level is None and "style_level" in self.model_fields_set: + _dict["styleLevel"] = None + + # set to None if loc (nullable) is None + # and model_fields_set contains the field + if self.loc is None and "loc" in self.model_fields_set: + _dict["loc"] = None + + # set to None if text_raw (nullable) is None + # and model_fields_set contains the field + if self.text_raw is None and "text_raw" in self.model_fields_set: + _dict["textRaw"] = None + + # set to None if text_rich (nullable) is None + # and model_fields_set contains the field + if self.text_rich is None and "text_rich" in self.model_fields_set: + _dict["textRich"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikiPageSectionHolder from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "id": obj.get("id"), + "title": obj.get("title"), + "styleLevel": obj.get("styleLevel"), + "loc": obj.get("loc"), + "textRaw": obj.get("textRaw"), + "textRich": obj.get("textRich"), + } + ) + return _obj diff --git a/perigon/models/wikipedia_search_filter.py b/perigon/models/wikipedia_search_filter.py new file mode 100644 index 0000000..5a3a665 --- /dev/null +++ b/perigon/models/wikipedia_search_filter.py @@ -0,0 +1,277 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt, StrictStr +from typing_extensions import Self + + +class WikipediaSearchFilter(BaseModel): + """ + Complex filter structure for Wikipedia page searches that supports nested logical operations (AND, OR, NOT) and multiple filtering criteria. + """ # noqa: E501 + + page_id: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific Perigon page identifiers. Accepts either a single ID or an array of IDs. Returns only pages matching these IDs.", + alias="pageId", + ) + section_id: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific section identifiers. Accepts either a single ID or an array of IDs. Returns only pages containing these sections.", + alias="sectionId", + ) + wiki_page_id: Optional[List[StrictInt]] = Field( + default=None, + description="Filter by specific Wikipedia page identifiers. Accepts either a single ID or an array of IDs. Returns only pages matching these IDs.", + alias="wikiPageId", + ) + wiki_revision_id: Optional[List[StrictInt]] = Field( + default=None, + description="Filter by specific Perigon page revision identifiers. Accepts either a single ID or an array of IDs. Returns only pages matching these IDs.", + alias="wikiRevisionId", + ) + wiki_code: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific Wikipedia project codes. Returns only pages matching these projects.", + alias="wikiCode", + ) + wiki_namespace: Optional[List[StrictInt]] = Field( + default=None, + description="Filter by specific Wikipedia namespaces. Returns only pages matching these namespaces.", + alias="wikiNamespace", + ) + wikidata_id: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific Wikidata entity IDs. Returns only pages whose Wikidata entities match those ids.", + alias="wikidataId", + ) + wikidata_instance_of_id: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific Wikidata entity IDs. Returns only pages whose Wikidata entities are instances of provided ids.", + alias="wikidataInstanceOfId", + ) + wikidata_instance_of_label: Optional[List[StrictStr]] = Field( + default=None, + description="Filter by specific Wikidata entity labels. Returns only pages whose Wikidata entities are instances of these labels.", + alias="wikidataInstanceOfLabel", + ) + var_and: Optional[List[WikipediaSearchFilter]] = Field( + default=None, + description="Adds additional AND filter objects. These objects must be of the same type as the original filter object and will be combined with the existing filter using the AND logical operator.", + alias="AND", + ) + var_or: Optional[List[WikipediaSearchFilter]] = Field( + default=None, + description="Adds additional OR filter objects. These objects must be of the same type as the original filter object and will be combined with the existing filter using the OR logical operator.", + alias="OR", + ) + var_not: Optional[List[WikipediaSearchFilter]] = Field( + default=None, + description="A filter object for logical NOT operations", + alias="NOT", + ) + __properties: ClassVar[List[str]] = [ + "pageId", + "sectionId", + "wikiPageId", + "wikiRevisionId", + "wikiCode", + "wikiNamespace", + "wikidataId", + "wikidataInstanceOfId", + "wikidataInstanceOfLabel", + "AND", + "OR", + "NOT", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikipediaSearchFilter from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in var_and (list) + _items = [] + if self.var_and: + for _item_var_and in self.var_and: + if _item_var_and: + _items.append(_item_var_and.to_dict()) + _dict["AND"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in var_or (list) + _items = [] + if self.var_or: + for _item_var_or in self.var_or: + if _item_var_or: + _items.append(_item_var_or.to_dict()) + _dict["OR"] = _items + # override the default output from pydantic by calling `to_dict()` of each item in var_not (list) + _items = [] + if self.var_not: + for _item_var_not in self.var_not: + if _item_var_not: + _items.append(_item_var_not.to_dict()) + _dict["NOT"] = _items + # set to None if page_id (nullable) is None + # and model_fields_set contains the field + if self.page_id is None and "page_id" in self.model_fields_set: + _dict["pageId"] = None + + # set to None if section_id (nullable) is None + # and model_fields_set contains the field + if self.section_id is None and "section_id" in self.model_fields_set: + _dict["sectionId"] = None + + # set to None if wiki_page_id (nullable) is None + # and model_fields_set contains the field + if self.wiki_page_id is None and "wiki_page_id" in self.model_fields_set: + _dict["wikiPageId"] = None + + # set to None if wiki_revision_id (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_id is None + and "wiki_revision_id" in self.model_fields_set + ): + _dict["wikiRevisionId"] = None + + # set to None if wiki_code (nullable) is None + # and model_fields_set contains the field + if self.wiki_code is None and "wiki_code" in self.model_fields_set: + _dict["wikiCode"] = None + + # set to None if wiki_namespace (nullable) is None + # and model_fields_set contains the field + if self.wiki_namespace is None and "wiki_namespace" in self.model_fields_set: + _dict["wikiNamespace"] = None + + # set to None if wikidata_id (nullable) is None + # and model_fields_set contains the field + if self.wikidata_id is None and "wikidata_id" in self.model_fields_set: + _dict["wikidataId"] = None + + # set to None if wikidata_instance_of_id (nullable) is None + # and model_fields_set contains the field + if ( + self.wikidata_instance_of_id is None + and "wikidata_instance_of_id" in self.model_fields_set + ): + _dict["wikidataInstanceOfId"] = None + + # set to None if wikidata_instance_of_label (nullable) is None + # and model_fields_set contains the field + if ( + self.wikidata_instance_of_label is None + and "wikidata_instance_of_label" in self.model_fields_set + ): + _dict["wikidataInstanceOfLabel"] = None + + # set to None if var_and (nullable) is None + # and model_fields_set contains the field + if self.var_and is None and "var_and" in self.model_fields_set: + _dict["AND"] = None + + # set to None if var_or (nullable) is None + # and model_fields_set contains the field + if self.var_or is None and "var_or" in self.model_fields_set: + _dict["OR"] = None + + # set to None if var_not (nullable) is None + # and model_fields_set contains the field + if self.var_not is None and "var_not" in self.model_fields_set: + _dict["NOT"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikipediaSearchFilter from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "pageId": obj.get("pageId"), + "sectionId": obj.get("sectionId"), + "wikiPageId": obj.get("wikiPageId"), + "wikiRevisionId": obj.get("wikiRevisionId"), + "wikiCode": obj.get("wikiCode"), + "wikiNamespace": obj.get("wikiNamespace"), + "wikidataId": obj.get("wikidataId"), + "wikidataInstanceOfId": obj.get("wikidataInstanceOfId"), + "wikidataInstanceOfLabel": obj.get("wikidataInstanceOfLabel"), + "AND": ( + [WikipediaSearchFilter.from_dict(_item) for _item in obj["AND"]] + if obj.get("AND") is not None + else None + ), + "OR": ( + [WikipediaSearchFilter.from_dict(_item) for _item in obj["OR"]] + if obj.get("OR") is not None + else None + ), + "NOT": ( + [WikipediaSearchFilter.from_dict(_item) for _item in obj["NOT"]] + if obj.get("NOT") is not None + else None + ), + } + ) + return _obj + + +# TODO: Rewrite to not use raise_errors +WikipediaSearchFilter.model_rebuild(raise_errors=False) diff --git a/perigon/models/wikipedia_search_params.py b/perigon/models/wikipedia_search_params.py new file mode 100644 index 0000000..d5871b8 --- /dev/null +++ b/perigon/models/wikipedia_search_params.py @@ -0,0 +1,179 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from datetime import datetime +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt +from typing_extensions import Annotated, Self + +from perigon.models.wikipedia_search_filter import WikipediaSearchFilter + + +class WikipediaSearchParams(BaseModel): + """ + WikipediaSearchParams + """ # noqa: E501 + + prompt: Annotated[str, Field(min_length=0, strict=True, max_length=1024)] = Field( + description="Natural language query to search the Wikipedia pages database" + ) + filter: Optional[WikipediaSearchFilter] = None + wiki_revision_from: Optional[datetime] = Field( + default=None, + description="'wikiRevisionFrom' filter, will search pages modified after the specified date, the date could be passed as ISO or 'yyyy-mm-dd'. Date time in ISO format, ie. 2024-01-01T00:00:00.", + alias="wikiRevisionFrom", + ) + wiki_revision_to: Optional[datetime] = Field( + default=None, + description="'wikiRevisionFrom' filter, will search pages modified before the specified date, the date could be passed as ISO or 'yyyy-mm-dd'. Date time in ISO format, ie. 2024-01-01T00:00:00.", + alias="wikiRevisionTo", + ) + pageviews_from: Optional[StrictInt] = Field( + default=None, + description="'pageviewsFrom' filter, will search pages with at least the provided number of views per day.", + alias="pageviewsFrom", + ) + pageviews_to: Optional[StrictInt] = Field( + default=None, + description="'pageviewsFrom' filter, will search pages with at most the provided number of views per day.", + alias="pageviewsTo", + ) + size: Optional[Annotated[int, Field(le=100, strict=True, ge=1)]] = Field( + default=None, description="The number of items per page." + ) + page: Optional[Annotated[int, Field(le=10000, strict=True, ge=0)]] = Field( + default=None, description="The page number to retrieve." + ) + __properties: ClassVar[List[str]] = [ + "prompt", + "filter", + "wikiRevisionFrom", + "wikiRevisionTo", + "pageviewsFrom", + "pageviewsTo", + "size", + "page", + ] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikipediaSearchParams from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of filter + if self.filter: + _dict["filter"] = self.filter.to_dict() + # set to None if wiki_revision_from (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_from is None + and "wiki_revision_from" in self.model_fields_set + ): + _dict["wikiRevisionFrom"] = None + + # set to None if wiki_revision_to (nullable) is None + # and model_fields_set contains the field + if ( + self.wiki_revision_to is None + and "wiki_revision_to" in self.model_fields_set + ): + _dict["wikiRevisionTo"] = None + + # set to None if pageviews_from (nullable) is None + # and model_fields_set contains the field + if self.pageviews_from is None and "pageviews_from" in self.model_fields_set: + _dict["pageviewsFrom"] = None + + # set to None if pageviews_to (nullable) is None + # and model_fields_set contains the field + if self.pageviews_to is None and "pageviews_to" in self.model_fields_set: + _dict["pageviewsTo"] = None + + # set to None if size (nullable) is None + # and model_fields_set contains the field + if self.size is None and "size" in self.model_fields_set: + _dict["size"] = None + + # set to None if page (nullable) is None + # and model_fields_set contains the field + if self.page is None and "page" in self.model_fields_set: + _dict["page"] = None + + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikipediaSearchParams from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "prompt": obj.get("prompt"), + "filter": ( + WikipediaSearchFilter.from_dict(obj["filter"]) + if obj.get("filter") is not None + else None + ), + "wikiRevisionFrom": obj.get("wikiRevisionFrom"), + "wikiRevisionTo": obj.get("wikiRevisionTo"), + "pageviewsFrom": obj.get("pageviewsFrom"), + "pageviewsTo": obj.get("pageviewsTo"), + "size": obj.get("size"), + "page": obj.get("page"), + } + ) + return _obj diff --git a/perigon/models/wikipedia_search_result.py b/perigon/models/wikipedia_search_result.py new file mode 100644 index 0000000..fed4b9d --- /dev/null +++ b/perigon/models/wikipedia_search_result.py @@ -0,0 +1,105 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, Field, StrictInt +from typing_extensions import Self + +from perigon.models.wiki_page import WikiPage + + +class WikipediaSearchResult(BaseModel): + """ + Wikipedia search result + """ # noqa: E501 + + status: StrictInt + num_results: StrictInt = Field(alias="numResults") + results: List[WikiPage] + __properties: ClassVar[List[str]] = ["status", "numResults", "results"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikipediaSearchResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikipediaSearchResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "status": obj.get("status"), + "numResults": obj.get("numResults"), + "results": ( + [WikiPage.from_dict(_item) for _item in obj["results"]] + if obj.get("results") is not None + else None + ), + } + ) + return _obj diff --git a/perigon/models/wikipedia_vector_search_result.py b/perigon/models/wikipedia_vector_search_result.py new file mode 100644 index 0000000..4a523d0 --- /dev/null +++ b/perigon/models/wikipedia_vector_search_result.py @@ -0,0 +1,103 @@ +# coding: utf-8 + +""" +Perigon API + +The Perigon API provides access to comprehensive news and web content data. To use the API, simply sign up for a Perigon Business Solutions account to obtain your API key. Your available features may vary based on your plan. See the Authentication section for details on how to use your API key. + +The version of the OpenAPI document: 1.0.0 +Contact: data@perigon.io +Generated by OpenAPI Generator (https://openapi-generator.tech) + +Do not edit the class manually. +""" # noqa: E501 + + +from __future__ import annotations + +import json +import pprint +import re # noqa: F401 +from typing import Any, ClassVar, Dict, List, Optional, Set + +from pydantic import BaseModel, ConfigDict, StrictInt +from typing_extensions import Self + +from perigon.models.scored_data_wiki_data import ScoredDataWikiData + + +class WikipediaVectorSearchResult(BaseModel): + """ + Wikipedia vector search result + """ # noqa: E501 + + status: StrictInt + results: List[ScoredDataWikiData] + __properties: ClassVar[List[str]] = ["status", "results"] + + model_config = ConfigDict( + populate_by_name=True, + validate_assignment=True, + protected_namespaces=(), + ) + + def to_str(self) -> str: + """Returns the string representation of the model using alias""" + return pprint.pformat(self.model_dump(by_alias=True)) + + def to_json(self) -> str: + """Returns the JSON representation of the model using alias""" + # TODO: pydantic v2: use .model_dump_json(by_alias=True, exclude_unset=True) instead + return json.dumps(self.to_dict()) + + @classmethod + def from_json(cls, json_str: str) -> Optional[Self]: + """Create an instance of WikipediaVectorSearchResult from a JSON string""" + return cls.from_dict(json.loads(json_str)) + + def to_dict(self) -> Dict[str, Any]: + """Return the dictionary representation of the model using alias. + + This has the following differences from calling pydantic's + `self.model_dump(by_alias=True)`: + + * `None` is only added to the output dict for nullable fields that + were set at model initialization. Other fields with value `None` + are ignored. + """ + excluded_fields: Set[str] = set([]) + + _dict = self.model_dump( + by_alias=True, + exclude=excluded_fields, + exclude_none=True, + ) + # override the default output from pydantic by calling `to_dict()` of each item in results (list) + _items = [] + if self.results: + for _item_results in self.results: + if _item_results: + _items.append(_item_results.to_dict()) + _dict["results"] = _items + return _dict + + @classmethod + def from_dict(cls, obj: Optional[Dict[str, Any]]) -> Optional[Self]: + """Create an instance of WikipediaVectorSearchResult from a dict""" + if obj is None: + return None + + if not isinstance(obj, dict): + return cls.model_validate(obj) + + _obj = cls.model_validate( + { + "status": obj.get("status"), + "results": ( + [ScoredDataWikiData.from_dict(_item) for _item in obj["results"]] + if obj.get("results") is not None + else None + ), + } + ) + return _obj diff --git a/poetry.lock b/poetry.lock index 2e9abe3..187436d 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -466,6 +466,21 @@ files = [ {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] +[[package]] +name = "openapi-generator-cli" +version = "7.14.0" +description = "CLI for openapi generator" +optional = false +python-versions = "<4,>=3.9" +groups = ["main"] +files = [ + {file = "openapi_generator_cli-7.14.0-py3-none-any.whl", hash = "sha256:fbf7b606671fd939ab1ee185942396aa4ba88f8ec211a30a47ce02f81855778e"}, + {file = "openapi_generator_cli-7.14.0.tar.gz", hash = "sha256:48b5478a83ee09dfd38018da3e1661acafd2ce06627aecce0ec10a66cbd1aa00"}, +] + +[package.extras] +jdk4py = ["jdk4py (>=21.0.4.1,<22) ; python_version >= \"3.10\""] + [[package]] name = "packaging" version = "25.0" @@ -916,4 +931,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.1" python-versions = "^3.9" -content-hash = "6a9f851597a57497c4f351548dc17ced608124ba817dbc10d65a9b49c51be3ed" +content-hash = "0cc5f7bd871dd7a0a77b4e0c3100bda1815fa9248995f1acbe5feaf590b73665" From 2fc6f087f74d6dbc1077782844a6bc581b2e6241 Mon Sep 17 00:00:00 2001 From: Islem Maboud Date: Wed, 23 Jul 2025 10:47:04 +0100 Subject: [PATCH 2/2] feat: update examples to include the new wikipedia endpoints --- .gitignore | 2 ++ examples/advanced.py | 53 ++++++++++++++++++++++++++++++++++++++++++-- examples/basic.py | 39 ++++++++++++++++++++++++++++++++ poetry.lock | 17 +------------- 4 files changed, 93 insertions(+), 18 deletions(-) diff --git a/.gitignore b/.gitignore index 43995bd..1b2eda4 100644 --- a/.gitignore +++ b/.gitignore @@ -64,3 +64,5 @@ target/ #Ipython Notebook .ipynb_checkpoints + +.env \ No newline at end of file diff --git a/examples/advanced.py b/examples/advanced.py index f1ad711..ed3b458 100644 --- a/examples/advanced.py +++ b/examples/advanced.py @@ -20,7 +20,7 @@ from datetime import datetime, timedelta, timezone from perigon import ApiClient, V1Api -from perigon.models import ArticleSearchParams, SummaryBody +from perigon.models import ArticleSearchParams, SummaryBody, WikipediaSearchParams def main(): @@ -152,7 +152,56 @@ def main(): except Exception as e: print(f" āŒ Error exploring topics: {e}") - # Example 6: Demonstrate async usage + # Example 6: Vector-based Wikipedia Search + print("\n🧠 Example 6: Vector-based Wikipedia Search") + print( + "Using semantic search to find Wikipedia pages related to artificial intelligence...\n" + ) + + try: + vector_wikipedia_result = api.vector_search_wikipedia( + wikipedia_search_params=WikipediaSearchParams( + prompt="artificial intelligence and neural networks in computing", + size=3, + pageviews_from=100, # Only pages with significant viewership + ) + ) + + print( + f"Found {len(vector_wikipedia_result.results)} semantically related Wikipedia pages:" + ) + for i, result in enumerate(vector_wikipedia_result.results, 1): + page = result.data + print(f" {i}. {page.wiki_title or 'Untitled' if page else 'Untitled'}") + print( + f" Relevance Score: {(result.score * 100):.1f}%" + if result.score + else " Relevance Score: N/A" + ) + print(f" URL: {page.url if page and hasattr(page, 'url') else 'N/A'}") + + summary = "No summary available" + if page and hasattr(page, "content") and page.content: + summary = ( + page.content[:200] + "..." + if len(page.content) > 200 + else page.content + ) + elif page and hasattr(page, "summary") and page.summary: + summary = ( + page.summary[:200] + "..." + if len(page.summary) > 200 + else page.summary + ) + print(f" Summary: {summary}") + + print(f" Views per day: {page.pageviews or 'N/A' if page else 'N/A'}") + print(f" Wikidata ID: {page.wikidata_id or 'N/A' if page else 'N/A'}\n") + + except Exception as e: + print(f" āŒ Error in vector Wikipedia search: {e}") + + # Example 7: Demonstrate async usage print("\nšŸ”„ Running async operations...") asyncio.run(async_example(api)) diff --git a/examples/basic.py b/examples/basic.py index 2a5d1f1..7fca3e9 100644 --- a/examples/basic.py +++ b/examples/basic.py @@ -12,6 +12,7 @@ """ import os +from datetime import datetime from perigon import ApiClient, V1Api @@ -83,6 +84,44 @@ def main(): except Exception as e: print(f" āŒ Error searching journalists: {e}") + # Example 4: Wikipedia Search + print("šŸ“š Example 4: Wikipedia Search") + print('Searching Wikipedia pages about "machine learning"...\n') + + try: + wikipedia_result = api.search_wikipedia( + q="machine learning", + size=3, + sort_by="relevance", + ) + + print(f"Found {wikipedia_result.num_results} Wikipedia pages:") + for i, page in enumerate(wikipedia_result.results, 1): + print(f" {i}. {page.wiki_title or 'Untitled'}") + print(f" URL: {page.url or 'N/A'}") + summary = page.summary if page.summary else "No summary available" + if len(summary) > 150: + summary = summary[:150] + "..." + print(f" Summary: {summary}") + print(f" Views per day: {page.pageviews or 'N/A'}") + + # Format the revision timestamp if available + last_modified = "Unknown" + if page.wiki_revision_ts: + try: + # Parse ISO timestamp and format as date + dt = datetime.fromisoformat( + page.wiki_revision_ts.replace("Z", "+00:00") + ) + last_modified = dt.strftime("%m/%d/%Y") + except: + last_modified = page.wiki_revision_ts + + print(f" Last modified: {last_modified}\n") + + except Exception as e: + print(f" āŒ Error searching Wikipedia: {e}") + print("āœ… Basic example completed!") diff --git a/poetry.lock b/poetry.lock index 187436d..b1e55b4 100644 --- a/poetry.lock +++ b/poetry.lock @@ -466,21 +466,6 @@ files = [ {file = "mypy_extensions-1.1.0.tar.gz", hash = "sha256:52e68efc3284861e772bbcd66823fde5ae21fd2fdb51c62a211403730b916558"}, ] -[[package]] -name = "openapi-generator-cli" -version = "7.14.0" -description = "CLI for openapi generator" -optional = false -python-versions = "<4,>=3.9" -groups = ["main"] -files = [ - {file = "openapi_generator_cli-7.14.0-py3-none-any.whl", hash = "sha256:fbf7b606671fd939ab1ee185942396aa4ba88f8ec211a30a47ce02f81855778e"}, - {file = "openapi_generator_cli-7.14.0.tar.gz", hash = "sha256:48b5478a83ee09dfd38018da3e1661acafd2ce06627aecce0ec10a66cbd1aa00"}, -] - -[package.extras] -jdk4py = ["jdk4py (>=21.0.4.1,<22) ; python_version >= \"3.10\""] - [[package]] name = "packaging" version = "25.0" @@ -931,4 +916,4 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [metadata] lock-version = "2.1" python-versions = "^3.9" -content-hash = "0cc5f7bd871dd7a0a77b4e0c3100bda1815fa9248995f1acbe5feaf590b73665" +content-hash = "6a9f851597a57497c4f351548dc17ced608124ba817dbc10d65a9b49c51be3ed"