diff --git a/.fern/metadata.json b/.fern/metadata.json index 31aa673..afb5b93 100644 --- a/.fern/metadata.json +++ b/.fern/metadata.json @@ -1,7 +1,7 @@ { - "cliVersion": "4.68.0", + "cliVersion": "4.90.0", "generatorName": "fernapi/fern-python-sdk", - "generatorVersion": "5.3.13", + "generatorVersion": "5.5.11", "generatorConfig": { "client": { "class_name": "BaseNewscatcherApi", @@ -10,6 +10,10 @@ "exported_filename": "client.py" } }, - "originGitCommit": "c6c9411cf393ebdaab54b4265a5a8775d22986da", - "sdkVersion": "2.0.3" + "originGitCommit": "3707beee5d0e236f2469e89f7b19c3a08efb6f95", + "originGitCommitIsDirty": false, + "invokedBy": "manual", + "requestedVersion": "2.1.0", + "ciProvider": null, + "sdkVersion": "2.1.0" } \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 443b1da..2a97347 100644 --- a/poetry.lock +++ b/poetry.lock @@ -233,13 +233,13 @@ files = [ [[package]] name = "certifi" -version = "2026.2.25" +version = "2026.4.22" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.7" files = [ - {file = "certifi-2026.2.25-py3-none-any.whl", hash = "sha256:027692e4402ad994f1c42e52a4997a9763c646b73e4096e4d5d6db8af1d6f0fa"}, - {file = "certifi-2026.2.25.tar.gz", hash = "sha256:e887ab5cee78ea814d3472169153c2d12cd43b14bd03329a39a9c6e2e80bfba7"}, + {file = "certifi-2026.4.22-py3-none-any.whl", hash = "sha256:3cb2210c8f88ba2318d29b0388d1023c8492ff72ecdde4ebdaddbb13a31b1c4a"}, + {file = "certifi-2026.4.22.tar.gz", hash = "sha256:8d455352a37b71bf76a79caa83a3d6c25afee4a385d632127b6afb3963f1c580"}, ] [[package]] @@ -496,17 +496,17 @@ httpx = ">=0.27.0" [[package]] name = "idna" -version = "3.11" +version = "3.13" description = "Internationalized Domain Names in Applications (IDNA)" optional = false python-versions = ">=3.8" files = [ - {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"}, - {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"}, + {file = "idna-3.13-py3-none-any.whl", hash = "sha256:892ea0cde124a99ce773decba204c5552b69c3c67ffd5f232eb7696135bc8bb3"}, + {file = "idna-3.13.tar.gz", hash = "sha256:585ea8fe5d69b9181ec1afba340451fba6ba764af97026f92a91d4eef164a242"}, ] [package.extras] -all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] +all = ["mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] [[package]] name = "iniconfig" @@ -1068,20 +1068,20 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pytest" -version = "8.4.2" +version = "9.0.3" description = "pytest: simple powerful testing with Python" optional = false -python-versions = ">=3.9" +python-versions = ">=3.10" files = [ - {file = "pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79"}, - {file = "pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01"}, + {file = "pytest-9.0.3-py3-none-any.whl", hash = "sha256:2c5efc453d45394fdd706ade797c0a81091eccd1d6e4bccfcd476e2b8e0ab5d9"}, + {file = "pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c"}, ] [package.dependencies] colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1", markers = "python_version < \"3.11\""} -iniconfig = ">=1" -packaging = ">=20" +iniconfig = ">=1.0.1" +packaging = ">=22" pluggy = ">=1.5,<2" pygments = ">=2.7.2" tomli = {version = ">=1", markers = "python_version < \"3.11\""} @@ -1273,6 +1273,23 @@ files = [ [package.dependencies] typing-extensions = ">=4.12.0" +[[package]] +name = "urllib3" +version = "2.6.3" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +files = [ + {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"}, + {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"}, +] + +[package.extras] +brotli = ["brotli (>=1.2.0)", "brotlicffi (>=1.2.0.0)"] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["backports-zstd (>=1.0.0)"] + [[package]] name = "yarl" version = "1.23.0" @@ -1421,4 +1438,4 @@ aiohttp = ["aiohttp", "httpx-aiohttp"] [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "c22c549ef574a50fc48074038793033112a025836768a63fcc3749869d1bcc8e" +content-hash = "02ee31852ff3143d28cf513ee3fa1b514fe2ba936dcffc8ab6cc98f7c9570c01" diff --git a/pyproject.toml b/pyproject.toml index a7f127a..c9c8dca 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ dynamic = ["version"] [tool.poetry] name = "newscatcher-sdk" -version = "2.0.3" +version = "2.1.0" description = "" readme = "README.md" authors = [] @@ -38,20 +38,21 @@ Repository = 'https://github.com/Newscatcher/newscatcher-python' [tool.poetry.dependencies] python = "^3.10" -aiohttp = { version = ">=3.10.0,<4", optional = true} +aiohttp = { version = ">=3.13.4,<4", optional = true, python = ">=3.9"} httpx = ">=0.21.2" -httpx-aiohttp = { version = "0.1.8", optional = true} +httpx-aiohttp = { version = "0.1.8", optional = true, python = ">=3.9"} pydantic = ">= 1.9.2" pydantic-core = ">=2.18.2,<2.44.0" typing_extensions = ">= 4.0.0" [tool.poetry.group.dev.dependencies] mypy = "==1.13.0" -pytest = "^8.2.0" +pytest = "^9.0.3" pytest-asyncio = "^1.0.0" pytest-xdist = "^3.6.1" python-dateutil = "^2.9.0" types-python-dateutil = "^2.9.0.20240316" +urllib3 = ">=1.26.19,<2.0.0 || >=2.2.2,<3.0.0" ruff = "==0.11.5" [tool.pytest.ini_options] diff --git a/reference.md b/reference.md index 8bc22eb..c0b59a5 100644 --- a/reference.md +++ b/reference.md @@ -49,8 +49,8 @@ client.search.get( countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat("2024-07-01T00:00:00+00:00"), - to=datetime.datetime.fromisoformat("2024-01-01T00:00:00+00:00"), + from_=datetime.datetime.fromisoformat("1 day ago"), + to=datetime.datetime.fromisoformat("1 day ago"), published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -71,7 +71,7 @@ client.search.get( page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_nlp_data=True, has_nlp=True, theme="Finance,Tech", @@ -1233,7 +1233,7 @@ client.latest_headlines.get( page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_translation_fields=True, include_nlp_data=True, has_nlp=True, @@ -2645,8 +2645,8 @@ client.authors.get( not_lang="fr,de", countries="US,CA", not_countries="UK,FR", - from_=datetime.datetime.fromisoformat("2024-07-01T00:00:00+00:00"), - to=datetime.datetime.fromisoformat("2024-01-01T00:00:00+00:00"), + from_=datetime.datetime.fromisoformat("1 day ago"), + to=datetime.datetime.fromisoformat("1 day ago"), published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -3584,8 +3584,8 @@ client = NewscatcherApi( client.search_by_link.get( ids="5f8d0d55b6e45e00179c6e7e", links="https://nytimes.com/article1,https://bbc.com/article2", - from_=datetime.datetime.fromisoformat("2024-07-01T00:00:00+00:00"), - to=datetime.datetime.fromisoformat("2024-01-01T00:00:00+00:00"), + from_=datetime.datetime.fromisoformat("1 day ago"), + to=datetime.datetime.fromisoformat("1 day ago"), page=2, page_size=50, robots_compliant=True, @@ -4211,8 +4211,8 @@ client.aggregation_count.get( countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat("2024-07-01T00:00:00+00:00"), - to=datetime.datetime.fromisoformat("2024-01-01T00:00:00+00:00"), + from_=datetime.datetime.fromisoformat("1 day ago"), + to=datetime.datetime.fromisoformat("1 day ago"), published_date_precision="full", by_parse_date=True, ranked_only=True, diff --git a/src/newscatcher/aggregation_count/client.py b/src/newscatcher/aggregation_count/client.py index b771554..355c61b 100644 --- a/src/newscatcher/aggregation_count/client.py +++ b/src/newscatcher/aggregation_count/client.py @@ -269,8 +269,6 @@ def get( Examples -------- - import datetime - from newscatcher import NewscatcherApi client = NewscatcherApi( @@ -287,12 +285,8 @@ def get( countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -805,7 +799,6 @@ async def get( Examples -------- import asyncio - import datetime from newscatcher import AsyncNewscatcherApi @@ -826,12 +819,8 @@ async def main() -> None: countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, diff --git a/src/newscatcher/authors/client.py b/src/newscatcher/authors/client.py index 8b3f4d0..8df664a 100644 --- a/src/newscatcher/authors/client.py +++ b/src/newscatcher/authors/client.py @@ -282,8 +282,6 @@ def get( Examples -------- - import datetime - from newscatcher import NewscatcherApi client = NewscatcherApi( @@ -299,12 +297,8 @@ def get( not_lang="fr,de", countries="US,CA", not_countries="UK,FR", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -826,7 +820,6 @@ async def get( Examples -------- import asyncio - import datetime from newscatcher import AsyncNewscatcherApi @@ -846,12 +839,8 @@ async def main() -> None: not_lang="fr,de", countries="US,CA", not_countries="UK,FR", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, diff --git a/src/newscatcher/core/client_wrapper.py b/src/newscatcher/core/client_wrapper.py index 0d74594..19baf46 100644 --- a/src/newscatcher/core/client_wrapper.py +++ b/src/newscatcher/core/client_wrapper.py @@ -27,12 +27,12 @@ def get_headers(self) -> typing.Dict[str, str]: import platform headers: typing.Dict[str, str] = { - "User-Agent": "newscatcher-sdk/2.0.3", + "User-Agent": "newscatcher-sdk/2.1.0", "X-Fern-Language": "Python", "X-Fern-Runtime": f"python/{platform.python_version()}", "X-Fern-Platform": f"{platform.system().lower()}/{platform.release()}", "X-Fern-SDK-Name": "newscatcher-sdk", - "X-Fern-SDK-Version": "2.0.3", + "X-Fern-SDK-Version": "2.1.0", **(self.get_custom_headers() or {}), } headers["x-api-token"] = self.api_key diff --git a/src/newscatcher/latest_headlines/client.py b/src/newscatcher/latest_headlines/client.py index c9df15d..19704d5 100644 --- a/src/newscatcher/latest_headlines/client.py +++ b/src/newscatcher/latest_headlines/client.py @@ -315,7 +315,7 @@ def get( page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_translation_fields=True, include_nlp_data=True, has_nlp=True, @@ -862,7 +862,7 @@ async def main() -> None: page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_translation_fields=True, include_nlp_data=True, has_nlp=True, diff --git a/src/newscatcher/search/client.py b/src/newscatcher/search/client.py index 4d73d8a..e3debf9 100644 --- a/src/newscatcher/search/client.py +++ b/src/newscatcher/search/client.py @@ -340,8 +340,6 @@ def get( Examples -------- - import datetime - from newscatcher import NewscatcherApi client = NewscatcherApi( @@ -360,12 +358,8 @@ def get( countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -386,7 +380,7 @@ def get( page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_nlp_data=True, has_nlp=True, theme="Finance,Tech", @@ -1006,7 +1000,6 @@ async def get( Examples -------- import asyncio - import datetime from newscatcher import AsyncNewscatcherApi @@ -1029,12 +1022,8 @@ async def main() -> None: countries="US,CA", not_countries="UK,FR", not_author_name="John Doe, Jane Doe", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", published_date_precision="full", by_parse_date=True, ranked_only=True, @@ -1055,7 +1044,7 @@ async def main() -> None: page=2, page_size=50, clustering_enabled=True, - clustering_threshold=0.6, + clustering_threshold=0.7, include_nlp_data=True, has_nlp=True, theme="Finance,Tech", diff --git a/src/newscatcher/search_by_link/client.py b/src/newscatcher/search_by_link/client.py index 8a00433..55917b5 100644 --- a/src/newscatcher/search_by_link/client.py +++ b/src/newscatcher/search_by_link/client.py @@ -80,8 +80,6 @@ def get( Examples -------- - import datetime - from newscatcher import NewscatcherApi client = NewscatcherApi( @@ -90,12 +88,8 @@ def get( client.search_by_link.get( ids="5f8d0d55b6e45e00179c6e7e", links="https://nytimes.com/article1,https://bbc.com/article2", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", page=2, page_size=50, robots_compliant=True, @@ -255,7 +249,6 @@ async def get( Examples -------- import asyncio - import datetime from newscatcher import AsyncNewscatcherApi @@ -268,12 +261,8 @@ async def main() -> None: await client.search_by_link.get( ids="5f8d0d55b6e45e00179c6e7e", links="https://nytimes.com/article1,https://bbc.com/article2", - from_=datetime.datetime.fromisoformat( - "2024-07-01 00:00:00+00:00", - ), - to=datetime.datetime.fromisoformat( - "2024-01-01 00:00:00+00:00", - ), + from_="1 day ago", + to="1 day ago", page=2, page_size=50, robots_compliant=True, diff --git a/src/newscatcher/types/additional_source_info.py b/src/newscatcher/types/additional_source_info.py index 55f984f..3a0b544 100644 --- a/src/newscatcher/types/additional_source_info.py +++ b/src/newscatcher/types/additional_source_info.py @@ -13,7 +13,7 @@ class AdditionalSourceInfo(UniversalBaseModel): The data model for additional information about a news source. """ - nb_articles_for_7_d: typing_extensions.Annotated[ + nb_articles_for7d: typing_extensions.Annotated[ typing.Optional[int], FieldMetadata(alias="nb_articles_for_7d"), pydantic.Field( diff --git a/src/newscatcher/types/clustering_threshold.py b/src/newscatcher/types/clustering_threshold.py index c80b634..a8da1a0 100644 --- a/src/newscatcher/types/clustering_threshold.py +++ b/src/newscatcher/types/clustering_threshold.py @@ -5,9 +5,9 @@ Sets the similarity threshold for grouping articles into clusters. A lower value creates more inclusive clusters, while a higher value requires greater similarity between articles. For example: -- `0.3`: Results in larger, more diverse clusters. -- `0.6`: Balances cluster size and article similarity (default). -- `0.9`: Creates smaller, tightly related clusters. +- `0.6`: Results in larger, more diverse clusters. +- `0.7`: Balances cluster size and article similarity (default). +- `0.8`: Creates smaller, tightly related clusters. To learn more, see [Clustering news articles](https://www.newscatcherapi.com/docs/news-api/guides-and-concepts/clustering-news-articles). """ diff --git a/src/newscatcher/types/has_nlp.py b/src/newscatcher/types/has_nlp.py index 5acd14d..bbf43f6 100644 --- a/src/newscatcher/types/has_nlp.py +++ b/src/newscatcher/types/has_nlp.py @@ -4,5 +4,7 @@ """ If true, filters results to include only articles that have NLP data. +**Note**: NLP data is only available for articles indexed from July 2023 onward. Applying this filter to a date range that predates July 2023 returns zero results. + To learn more, see [NLP features](https://www.newscatcherapi.com/docs/news-api/guides-and-concepts/nlp-features). """ diff --git a/src/newscatcher/types/include_nlp_data.py b/src/newscatcher/types/include_nlp_data.py index 0478677..2d6ddb5 100644 --- a/src/newscatcher/types/include_nlp_data.py +++ b/src/newscatcher/types/include_nlp_data.py @@ -4,5 +4,7 @@ """ If true, includes an NLP object for each article in the response. This object provides results of NLP analysis, including article theme, summary, sentiment, tags, and named entity recognition if available. +**Note**: NLP data is only available for articles indexed from July 2023 onward. For articles indexed before July 2023, the `nlp` field is returned as an empty object `{}`. + To learn more, see [NLP features](https://www.newscatcherapi.com/docs/news-api/guides-and-concepts/nlp-features). """ diff --git a/src/newscatcher/types/nlp_data_entity.py b/src/newscatcher/types/nlp_data_entity.py index 98bc8d6..882b590 100644 --- a/src/newscatcher/types/nlp_data_entity.py +++ b/src/newscatcher/types/nlp_data_entity.py @@ -33,11 +33,18 @@ class NlpDataEntity(UniversalBaseModel): sentiment: typing.Optional[SentimentScores] = None new_embedding: typing.Optional[typing.List[float]] = pydantic.Field(default=None) """ - A dense 1024-dimensional vector representation of the article content, generated using the [multilingual-e5-large](https://huggingface.co/intfloat/multilingual-e5-large) model. + A dense 1024-dimensional vector representation of the article content, generated using the [multilingual-e5-large](https://huggingface.co/intfloat/multilingual-e5-large) model. Available for articles indexed before January 1, 2026. **Note**: The `new_embedding` field is only available in the `v3_nlp_embeddings` subscription plan. """ + qwen_embedding: typing.Optional[typing.List[float]] = pydantic.Field(default=None) + """ + A dense 1024-dimensional vector representation of the article content, generated using the [Qwen3-Embedding-0.6B](https://huggingface.co/Qwen/Qwen3-Embedding) model. Available for articles indexed from January 1, 2026 onward. Embeddings are computed from a combination of the article `title` and `content` fields. + + **Note**: The `qwen_embedding` field is only available in the `v3_nlp_embeddings` subscription plan. + """ + ner_per: typing_extensions.Annotated[ typing.Optional[NamedEntityList], FieldMetadata(alias="ner_PER"),