diff --git a/.fern/metadata.json b/.fern/metadata.json
new file mode 100644
index 0000000..3c6b7f6
--- /dev/null
+++ b/.fern/metadata.json
@@ -0,0 +1,13 @@
+{
+ "cliVersion": "1.7.0",
+ "generatorName": "fernapi/fern-python-sdk",
+ "generatorVersion": "4.37.0",
+ "generatorConfig": {
+ "client": {
+ "class_name": "BaseNewscatcherApi",
+ "filename": "base_client.py",
+ "exported_class_name": "NewscatcherApi",
+ "exported_filename": "client.py"
+ }
+ }
+}
\ No newline at end of file
diff --git a/changelog.md b/changelog.md
new file mode 100644
index 0000000..a7781e9
--- /dev/null
+++ b/changelog.md
@@ -0,0 +1,4 @@
+## 1.4.1 - 2025-12-29
+* SDK regeneration
+* Unable to analyze changes with AI, incrementing PATCH version.
+
diff --git a/poetry.lock b/poetry.lock
index c2ddd86..a19d7e2 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -38,13 +38,13 @@ trio = ["trio (>=0.26.1)"]
[[package]]
name = "certifi"
-version = "2025.8.3"
+version = "2025.11.12"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.7"
files = [
- {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"},
- {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"},
+ {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"},
+ {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"},
]
[[package]]
@@ -60,13 +60,13 @@ files = [
[[package]]
name = "exceptiongroup"
-version = "1.3.0"
+version = "1.3.1"
description = "Backport of PEP 654 (exception groups)"
optional = false
python-versions = ">=3.7"
files = [
- {file = "exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10"},
- {file = "exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88"},
+ {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"},
+ {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"},
]
[package.dependencies]
@@ -133,13 +133,13 @@ zstd = ["zstandard (>=0.18.0)"]
[[package]]
name = "idna"
-version = "3.10"
+version = "3.11"
description = "Internationalized Domain Names in Applications (IDNA)"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
files = [
- {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"},
- {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"},
+ {file = "idna-3.11-py3-none-any.whl", hash = "sha256:771a87f49d9defaf64091e6e6fe9c18d4833f140bd19464795bc32d966ca37ea"},
+ {file = "idna-3.11.tar.gz", hash = "sha256:795dafcc9c04ed0c1fb032c2aa73654d8e8c5023a7df64a53f39190ada629902"},
]
[package.extras]
@@ -483,43 +483,53 @@ files = [
[[package]]
name = "tomli"
-version = "2.2.1"
+version = "2.3.0"
description = "A lil' TOML parser"
optional = false
python-versions = ">=3.8"
files = [
- {file = "tomli-2.2.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:678e4fa69e4575eb77d103de3df8a895e1591b48e740211bd1067378c69e8249"},
- {file = "tomli-2.2.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:023aa114dd824ade0100497eb2318602af309e5a55595f76b626d6d9f3b7b0a6"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ece47d672db52ac607a3d9599a9d48dcb2f2f735c6c2d1f34130085bb12b112a"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6972ca9c9cc9f0acaa56a8ca1ff51e7af152a9f87fb64623e31d5c83700080ee"},
- {file = "tomli-2.2.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c954d2250168d28797dd4e3ac5cf812a406cd5a92674ee4c8f123c889786aa8e"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:8dd28b3e155b80f4d54beb40a441d366adcfe740969820caf156c019fb5c7ec4"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:e59e304978767a54663af13c07b3d1af22ddee3bb2fb0618ca1593e4f593a106"},
- {file = "tomli-2.2.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:33580bccab0338d00994d7f16f4c4ec25b776af3ffaac1ed74e0b3fc95e885a8"},
- {file = "tomli-2.2.1-cp311-cp311-win32.whl", hash = "sha256:465af0e0875402f1d226519c9904f37254b3045fc5084697cefb9bdde1ff99ff"},
- {file = "tomli-2.2.1-cp311-cp311-win_amd64.whl", hash = "sha256:2d0f2fdd22b02c6d81637a3c95f8cd77f995846af7414c5c4b8d0545afa1bc4b"},
- {file = "tomli-2.2.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:4a8f6e44de52d5e6c657c9fe83b562f5f4256d8ebbfe4ff922c495620a7f6cea"},
- {file = "tomli-2.2.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8d57ca8095a641b8237d5b079147646153d22552f1c637fd3ba7f4b0b29167a8"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e340144ad7ae1533cb897d406382b4b6fede8890a03738ff1683af800d54192"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2b95f9de79181805df90bedc5a5ab4c165e6ec3fe99f970d0e302f384ad222"},
- {file = "tomli-2.2.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:40741994320b232529c802f8bc86da4e1aa9f413db394617b9a256ae0f9a7f77"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:400e720fe168c0f8521520190686ef8ef033fb19fc493da09779e592861b78c6"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:02abe224de6ae62c19f090f68da4e27b10af2b93213d36cf44e6e1c5abd19fdd"},
- {file = "tomli-2.2.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b82ebccc8c8a36f2094e969560a1b836758481f3dc360ce9a3277c65f374285e"},
- {file = "tomli-2.2.1-cp312-cp312-win32.whl", hash = "sha256:889f80ef92701b9dbb224e49ec87c645ce5df3fa2cc548664eb8a25e03127a98"},
- {file = "tomli-2.2.1-cp312-cp312-win_amd64.whl", hash = "sha256:7fc04e92e1d624a4a63c76474610238576942d6b8950a2d7f908a340494e67e4"},
- {file = "tomli-2.2.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f4039b9cbc3048b2416cc57ab3bda989a6fcf9b36cf8937f01a6e731b64f80d7"},
- {file = "tomli-2.2.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:286f0ca2ffeeb5b9bd4fcc8d6c330534323ec51b2f52da063b11c502da16f30c"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a92ef1a44547e894e2a17d24e7557a5e85a9e1d0048b0b5e7541f76c5032cb13"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9316dc65bed1684c9a98ee68759ceaed29d229e985297003e494aa825ebb0281"},
- {file = "tomli-2.2.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e85e99945e688e32d5a35c1ff38ed0b3f41f43fad8df0bdf79f72b2ba7bc5272"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ac065718db92ca818f8d6141b5f66369833d4a80a9d74435a268c52bdfa73140"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d920f33822747519673ee656a4b6ac33e382eca9d331c87770faa3eef562aeb2"},
- {file = "tomli-2.2.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a198f10c4d1b1375d7687bc25294306e551bf1abfa4eace6650070a5c1ae2744"},
- {file = "tomli-2.2.1-cp313-cp313-win32.whl", hash = "sha256:d3f5614314d758649ab2ab3a62d4f2004c825922f9e370b29416484086b264ec"},
- {file = "tomli-2.2.1-cp313-cp313-win_amd64.whl", hash = "sha256:a38aa0308e754b0e3c67e344754dff64999ff9b513e691d0e786265c93583c69"},
- {file = "tomli-2.2.1-py3-none-any.whl", hash = "sha256:cb55c73c5f4408779d0cf3eef9f762b9c9f147a77de7b258bef0a5628adc85cc"},
- {file = "tomli-2.2.1.tar.gz", hash = "sha256:cd45e1dc79c835ce60f7404ec8119f2eb06d38b1deba146f07ced3bbc44505ff"},
+ {file = "tomli-2.3.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:88bd15eb972f3664f5ed4b57c1634a97153b4bac4479dcb6a495f41921eb7f45"},
+ {file = "tomli-2.3.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:883b1c0d6398a6a9d29b508c331fa56adbcdff647f6ace4dfca0f50e90dfd0ba"},
+ {file = "tomli-2.3.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d1381caf13ab9f300e30dd8feadb3de072aeb86f1d34a8569453ff32a7dea4bf"},
+ {file = "tomli-2.3.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a0e285d2649b78c0d9027570d4da3425bdb49830a6156121360b3f8511ea3441"},
+ {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0a154a9ae14bfcf5d8917a59b51ffd5a3ac1fd149b71b47a3a104ca4edcfa845"},
+ {file = "tomli-2.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:74bf8464ff93e413514fefd2be591c3b0b23231a77f901db1eb30d6f712fc42c"},
+ {file = "tomli-2.3.0-cp311-cp311-win32.whl", hash = "sha256:00b5f5d95bbfc7d12f91ad8c593a1659b6387b43f054104cda404be6bda62456"},
+ {file = "tomli-2.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:4dc4ce8483a5d429ab602f111a93a6ab1ed425eae3122032db7e9acf449451be"},
+ {file = "tomli-2.3.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:d7d86942e56ded512a594786a5ba0a5e521d02529b3826e7761a05138341a2ac"},
+ {file = "tomli-2.3.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:73ee0b47d4dad1c5e996e3cd33b8a76a50167ae5f96a2607cbe8cc773506ab22"},
+ {file = "tomli-2.3.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:792262b94d5d0a466afb5bc63c7daa9d75520110971ee269152083270998316f"},
+ {file = "tomli-2.3.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f195fe57ecceac95a66a75ac24d9d5fbc98ef0962e09b2eddec5d39375aae52"},
+ {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e31d432427dcbf4d86958c184b9bfd1e96b5b71f8eb17e6d02531f434fd335b8"},
+ {file = "tomli-2.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b0882799624980785240ab732537fcfc372601015c00f7fc367c55308c186f6"},
+ {file = "tomli-2.3.0-cp312-cp312-win32.whl", hash = "sha256:ff72b71b5d10d22ecb084d345fc26f42b5143c5533db5e2eaba7d2d335358876"},
+ {file = "tomli-2.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:1cb4ed918939151a03f33d4242ccd0aa5f11b3547d0cf30f7c74a408a5b99878"},
+ {file = "tomli-2.3.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:5192f562738228945d7b13d4930baffda67b69425a7f0da96d360b0a3888136b"},
+ {file = "tomli-2.3.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:be71c93a63d738597996be9528f4abe628d1adf5e6eb11607bc8fe1a510b5dae"},
+ {file = "tomli-2.3.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c4665508bcbac83a31ff8ab08f424b665200c0e1e645d2bd9ab3d3e557b6185b"},
+ {file = "tomli-2.3.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4021923f97266babc6ccab9f5068642a0095faa0a51a246a6a02fccbb3514eaf"},
+ {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a4ea38c40145a357d513bffad0ed869f13c1773716cf71ccaa83b0fa0cc4e42f"},
+ {file = "tomli-2.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ad805ea85eda330dbad64c7ea7a4556259665bdf9d2672f5dccc740eb9d3ca05"},
+ {file = "tomli-2.3.0-cp313-cp313-win32.whl", hash = "sha256:97d5eec30149fd3294270e889b4234023f2c69747e555a27bd708828353ab606"},
+ {file = "tomli-2.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:0c95ca56fbe89e065c6ead5b593ee64b84a26fca063b5d71a1122bf26e533999"},
+ {file = "tomli-2.3.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:cebc6fe843e0733ee827a282aca4999b596241195f43b4cc371d64fc6639da9e"},
+ {file = "tomli-2.3.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4c2ef0244c75aba9355561272009d934953817c49f47d768070c3c94355c2aa3"},
+ {file = "tomli-2.3.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c22a8bf253bacc0cf11f35ad9808b6cb75ada2631c2d97c971122583b129afbc"},
+ {file = "tomli-2.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0eea8cc5c5e9f89c9b90c4896a8deefc74f518db5927d0e0e8d4a80953d774d0"},
+ {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b74a0e59ec5d15127acdabd75ea17726ac4c5178ae51b85bfe39c4f8a278e879"},
+ {file = "tomli-2.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5870b50c9db823c595983571d1296a6ff3e1b88f734a4c8f6fc6188397de005"},
+ {file = "tomli-2.3.0-cp314-cp314-win32.whl", hash = "sha256:feb0dacc61170ed7ab602d3d972a58f14ee3ee60494292d384649a3dc38ef463"},
+ {file = "tomli-2.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:b273fcbd7fc64dc3600c098e39136522650c49bca95df2d11cf3b626422392c8"},
+ {file = "tomli-2.3.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:940d56ee0410fa17ee1f12b817b37a4d4e4dc4d27340863cc67236c74f582e77"},
+ {file = "tomli-2.3.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:f85209946d1fe94416debbb88d00eb92ce9cd5266775424ff81bc959e001acaf"},
+ {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a56212bdcce682e56b0aaf79e869ba5d15a6163f88d5451cbde388d48b13f530"},
+ {file = "tomli-2.3.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c5f3ffd1e098dfc032d4d3af5c0ac64f6d286d98bc148698356847b80fa4de1b"},
+ {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5e01decd096b1530d97d5d85cb4dff4af2d8347bd35686654a004f8dea20fc67"},
+ {file = "tomli-2.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:8a35dd0e643bb2610f156cca8db95d213a90015c11fee76c946aa62b7ae7e02f"},
+ {file = "tomli-2.3.0-cp314-cp314t-win32.whl", hash = "sha256:a1f7f282fe248311650081faafa5f4732bdbfef5d45fe3f2e702fbc6f2d496e0"},
+ {file = "tomli-2.3.0-cp314-cp314t-win_amd64.whl", hash = "sha256:70a251f8d4ba2d9ac2542eecf008b3c8a9fc5c3f9f02c56a9d7952612be2fdba"},
+ {file = "tomli-2.3.0-py3-none-any.whl", hash = "sha256:e95b1af3c5b07d9e643909b5abbec77cd9f1217e6d0bca72b0234736b9fb1f1b"},
+ {file = "tomli-2.3.0.tar.gz", hash = "sha256:64be704a875d2a59753d80ee8a533c3fe183e3f06807ff7dc2232938ccb01549"},
]
[[package]]
diff --git a/pyproject.toml b/pyproject.toml
index ba72212..bffa0c7 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -3,7 +3,7 @@ name = "newscatcher-sdk"
[tool.poetry]
name = "newscatcher-sdk"
-version = "1.4.0"
+version = "1.4.1"
description = ""
readme = "README.md"
authors = []
@@ -31,7 +31,7 @@ packages = [
{ include = "newscatcher", from = "src"}
]
-[project.urls]
+[tool.poetry.urls]
Repository = 'https://github.com/Newscatcher/newscatcher-python'
[tool.poetry.dependencies]
diff --git a/reference.md b/reference.md
index 367099b..28edec0 100644
--- a/reference.md
+++ b/reference.md
@@ -35,20 +35,36 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.search.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
+ news_type="General News Outlets",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -70,18 +86,7 @@ client.search.get(
-
-**q:** `str`
-
-The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
-- For an exact match, use double quotes. For example, `"technology news"`.
-- Use `*` to search for any keyword.
-- Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
-- Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
-For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+**q:** `Q`
@@ -231,7 +236,7 @@ Example: `"John Doe, Jane Doe"`
-
-**from_:** `typing.Optional[dt.datetime]`
+**from_:** `typing.Optional[SearchGetRequestFrom]`
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -250,7 +255,7 @@ Formats with examples:
-
-**to:** `typing.Optional[dt.datetime]`
+**to:** `typing.Optional[SearchGetRequestTo]`
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -852,25 +857,14 @@ Searches for articles based on specified criteria such as keyword, language, cou
-
```python
-import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.search.post(
- q="renewable energy",
- predefined_sources=["top 50 US"],
- lang=["en"],
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
- additional_domain_info=True,
- is_news_domain=True,
+ q='"supply chain" AND Amazon NOT China',
+ page_size=1,
)
```
@@ -1381,12 +1375,27 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.latestheadlines.get(
+ when="7d",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ not_author_name="John Doe",
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -2029,10 +2038,8 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.latestheadlines.post(
- lang="en",
- predefined_sources=["top 50 US", "top 20 GB"],
- is_opinion=False,
- page_size=10,
+ when="7d",
+ page_size=1,
)
```
@@ -2445,6 +2452,10 @@ client.breaking_news.breaking_news_get(
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
)
```
@@ -2778,9 +2789,8 @@ client = NewscatcherApi(
)
client.breaking_news.breaking_news_post(
sort_by="relevancy",
- page=1,
- page_size=100,
- include_nlp_data=True,
+ ranked_only=True,
+ top_n_articles=1,
)
```
@@ -3014,13 +3024,23 @@ client = NewscatcherApi(
)
client.authors.get(
author_name="Jane Smith",
+ not_author_name="John Doe",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
@@ -3168,7 +3188,7 @@ To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/over
-
-**from_:** `typing.Optional[dt.datetime]`
+**from_:** `typing.Optional[AuthorsGetRequestFrom]`
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -3187,7 +3207,7 @@ Formats with examples:
-
-**to:** `typing.Optional[dt.datetime]`
+**to:** `typing.Optional[AuthorsGetRequestTo]`
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -3637,23 +3657,13 @@ Searches for articles by author. You can filter results by language, country, so
-
```python
-import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.authors.post(
- author_name="Joanna Stern",
- sources=["wsj.com", "nytimes.com"],
- lang="en",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
+ author_name="David Muir",
)
```
@@ -4062,6 +4072,9 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.search_link.search_url_get(
+ ids="5f8d0d55b6e45e00179c6e7e",
+ links="https://nytimes.com/article1",
+ source="articles.id,articles.title,articles.link,articles.published_date",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
@@ -4112,6 +4125,14 @@ Example: `"https://example.com/article1, https://example.com/article2"`
-
+**source:** `typing.Optional[Source]`
+
+
+
+
+
+-
+
**from_:** `typing.Optional[From]`
@@ -4201,14 +4222,8 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.search_link.search_url_post(
- ids=[
- "8ea8a784568ffaa05cb6d1ab2d2e84dd",
- "0146a551ef05ab1c494a55e806e3ce64",
- ],
- links=[
- "https://www.nytimes.com/2024/08/30/technology/ai-chatbot-chatgpt-manipulation.html",
- "https://www.bbc.com/news/articles/c39k379grzlo",
- ],
+ links="https://www.reuters.com/business/energy/oil-prices-up-after-israeli-attacks-oversupply-caps-gains-2025-09-10/",
+ source="articles.id,articles.title,articles.link,articles.canonical_url",
)
```
@@ -4241,6 +4256,14 @@ client.search_link.search_url_post(
-
+**source:** `typing.Optional[Source]`
+
+
+
+
+
+-
+
**from_:** `typing.Optional[From]`
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text strings. The default time zone is UTC.
@@ -4347,17 +4370,26 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.searchsimilar.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
similar_documents_fields="title,summary",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
@@ -4382,18 +4414,7 @@ client.searchsimilar.get(
-
-**q:** `str`
-
-The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
-- For an exact match, use double quotes. For example, `"technology news"`.
-- Use `*` to search for any keyword.
-- Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
-- Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
-For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+**q:** `Q`
@@ -4541,7 +4562,7 @@ To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/over
-
-**from_:** `typing.Optional[dt.datetime]`
+**from_:** `typing.Optional[SearchSimilarGetRequestFrom]`
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -4560,7 +4581,7 @@ Formats with examples:
-
-**to:** `typing.Optional[dt.datetime]`
+**to:** `typing.Optional[SearchSimilarGetRequestTo]`
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -4976,9 +4997,10 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.searchsimilar.post(
- q="artificial intelligence",
+ q='"supply chain" AND Amazon NOT China',
include_similar_documents=True,
similar_documents_number=5,
+ page_size=10,
)
```
@@ -5393,8 +5415,12 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.sources.get(
+ lang="en",
+ countries="US",
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
source_url="bbc.com",
+ news_type="General News Outlets",
)
```
@@ -5598,11 +5624,7 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.sources.post(
- predefined_sources=["top 50 US"],
- include_additional_info=True,
- is_news_domain=True,
- news_domain_type="Original Content",
- news_type="General News Outlets",
+ predefined_sources="top 10 US",
)
```
@@ -5755,19 +5777,33 @@ client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.aggregation.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
)
@@ -5786,18 +5822,7 @@ client.aggregation.get(
-
-**q:** `str`
-
-The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
-- For an exact match, use double quotes. For example, `"technology news"`.
-- Use `*` to search for any keyword.
-- Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
-- Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
-For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+**q:** `Q`
@@ -5933,7 +5958,7 @@ Example: `"John Doe, Jane Doe"`
-
-**from_:** `typing.Optional[dt.datetime]`
+**from_:** `typing.Optional[AggregationGetRequestFrom]`
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -5952,7 +5977,7 @@ Formats with examples:
-
-**to:** `typing.Optional[dt.datetime]`
+**to:** `typing.Optional[AggregationGetRequestTo]`
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
@@ -6398,23 +6423,14 @@ Retrieves the count of articles aggregated by day or hour based on various searc
-
```python
-import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.aggregation.post(
- q="renewable energy",
+ q='"supply chain" AND Amazon NOT China',
aggregation_by="day",
- predefined_sources="top 50 US",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
)
```
diff --git a/src/newscatcher/__init__.py b/src/newscatcher/__init__.py
index 17df0a5..461cd38 100644
--- a/src/newscatcher/__init__.py
+++ b/src/newscatcher/__init__.py
@@ -2,170 +2,371 @@
# isort: skip_file
-from .types import (
- AdditionalDomainInfo,
- AdditionalDomainInfoEntity,
- AdditionalSourceInfo,
- AggregationBy,
- AggregationCountResponseDto,
- AggregationItem,
- Aggregations,
- AllDomainLinks,
- AllLinks,
- ArticleEntity,
- ArticleEntityAllDomainLinks,
- ArticleEntityAllLinks,
- Articles,
- AuthorName,
- Authors,
- BaseSearchResponseDto,
- BreakingNewsArticleEntity,
- BreakingNewsArticleEntityAllDomainLinks,
- BreakingNewsArticleEntityAllLinks,
- BreakingNewsEventEntity,
- BreakingNewsResponseDto,
- ByParseDate,
- ClusterEntity,
- ClusteredArticlesDto,
- ClusteredSearchResponseDto,
- ClusteringEnabled,
- ClusteringThreshold,
- ClusteringVariable,
- ContentSentimentMax,
- ContentSentimentMin,
- Countries,
- CustomTags,
- Error,
- ExcludeDuplicates,
- FailedAggregationCountResponseDto,
- FailedAuthorsResponseDto,
- FailedSearchSimilarResponseDto,
- From,
- FromRank,
- HasNlp,
- IabTags,
- Ids,
- IncludeAdditionalInfo,
- IncludeNlpData,
- IncludeSimilarDocuments,
- IncludeTranslationFields,
- IptcTags,
- IsHeadline,
- IsNewsDomain,
- IsOpinion,
- IsPaidContent,
- Journalists,
- Lang,
- Links,
- LocEntityName,
- MiscEntityName,
- NamedEntityList,
- NamedEntityListItem,
- NerName,
- NewsDomainType,
- NewsType,
- NlpDataEntity,
- NotAuthorName,
- NotCountries,
- NotIabTags,
- NotIptcTags,
- NotLang,
- NotSources,
- NotTheme,
- OrgEntityName,
- Page,
- PageSize,
- ParentUrl,
- PerEntityName,
- PredefinedSources,
- PublishedDatePrecision,
- Q,
- RankedOnly,
- RobotsCompliant,
- SearchIn,
- SearchResponseDto,
- SearchSimilarResponseDto,
- SentimentScores,
- SimilarArticleEntity,
- SimilarDocument,
- SimilarDocumentsFields,
- SimilarDocumentsNumber,
- SortBy,
- SourceInfo,
- SourceName,
- SourceUrl,
- Sources,
- SourcesResponseDto,
- SourcesResponseDtoSourcesItem,
- SubscriptionResponseDto,
- Theme,
- TimeFrameCount,
- TitleSentimentMax,
- TitleSentimentMin,
- To,
- ToRank,
- TopNArticles,
- UserInputDto,
- When,
- WordCountMax,
- WordCountMin,
-)
-from .errors import (
- BadRequestError,
- ForbiddenError,
- InternalServerError,
- RequestTimeoutError,
- TooManyRequestsError,
- UnauthorizedError,
- UnprocessableEntityError,
-)
-from . import (
- aggregation,
- authors,
- breaking_news,
- latestheadlines,
- search,
- search_link,
- searchsimilar,
- sources,
- subscription,
-)
-from .aggregation import (
- AggregationGetRequestPublishedDatePrecision,
- AggregationGetRequestSortBy,
- AggregationGetResponse,
- AggregationPostResponse,
-)
-from .authors import (
- AuthorsGetRequestPublishedDatePrecision,
- AuthorsGetRequestSortBy,
- AuthorsGetResponse,
- AuthorsPostResponse,
-)
-from .breaking_news import BreakingNewsGetRequestSortBy
-from .client import AsyncNewscatcherApi, NewscatcherApi
-from .environment import NewscatcherApiEnvironment
-from .latestheadlines import (
- LatestHeadlinesGetRequestClusteringVariable,
- LatestHeadlinesGetResponse,
- LatestHeadlinesPostResponse,
-)
-from .search import (
- SearchGetRequestClusteringVariable,
- SearchGetRequestNewsDomainType,
- SearchGetRequestPublishedDatePrecision,
- SearchGetRequestSortBy,
- SearchGetResponse,
- SearchPostResponse,
-)
-from .searchsimilar import (
- SearchSimilarGetRequestPublishedDatePrecision,
- SearchSimilarGetRequestSortBy,
- SearchSimilarGetResponse,
- SearchSimilarPostResponse,
-)
-from .sources import SourcesGetRequestNewsDomainType
-from .version import __version__
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ AdditionalDomainInfo,
+ AdditionalDomainInfoEntity,
+ AdditionalSourceInfo,
+ AggregationBy,
+ AggregationCountResponseDto,
+ AggregationCountResponseDtoAggregations,
+ AggregationGetRequestFrom,
+ AggregationGetRequestTo,
+ AggregationItem,
+ AllDomainLinks,
+ AllLinks,
+ ArticleEntity,
+ ArticleEntityAllDomainLinks,
+ ArticleEntityAllLinks,
+ ArticleEntityAuthors,
+ ArticleEntityJournalists,
+ ArticlesDto,
+ AuthorName,
+ AuthorsGetRequestFrom,
+ AuthorsGetRequestTo,
+ BaseSearchResponseDto,
+ BreakingNewsArticleEntity,
+ BreakingNewsArticleEntityAllDomainLinks,
+ BreakingNewsArticleEntityAllLinks,
+ BreakingNewsArticleEntityAuthors,
+ BreakingNewsArticleEntityJournalists,
+ BreakingNewsEventEntity,
+ BreakingNewsResponseDto,
+ ByParseDate,
+ CanonicalUrl,
+ ClusterEntity,
+ ClusteredArticlesDto,
+ ClusteredSearchResponseDto,
+ ClusteringEnabled,
+ ClusteringThreshold,
+ ClusteringVariable,
+ ContentSentimentMax,
+ ContentSentimentMin,
+ Countries,
+ CustomTags,
+ Error,
+ ExcludeDuplicates,
+ FailedAggregationCountResponseDto,
+ FailedAuthorsResponseDto,
+ FailedSearchSimilarResponseDto,
+ From,
+ FromRank,
+ HasNlp,
+ IabTags,
+ Ids,
+ IncludeAdditionalInfo,
+ IncludeNlpData,
+ IncludeSimilarDocuments,
+ IncludeTranslationFields,
+ IptcTags,
+ IsHeadline,
+ IsNewsDomain,
+ IsOpinion,
+ IsPaidContent,
+ Lang,
+ Links,
+ LocEntityName,
+ MiscEntityName,
+ NamedEntityList,
+ NamedEntityListItem,
+ NerName,
+ NewsDomainType,
+ NewsType,
+ NlpDataEntity,
+ NotAuthorName,
+ NotCountries,
+ NotIabTags,
+ NotIptcTags,
+ NotLang,
+ NotSources,
+ NotTheme,
+ OrgEntityName,
+ Page,
+ PageSize,
+ ParentUrl,
+ PerEntityName,
+ PredefinedSources,
+ PublishedDatePrecision,
+ Q,
+ RankedOnly,
+ RobotsCompliant,
+ SearchGetRequestFrom,
+ SearchGetRequestTo,
+ SearchIn,
+ SearchResponseDto,
+ SearchSimilarGetRequestFrom,
+ SearchSimilarGetRequestTo,
+ SearchSimilarResponseDto,
+ SentimentScores,
+ SimilarArticleEntity,
+ SimilarDocument,
+ SimilarDocumentsFields,
+ SimilarDocumentsNumber,
+ SortBy,
+ Source,
+ SourceInfo,
+ SourceName,
+ SourceUrl,
+ Sources,
+ SourcesResponseDto,
+ SourcesResponseDtoSourcesItem,
+ SubscriptionResponseDto,
+ Theme,
+ TimeFrameCount,
+ TitleSentimentMax,
+ TitleSentimentMin,
+ To,
+ ToRank,
+ TopNArticles,
+ UserInputDto,
+ When,
+ WordCountMax,
+ WordCountMin,
+ )
+ from .errors import (
+ BadRequestError,
+ ForbiddenError,
+ InternalServerError,
+ RequestTimeoutError,
+ TooManyRequestsError,
+ UnauthorizedError,
+ UnprocessableEntityError,
+ )
+ from . import (
+ aggregation,
+ authors,
+ breaking_news,
+ latestheadlines,
+ search,
+ search_link,
+ searchsimilar,
+ sources,
+ subscription,
+ )
+ from .aggregation import (
+ AggregationGetRequestPublishedDatePrecision,
+ AggregationGetRequestSortBy,
+ AggregationGetResponse,
+ AggregationPostResponse,
+ )
+ from .authors import (
+ AuthorsGetRequestPublishedDatePrecision,
+ AuthorsGetRequestSortBy,
+ AuthorsGetResponse,
+ AuthorsPostResponse,
+ )
+ from .breaking_news import BreakingNewsGetRequestSortBy
+ from .client import AsyncNewscatcherApi, NewscatcherApi
+ from .environment import NewscatcherApiEnvironment
+ from .latestheadlines import (
+ LatestHeadlinesGetRequestClusteringVariable,
+ LatestHeadlinesGetResponse,
+ LatestHeadlinesPostResponse,
+ )
+ from .search import (
+ SearchGetRequestClusteringVariable,
+ SearchGetRequestNewsDomainType,
+ SearchGetRequestPublishedDatePrecision,
+ SearchGetRequestSortBy,
+ SearchGetResponse,
+ SearchPostResponse,
+ )
+ from .searchsimilar import (
+ SearchSimilarGetRequestPublishedDatePrecision,
+ SearchSimilarGetRequestSortBy,
+ SearchSimilarGetResponse,
+ SearchSimilarPostResponse,
+ )
+ from .sources import SourcesGetRequestNewsDomainType
+ from .version import __version__
+_dynamic_imports: typing.Dict[str, str] = {
+ "AdditionalDomainInfo": ".types",
+ "AdditionalDomainInfoEntity": ".types",
+ "AdditionalSourceInfo": ".types",
+ "AggregationBy": ".types",
+ "AggregationCountResponseDto": ".types",
+ "AggregationCountResponseDtoAggregations": ".types",
+ "AggregationGetRequestFrom": ".types",
+ "AggregationGetRequestPublishedDatePrecision": ".aggregation",
+ "AggregationGetRequestSortBy": ".aggregation",
+ "AggregationGetRequestTo": ".types",
+ "AggregationGetResponse": ".aggregation",
+ "AggregationItem": ".types",
+ "AggregationPostResponse": ".aggregation",
+ "AllDomainLinks": ".types",
+ "AllLinks": ".types",
+ "ArticleEntity": ".types",
+ "ArticleEntityAllDomainLinks": ".types",
+ "ArticleEntityAllLinks": ".types",
+ "ArticleEntityAuthors": ".types",
+ "ArticleEntityJournalists": ".types",
+ "ArticlesDto": ".types",
+ "AsyncNewscatcherApi": ".client",
+ "AuthorName": ".types",
+ "AuthorsGetRequestFrom": ".types",
+ "AuthorsGetRequestPublishedDatePrecision": ".authors",
+ "AuthorsGetRequestSortBy": ".authors",
+ "AuthorsGetRequestTo": ".types",
+ "AuthorsGetResponse": ".authors",
+ "AuthorsPostResponse": ".authors",
+ "BadRequestError": ".errors",
+ "BaseSearchResponseDto": ".types",
+ "BreakingNewsArticleEntity": ".types",
+ "BreakingNewsArticleEntityAllDomainLinks": ".types",
+ "BreakingNewsArticleEntityAllLinks": ".types",
+ "BreakingNewsArticleEntityAuthors": ".types",
+ "BreakingNewsArticleEntityJournalists": ".types",
+ "BreakingNewsEventEntity": ".types",
+ "BreakingNewsGetRequestSortBy": ".breaking_news",
+ "BreakingNewsResponseDto": ".types",
+ "ByParseDate": ".types",
+ "CanonicalUrl": ".types",
+ "ClusterEntity": ".types",
+ "ClusteredArticlesDto": ".types",
+ "ClusteredSearchResponseDto": ".types",
+ "ClusteringEnabled": ".types",
+ "ClusteringThreshold": ".types",
+ "ClusteringVariable": ".types",
+ "ContentSentimentMax": ".types",
+ "ContentSentimentMin": ".types",
+ "Countries": ".types",
+ "CustomTags": ".types",
+ "Error": ".types",
+ "ExcludeDuplicates": ".types",
+ "FailedAggregationCountResponseDto": ".types",
+ "FailedAuthorsResponseDto": ".types",
+ "FailedSearchSimilarResponseDto": ".types",
+ "ForbiddenError": ".errors",
+ "From": ".types",
+ "FromRank": ".types",
+ "HasNlp": ".types",
+ "IabTags": ".types",
+ "Ids": ".types",
+ "IncludeAdditionalInfo": ".types",
+ "IncludeNlpData": ".types",
+ "IncludeSimilarDocuments": ".types",
+ "IncludeTranslationFields": ".types",
+ "InternalServerError": ".errors",
+ "IptcTags": ".types",
+ "IsHeadline": ".types",
+ "IsNewsDomain": ".types",
+ "IsOpinion": ".types",
+ "IsPaidContent": ".types",
+ "Lang": ".types",
+ "LatestHeadlinesGetRequestClusteringVariable": ".latestheadlines",
+ "LatestHeadlinesGetResponse": ".latestheadlines",
+ "LatestHeadlinesPostResponse": ".latestheadlines",
+ "Links": ".types",
+ "LocEntityName": ".types",
+ "MiscEntityName": ".types",
+ "NamedEntityList": ".types",
+ "NamedEntityListItem": ".types",
+ "NerName": ".types",
+ "NewsDomainType": ".types",
+ "NewsType": ".types",
+ "NewscatcherApi": ".client",
+ "NewscatcherApiEnvironment": ".environment",
+ "NlpDataEntity": ".types",
+ "NotAuthorName": ".types",
+ "NotCountries": ".types",
+ "NotIabTags": ".types",
+ "NotIptcTags": ".types",
+ "NotLang": ".types",
+ "NotSources": ".types",
+ "NotTheme": ".types",
+ "OrgEntityName": ".types",
+ "Page": ".types",
+ "PageSize": ".types",
+ "ParentUrl": ".types",
+ "PerEntityName": ".types",
+ "PredefinedSources": ".types",
+ "PublishedDatePrecision": ".types",
+ "Q": ".types",
+ "RankedOnly": ".types",
+ "RequestTimeoutError": ".errors",
+ "RobotsCompliant": ".types",
+ "SearchGetRequestClusteringVariable": ".search",
+ "SearchGetRequestFrom": ".types",
+ "SearchGetRequestNewsDomainType": ".search",
+ "SearchGetRequestPublishedDatePrecision": ".search",
+ "SearchGetRequestSortBy": ".search",
+ "SearchGetRequestTo": ".types",
+ "SearchGetResponse": ".search",
+ "SearchIn": ".types",
+ "SearchPostResponse": ".search",
+ "SearchResponseDto": ".types",
+ "SearchSimilarGetRequestFrom": ".types",
+ "SearchSimilarGetRequestPublishedDatePrecision": ".searchsimilar",
+ "SearchSimilarGetRequestSortBy": ".searchsimilar",
+ "SearchSimilarGetRequestTo": ".types",
+ "SearchSimilarGetResponse": ".searchsimilar",
+ "SearchSimilarPostResponse": ".searchsimilar",
+ "SearchSimilarResponseDto": ".types",
+ "SentimentScores": ".types",
+ "SimilarArticleEntity": ".types",
+ "SimilarDocument": ".types",
+ "SimilarDocumentsFields": ".types",
+ "SimilarDocumentsNumber": ".types",
+ "SortBy": ".types",
+ "Source": ".types",
+ "SourceInfo": ".types",
+ "SourceName": ".types",
+ "SourceUrl": ".types",
+ "Sources": ".types",
+ "SourcesGetRequestNewsDomainType": ".sources",
+ "SourcesResponseDto": ".types",
+ "SourcesResponseDtoSourcesItem": ".types",
+ "SubscriptionResponseDto": ".types",
+ "Theme": ".types",
+ "TimeFrameCount": ".types",
+ "TitleSentimentMax": ".types",
+ "TitleSentimentMin": ".types",
+ "To": ".types",
+ "ToRank": ".types",
+ "TooManyRequestsError": ".errors",
+ "TopNArticles": ".types",
+ "UnauthorizedError": ".errors",
+ "UnprocessableEntityError": ".errors",
+ "UserInputDto": ".types",
+ "When": ".types",
+ "WordCountMax": ".types",
+ "WordCountMin": ".types",
+ "__version__": ".version",
+ "aggregation": ".aggregation",
+ "authors": ".authors",
+ "breaking_news": ".breaking_news",
+ "latestheadlines": ".latestheadlines",
+ "search": ".search",
+ "search_link": ".search_link",
+ "searchsimilar": ".searchsimilar",
+ "sources": ".sources",
+ "subscription": ".subscription",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AdditionalDomainInfo",
@@ -173,23 +374,28 @@
"AdditionalSourceInfo",
"AggregationBy",
"AggregationCountResponseDto",
+ "AggregationCountResponseDtoAggregations",
+ "AggregationGetRequestFrom",
"AggregationGetRequestPublishedDatePrecision",
"AggregationGetRequestSortBy",
+ "AggregationGetRequestTo",
"AggregationGetResponse",
"AggregationItem",
"AggregationPostResponse",
- "Aggregations",
"AllDomainLinks",
"AllLinks",
"ArticleEntity",
"ArticleEntityAllDomainLinks",
"ArticleEntityAllLinks",
- "Articles",
+ "ArticleEntityAuthors",
+ "ArticleEntityJournalists",
+ "ArticlesDto",
"AsyncNewscatcherApi",
"AuthorName",
- "Authors",
+ "AuthorsGetRequestFrom",
"AuthorsGetRequestPublishedDatePrecision",
"AuthorsGetRequestSortBy",
+ "AuthorsGetRequestTo",
"AuthorsGetResponse",
"AuthorsPostResponse",
"BadRequestError",
@@ -197,10 +403,13 @@
"BreakingNewsArticleEntity",
"BreakingNewsArticleEntityAllDomainLinks",
"BreakingNewsArticleEntityAllLinks",
+ "BreakingNewsArticleEntityAuthors",
+ "BreakingNewsArticleEntityJournalists",
"BreakingNewsEventEntity",
"BreakingNewsGetRequestSortBy",
"BreakingNewsResponseDto",
"ByParseDate",
+ "CanonicalUrl",
"ClusterEntity",
"ClusteredArticlesDto",
"ClusteredSearchResponseDto",
@@ -232,7 +441,6 @@
"IsNewsDomain",
"IsOpinion",
"IsPaidContent",
- "Journalists",
"Lang",
"LatestHeadlinesGetRequestClusteringVariable",
"LatestHeadlinesGetResponse",
@@ -267,15 +475,19 @@
"RequestTimeoutError",
"RobotsCompliant",
"SearchGetRequestClusteringVariable",
+ "SearchGetRequestFrom",
"SearchGetRequestNewsDomainType",
"SearchGetRequestPublishedDatePrecision",
"SearchGetRequestSortBy",
+ "SearchGetRequestTo",
"SearchGetResponse",
"SearchIn",
"SearchPostResponse",
"SearchResponseDto",
+ "SearchSimilarGetRequestFrom",
"SearchSimilarGetRequestPublishedDatePrecision",
"SearchSimilarGetRequestSortBy",
+ "SearchSimilarGetRequestTo",
"SearchSimilarGetResponse",
"SearchSimilarPostResponse",
"SearchSimilarResponseDto",
@@ -285,6 +497,7 @@
"SimilarDocumentsFields",
"SimilarDocumentsNumber",
"SortBy",
+ "Source",
"SourceInfo",
"SourceName",
"SourceUrl",
diff --git a/src/newscatcher/aggregation/__init__.py b/src/newscatcher/aggregation/__init__.py
index c4d8649..3e3f1cc 100644
--- a/src/newscatcher/aggregation/__init__.py
+++ b/src/newscatcher/aggregation/__init__.py
@@ -2,12 +2,44 @@
# isort: skip_file
-from .types import (
- AggregationGetRequestPublishedDatePrecision,
- AggregationGetRequestSortBy,
- AggregationGetResponse,
- AggregationPostResponse,
-)
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ AggregationGetRequestPublishedDatePrecision,
+ AggregationGetRequestSortBy,
+ AggregationGetResponse,
+ AggregationPostResponse,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "AggregationGetRequestPublishedDatePrecision": ".types",
+ "AggregationGetRequestSortBy": ".types",
+ "AggregationGetResponse": ".types",
+ "AggregationPostResponse": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AggregationGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/aggregation/client.py b/src/newscatcher/aggregation/client.py
index a512b41..c0ce14e 100644
--- a/src/newscatcher/aggregation/client.py
+++ b/src/newscatcher/aggregation/client.py
@@ -1,11 +1,12 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from ..core.request_options import RequestOptions
from ..types.aggregation_by import AggregationBy
+from ..types.aggregation_get_request_from import AggregationGetRequestFrom
+from ..types.aggregation_get_request_to import AggregationGetRequestTo
from ..types.all_domain_links import AllDomainLinks
from ..types.all_links import AllLinks
from ..types.by_parse_date import ByParseDate
@@ -77,7 +78,7 @@ def with_raw_response(self) -> RawAggregationClient:
def get(
self,
*,
- q: str,
+ q: Q,
aggregation_by: typing.Optional[AggregationBy] = None,
search_in: typing.Optional[SearchIn] = None,
predefined_sources: typing.Optional[str] = None,
@@ -88,8 +89,8 @@ def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AggregationGetRequestFrom] = None,
+ to: typing.Optional[AggregationGetRequestTo] = None,
published_date_precision: typing.Optional[AggregationGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AggregationGetRequestSortBy] = None,
@@ -128,17 +129,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
aggregation_by : typing.Optional[AggregationBy]
@@ -200,7 +191,7 @@ def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AggregationGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -212,7 +203,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AggregationGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -437,19 +428,33 @@ def get(
api_key="YOUR_API_KEY",
)
client.aggregation.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
)
@@ -655,23 +660,14 @@ def post(
Examples
--------
- import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.aggregation.post(
- q="renewable energy",
+ q='"supply chain" AND Amazon NOT China',
aggregation_by="day",
- predefined_sources="top 50 US",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
)
"""
_response = self._raw_client.post(
@@ -742,7 +738,7 @@ def with_raw_response(self) -> AsyncRawAggregationClient:
async def get(
self,
*,
- q: str,
+ q: Q,
aggregation_by: typing.Optional[AggregationBy] = None,
search_in: typing.Optional[SearchIn] = None,
predefined_sources: typing.Optional[str] = None,
@@ -753,8 +749,8 @@ async def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AggregationGetRequestFrom] = None,
+ to: typing.Optional[AggregationGetRequestTo] = None,
published_date_precision: typing.Optional[AggregationGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AggregationGetRequestSortBy] = None,
@@ -793,17 +789,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
aggregation_by : typing.Optional[AggregationBy]
@@ -865,7 +851,7 @@ async def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AggregationGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -877,7 +863,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AggregationGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1106,19 +1092,33 @@ async def get(
async def main() -> None:
await client.aggregation.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
)
@@ -1328,7 +1328,6 @@ async def post(
Examples
--------
import asyncio
- import datetime
from newscatcher import AsyncNewscatcherApi
@@ -1339,15 +1338,8 @@ async def post(
async def main() -> None:
await client.aggregation.post(
- q="renewable energy",
+ q='"supply chain" AND Amazon NOT China',
aggregation_by="day",
- predefined_sources="top 50 US",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
)
diff --git a/src/newscatcher/aggregation/raw_client.py b/src/newscatcher/aggregation/raw_client.py
index 66a8064..1547eeb 100644
--- a/src/newscatcher/aggregation/raw_client.py
+++ b/src/newscatcher/aggregation/raw_client.py
@@ -1,12 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.datetime_utils import serialize_datetime
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
@@ -19,6 +17,8 @@
from ..errors.unauthorized_error import UnauthorizedError
from ..errors.unprocessable_entity_error import UnprocessableEntityError
from ..types.aggregation_by import AggregationBy
+from ..types.aggregation_get_request_from import AggregationGetRequestFrom
+from ..types.aggregation_get_request_to import AggregationGetRequestTo
from ..types.all_domain_links import AllDomainLinks
from ..types.all_links import AllLinks
from ..types.by_parse_date import ByParseDate
@@ -79,7 +79,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper):
def get(
self,
*,
- q: str,
+ q: Q,
aggregation_by: typing.Optional[AggregationBy] = None,
search_in: typing.Optional[SearchIn] = None,
predefined_sources: typing.Optional[str] = None,
@@ -90,8 +90,8 @@ def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AggregationGetRequestFrom] = None,
+ to: typing.Optional[AggregationGetRequestTo] = None,
published_date_precision: typing.Optional[AggregationGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AggregationGetRequestSortBy] = None,
@@ -130,17 +130,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
aggregation_by : typing.Optional[AggregationBy]
@@ -202,7 +192,7 @@ def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AggregationGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -214,7 +204,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AggregationGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -444,8 +434,12 @@ def get(
"countries": countries,
"not_countries": not_countries,
"not_author_name": not_author_name,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=AggregationGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=AggregationGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
@@ -903,7 +897,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper):
async def get(
self,
*,
- q: str,
+ q: Q,
aggregation_by: typing.Optional[AggregationBy] = None,
search_in: typing.Optional[SearchIn] = None,
predefined_sources: typing.Optional[str] = None,
@@ -914,8 +908,8 @@ async def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AggregationGetRequestFrom] = None,
+ to: typing.Optional[AggregationGetRequestTo] = None,
published_date_precision: typing.Optional[AggregationGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AggregationGetRequestSortBy] = None,
@@ -954,17 +948,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
aggregation_by : typing.Optional[AggregationBy]
@@ -1026,7 +1010,7 @@ async def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AggregationGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1038,7 +1022,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AggregationGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1268,8 +1252,12 @@ async def get(
"countries": countries,
"not_countries": not_countries,
"not_author_name": not_author_name,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=AggregationGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=AggregationGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
diff --git a/src/newscatcher/aggregation/types/__init__.py b/src/newscatcher/aggregation/types/__init__.py
index 324ce07..d99ba3c 100644
--- a/src/newscatcher/aggregation/types/__init__.py
+++ b/src/newscatcher/aggregation/types/__init__.py
@@ -2,10 +2,42 @@
# isort: skip_file
-from .aggregation_get_request_published_date_precision import AggregationGetRequestPublishedDatePrecision
-from .aggregation_get_request_sort_by import AggregationGetRequestSortBy
-from .aggregation_get_response import AggregationGetResponse
-from .aggregation_post_response import AggregationPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .aggregation_get_request_published_date_precision import AggregationGetRequestPublishedDatePrecision
+ from .aggregation_get_request_sort_by import AggregationGetRequestSortBy
+ from .aggregation_get_response import AggregationGetResponse
+ from .aggregation_post_response import AggregationPostResponse
+_dynamic_imports: typing.Dict[str, str] = {
+ "AggregationGetRequestPublishedDatePrecision": ".aggregation_get_request_published_date_precision",
+ "AggregationGetRequestSortBy": ".aggregation_get_request_sort_by",
+ "AggregationGetResponse": ".aggregation_get_response",
+ "AggregationPostResponse": ".aggregation_post_response",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AggregationGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/authors/__init__.py b/src/newscatcher/authors/__init__.py
index 420f07c..7284e04 100644
--- a/src/newscatcher/authors/__init__.py
+++ b/src/newscatcher/authors/__init__.py
@@ -2,12 +2,44 @@
# isort: skip_file
-from .types import (
- AuthorsGetRequestPublishedDatePrecision,
- AuthorsGetRequestSortBy,
- AuthorsGetResponse,
- AuthorsPostResponse,
-)
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ AuthorsGetRequestPublishedDatePrecision,
+ AuthorsGetRequestSortBy,
+ AuthorsGetResponse,
+ AuthorsPostResponse,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "AuthorsGetRequestPublishedDatePrecision": ".types",
+ "AuthorsGetRequestSortBy": ".types",
+ "AuthorsGetResponse": ".types",
+ "AuthorsPostResponse": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AuthorsGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/authors/client.py b/src/newscatcher/authors/client.py
index c2a1c65..62e03ec 100644
--- a/src/newscatcher/authors/client.py
+++ b/src/newscatcher/authors/client.py
@@ -1,6 +1,5 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
@@ -8,6 +7,8 @@
from ..types.all_domain_links import AllDomainLinks
from ..types.all_links import AllLinks
from ..types.author_name import AuthorName
+from ..types.authors_get_request_from import AuthorsGetRequestFrom
+from ..types.authors_get_request_to import AuthorsGetRequestTo
from ..types.by_parse_date import ByParseDate
from ..types.content_sentiment_max import ContentSentimentMax
from ..types.content_sentiment_min import ContentSentimentMin
@@ -85,8 +86,8 @@ def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AuthorsGetRequestFrom] = None,
+ to: typing.Optional[AuthorsGetRequestTo] = None,
published_date_precision: typing.Optional[AuthorsGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AuthorsGetRequestSortBy] = None,
@@ -185,7 +186,7 @@ def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AuthorsGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -197,7 +198,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AuthorsGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -421,13 +422,23 @@ def get(
)
client.authors.get(
author_name="Jane Smith",
+ not_author_name="John Doe",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
@@ -638,23 +649,13 @@ def post(
Examples
--------
- import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.authors.post(
- author_name="Joanna Stern",
- sources=["wsj.com", "nytimes.com"],
- lang="en",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
+ author_name="David Muir",
)
"""
_response = self._raw_client.post(
@@ -733,8 +734,8 @@ async def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AuthorsGetRequestFrom] = None,
+ to: typing.Optional[AuthorsGetRequestTo] = None,
published_date_precision: typing.Optional[AuthorsGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AuthorsGetRequestSortBy] = None,
@@ -833,7 +834,7 @@ async def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AuthorsGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -845,7 +846,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AuthorsGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1073,13 +1074,23 @@ async def get(
async def main() -> None:
await client.authors.get(
author_name="Jane Smith",
+ not_author_name="John Doe",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
@@ -1294,7 +1305,6 @@ async def post(
Examples
--------
import asyncio
- import datetime
from newscatcher import AsyncNewscatcherApi
@@ -1305,15 +1315,7 @@ async def post(
async def main() -> None:
await client.authors.post(
- author_name="Joanna Stern",
- sources=["wsj.com", "nytimes.com"],
- lang="en",
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
+ author_name="David Muir",
)
diff --git a/src/newscatcher/authors/raw_client.py b/src/newscatcher/authors/raw_client.py
index 6f244c2..7a54689 100644
--- a/src/newscatcher/authors/raw_client.py
+++ b/src/newscatcher/authors/raw_client.py
@@ -1,12 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.datetime_utils import serialize_datetime
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
@@ -21,6 +19,8 @@
from ..types.all_domain_links import AllDomainLinks
from ..types.all_links import AllLinks
from ..types.author_name import AuthorName
+from ..types.authors_get_request_from import AuthorsGetRequestFrom
+from ..types.authors_get_request_to import AuthorsGetRequestTo
from ..types.by_parse_date import ByParseDate
from ..types.content_sentiment_max import ContentSentimentMax
from ..types.content_sentiment_min import ContentSentimentMin
@@ -87,8 +87,8 @@ def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AuthorsGetRequestFrom] = None,
+ to: typing.Optional[AuthorsGetRequestTo] = None,
published_date_precision: typing.Optional[AuthorsGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AuthorsGetRequestSortBy] = None,
@@ -187,7 +187,7 @@ def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AuthorsGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -199,7 +199,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AuthorsGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -425,8 +425,12 @@ def get(
"not_lang": not_lang,
"countries": countries,
"not_countries": not_countries,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=AuthorsGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=AuthorsGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
@@ -896,8 +900,8 @@ async def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[AuthorsGetRequestFrom] = None,
+ to: typing.Optional[AuthorsGetRequestTo] = None,
published_date_precision: typing.Optional[AuthorsGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[AuthorsGetRequestSortBy] = None,
@@ -996,7 +1000,7 @@ async def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[AuthorsGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1008,7 +1012,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[AuthorsGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1234,8 +1238,12 @@ async def get(
"not_lang": not_lang,
"countries": countries,
"not_countries": not_countries,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=AuthorsGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=AuthorsGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
diff --git a/src/newscatcher/authors/types/__init__.py b/src/newscatcher/authors/types/__init__.py
index afa44b2..5023575 100644
--- a/src/newscatcher/authors/types/__init__.py
+++ b/src/newscatcher/authors/types/__init__.py
@@ -2,10 +2,42 @@
# isort: skip_file
-from .authors_get_request_published_date_precision import AuthorsGetRequestPublishedDatePrecision
-from .authors_get_request_sort_by import AuthorsGetRequestSortBy
-from .authors_get_response import AuthorsGetResponse
-from .authors_post_response import AuthorsPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .authors_get_request_published_date_precision import AuthorsGetRequestPublishedDatePrecision
+ from .authors_get_request_sort_by import AuthorsGetRequestSortBy
+ from .authors_get_response import AuthorsGetResponse
+ from .authors_post_response import AuthorsPostResponse
+_dynamic_imports: typing.Dict[str, str] = {
+ "AuthorsGetRequestPublishedDatePrecision": ".authors_get_request_published_date_precision",
+ "AuthorsGetRequestSortBy": ".authors_get_request_sort_by",
+ "AuthorsGetResponse": ".authors_get_response",
+ "AuthorsPostResponse": ".authors_post_response",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AuthorsGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/base_client.py b/src/newscatcher/base_client.py
index 04a1f90..20af955 100644
--- a/src/newscatcher/base_client.py
+++ b/src/newscatcher/base_client.py
@@ -1,19 +1,23 @@
# This file was auto-generated by Fern from our API Definition.
+from __future__ import annotations
+
import typing
import httpx
-from .aggregation.client import AggregationClient, AsyncAggregationClient
-from .authors.client import AsyncAuthorsClient, AuthorsClient
-from .breaking_news.client import AsyncBreakingNewsClient, BreakingNewsClient
from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
from .environment import NewscatcherApiEnvironment
-from .latestheadlines.client import AsyncLatestheadlinesClient, LatestheadlinesClient
-from .search.client import AsyncSearchClient, SearchClient
-from .search_link.client import AsyncSearchLinkClient, SearchLinkClient
-from .searchsimilar.client import AsyncSearchsimilarClient, SearchsimilarClient
-from .sources.client import AsyncSourcesClient, SourcesClient
-from .subscription.client import AsyncSubscriptionClient, SubscriptionClient
+
+if typing.TYPE_CHECKING:
+ from .aggregation.client import AggregationClient, AsyncAggregationClient
+ from .authors.client import AsyncAuthorsClient, AuthorsClient
+ from .breaking_news.client import AsyncBreakingNewsClient, BreakingNewsClient
+ from .latestheadlines.client import AsyncLatestheadlinesClient, LatestheadlinesClient
+ from .search.client import AsyncSearchClient, SearchClient
+ from .search_link.client import AsyncSearchLinkClient, SearchLinkClient
+ from .searchsimilar.client import AsyncSearchsimilarClient, SearchsimilarClient
+ from .sources.client import AsyncSourcesClient, SourcesClient
+ from .subscription.client import AsyncSubscriptionClient, SubscriptionClient
class BaseNewscatcherApi:
@@ -81,15 +85,87 @@ def __init__(
else httpx.Client(timeout=_defaulted_timeout),
timeout=_defaulted_timeout,
)
- self.search = SearchClient(client_wrapper=self._client_wrapper)
- self.latestheadlines = LatestheadlinesClient(client_wrapper=self._client_wrapper)
- self.breaking_news = BreakingNewsClient(client_wrapper=self._client_wrapper)
- self.authors = AuthorsClient(client_wrapper=self._client_wrapper)
- self.search_link = SearchLinkClient(client_wrapper=self._client_wrapper)
- self.searchsimilar = SearchsimilarClient(client_wrapper=self._client_wrapper)
- self.sources = SourcesClient(client_wrapper=self._client_wrapper)
- self.aggregation = AggregationClient(client_wrapper=self._client_wrapper)
- self.subscription = SubscriptionClient(client_wrapper=self._client_wrapper)
+ self._search: typing.Optional[SearchClient] = None
+ self._latestheadlines: typing.Optional[LatestheadlinesClient] = None
+ self._breaking_news: typing.Optional[BreakingNewsClient] = None
+ self._authors: typing.Optional[AuthorsClient] = None
+ self._search_link: typing.Optional[SearchLinkClient] = None
+ self._searchsimilar: typing.Optional[SearchsimilarClient] = None
+ self._sources: typing.Optional[SourcesClient] = None
+ self._aggregation: typing.Optional[AggregationClient] = None
+ self._subscription: typing.Optional[SubscriptionClient] = None
+
+ @property
+ def search(self):
+ if self._search is None:
+ from .search.client import SearchClient # noqa: E402
+
+ self._search = SearchClient(client_wrapper=self._client_wrapper)
+ return self._search
+
+ @property
+ def latestheadlines(self):
+ if self._latestheadlines is None:
+ from .latestheadlines.client import LatestheadlinesClient # noqa: E402
+
+ self._latestheadlines = LatestheadlinesClient(client_wrapper=self._client_wrapper)
+ return self._latestheadlines
+
+ @property
+ def breaking_news(self):
+ if self._breaking_news is None:
+ from .breaking_news.client import BreakingNewsClient # noqa: E402
+
+ self._breaking_news = BreakingNewsClient(client_wrapper=self._client_wrapper)
+ return self._breaking_news
+
+ @property
+ def authors(self):
+ if self._authors is None:
+ from .authors.client import AuthorsClient # noqa: E402
+
+ self._authors = AuthorsClient(client_wrapper=self._client_wrapper)
+ return self._authors
+
+ @property
+ def search_link(self):
+ if self._search_link is None:
+ from .search_link.client import SearchLinkClient # noqa: E402
+
+ self._search_link = SearchLinkClient(client_wrapper=self._client_wrapper)
+ return self._search_link
+
+ @property
+ def searchsimilar(self):
+ if self._searchsimilar is None:
+ from .searchsimilar.client import SearchsimilarClient # noqa: E402
+
+ self._searchsimilar = SearchsimilarClient(client_wrapper=self._client_wrapper)
+ return self._searchsimilar
+
+ @property
+ def sources(self):
+ if self._sources is None:
+ from .sources.client import SourcesClient # noqa: E402
+
+ self._sources = SourcesClient(client_wrapper=self._client_wrapper)
+ return self._sources
+
+ @property
+ def aggregation(self):
+ if self._aggregation is None:
+ from .aggregation.client import AggregationClient # noqa: E402
+
+ self._aggregation = AggregationClient(client_wrapper=self._client_wrapper)
+ return self._aggregation
+
+ @property
+ def subscription(self):
+ if self._subscription is None:
+ from .subscription.client import SubscriptionClient # noqa: E402
+
+ self._subscription = SubscriptionClient(client_wrapper=self._client_wrapper)
+ return self._subscription
class AsyncBaseNewscatcherApi:
@@ -157,15 +233,87 @@ def __init__(
else httpx.AsyncClient(timeout=_defaulted_timeout),
timeout=_defaulted_timeout,
)
- self.search = AsyncSearchClient(client_wrapper=self._client_wrapper)
- self.latestheadlines = AsyncLatestheadlinesClient(client_wrapper=self._client_wrapper)
- self.breaking_news = AsyncBreakingNewsClient(client_wrapper=self._client_wrapper)
- self.authors = AsyncAuthorsClient(client_wrapper=self._client_wrapper)
- self.search_link = AsyncSearchLinkClient(client_wrapper=self._client_wrapper)
- self.searchsimilar = AsyncSearchsimilarClient(client_wrapper=self._client_wrapper)
- self.sources = AsyncSourcesClient(client_wrapper=self._client_wrapper)
- self.aggregation = AsyncAggregationClient(client_wrapper=self._client_wrapper)
- self.subscription = AsyncSubscriptionClient(client_wrapper=self._client_wrapper)
+ self._search: typing.Optional[AsyncSearchClient] = None
+ self._latestheadlines: typing.Optional[AsyncLatestheadlinesClient] = None
+ self._breaking_news: typing.Optional[AsyncBreakingNewsClient] = None
+ self._authors: typing.Optional[AsyncAuthorsClient] = None
+ self._search_link: typing.Optional[AsyncSearchLinkClient] = None
+ self._searchsimilar: typing.Optional[AsyncSearchsimilarClient] = None
+ self._sources: typing.Optional[AsyncSourcesClient] = None
+ self._aggregation: typing.Optional[AsyncAggregationClient] = None
+ self._subscription: typing.Optional[AsyncSubscriptionClient] = None
+
+ @property
+ def search(self):
+ if self._search is None:
+ from .search.client import AsyncSearchClient # noqa: E402
+
+ self._search = AsyncSearchClient(client_wrapper=self._client_wrapper)
+ return self._search
+
+ @property
+ def latestheadlines(self):
+ if self._latestheadlines is None:
+ from .latestheadlines.client import AsyncLatestheadlinesClient # noqa: E402
+
+ self._latestheadlines = AsyncLatestheadlinesClient(client_wrapper=self._client_wrapper)
+ return self._latestheadlines
+
+ @property
+ def breaking_news(self):
+ if self._breaking_news is None:
+ from .breaking_news.client import AsyncBreakingNewsClient # noqa: E402
+
+ self._breaking_news = AsyncBreakingNewsClient(client_wrapper=self._client_wrapper)
+ return self._breaking_news
+
+ @property
+ def authors(self):
+ if self._authors is None:
+ from .authors.client import AsyncAuthorsClient # noqa: E402
+
+ self._authors = AsyncAuthorsClient(client_wrapper=self._client_wrapper)
+ return self._authors
+
+ @property
+ def search_link(self):
+ if self._search_link is None:
+ from .search_link.client import AsyncSearchLinkClient # noqa: E402
+
+ self._search_link = AsyncSearchLinkClient(client_wrapper=self._client_wrapper)
+ return self._search_link
+
+ @property
+ def searchsimilar(self):
+ if self._searchsimilar is None:
+ from .searchsimilar.client import AsyncSearchsimilarClient # noqa: E402
+
+ self._searchsimilar = AsyncSearchsimilarClient(client_wrapper=self._client_wrapper)
+ return self._searchsimilar
+
+ @property
+ def sources(self):
+ if self._sources is None:
+ from .sources.client import AsyncSourcesClient # noqa: E402
+
+ self._sources = AsyncSourcesClient(client_wrapper=self._client_wrapper)
+ return self._sources
+
+ @property
+ def aggregation(self):
+ if self._aggregation is None:
+ from .aggregation.client import AsyncAggregationClient # noqa: E402
+
+ self._aggregation = AsyncAggregationClient(client_wrapper=self._client_wrapper)
+ return self._aggregation
+
+ @property
+ def subscription(self):
+ if self._subscription is None:
+ from .subscription.client import AsyncSubscriptionClient # noqa: E402
+
+ self._subscription = AsyncSubscriptionClient(client_wrapper=self._client_wrapper)
+ return self._subscription
def _get_base_url(*, base_url: typing.Optional[str] = None, environment: NewscatcherApiEnvironment) -> str:
diff --git a/src/newscatcher/breaking_news/__init__.py b/src/newscatcher/breaking_news/__init__.py
index 8661612..bde27e6 100644
--- a/src/newscatcher/breaking_news/__init__.py
+++ b/src/newscatcher/breaking_news/__init__.py
@@ -2,6 +2,33 @@
# isort: skip_file
-from .types import BreakingNewsGetRequestSortBy
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import BreakingNewsGetRequestSortBy
+_dynamic_imports: typing.Dict[str, str] = {"BreakingNewsGetRequestSortBy": ".types"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["BreakingNewsGetRequestSortBy"]
diff --git a/src/newscatcher/breaking_news/client.py b/src/newscatcher/breaking_news/client.py
index 350a29a..880a5c1 100644
--- a/src/newscatcher/breaking_news/client.py
+++ b/src/newscatcher/breaking_news/client.py
@@ -239,6 +239,10 @@ def breaking_news_get(
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
)
"""
_response = self._raw_client.breaking_news_get(
@@ -357,9 +361,8 @@ def breaking_news_post(
)
client.breaking_news.breaking_news_post(
sort_by="relevancy",
- page=1,
- page_size=100,
- include_nlp_data=True,
+ ranked_only=True,
+ top_n_articles=1,
)
"""
_response = self._raw_client.breaking_news_post(
@@ -600,6 +603,10 @@ async def main() -> None:
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
)
@@ -726,9 +733,8 @@ async def breaking_news_post(
async def main() -> None:
await client.breaking_news.breaking_news_post(
sort_by="relevancy",
- page=1,
- page_size=100,
- include_nlp_data=True,
+ ranked_only=True,
+ top_n_articles=1,
)
diff --git a/src/newscatcher/breaking_news/types/__init__.py b/src/newscatcher/breaking_news/types/__init__.py
index 7ad450d..43f2771 100644
--- a/src/newscatcher/breaking_news/types/__init__.py
+++ b/src/newscatcher/breaking_news/types/__init__.py
@@ -2,6 +2,33 @@
# isort: skip_file
-from .breaking_news_get_request_sort_by import BreakingNewsGetRequestSortBy
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .breaking_news_get_request_sort_by import BreakingNewsGetRequestSortBy
+_dynamic_imports: typing.Dict[str, str] = {"BreakingNewsGetRequestSortBy": ".breaking_news_get_request_sort_by"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["BreakingNewsGetRequestSortBy"]
diff --git a/src/newscatcher/core/__init__.py b/src/newscatcher/core/__init__.py
index 31bbb81..9a33e23 100644
--- a/src/newscatcher/core/__init__.py
+++ b/src/newscatcher/core/__init__.py
@@ -2,26 +2,79 @@
# isort: skip_file
-from .api_error import ApiError
-from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
-from .datetime_utils import serialize_datetime
-from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
-from .http_client import AsyncHttpClient, HttpClient
-from .http_response import AsyncHttpResponse, HttpResponse
-from .jsonable_encoder import jsonable_encoder
-from .pydantic_utilities import (
- IS_PYDANTIC_V2,
- UniversalBaseModel,
- UniversalRootModel,
- parse_obj_as,
- universal_field_validator,
- universal_root_validator,
- update_forward_refs,
-)
-from .query_encoder import encode_query
-from .remove_none_from_dict import remove_none_from_dict
-from .request_options import RequestOptions
-from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .api_error import ApiError
+ from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
+ from .datetime_utils import serialize_datetime
+ from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
+ from .http_client import AsyncHttpClient, HttpClient
+ from .http_response import AsyncHttpResponse, HttpResponse
+ from .jsonable_encoder import jsonable_encoder
+ from .pydantic_utilities import (
+ IS_PYDANTIC_V2,
+ UniversalBaseModel,
+ UniversalRootModel,
+ parse_obj_as,
+ universal_field_validator,
+ universal_root_validator,
+ update_forward_refs,
+ )
+ from .query_encoder import encode_query
+ from .remove_none_from_dict import remove_none_from_dict
+ from .request_options import RequestOptions
+ from .serialization import FieldMetadata, convert_and_respect_annotation_metadata
+_dynamic_imports: typing.Dict[str, str] = {
+ "ApiError": ".api_error",
+ "AsyncClientWrapper": ".client_wrapper",
+ "AsyncHttpClient": ".http_client",
+ "AsyncHttpResponse": ".http_response",
+ "BaseClientWrapper": ".client_wrapper",
+ "FieldMetadata": ".serialization",
+ "File": ".file",
+ "HttpClient": ".http_client",
+ "HttpResponse": ".http_response",
+ "IS_PYDANTIC_V2": ".pydantic_utilities",
+ "RequestOptions": ".request_options",
+ "SyncClientWrapper": ".client_wrapper",
+ "UniversalBaseModel": ".pydantic_utilities",
+ "UniversalRootModel": ".pydantic_utilities",
+ "convert_and_respect_annotation_metadata": ".serialization",
+ "convert_file_dict_to_httpx_tuples": ".file",
+ "encode_query": ".query_encoder",
+ "jsonable_encoder": ".jsonable_encoder",
+ "parse_obj_as": ".pydantic_utilities",
+ "remove_none_from_dict": ".remove_none_from_dict",
+ "serialize_datetime": ".datetime_utils",
+ "universal_field_validator": ".pydantic_utilities",
+ "universal_root_validator": ".pydantic_utilities",
+ "update_forward_refs": ".pydantic_utilities",
+ "with_content_type": ".file",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"ApiError",
diff --git a/src/newscatcher/core/client_wrapper.py b/src/newscatcher/core/client_wrapper.py
index 2c185f8..a4347ec 100644
--- a/src/newscatcher/core/client_wrapper.py
+++ b/src/newscatcher/core/client_wrapper.py
@@ -22,10 +22,10 @@ def __init__(
def get_headers(self) -> typing.Dict[str, str]:
headers: typing.Dict[str, str] = {
- "User-Agent": "newscatcher-sdk/1.4.0",
+ "User-Agent": "newscatcher-sdk/AUTO",
"X-Fern-Language": "Python",
"X-Fern-SDK-Name": "newscatcher-sdk",
- "X-Fern-SDK-Version": "1.4.0",
+ "X-Fern-SDK-Version": "1.4.1",
**(self.get_custom_headers() or {}),
}
headers["x-api-token"] = self.api_key
diff --git a/src/newscatcher/core/force_multipart.py b/src/newscatcher/core/force_multipart.py
index ae24ccf..5440913 100644
--- a/src/newscatcher/core/force_multipart.py
+++ b/src/newscatcher/core/force_multipart.py
@@ -1,7 +1,9 @@
# This file was auto-generated by Fern from our API Definition.
+from typing import Any, Dict
-class ForceMultipartDict(dict):
+
+class ForceMultipartDict(Dict[str, Any]):
"""
A dictionary subclass that always evaluates to True in boolean contexts.
@@ -9,7 +11,7 @@ class ForceMultipartDict(dict):
the dictionary is empty, which would normally evaluate to False.
"""
- def __bool__(self):
+ def __bool__(self) -> bool:
return True
diff --git a/src/newscatcher/core/http_response.py b/src/newscatcher/core/http_response.py
index 48a1798..2479747 100644
--- a/src/newscatcher/core/http_response.py
+++ b/src/newscatcher/core/http_response.py
@@ -4,8 +4,8 @@
import httpx
+# Generic to represent the underlying type of the data wrapped by the HTTP response.
T = TypeVar("T")
-"""Generic to represent the underlying type of the data wrapped by the HTTP response."""
class BaseHttpResponse:
diff --git a/src/newscatcher/core/http_sse/__init__.py b/src/newscatcher/core/http_sse/__init__.py
new file mode 100644
index 0000000..730e5a3
--- /dev/null
+++ b/src/newscatcher/core/http_sse/__init__.py
@@ -0,0 +1,42 @@
+# This file was auto-generated by Fern from our API Definition.
+
+# isort: skip_file
+
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from ._api import EventSource, aconnect_sse, connect_sse
+ from ._exceptions import SSEError
+ from ._models import ServerSentEvent
+_dynamic_imports: typing.Dict[str, str] = {
+ "EventSource": "._api",
+ "SSEError": "._exceptions",
+ "ServerSentEvent": "._models",
+ "aconnect_sse": "._api",
+ "connect_sse": "._api",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
+
+__all__ = ["EventSource", "SSEError", "ServerSentEvent", "aconnect_sse", "connect_sse"]
diff --git a/src/newscatcher/core/http_sse/_api.py b/src/newscatcher/core/http_sse/_api.py
new file mode 100644
index 0000000..f900b3b
--- /dev/null
+++ b/src/newscatcher/core/http_sse/_api.py
@@ -0,0 +1,112 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import re
+from contextlib import asynccontextmanager, contextmanager
+from typing import Any, AsyncGenerator, AsyncIterator, Iterator, cast
+
+import httpx
+from ._decoders import SSEDecoder
+from ._exceptions import SSEError
+from ._models import ServerSentEvent
+
+
+class EventSource:
+ def __init__(self, response: httpx.Response) -> None:
+ self._response = response
+
+ def _check_content_type(self) -> None:
+ content_type = self._response.headers.get("content-type", "").partition(";")[0]
+ if "text/event-stream" not in content_type:
+ raise SSEError(
+ f"Expected response header Content-Type to contain 'text/event-stream', got {content_type!r}"
+ )
+
+ def _get_charset(self) -> str:
+ """Extract charset from Content-Type header, fallback to UTF-8."""
+ content_type = self._response.headers.get("content-type", "")
+
+ # Parse charset parameter using regex
+ charset_match = re.search(r"charset=([^;\s]+)", content_type, re.IGNORECASE)
+ if charset_match:
+ charset = charset_match.group(1).strip("\"'")
+ # Validate that it's a known encoding
+ try:
+ # Test if the charset is valid by trying to encode/decode
+ "test".encode(charset).decode(charset)
+ return charset
+ except (LookupError, UnicodeError):
+ # If charset is invalid, fall back to UTF-8
+ pass
+
+ # Default to UTF-8 if no charset specified or invalid charset
+ return "utf-8"
+
+ @property
+ def response(self) -> httpx.Response:
+ return self._response
+
+ def iter_sse(self) -> Iterator[ServerSentEvent]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ charset = self._get_charset()
+
+ buffer = ""
+ for chunk in self._response.iter_bytes():
+ # Decode chunk using detected charset
+ text_chunk = chunk.decode(charset, errors="replace")
+ buffer += text_chunk
+
+ # Process complete lines
+ while "\n" in buffer:
+ line, buffer = buffer.split("\n", 1)
+ line = line.rstrip("\r")
+ sse = decoder.decode(line)
+ # when we reach a "\n\n" => line = ''
+ # => decoder will attempt to return an SSE Event
+ if sse is not None:
+ yield sse
+
+ # Process any remaining data in buffer
+ if buffer.strip():
+ line = buffer.rstrip("\r")
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+
+ async def aiter_sse(self) -> AsyncGenerator[ServerSentEvent, None]:
+ self._check_content_type()
+ decoder = SSEDecoder()
+ lines = cast(AsyncGenerator[str, None], self._response.aiter_lines())
+ try:
+ async for line in lines:
+ line = line.rstrip("\n")
+ sse = decoder.decode(line)
+ if sse is not None:
+ yield sse
+ finally:
+ await lines.aclose()
+
+
+@contextmanager
+def connect_sse(client: httpx.Client, method: str, url: str, **kwargs: Any) -> Iterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
+
+
+@asynccontextmanager
+async def aconnect_sse(
+ client: httpx.AsyncClient,
+ method: str,
+ url: str,
+ **kwargs: Any,
+) -> AsyncIterator[EventSource]:
+ headers = kwargs.pop("headers", {})
+ headers["Accept"] = "text/event-stream"
+ headers["Cache-Control"] = "no-store"
+
+ async with client.stream(method, url, headers=headers, **kwargs) as response:
+ yield EventSource(response)
diff --git a/src/newscatcher/core/http_sse/_decoders.py b/src/newscatcher/core/http_sse/_decoders.py
new file mode 100644
index 0000000..339b089
--- /dev/null
+++ b/src/newscatcher/core/http_sse/_decoders.py
@@ -0,0 +1,61 @@
+# This file was auto-generated by Fern from our API Definition.
+
+from typing import List, Optional
+
+from ._models import ServerSentEvent
+
+
+class SSEDecoder:
+ def __init__(self) -> None:
+ self._event = ""
+ self._data: List[str] = []
+ self._last_event_id = ""
+ self._retry: Optional[int] = None
+
+ def decode(self, line: str) -> Optional[ServerSentEvent]:
+ # See: https://html.spec.whatwg.org/multipage/server-sent-events.html#event-stream-interpretation # noqa: E501
+
+ if not line:
+ if not self._event and not self._data and not self._last_event_id and self._retry is None:
+ return None
+
+ sse = ServerSentEvent(
+ event=self._event,
+ data="\n".join(self._data),
+ id=self._last_event_id,
+ retry=self._retry,
+ )
+
+ # NOTE: as per the SSE spec, do not reset last_event_id.
+ self._event = ""
+ self._data = []
+ self._retry = None
+
+ return sse
+
+ if line.startswith(":"):
+ return None
+
+ fieldname, _, value = line.partition(":")
+
+ if value.startswith(" "):
+ value = value[1:]
+
+ if fieldname == "event":
+ self._event = value
+ elif fieldname == "data":
+ self._data.append(value)
+ elif fieldname == "id":
+ if "\0" in value:
+ pass
+ else:
+ self._last_event_id = value
+ elif fieldname == "retry":
+ try:
+ self._retry = int(value)
+ except (TypeError, ValueError):
+ pass
+ else:
+ pass # Field is ignored.
+
+ return None
diff --git a/src/newscatcher/core/http_sse/_exceptions.py b/src/newscatcher/core/http_sse/_exceptions.py
new file mode 100644
index 0000000..81605a8
--- /dev/null
+++ b/src/newscatcher/core/http_sse/_exceptions.py
@@ -0,0 +1,7 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import httpx
+
+
+class SSEError(httpx.TransportError):
+ pass
diff --git a/src/newscatcher/core/http_sse/_models.py b/src/newscatcher/core/http_sse/_models.py
new file mode 100644
index 0000000..1af57f8
--- /dev/null
+++ b/src/newscatcher/core/http_sse/_models.py
@@ -0,0 +1,17 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import json
+from dataclasses import dataclass
+from typing import Any, Optional
+
+
+@dataclass(frozen=True)
+class ServerSentEvent:
+ event: str = "message"
+ data: str = ""
+ id: str = ""
+ retry: Optional[int] = None
+
+ def json(self) -> Any:
+ """Parse the data field as JSON."""
+ return json.loads(self.data)
diff --git a/src/newscatcher/core/pydantic_utilities.py b/src/newscatcher/core/pydantic_utilities.py
index 7db2950..185e5c4 100644
--- a/src/newscatcher/core/pydantic_utilities.py
+++ b/src/newscatcher/core/pydantic_utilities.py
@@ -61,7 +61,7 @@ class UniversalBaseModel(pydantic.BaseModel):
@pydantic.model_serializer(mode="plain", when_used="json") # type: ignore[attr-defined]
def serialize_model(self) -> Any: # type: ignore[name-defined]
- serialized = self.model_dump()
+ serialized = self.dict() # type: ignore[attr-defined]
data = {k: serialize_datetime(v) if isinstance(v, dt.datetime) else v for k, v in serialized.items()}
return data
@@ -147,7 +147,10 @@ def dict(self, **kwargs: Any) -> Dict[str, Any]:
dict_dump = super().dict(**kwargs_with_defaults_exclude_unset_include_fields)
- return convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write")
+ return cast(
+ Dict[str, Any],
+ convert_and_respect_annotation_metadata(object_=dict_dump, annotation=self.__class__, direction="write"),
+ )
def _union_list_of_pydantic_dicts(source: List[Any], destination: List[Any]) -> List[Any]:
@@ -217,7 +220,9 @@ def universal_root_validator(
) -> Callable[[AnyCallable], AnyCallable]:
def decorator(func: AnyCallable) -> AnyCallable:
if IS_PYDANTIC_V2:
- return cast(AnyCallable, pydantic.model_validator(mode="before" if pre else "after")(func)) # type: ignore[attr-defined]
+ # In Pydantic v2, for RootModel we always use "before" mode
+ # The custom validators transform the input value before the model is created
+ return cast(AnyCallable, pydantic.model_validator(mode="before")(func)) # type: ignore[attr-defined]
return cast(AnyCallable, pydantic.root_validator(pre=pre)(func)) # type: ignore[call-overload]
return decorator
diff --git a/src/newscatcher/errors/__init__.py b/src/newscatcher/errors/__init__.py
index ac3639a..fee5ae7 100644
--- a/src/newscatcher/errors/__init__.py
+++ b/src/newscatcher/errors/__init__.py
@@ -2,13 +2,48 @@
# isort: skip_file
-from .bad_request_error import BadRequestError
-from .forbidden_error import ForbiddenError
-from .internal_server_error import InternalServerError
-from .request_timeout_error import RequestTimeoutError
-from .too_many_requests_error import TooManyRequestsError
-from .unauthorized_error import UnauthorizedError
-from .unprocessable_entity_error import UnprocessableEntityError
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .bad_request_error import BadRequestError
+ from .forbidden_error import ForbiddenError
+ from .internal_server_error import InternalServerError
+ from .request_timeout_error import RequestTimeoutError
+ from .too_many_requests_error import TooManyRequestsError
+ from .unauthorized_error import UnauthorizedError
+ from .unprocessable_entity_error import UnprocessableEntityError
+_dynamic_imports: typing.Dict[str, str] = {
+ "BadRequestError": ".bad_request_error",
+ "ForbiddenError": ".forbidden_error",
+ "InternalServerError": ".internal_server_error",
+ "RequestTimeoutError": ".request_timeout_error",
+ "TooManyRequestsError": ".too_many_requests_error",
+ "UnauthorizedError": ".unauthorized_error",
+ "UnprocessableEntityError": ".unprocessable_entity_error",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"BadRequestError",
diff --git a/src/newscatcher/latestheadlines/__init__.py b/src/newscatcher/latestheadlines/__init__.py
index 79cd966..5787d6d 100644
--- a/src/newscatcher/latestheadlines/__init__.py
+++ b/src/newscatcher/latestheadlines/__init__.py
@@ -2,6 +2,41 @@
# isort: skip_file
-from .types import LatestHeadlinesGetRequestClusteringVariable, LatestHeadlinesGetResponse, LatestHeadlinesPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ LatestHeadlinesGetRequestClusteringVariable,
+ LatestHeadlinesGetResponse,
+ LatestHeadlinesPostResponse,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "LatestHeadlinesGetRequestClusteringVariable": ".types",
+ "LatestHeadlinesGetResponse": ".types",
+ "LatestHeadlinesPostResponse": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["LatestHeadlinesGetRequestClusteringVariable", "LatestHeadlinesGetResponse", "LatestHeadlinesPostResponse"]
diff --git a/src/newscatcher/latestheadlines/client.py b/src/newscatcher/latestheadlines/client.py
index ac90a8e..50778d0 100644
--- a/src/newscatcher/latestheadlines/client.py
+++ b/src/newscatcher/latestheadlines/client.py
@@ -436,12 +436,27 @@ def get(
api_key="YOUR_API_KEY",
)
client.latestheadlines.get(
+ when="7d",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ not_author_name="John Doe",
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -652,10 +667,8 @@ def post(
api_key="YOUR_API_KEY",
)
client.latestheadlines.post(
- lang="en",
- predefined_sources=["top 50 US", "top 20 GB"],
- is_opinion=False,
- page_size=10,
+ when="7d",
+ page_size=1,
)
"""
_response = self._raw_client.post(
@@ -1092,12 +1105,27 @@ async def get(
async def main() -> None:
await client.latestheadlines.get(
+ when="7d",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ not_author_name="John Doe",
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_translation_fields=True,
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -1316,10 +1344,8 @@ async def post(
async def main() -> None:
await client.latestheadlines.post(
- lang="en",
- predefined_sources=["top 50 US", "top 20 GB"],
- is_opinion=False,
- page_size=10,
+ when="7d",
+ page_size=1,
)
diff --git a/src/newscatcher/latestheadlines/types/__init__.py b/src/newscatcher/latestheadlines/types/__init__.py
index a3c6699..b476e7a 100644
--- a/src/newscatcher/latestheadlines/types/__init__.py
+++ b/src/newscatcher/latestheadlines/types/__init__.py
@@ -2,8 +2,39 @@
# isort: skip_file
-from .latest_headlines_get_request_clustering_variable import LatestHeadlinesGetRequestClusteringVariable
-from .latest_headlines_get_response import LatestHeadlinesGetResponse
-from .latest_headlines_post_response import LatestHeadlinesPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .latest_headlines_get_request_clustering_variable import LatestHeadlinesGetRequestClusteringVariable
+ from .latest_headlines_get_response import LatestHeadlinesGetResponse
+ from .latest_headlines_post_response import LatestHeadlinesPostResponse
+_dynamic_imports: typing.Dict[str, str] = {
+ "LatestHeadlinesGetRequestClusteringVariable": ".latest_headlines_get_request_clustering_variable",
+ "LatestHeadlinesGetResponse": ".latest_headlines_get_response",
+ "LatestHeadlinesPostResponse": ".latest_headlines_post_response",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["LatestHeadlinesGetRequestClusteringVariable", "LatestHeadlinesGetResponse", "LatestHeadlinesPostResponse"]
diff --git a/src/newscatcher/search/__init__.py b/src/newscatcher/search/__init__.py
index b2bfd44..ded5b09 100644
--- a/src/newscatcher/search/__init__.py
+++ b/src/newscatcher/search/__init__.py
@@ -2,14 +2,48 @@
# isort: skip_file
-from .types import (
- SearchGetRequestClusteringVariable,
- SearchGetRequestNewsDomainType,
- SearchGetRequestPublishedDatePrecision,
- SearchGetRequestSortBy,
- SearchGetResponse,
- SearchPostResponse,
-)
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ SearchGetRequestClusteringVariable,
+ SearchGetRequestNewsDomainType,
+ SearchGetRequestPublishedDatePrecision,
+ SearchGetRequestSortBy,
+ SearchGetResponse,
+ SearchPostResponse,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "SearchGetRequestClusteringVariable": ".types",
+ "SearchGetRequestNewsDomainType": ".types",
+ "SearchGetRequestPublishedDatePrecision": ".types",
+ "SearchGetRequestSortBy": ".types",
+ "SearchGetResponse": ".types",
+ "SearchPostResponse": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"SearchGetRequestClusteringVariable",
diff --git a/src/newscatcher/search/client.py b/src/newscatcher/search/client.py
index 40ea215..f68cc54 100644
--- a/src/newscatcher/search/client.py
+++ b/src/newscatcher/search/client.py
@@ -1,6 +1,5 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
@@ -50,6 +49,8 @@
from ..types.q import Q
from ..types.ranked_only import RankedOnly
from ..types.robots_compliant import RobotsCompliant
+from ..types.search_get_request_from import SearchGetRequestFrom
+from ..types.search_get_request_to import SearchGetRequestTo
from ..types.search_in import SearchIn
from ..types.sort_by import SortBy
from ..types.source_name import SourceName
@@ -91,7 +92,7 @@ def with_raw_response(self) -> RawSearchClient:
def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
predefined_sources: typing.Optional[str] = None,
@@ -103,8 +104,8 @@ def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchGetRequestFrom] = None,
+ to: typing.Optional[SearchGetRequestTo] = None,
published_date_precision: typing.Optional[SearchGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[SearchGetRequestSortBy] = None,
@@ -154,17 +155,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -233,7 +224,7 @@ def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -245,7 +236,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -551,20 +542,36 @@ def get(
api_key="YOUR_API_KEY",
)
client.search.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
+ news_type="General News Outlets",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -821,25 +828,14 @@ def post(
Examples
--------
- import datetime
-
from newscatcher import NewscatcherApi
client = NewscatcherApi(
api_key="YOUR_API_KEY",
)
client.search.post(
- q="renewable energy",
- predefined_sources=["top 50 US"],
- lang=["en"],
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
- additional_domain_info=True,
- is_news_domain=True,
+ q='"supply chain" AND Amazon NOT China',
+ page_size=1,
)
"""
_response = self._raw_client.post(
@@ -922,7 +918,7 @@ def with_raw_response(self) -> AsyncRawSearchClient:
async def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
predefined_sources: typing.Optional[str] = None,
@@ -934,8 +930,8 @@ async def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchGetRequestFrom] = None,
+ to: typing.Optional[SearchGetRequestTo] = None,
published_date_precision: typing.Optional[SearchGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[SearchGetRequestSortBy] = None,
@@ -985,17 +981,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -1064,7 +1050,7 @@ async def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1076,7 +1062,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1386,20 +1372,36 @@ async def get(
async def main() -> None:
await client.search.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
+ not_author_name="John Doe",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
+ news_type="General News Outlets",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
not_theme="Crime",
+ org_entity_name="Apple",
+ per_entity_name="Elon Musk",
+ loc_entity_name="California",
+ misc_entity_name="Bitcoin",
iptc_tags="20000199,20000209",
not_iptc_tags="20000205,20000209",
iab_tags="Business,Events",
@@ -1660,7 +1662,6 @@ async def post(
Examples
--------
import asyncio
- import datetime
from newscatcher import AsyncNewscatcherApi
@@ -1671,17 +1672,8 @@ async def post(
async def main() -> None:
await client.search.post(
- q="renewable energy",
- predefined_sources=["top 50 US"],
- lang=["en"],
- from_=datetime.datetime.fromisoformat(
- "2024-01-01 00:00:00+00:00",
- ),
- to=datetime.datetime.fromisoformat(
- "2024-06-30 00:00:00+00:00",
- ),
- additional_domain_info=True,
- is_news_domain=True,
+ q='"supply chain" AND Amazon NOT China',
+ page_size=1,
)
diff --git a/src/newscatcher/search/raw_client.py b/src/newscatcher/search/raw_client.py
index ec01ca2..014b13b 100644
--- a/src/newscatcher/search/raw_client.py
+++ b/src/newscatcher/search/raw_client.py
@@ -1,12 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.datetime_utils import serialize_datetime
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
@@ -64,6 +62,8 @@
from ..types.q import Q
from ..types.ranked_only import RankedOnly
from ..types.robots_compliant import RobotsCompliant
+from ..types.search_get_request_from import SearchGetRequestFrom
+from ..types.search_get_request_to import SearchGetRequestTo
from ..types.search_in import SearchIn
from ..types.sort_by import SortBy
from ..types.source_name import SourceName
@@ -93,7 +93,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper):
def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
predefined_sources: typing.Optional[str] = None,
@@ -105,8 +105,8 @@ def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchGetRequestFrom] = None,
+ to: typing.Optional[SearchGetRequestTo] = None,
published_date_precision: typing.Optional[SearchGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[SearchGetRequestSortBy] = None,
@@ -156,17 +156,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -235,7 +225,7 @@ def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -247,7 +237,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -559,8 +549,12 @@ def get(
"countries": countries,
"not_countries": not_countries,
"not_author_name": not_author_name,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=SearchGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=SearchGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
@@ -1087,7 +1081,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper):
async def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
predefined_sources: typing.Optional[str] = None,
@@ -1099,8 +1093,8 @@ async def get(
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
not_author_name: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchGetRequestFrom] = None,
+ to: typing.Optional[SearchGetRequestTo] = None,
published_date_precision: typing.Optional[SearchGetRequestPublishedDatePrecision] = None,
by_parse_date: typing.Optional[bool] = None,
sort_by: typing.Optional[SearchGetRequestSortBy] = None,
@@ -1150,17 +1144,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -1229,7 +1213,7 @@ async def get(
Example: `"John Doe, Jane Doe"`
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1241,7 +1225,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1553,8 +1537,12 @@ async def get(
"countries": countries,
"not_countries": not_countries,
"not_author_name": not_author_name,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=SearchGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=SearchGetRequestTo, direction="write"
+ ),
"published_date_precision": published_date_precision,
"by_parse_date": by_parse_date,
"sort_by": sort_by,
diff --git a/src/newscatcher/search/types/__init__.py b/src/newscatcher/search/types/__init__.py
index e6be70d..240256e 100644
--- a/src/newscatcher/search/types/__init__.py
+++ b/src/newscatcher/search/types/__init__.py
@@ -2,12 +2,46 @@
# isort: skip_file
-from .search_get_request_clustering_variable import SearchGetRequestClusteringVariable
-from .search_get_request_news_domain_type import SearchGetRequestNewsDomainType
-from .search_get_request_published_date_precision import SearchGetRequestPublishedDatePrecision
-from .search_get_request_sort_by import SearchGetRequestSortBy
-from .search_get_response import SearchGetResponse
-from .search_post_response import SearchPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .search_get_request_clustering_variable import SearchGetRequestClusteringVariable
+ from .search_get_request_news_domain_type import SearchGetRequestNewsDomainType
+ from .search_get_request_published_date_precision import SearchGetRequestPublishedDatePrecision
+ from .search_get_request_sort_by import SearchGetRequestSortBy
+ from .search_get_response import SearchGetResponse
+ from .search_post_response import SearchPostResponse
+_dynamic_imports: typing.Dict[str, str] = {
+ "SearchGetRequestClusteringVariable": ".search_get_request_clustering_variable",
+ "SearchGetRequestNewsDomainType": ".search_get_request_news_domain_type",
+ "SearchGetRequestPublishedDatePrecision": ".search_get_request_published_date_precision",
+ "SearchGetRequestSortBy": ".search_get_request_sort_by",
+ "SearchGetResponse": ".search_get_response",
+ "SearchPostResponse": ".search_post_response",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"SearchGetRequestClusteringVariable",
diff --git a/src/newscatcher/search_link/client.py b/src/newscatcher/search_link/client.py
index e0ad325..ffe191e 100644
--- a/src/newscatcher/search_link/client.py
+++ b/src/newscatcher/search_link/client.py
@@ -11,6 +11,7 @@
from ..types.page_size import PageSize
from ..types.robots_compliant import RobotsCompliant
from ..types.search_response_dto import SearchResponseDto
+from ..types.source import Source
from ..types.to import To
from .raw_client import AsyncRawSearchLinkClient, RawSearchLinkClient
@@ -38,6 +39,7 @@ def search_url_get(
*,
ids: typing.Optional[str] = None,
links: typing.Optional[str] = None,
+ source: typing.Optional[Source] = None,
from_: typing.Optional[From] = None,
to: typing.Optional[To] = None,
page: typing.Optional[int] = None,
@@ -64,6 +66,8 @@ def search_url_get(
**Caution**: You can use either the `links` or the `ids` parameter, but not both at the same time.
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
to : typing.Optional[To]
@@ -97,6 +101,9 @@ def search_url_get(
api_key="YOUR_API_KEY",
)
client.search_link.search_url_get(
+ ids="5f8d0d55b6e45e00179c6e7e",
+ links="https://nytimes.com/article1",
+ source="articles.id,articles.title,articles.link,articles.published_date",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
@@ -108,6 +115,7 @@ def search_url_get(
_response = self._raw_client.search_url_get(
ids=ids,
links=links,
+ source=source,
from_=from_,
to=to,
page=page,
@@ -122,6 +130,7 @@ def search_url_post(
*,
ids: typing.Optional[Ids] = OMIT,
links: typing.Optional[Links] = OMIT,
+ source: typing.Optional[Source] = OMIT,
from_: typing.Optional[From] = OMIT,
to: typing.Optional[To] = OMIT,
page: typing.Optional[Page] = OMIT,
@@ -138,6 +147,8 @@ def search_url_post(
links : typing.Optional[Links]
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text strings. The default time zone is UTC.
@@ -180,19 +191,14 @@ def search_url_post(
api_key="YOUR_API_KEY",
)
client.search_link.search_url_post(
- ids=[
- "8ea8a784568ffaa05cb6d1ab2d2e84dd",
- "0146a551ef05ab1c494a55e806e3ce64",
- ],
- links=[
- "https://www.nytimes.com/2024/08/30/technology/ai-chatbot-chatgpt-manipulation.html",
- "https://www.bbc.com/news/articles/c39k379grzlo",
- ],
+ links="https://www.reuters.com/business/energy/oil-prices-up-after-israeli-attacks-oversupply-caps-gains-2025-09-10/",
+ source="articles.id,articles.title,articles.link,articles.canonical_url",
)
"""
_response = self._raw_client.search_url_post(
ids=ids,
links=links,
+ source=source,
from_=from_,
to=to,
page=page,
@@ -223,6 +229,7 @@ async def search_url_get(
*,
ids: typing.Optional[str] = None,
links: typing.Optional[str] = None,
+ source: typing.Optional[Source] = None,
from_: typing.Optional[From] = None,
to: typing.Optional[To] = None,
page: typing.Optional[int] = None,
@@ -249,6 +256,8 @@ async def search_url_get(
**Caution**: You can use either the `links` or the `ids` parameter, but not both at the same time.
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
to : typing.Optional[To]
@@ -286,6 +295,9 @@ async def search_url_get(
async def main() -> None:
await client.search_link.search_url_get(
+ ids="5f8d0d55b6e45e00179c6e7e",
+ links="https://nytimes.com/article1",
+ source="articles.id,articles.title,articles.link,articles.published_date",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
@@ -300,6 +312,7 @@ async def main() -> None:
_response = await self._raw_client.search_url_get(
ids=ids,
links=links,
+ source=source,
from_=from_,
to=to,
page=page,
@@ -314,6 +327,7 @@ async def search_url_post(
*,
ids: typing.Optional[Ids] = OMIT,
links: typing.Optional[Links] = OMIT,
+ source: typing.Optional[Source] = OMIT,
from_: typing.Optional[From] = OMIT,
to: typing.Optional[To] = OMIT,
page: typing.Optional[Page] = OMIT,
@@ -330,6 +344,8 @@ async def search_url_post(
links : typing.Optional[Links]
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text strings. The default time zone is UTC.
@@ -377,14 +393,8 @@ async def search_url_post(
async def main() -> None:
await client.search_link.search_url_post(
- ids=[
- "8ea8a784568ffaa05cb6d1ab2d2e84dd",
- "0146a551ef05ab1c494a55e806e3ce64",
- ],
- links=[
- "https://www.nytimes.com/2024/08/30/technology/ai-chatbot-chatgpt-manipulation.html",
- "https://www.bbc.com/news/articles/c39k379grzlo",
- ],
+ links="https://www.reuters.com/business/energy/oil-prices-up-after-israeli-attacks-oversupply-caps-gains-2025-09-10/",
+ source="articles.id,articles.title,articles.link,articles.canonical_url",
)
@@ -393,6 +403,7 @@ async def main() -> None:
_response = await self._raw_client.search_url_post(
ids=ids,
links=links,
+ source=source,
from_=from_,
to=to,
page=page,
diff --git a/src/newscatcher/search_link/raw_client.py b/src/newscatcher/search_link/raw_client.py
index 9823286..cab7513 100644
--- a/src/newscatcher/search_link/raw_client.py
+++ b/src/newscatcher/search_link/raw_client.py
@@ -24,6 +24,7 @@
from ..types.page_size import PageSize
from ..types.robots_compliant import RobotsCompliant
from ..types.search_response_dto import SearchResponseDto
+from ..types.source import Source
from ..types.to import To
# this is used as the default value for optional parameters
@@ -39,6 +40,7 @@ def search_url_get(
*,
ids: typing.Optional[str] = None,
links: typing.Optional[str] = None,
+ source: typing.Optional[Source] = None,
from_: typing.Optional[From] = None,
to: typing.Optional[To] = None,
page: typing.Optional[int] = None,
@@ -65,6 +67,8 @@ def search_url_get(
**Caution**: You can use either the `links` or the `ids` parameter, but not both at the same time.
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
to : typing.Optional[To]
@@ -94,6 +98,7 @@ def search_url_get(
params={
"ids": ids,
"links": links,
+ "_source": source,
"from_": convert_and_respect_annotation_metadata(object_=from_, annotation=From, direction="write"),
"to_": convert_and_respect_annotation_metadata(object_=to, annotation=To, direction="write"),
"page": page,
@@ -199,6 +204,7 @@ def search_url_post(
*,
ids: typing.Optional[Ids] = OMIT,
links: typing.Optional[Links] = OMIT,
+ source: typing.Optional[Source] = OMIT,
from_: typing.Optional[From] = OMIT,
to: typing.Optional[To] = OMIT,
page: typing.Optional[Page] = OMIT,
@@ -215,6 +221,8 @@ def search_url_post(
links : typing.Optional[Links]
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text strings. The default time zone is UTC.
@@ -255,6 +263,7 @@ def search_url_post(
json={
"ids": convert_and_respect_annotation_metadata(object_=ids, annotation=Ids, direction="write"),
"links": convert_and_respect_annotation_metadata(object_=links, annotation=Links, direction="write"),
+ "_source": source,
"from_": convert_and_respect_annotation_metadata(object_=from_, annotation=From, direction="write"),
"to_": convert_and_respect_annotation_metadata(object_=to, annotation=To, direction="write"),
"page": page,
@@ -369,6 +378,7 @@ async def search_url_get(
*,
ids: typing.Optional[str] = None,
links: typing.Optional[str] = None,
+ source: typing.Optional[Source] = None,
from_: typing.Optional[From] = None,
to: typing.Optional[To] = None,
page: typing.Optional[int] = None,
@@ -395,6 +405,8 @@ async def search_url_get(
**Caution**: You can use either the `links` or the `ids` parameter, but not both at the same time.
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
to : typing.Optional[To]
@@ -424,6 +436,7 @@ async def search_url_get(
params={
"ids": ids,
"links": links,
+ "_source": source,
"from_": convert_and_respect_annotation_metadata(object_=from_, annotation=From, direction="write"),
"to_": convert_and_respect_annotation_metadata(object_=to, annotation=To, direction="write"),
"page": page,
@@ -529,6 +542,7 @@ async def search_url_post(
*,
ids: typing.Optional[Ids] = OMIT,
links: typing.Optional[Links] = OMIT,
+ source: typing.Optional[Source] = OMIT,
from_: typing.Optional[From] = OMIT,
to: typing.Optional[To] = OMIT,
page: typing.Optional[Page] = OMIT,
@@ -545,6 +559,8 @@ async def search_url_post(
links : typing.Optional[Links]
+ source : typing.Optional[Source]
+
from_ : typing.Optional[From]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text strings. The default time zone is UTC.
@@ -585,6 +601,7 @@ async def search_url_post(
json={
"ids": convert_and_respect_annotation_metadata(object_=ids, annotation=Ids, direction="write"),
"links": convert_and_respect_annotation_metadata(object_=links, annotation=Links, direction="write"),
+ "_source": source,
"from_": convert_and_respect_annotation_metadata(object_=from_, annotation=From, direction="write"),
"to_": convert_and_respect_annotation_metadata(object_=to, annotation=To, direction="write"),
"page": page,
diff --git a/src/newscatcher/searchsimilar/__init__.py b/src/newscatcher/searchsimilar/__init__.py
index da93e88..b90322f 100644
--- a/src/newscatcher/searchsimilar/__init__.py
+++ b/src/newscatcher/searchsimilar/__init__.py
@@ -2,12 +2,44 @@
# isort: skip_file
-from .types import (
- SearchSimilarGetRequestPublishedDatePrecision,
- SearchSimilarGetRequestSortBy,
- SearchSimilarGetResponse,
- SearchSimilarPostResponse,
-)
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import (
+ SearchSimilarGetRequestPublishedDatePrecision,
+ SearchSimilarGetRequestSortBy,
+ SearchSimilarGetResponse,
+ SearchSimilarPostResponse,
+ )
+_dynamic_imports: typing.Dict[str, str] = {
+ "SearchSimilarGetRequestPublishedDatePrecision": ".types",
+ "SearchSimilarGetRequestSortBy": ".types",
+ "SearchSimilarGetResponse": ".types",
+ "SearchSimilarPostResponse": ".types",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"SearchSimilarGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/searchsimilar/client.py b/src/newscatcher/searchsimilar/client.py
index e5659d4..5af7d63 100644
--- a/src/newscatcher/searchsimilar/client.py
+++ b/src/newscatcher/searchsimilar/client.py
@@ -1,6 +1,5 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
@@ -38,6 +37,8 @@
from ..types.ranked_only import RankedOnly
from ..types.robots_compliant import RobotsCompliant
from ..types.search_in import SearchIn
+from ..types.search_similar_get_request_from import SearchSimilarGetRequestFrom
+from ..types.search_similar_get_request_to import SearchSimilarGetRequestTo
from ..types.similar_documents_fields import SimilarDocumentsFields
from ..types.similar_documents_number import SimilarDocumentsNumber
from ..types.sort_by import SortBy
@@ -77,7 +78,7 @@ def with_raw_response(self) -> RawSearchsimilarClient:
def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
include_similar_documents: typing.Optional[bool] = None,
@@ -90,8 +91,8 @@ def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchSimilarGetRequestFrom] = None,
+ to: typing.Optional[SearchSimilarGetRequestTo] = None,
by_parse_date: typing.Optional[bool] = None,
published_date_precision: typing.Optional[SearchSimilarGetRequestPublishedDatePrecision] = None,
sort_by: typing.Optional[SearchSimilarGetRequestSortBy] = None,
@@ -128,17 +129,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -204,7 +195,7 @@ def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchSimilarGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -216,7 +207,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchSimilarGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -419,17 +410,26 @@ def get(
api_key="YOUR_API_KEY",
)
client.searchsimilar.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
similar_documents_fields="title,summary",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
@@ -647,9 +647,10 @@ def post(
api_key="YOUR_API_KEY",
)
client.searchsimilar.post(
- q="artificial intelligence",
+ q='"supply chain" AND Amazon NOT China',
include_similar_documents=True,
similar_documents_number=5,
+ page_size=10,
)
"""
_response = self._raw_client.post(
@@ -720,7 +721,7 @@ def with_raw_response(self) -> AsyncRawSearchsimilarClient:
async def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
include_similar_documents: typing.Optional[bool] = None,
@@ -733,8 +734,8 @@ async def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchSimilarGetRequestFrom] = None,
+ to: typing.Optional[SearchSimilarGetRequestTo] = None,
by_parse_date: typing.Optional[bool] = None,
published_date_precision: typing.Optional[SearchSimilarGetRequestPublishedDatePrecision] = None,
sort_by: typing.Optional[SearchSimilarGetRequestSortBy] = None,
@@ -771,17 +772,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -847,7 +838,7 @@ async def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchSimilarGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -859,7 +850,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchSimilarGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1066,17 +1057,26 @@ async def get(
async def main() -> None:
await client.searchsimilar.get(
- q="technology AND (Apple OR Microsoft) NOT Google",
+ q='"supply chain" AND Amazon NOT China',
search_in="title_content, title_content_translated",
include_translation_fields=True,
similar_documents_fields="title,summary",
predefined_sources="top 100 US, top 5 GB",
+ sources="nytimes.com",
+ not_sources="cnn.com",
+ lang="en",
+ not_lang="fr",
+ countries="US",
+ not_countries="UK",
from_=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
to=datetime.datetime.fromisoformat(
"2024-07-01 00:00:00+00:00",
),
+ parent_url="https://www.washingtonpost.com/politics",
+ all_links="https://aiindex.stanford.edu/report",
+ all_domain_links="nvidia.com",
include_nlp_data=True,
has_nlp=True,
theme="Business,Finance",
@@ -1302,9 +1302,10 @@ async def post(
async def main() -> None:
await client.searchsimilar.post(
- q="artificial intelligence",
+ q='"supply chain" AND Amazon NOT China',
include_similar_documents=True,
similar_documents_number=5,
+ page_size=10,
)
diff --git a/src/newscatcher/searchsimilar/raw_client.py b/src/newscatcher/searchsimilar/raw_client.py
index 68c4769..7af2fe1 100644
--- a/src/newscatcher/searchsimilar/raw_client.py
+++ b/src/newscatcher/searchsimilar/raw_client.py
@@ -1,12 +1,10 @@
# This file was auto-generated by Fern from our API Definition.
-import datetime as dt
import typing
from json.decoder import JSONDecodeError
from ..core.api_error import ApiError
from ..core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
-from ..core.datetime_utils import serialize_datetime
from ..core.http_response import AsyncHttpResponse, HttpResponse
from ..core.pydantic_utilities import parse_obj_as
from ..core.request_options import RequestOptions
@@ -52,6 +50,8 @@
from ..types.ranked_only import RankedOnly
from ..types.robots_compliant import RobotsCompliant
from ..types.search_in import SearchIn
+from ..types.search_similar_get_request_from import SearchSimilarGetRequestFrom
+from ..types.search_similar_get_request_to import SearchSimilarGetRequestTo
from ..types.similar_documents_fields import SimilarDocumentsFields
from ..types.similar_documents_number import SimilarDocumentsNumber
from ..types.sort_by import SortBy
@@ -79,7 +79,7 @@ def __init__(self, *, client_wrapper: SyncClientWrapper):
def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
include_similar_documents: typing.Optional[bool] = None,
@@ -92,8 +92,8 @@ def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchSimilarGetRequestFrom] = None,
+ to: typing.Optional[SearchSimilarGetRequestTo] = None,
by_parse_date: typing.Optional[bool] = None,
published_date_precision: typing.Optional[SearchSimilarGetRequestPublishedDatePrecision] = None,
sort_by: typing.Optional[SearchSimilarGetRequestSortBy] = None,
@@ -130,17 +130,7 @@ def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -206,7 +196,7 @@ def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchSimilarGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -218,7 +208,7 @@ def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchSimilarGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -428,8 +418,12 @@ def get(
"not_lang": not_lang,
"countries": countries,
"not_countries": not_countries,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=SearchSimilarGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=SearchSimilarGetRequestTo, direction="write"
+ ),
"by_parse_date": by_parse_date,
"published_date_precision": published_date_precision,
"sort_by": sort_by,
@@ -885,7 +879,7 @@ def __init__(self, *, client_wrapper: AsyncClientWrapper):
async def get(
self,
*,
- q: str,
+ q: Q,
search_in: typing.Optional[SearchIn] = None,
include_translation_fields: typing.Optional[IncludeTranslationFields] = None,
include_similar_documents: typing.Optional[bool] = None,
@@ -898,8 +892,8 @@ async def get(
not_lang: typing.Optional[str] = None,
countries: typing.Optional[str] = None,
not_countries: typing.Optional[str] = None,
- from_: typing.Optional[dt.datetime] = None,
- to: typing.Optional[dt.datetime] = None,
+ from_: typing.Optional[SearchSimilarGetRequestFrom] = None,
+ to: typing.Optional[SearchSimilarGetRequestTo] = None,
by_parse_date: typing.Optional[bool] = None,
published_date_precision: typing.Optional[SearchSimilarGetRequestPublishedDatePrecision] = None,
sort_by: typing.Optional[SearchSimilarGetRequestSortBy] = None,
@@ -936,17 +930,7 @@ async def get(
Parameters
----------
- q : str
- The keyword(s) to search for in articles. Query syntax supports logical operators (`AND`, `OR`, `NOT`) and wildcards:
-
- - For an exact match, use double quotes. For example, `"technology news"`.
- - Use `*` to search for any keyword.
- - Use `+` to include and `-` to exclude specific words or phrases.
- For example, `+Apple`, `-Google`.
- - Use `AND`, `OR`, and `NOT` to refine search results.
- For example, `technology AND (Apple OR Microsoft) NOT Google`.
-
- For more details, see [Advanced querying](/docs/v3/documentation/guides-and-concepts/advanced-querying).
+ q : Q
search_in : typing.Optional[SearchIn]
@@ -1012,7 +996,7 @@ async def get(
To learn more, see [Enumerated parameters > Country](/docs/v3/api-reference/overview/enumerated-parameters#country-country-and-not-country).
- from_ : typing.Optional[dt.datetime]
+ from_ : typing.Optional[SearchSimilarGetRequestFrom]
The starting point in time to search from. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1024,7 +1008,7 @@ async def get(
**Note**: By default, applied to the publication date of the article. To use the article's parse date instead, set the `by_parse_date` parameter to `true`.
- to : typing.Optional[dt.datetime]
+ to : typing.Optional[SearchSimilarGetRequestTo]
The ending point in time to search up to. Accepts date-time strings in ISO 8601 format and plain text. The default time zone is UTC.
Formats with examples:
@@ -1234,8 +1218,12 @@ async def get(
"not_lang": not_lang,
"countries": countries,
"not_countries": not_countries,
- "from_": serialize_datetime(from_) if from_ is not None else None,
- "to_": serialize_datetime(to) if to is not None else None,
+ "from_": convert_and_respect_annotation_metadata(
+ object_=from_, annotation=SearchSimilarGetRequestFrom, direction="write"
+ ),
+ "to_": convert_and_respect_annotation_metadata(
+ object_=to, annotation=SearchSimilarGetRequestTo, direction="write"
+ ),
"by_parse_date": by_parse_date,
"published_date_precision": published_date_precision,
"sort_by": sort_by,
diff --git a/src/newscatcher/searchsimilar/types/__init__.py b/src/newscatcher/searchsimilar/types/__init__.py
index 5992030..ef4f537 100644
--- a/src/newscatcher/searchsimilar/types/__init__.py
+++ b/src/newscatcher/searchsimilar/types/__init__.py
@@ -2,10 +2,42 @@
# isort: skip_file
-from .search_similar_get_request_published_date_precision import SearchSimilarGetRequestPublishedDatePrecision
-from .search_similar_get_request_sort_by import SearchSimilarGetRequestSortBy
-from .search_similar_get_response import SearchSimilarGetResponse
-from .search_similar_post_response import SearchSimilarPostResponse
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .search_similar_get_request_published_date_precision import SearchSimilarGetRequestPublishedDatePrecision
+ from .search_similar_get_request_sort_by import SearchSimilarGetRequestSortBy
+ from .search_similar_get_response import SearchSimilarGetResponse
+ from .search_similar_post_response import SearchSimilarPostResponse
+_dynamic_imports: typing.Dict[str, str] = {
+ "SearchSimilarGetRequestPublishedDatePrecision": ".search_similar_get_request_published_date_precision",
+ "SearchSimilarGetRequestSortBy": ".search_similar_get_request_sort_by",
+ "SearchSimilarGetResponse": ".search_similar_get_response",
+ "SearchSimilarPostResponse": ".search_similar_post_response",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"SearchSimilarGetRequestPublishedDatePrecision",
diff --git a/src/newscatcher/sources/__init__.py b/src/newscatcher/sources/__init__.py
index 6f0dd5f..ba4db9e 100644
--- a/src/newscatcher/sources/__init__.py
+++ b/src/newscatcher/sources/__init__.py
@@ -2,6 +2,33 @@
# isort: skip_file
-from .types import SourcesGetRequestNewsDomainType
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .types import SourcesGetRequestNewsDomainType
+_dynamic_imports: typing.Dict[str, str] = {"SourcesGetRequestNewsDomainType": ".types"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["SourcesGetRequestNewsDomainType"]
diff --git a/src/newscatcher/sources/client.py b/src/newscatcher/sources/client.py
index 3430e18..232fb62 100644
--- a/src/newscatcher/sources/client.py
+++ b/src/newscatcher/sources/client.py
@@ -146,8 +146,12 @@ def get(
api_key="YOUR_API_KEY",
)
client.sources.get(
+ lang="en",
+ countries="US",
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
source_url="bbc.com",
+ news_type="General News Outlets",
)
"""
_response = self._raw_client.get(
@@ -225,11 +229,7 @@ def post(
api_key="YOUR_API_KEY",
)
client.sources.post(
- predefined_sources=["top 50 US"],
- include_additional_info=True,
- is_news_domain=True,
- news_domain_type="Original Content",
- news_type="General News Outlets",
+ predefined_sources="top 10 US",
)
"""
_response = self._raw_client.post(
@@ -377,8 +377,12 @@ async def get(
async def main() -> None:
await client.sources.get(
+ lang="en",
+ countries="US",
predefined_sources="top 100 US, top 5 GB",
+ source_name="sport",
source_url="bbc.com",
+ news_type="General News Outlets",
)
@@ -464,11 +468,7 @@ async def post(
async def main() -> None:
await client.sources.post(
- predefined_sources=["top 50 US"],
- include_additional_info=True,
- is_news_domain=True,
- news_domain_type="Original Content",
- news_type="General News Outlets",
+ predefined_sources="top 10 US",
)
diff --git a/src/newscatcher/sources/types/__init__.py b/src/newscatcher/sources/types/__init__.py
index d40ef61..bd39a12 100644
--- a/src/newscatcher/sources/types/__init__.py
+++ b/src/newscatcher/sources/types/__init__.py
@@ -2,6 +2,33 @@
# isort: skip_file
-from .sources_get_request_news_domain_type import SourcesGetRequestNewsDomainType
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .sources_get_request_news_domain_type import SourcesGetRequestNewsDomainType
+_dynamic_imports: typing.Dict[str, str] = {"SourcesGetRequestNewsDomainType": ".sources_get_request_news_domain_type"}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = ["SourcesGetRequestNewsDomainType"]
diff --git a/src/newscatcher/types/__init__.py b/src/newscatcher/types/__init__.py
index b458a49..2ca597e 100644
--- a/src/newscatcher/types/__init__.py
+++ b/src/newscatcher/types/__init__.py
@@ -2,112 +2,270 @@
# isort: skip_file
-from .additional_domain_info import AdditionalDomainInfo
-from .additional_domain_info_entity import AdditionalDomainInfoEntity
-from .additional_source_info import AdditionalSourceInfo
-from .aggregation_by import AggregationBy
-from .aggregation_count_response_dto import AggregationCountResponseDto
-from .aggregation_item import AggregationItem
-from .aggregations import Aggregations
-from .all_domain_links import AllDomainLinks
-from .all_links import AllLinks
-from .article_entity import ArticleEntity
-from .article_entity_all_domain_links import ArticleEntityAllDomainLinks
-from .article_entity_all_links import ArticleEntityAllLinks
-from .articles import Articles
-from .author_name import AuthorName
-from .authors import Authors
-from .base_search_response_dto import BaseSearchResponseDto
-from .breaking_news_article_entity import BreakingNewsArticleEntity
-from .breaking_news_article_entity_all_domain_links import BreakingNewsArticleEntityAllDomainLinks
-from .breaking_news_article_entity_all_links import BreakingNewsArticleEntityAllLinks
-from .breaking_news_event_entity import BreakingNewsEventEntity
-from .breaking_news_response_dto import BreakingNewsResponseDto
-from .by_parse_date import ByParseDate
-from .cluster_entity import ClusterEntity
-from .clustered_articles_dto import ClusteredArticlesDto
-from .clustered_search_response_dto import ClusteredSearchResponseDto
-from .clustering_enabled import ClusteringEnabled
-from .clustering_threshold import ClusteringThreshold
-from .clustering_variable import ClusteringVariable
-from .content_sentiment_max import ContentSentimentMax
-from .content_sentiment_min import ContentSentimentMin
-from .countries import Countries
-from .custom_tags import CustomTags
-from .error import Error
-from .exclude_duplicates import ExcludeDuplicates
-from .failed_aggregation_count_response_dto import FailedAggregationCountResponseDto
-from .failed_authors_response_dto import FailedAuthorsResponseDto
-from .failed_search_similar_response_dto import FailedSearchSimilarResponseDto
-from .from_ import From
-from .from_rank import FromRank
-from .has_nlp import HasNlp
-from .iab_tags import IabTags
-from .ids import Ids
-from .include_additional_info import IncludeAdditionalInfo
-from .include_nlp_data import IncludeNlpData
-from .include_similar_documents import IncludeSimilarDocuments
-from .include_translation_fields import IncludeTranslationFields
-from .iptc_tags import IptcTags
-from .is_headline import IsHeadline
-from .is_news_domain import IsNewsDomain
-from .is_opinion import IsOpinion
-from .is_paid_content import IsPaidContent
-from .journalists import Journalists
-from .lang import Lang
-from .links import Links
-from .loc_entity_name import LocEntityName
-from .misc_entity_name import MiscEntityName
-from .named_entity_list import NamedEntityList
-from .named_entity_list_item import NamedEntityListItem
-from .ner_name import NerName
-from .news_domain_type import NewsDomainType
-from .news_type import NewsType
-from .nlp_data_entity import NlpDataEntity
-from .not_author_name import NotAuthorName
-from .not_countries import NotCountries
-from .not_iab_tags import NotIabTags
-from .not_iptc_tags import NotIptcTags
-from .not_lang import NotLang
-from .not_sources import NotSources
-from .not_theme import NotTheme
-from .org_entity_name import OrgEntityName
-from .page import Page
-from .page_size import PageSize
-from .parent_url import ParentUrl
-from .per_entity_name import PerEntityName
-from .predefined_sources import PredefinedSources
-from .published_date_precision import PublishedDatePrecision
-from .q import Q
-from .ranked_only import RankedOnly
-from .robots_compliant import RobotsCompliant
-from .search_in import SearchIn
-from .search_response_dto import SearchResponseDto
-from .search_similar_response_dto import SearchSimilarResponseDto
-from .sentiment_scores import SentimentScores
-from .similar_article_entity import SimilarArticleEntity
-from .similar_document import SimilarDocument
-from .similar_documents_fields import SimilarDocumentsFields
-from .similar_documents_number import SimilarDocumentsNumber
-from .sort_by import SortBy
-from .source_info import SourceInfo
-from .source_name import SourceName
-from .source_url import SourceUrl
-from .sources import Sources
-from .sources_response_dto import SourcesResponseDto
-from .sources_response_dto_sources_item import SourcesResponseDtoSourcesItem
-from .subscription_response_dto import SubscriptionResponseDto
-from .theme import Theme
-from .time_frame_count import TimeFrameCount
-from .title_sentiment_max import TitleSentimentMax
-from .title_sentiment_min import TitleSentimentMin
-from .to import To
-from .to_rank import ToRank
-from .top_n_articles import TopNArticles
-from .user_input_dto import UserInputDto
-from .when import When
-from .word_count_max import WordCountMax
-from .word_count_min import WordCountMin
+import typing
+from importlib import import_module
+
+if typing.TYPE_CHECKING:
+ from .additional_domain_info import AdditionalDomainInfo
+ from .additional_domain_info_entity import AdditionalDomainInfoEntity
+ from .additional_source_info import AdditionalSourceInfo
+ from .aggregation_by import AggregationBy
+ from .aggregation_count_response_dto import AggregationCountResponseDto
+ from .aggregation_count_response_dto_aggregations import AggregationCountResponseDtoAggregations
+ from .aggregation_get_request_from import AggregationGetRequestFrom
+ from .aggregation_get_request_to import AggregationGetRequestTo
+ from .aggregation_item import AggregationItem
+ from .all_domain_links import AllDomainLinks
+ from .all_links import AllLinks
+ from .article_entity import ArticleEntity
+ from .article_entity_all_domain_links import ArticleEntityAllDomainLinks
+ from .article_entity_all_links import ArticleEntityAllLinks
+ from .article_entity_authors import ArticleEntityAuthors
+ from .article_entity_journalists import ArticleEntityJournalists
+ from .articles_dto import ArticlesDto
+ from .author_name import AuthorName
+ from .authors_get_request_from import AuthorsGetRequestFrom
+ from .authors_get_request_to import AuthorsGetRequestTo
+ from .base_search_response_dto import BaseSearchResponseDto
+ from .breaking_news_article_entity import BreakingNewsArticleEntity
+ from .breaking_news_article_entity_all_domain_links import BreakingNewsArticleEntityAllDomainLinks
+ from .breaking_news_article_entity_all_links import BreakingNewsArticleEntityAllLinks
+ from .breaking_news_article_entity_authors import BreakingNewsArticleEntityAuthors
+ from .breaking_news_article_entity_journalists import BreakingNewsArticleEntityJournalists
+ from .breaking_news_event_entity import BreakingNewsEventEntity
+ from .breaking_news_response_dto import BreakingNewsResponseDto
+ from .by_parse_date import ByParseDate
+ from .canonical_url import CanonicalUrl
+ from .cluster_entity import ClusterEntity
+ from .clustered_articles_dto import ClusteredArticlesDto
+ from .clustered_search_response_dto import ClusteredSearchResponseDto
+ from .clustering_enabled import ClusteringEnabled
+ from .clustering_threshold import ClusteringThreshold
+ from .clustering_variable import ClusteringVariable
+ from .content_sentiment_max import ContentSentimentMax
+ from .content_sentiment_min import ContentSentimentMin
+ from .countries import Countries
+ from .custom_tags import CustomTags
+ from .error import Error
+ from .exclude_duplicates import ExcludeDuplicates
+ from .failed_aggregation_count_response_dto import FailedAggregationCountResponseDto
+ from .failed_authors_response_dto import FailedAuthorsResponseDto
+ from .failed_search_similar_response_dto import FailedSearchSimilarResponseDto
+ from .from_ import From
+ from .from_rank import FromRank
+ from .has_nlp import HasNlp
+ from .iab_tags import IabTags
+ from .ids import Ids
+ from .include_additional_info import IncludeAdditionalInfo
+ from .include_nlp_data import IncludeNlpData
+ from .include_similar_documents import IncludeSimilarDocuments
+ from .include_translation_fields import IncludeTranslationFields
+ from .iptc_tags import IptcTags
+ from .is_headline import IsHeadline
+ from .is_news_domain import IsNewsDomain
+ from .is_opinion import IsOpinion
+ from .is_paid_content import IsPaidContent
+ from .lang import Lang
+ from .links import Links
+ from .loc_entity_name import LocEntityName
+ from .misc_entity_name import MiscEntityName
+ from .named_entity_list import NamedEntityList
+ from .named_entity_list_item import NamedEntityListItem
+ from .ner_name import NerName
+ from .news_domain_type import NewsDomainType
+ from .news_type import NewsType
+ from .nlp_data_entity import NlpDataEntity
+ from .not_author_name import NotAuthorName
+ from .not_countries import NotCountries
+ from .not_iab_tags import NotIabTags
+ from .not_iptc_tags import NotIptcTags
+ from .not_lang import NotLang
+ from .not_sources import NotSources
+ from .not_theme import NotTheme
+ from .org_entity_name import OrgEntityName
+ from .page import Page
+ from .page_size import PageSize
+ from .parent_url import ParentUrl
+ from .per_entity_name import PerEntityName
+ from .predefined_sources import PredefinedSources
+ from .published_date_precision import PublishedDatePrecision
+ from .q import Q
+ from .ranked_only import RankedOnly
+ from .robots_compliant import RobotsCompliant
+ from .search_get_request_from import SearchGetRequestFrom
+ from .search_get_request_to import SearchGetRequestTo
+ from .search_in import SearchIn
+ from .search_response_dto import SearchResponseDto
+ from .search_similar_get_request_from import SearchSimilarGetRequestFrom
+ from .search_similar_get_request_to import SearchSimilarGetRequestTo
+ from .search_similar_response_dto import SearchSimilarResponseDto
+ from .sentiment_scores import SentimentScores
+ from .similar_article_entity import SimilarArticleEntity
+ from .similar_document import SimilarDocument
+ from .similar_documents_fields import SimilarDocumentsFields
+ from .similar_documents_number import SimilarDocumentsNumber
+ from .sort_by import SortBy
+ from .source import Source
+ from .source_info import SourceInfo
+ from .source_name import SourceName
+ from .source_url import SourceUrl
+ from .sources import Sources
+ from .sources_response_dto import SourcesResponseDto
+ from .sources_response_dto_sources_item import SourcesResponseDtoSourcesItem
+ from .subscription_response_dto import SubscriptionResponseDto
+ from .theme import Theme
+ from .time_frame_count import TimeFrameCount
+ from .title_sentiment_max import TitleSentimentMax
+ from .title_sentiment_min import TitleSentimentMin
+ from .to import To
+ from .to_rank import ToRank
+ from .top_n_articles import TopNArticles
+ from .user_input_dto import UserInputDto
+ from .when import When
+ from .word_count_max import WordCountMax
+ from .word_count_min import WordCountMin
+_dynamic_imports: typing.Dict[str, str] = {
+ "AdditionalDomainInfo": ".additional_domain_info",
+ "AdditionalDomainInfoEntity": ".additional_domain_info_entity",
+ "AdditionalSourceInfo": ".additional_source_info",
+ "AggregationBy": ".aggregation_by",
+ "AggregationCountResponseDto": ".aggregation_count_response_dto",
+ "AggregationCountResponseDtoAggregations": ".aggregation_count_response_dto_aggregations",
+ "AggregationGetRequestFrom": ".aggregation_get_request_from",
+ "AggregationGetRequestTo": ".aggregation_get_request_to",
+ "AggregationItem": ".aggregation_item",
+ "AllDomainLinks": ".all_domain_links",
+ "AllLinks": ".all_links",
+ "ArticleEntity": ".article_entity",
+ "ArticleEntityAllDomainLinks": ".article_entity_all_domain_links",
+ "ArticleEntityAllLinks": ".article_entity_all_links",
+ "ArticleEntityAuthors": ".article_entity_authors",
+ "ArticleEntityJournalists": ".article_entity_journalists",
+ "ArticlesDto": ".articles_dto",
+ "AuthorName": ".author_name",
+ "AuthorsGetRequestFrom": ".authors_get_request_from",
+ "AuthorsGetRequestTo": ".authors_get_request_to",
+ "BaseSearchResponseDto": ".base_search_response_dto",
+ "BreakingNewsArticleEntity": ".breaking_news_article_entity",
+ "BreakingNewsArticleEntityAllDomainLinks": ".breaking_news_article_entity_all_domain_links",
+ "BreakingNewsArticleEntityAllLinks": ".breaking_news_article_entity_all_links",
+ "BreakingNewsArticleEntityAuthors": ".breaking_news_article_entity_authors",
+ "BreakingNewsArticleEntityJournalists": ".breaking_news_article_entity_journalists",
+ "BreakingNewsEventEntity": ".breaking_news_event_entity",
+ "BreakingNewsResponseDto": ".breaking_news_response_dto",
+ "ByParseDate": ".by_parse_date",
+ "CanonicalUrl": ".canonical_url",
+ "ClusterEntity": ".cluster_entity",
+ "ClusteredArticlesDto": ".clustered_articles_dto",
+ "ClusteredSearchResponseDto": ".clustered_search_response_dto",
+ "ClusteringEnabled": ".clustering_enabled",
+ "ClusteringThreshold": ".clustering_threshold",
+ "ClusteringVariable": ".clustering_variable",
+ "ContentSentimentMax": ".content_sentiment_max",
+ "ContentSentimentMin": ".content_sentiment_min",
+ "Countries": ".countries",
+ "CustomTags": ".custom_tags",
+ "Error": ".error",
+ "ExcludeDuplicates": ".exclude_duplicates",
+ "FailedAggregationCountResponseDto": ".failed_aggregation_count_response_dto",
+ "FailedAuthorsResponseDto": ".failed_authors_response_dto",
+ "FailedSearchSimilarResponseDto": ".failed_search_similar_response_dto",
+ "From": ".from_",
+ "FromRank": ".from_rank",
+ "HasNlp": ".has_nlp",
+ "IabTags": ".iab_tags",
+ "Ids": ".ids",
+ "IncludeAdditionalInfo": ".include_additional_info",
+ "IncludeNlpData": ".include_nlp_data",
+ "IncludeSimilarDocuments": ".include_similar_documents",
+ "IncludeTranslationFields": ".include_translation_fields",
+ "IptcTags": ".iptc_tags",
+ "IsHeadline": ".is_headline",
+ "IsNewsDomain": ".is_news_domain",
+ "IsOpinion": ".is_opinion",
+ "IsPaidContent": ".is_paid_content",
+ "Lang": ".lang",
+ "Links": ".links",
+ "LocEntityName": ".loc_entity_name",
+ "MiscEntityName": ".misc_entity_name",
+ "NamedEntityList": ".named_entity_list",
+ "NamedEntityListItem": ".named_entity_list_item",
+ "NerName": ".ner_name",
+ "NewsDomainType": ".news_domain_type",
+ "NewsType": ".news_type",
+ "NlpDataEntity": ".nlp_data_entity",
+ "NotAuthorName": ".not_author_name",
+ "NotCountries": ".not_countries",
+ "NotIabTags": ".not_iab_tags",
+ "NotIptcTags": ".not_iptc_tags",
+ "NotLang": ".not_lang",
+ "NotSources": ".not_sources",
+ "NotTheme": ".not_theme",
+ "OrgEntityName": ".org_entity_name",
+ "Page": ".page",
+ "PageSize": ".page_size",
+ "ParentUrl": ".parent_url",
+ "PerEntityName": ".per_entity_name",
+ "PredefinedSources": ".predefined_sources",
+ "PublishedDatePrecision": ".published_date_precision",
+ "Q": ".q",
+ "RankedOnly": ".ranked_only",
+ "RobotsCompliant": ".robots_compliant",
+ "SearchGetRequestFrom": ".search_get_request_from",
+ "SearchGetRequestTo": ".search_get_request_to",
+ "SearchIn": ".search_in",
+ "SearchResponseDto": ".search_response_dto",
+ "SearchSimilarGetRequestFrom": ".search_similar_get_request_from",
+ "SearchSimilarGetRequestTo": ".search_similar_get_request_to",
+ "SearchSimilarResponseDto": ".search_similar_response_dto",
+ "SentimentScores": ".sentiment_scores",
+ "SimilarArticleEntity": ".similar_article_entity",
+ "SimilarDocument": ".similar_document",
+ "SimilarDocumentsFields": ".similar_documents_fields",
+ "SimilarDocumentsNumber": ".similar_documents_number",
+ "SortBy": ".sort_by",
+ "Source": ".source",
+ "SourceInfo": ".source_info",
+ "SourceName": ".source_name",
+ "SourceUrl": ".source_url",
+ "Sources": ".sources",
+ "SourcesResponseDto": ".sources_response_dto",
+ "SourcesResponseDtoSourcesItem": ".sources_response_dto_sources_item",
+ "SubscriptionResponseDto": ".subscription_response_dto",
+ "Theme": ".theme",
+ "TimeFrameCount": ".time_frame_count",
+ "TitleSentimentMax": ".title_sentiment_max",
+ "TitleSentimentMin": ".title_sentiment_min",
+ "To": ".to",
+ "ToRank": ".to_rank",
+ "TopNArticles": ".top_n_articles",
+ "UserInputDto": ".user_input_dto",
+ "When": ".when",
+ "WordCountMax": ".word_count_max",
+ "WordCountMin": ".word_count_min",
+}
+
+
+def __getattr__(attr_name: str) -> typing.Any:
+ module_name = _dynamic_imports.get(attr_name)
+ if module_name is None:
+ raise AttributeError(f"No {attr_name} found in _dynamic_imports for module name -> {__name__}")
+ try:
+ module = import_module(module_name, __package__)
+ if module_name == f".{attr_name}":
+ return module
+ else:
+ return getattr(module, attr_name)
+ except ImportError as e:
+ raise ImportError(f"Failed to import {attr_name} from {module_name}: {e}") from e
+ except AttributeError as e:
+ raise AttributeError(f"Failed to get {attr_name} from {module_name}: {e}") from e
+
+
+def __dir__():
+ lazy_attrs = list(_dynamic_imports.keys())
+ return sorted(lazy_attrs)
+
__all__ = [
"AdditionalDomainInfo",
@@ -115,23 +273,31 @@
"AdditionalSourceInfo",
"AggregationBy",
"AggregationCountResponseDto",
+ "AggregationCountResponseDtoAggregations",
+ "AggregationGetRequestFrom",
+ "AggregationGetRequestTo",
"AggregationItem",
- "Aggregations",
"AllDomainLinks",
"AllLinks",
"ArticleEntity",
"ArticleEntityAllDomainLinks",
"ArticleEntityAllLinks",
- "Articles",
+ "ArticleEntityAuthors",
+ "ArticleEntityJournalists",
+ "ArticlesDto",
"AuthorName",
- "Authors",
+ "AuthorsGetRequestFrom",
+ "AuthorsGetRequestTo",
"BaseSearchResponseDto",
"BreakingNewsArticleEntity",
"BreakingNewsArticleEntityAllDomainLinks",
"BreakingNewsArticleEntityAllLinks",
+ "BreakingNewsArticleEntityAuthors",
+ "BreakingNewsArticleEntityJournalists",
"BreakingNewsEventEntity",
"BreakingNewsResponseDto",
"ByParseDate",
+ "CanonicalUrl",
"ClusterEntity",
"ClusteredArticlesDto",
"ClusteredSearchResponseDto",
@@ -161,7 +327,6 @@
"IsNewsDomain",
"IsOpinion",
"IsPaidContent",
- "Journalists",
"Lang",
"Links",
"LocEntityName",
@@ -189,8 +354,12 @@
"Q",
"RankedOnly",
"RobotsCompliant",
+ "SearchGetRequestFrom",
+ "SearchGetRequestTo",
"SearchIn",
"SearchResponseDto",
+ "SearchSimilarGetRequestFrom",
+ "SearchSimilarGetRequestTo",
"SearchSimilarResponseDto",
"SentimentScores",
"SimilarArticleEntity",
@@ -198,6 +367,7 @@
"SimilarDocumentsFields",
"SimilarDocumentsNumber",
"SortBy",
+ "Source",
"SourceInfo",
"SourceName",
"SourceUrl",
diff --git a/src/newscatcher/types/aggregation_count_response_dto.py b/src/newscatcher/types/aggregation_count_response_dto.py
index 8492c80..3b3e96a 100644
--- a/src/newscatcher/types/aggregation_count_response_dto.py
+++ b/src/newscatcher/types/aggregation_count_response_dto.py
@@ -4,7 +4,7 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2
-from .aggregations import Aggregations
+from .aggregation_count_response_dto_aggregations import AggregationCountResponseDtoAggregations
from .base_search_response_dto import BaseSearchResponseDto
from .user_input_dto import UserInputDto
@@ -16,7 +16,7 @@ class AggregationCountResponseDto(BaseSearchResponseDto):
- Optional fields may be `null` or `undefined` if the data point is not presented or couldn't be extracted during processing.
"""
- aggregations: typing.Optional[Aggregations] = pydantic.Field(default=None)
+ aggregations: typing.Optional[AggregationCountResponseDtoAggregations] = pydantic.Field(default=None)
"""
The aggregation results. Can be either a dictionary or a list of dictionaries.
"""
diff --git a/src/newscatcher/types/aggregations.py b/src/newscatcher/types/aggregation_count_response_dto_aggregations.py
similarity index 55%
rename from src/newscatcher/types/aggregations.py
rename to src/newscatcher/types/aggregation_count_response_dto_aggregations.py
index 16b1d5f..aa0eb09 100644
--- a/src/newscatcher/types/aggregations.py
+++ b/src/newscatcher/types/aggregation_count_response_dto_aggregations.py
@@ -4,4 +4,4 @@
from .aggregation_item import AggregationItem
-Aggregations = typing.Union[AggregationItem, typing.List[AggregationItem]]
+AggregationCountResponseDtoAggregations = typing.Union[AggregationItem, typing.List[AggregationItem]]
diff --git a/src/newscatcher/types/aggregation_get_request_from.py b/src/newscatcher/types/aggregation_get_request_from.py
new file mode 100644
index 0000000..4fd8bc3
--- /dev/null
+++ b/src/newscatcher/types/aggregation_get_request_from.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+AggregationGetRequestFrom = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/aggregation_get_request_to.py b/src/newscatcher/types/aggregation_get_request_to.py
new file mode 100644
index 0000000..bd46a8e
--- /dev/null
+++ b/src/newscatcher/types/aggregation_get_request_to.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+AggregationGetRequestTo = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/article_entity.py b/src/newscatcher/types/article_entity.py
index ff89b24..7a7613c 100644
--- a/src/newscatcher/types/article_entity.py
+++ b/src/newscatcher/types/article_entity.py
@@ -7,8 +7,8 @@
from .additional_domain_info_entity import AdditionalDomainInfoEntity
from .article_entity_all_domain_links import ArticleEntityAllDomainLinks
from .article_entity_all_links import ArticleEntityAllLinks
-from .authors import Authors
-from .journalists import Journalists
+from .article_entity_authors import ArticleEntityAuthors
+from .article_entity_journalists import ArticleEntityJournalists
from .nlp_data_entity import NlpDataEntity
@@ -17,7 +17,7 @@ class ArticleEntity(UniversalBaseModel):
The data model representing a single article in the search results.
"""
- title: str = pydantic.Field()
+ title: typing.Optional[str] = pydantic.Field(default=None)
"""
The title of the article.
"""
@@ -27,12 +27,12 @@ class ArticleEntity(UniversalBaseModel):
The primary author of the article.
"""
- authors: typing.Optional[Authors] = pydantic.Field(default=None)
+ authors: typing.Optional[ArticleEntityAuthors] = pydantic.Field(default=None)
"""
A list of authors of the article.
"""
- journalists: typing.Optional[Journalists] = pydantic.Field(default=None)
+ journalists: typing.Optional[ArticleEntityJournalists] = pydantic.Field(default=None)
"""
A list of journalists associated with the article.
"""
@@ -62,17 +62,22 @@ class ArticleEntity(UniversalBaseModel):
The date the article was parsed.
"""
- link: str = pydantic.Field()
+ link: typing.Optional[str] = pydantic.Field(default=None)
"""
The URL link to the article.
"""
- domain_url: str = pydantic.Field()
+ canonical_url: typing.Optional[bool] = pydantic.Field(default=None)
+ """
+ Indicates whether the article URL is canonical.
+ """
+
+ domain_url: typing.Optional[str] = pydantic.Field(default=None)
"""
The domain URL of the article.
"""
- full_domain_url: str = pydantic.Field()
+ full_domain_url: typing.Optional[str] = pydantic.Field(default=None)
"""
The full domain URL of the article.
"""
@@ -92,7 +97,7 @@ class ArticleEntity(UniversalBaseModel):
Indicates if the article is paid content.
"""
- parent_url: str = pydantic.Field()
+ parent_url: typing.Optional[str] = pydantic.Field(default=None)
"""
The categorical URL of the article.
"""
@@ -107,7 +112,7 @@ class ArticleEntity(UniversalBaseModel):
The rights information for the article.
"""
- rank: int = pydantic.Field()
+ rank: typing.Optional[int] = pydantic.Field(default=None)
"""
The rank of the article's source.
"""
@@ -127,7 +132,7 @@ class ArticleEntity(UniversalBaseModel):
A brief description of the article.
"""
- content: str = pydantic.Field()
+ content: typing.Optional[str] = pydantic.Field(default=None)
"""
The content of the article.
"""
@@ -168,12 +173,12 @@ class ArticleEntity(UniversalBaseModel):
"""
nlp: typing.Optional[NlpDataEntity] = None
- id: str = pydantic.Field()
+ id: typing.Optional[str] = pydantic.Field(default=None)
"""
The unique identifier for the article.
"""
- score: float = pydantic.Field()
+ score: typing.Optional[float] = pydantic.Field(default=None)
"""
The relevance score of the article.
"""
diff --git a/src/newscatcher/types/authors.py b/src/newscatcher/types/article_entity_authors.py
similarity index 57%
rename from src/newscatcher/types/authors.py
rename to src/newscatcher/types/article_entity_authors.py
index 2393876..f1dd11f 100644
--- a/src/newscatcher/types/authors.py
+++ b/src/newscatcher/types/article_entity_authors.py
@@ -2,4 +2,4 @@
import typing
-Authors = typing.Union[typing.List[str], str]
+ArticleEntityAuthors = typing.Union[typing.List[str], str]
diff --git a/src/newscatcher/types/journalists.py b/src/newscatcher/types/article_entity_journalists.py
similarity index 55%
rename from src/newscatcher/types/journalists.py
rename to src/newscatcher/types/article_entity_journalists.py
index 5dfe0f6..c9dabe1 100644
--- a/src/newscatcher/types/journalists.py
+++ b/src/newscatcher/types/article_entity_journalists.py
@@ -2,4 +2,4 @@
import typing
-Journalists = typing.Union[typing.List[str], str]
+ArticleEntityJournalists = typing.Union[typing.List[str], str]
diff --git a/src/newscatcher/types/articles.py b/src/newscatcher/types/articles_dto.py
similarity index 75%
rename from src/newscatcher/types/articles.py
rename to src/newscatcher/types/articles_dto.py
index 14d2ac6..839bb31 100644
--- a/src/newscatcher/types/articles.py
+++ b/src/newscatcher/types/articles_dto.py
@@ -4,4 +4,4 @@
from .article_entity import ArticleEntity
-Articles = typing.List[ArticleEntity]
+ArticlesDto = typing.List[ArticleEntity]
diff --git a/src/newscatcher/types/authors_get_request_from.py b/src/newscatcher/types/authors_get_request_from.py
new file mode 100644
index 0000000..b35ebe1
--- /dev/null
+++ b/src/newscatcher/types/authors_get_request_from.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+AuthorsGetRequestFrom = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/authors_get_request_to.py b/src/newscatcher/types/authors_get_request_to.py
new file mode 100644
index 0000000..2101d1f
--- /dev/null
+++ b/src/newscatcher/types/authors_get_request_to.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+AuthorsGetRequestTo = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/base_search_response_dto.py b/src/newscatcher/types/base_search_response_dto.py
index 07c2357..fe3aabd 100644
--- a/src/newscatcher/types/base_search_response_dto.py
+++ b/src/newscatcher/types/base_search_response_dto.py
@@ -11,27 +11,27 @@ class BaseSearchResponseDto(UniversalBaseModel):
The base response model containing common fields for search operations.
"""
- status: str = pydantic.Field()
+ status: typing.Optional[str] = pydantic.Field(default=None)
"""
The status of the response.
"""
- total_hits: int = pydantic.Field()
+ total_hits: typing.Optional[int] = pydantic.Field(default=None)
"""
The total number of articles matching the search criteria.
"""
- page: int = pydantic.Field()
+ page: typing.Optional[int] = pydantic.Field(default=None)
"""
The current page number of the results.
"""
- total_pages: int = pydantic.Field()
+ total_pages: typing.Optional[int] = pydantic.Field(default=None)
"""
The total number of pages available for the given search criteria.
"""
- page_size: int = pydantic.Field()
+ page_size: typing.Optional[int] = pydantic.Field(default=None)
"""
The number of articles per page.
"""
diff --git a/src/newscatcher/types/breaking_news_article_entity.py b/src/newscatcher/types/breaking_news_article_entity.py
index 0a76272..94f1324 100644
--- a/src/newscatcher/types/breaking_news_article_entity.py
+++ b/src/newscatcher/types/breaking_news_article_entity.py
@@ -4,10 +4,10 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
-from .authors import Authors
from .breaking_news_article_entity_all_domain_links import BreakingNewsArticleEntityAllDomainLinks
from .breaking_news_article_entity_all_links import BreakingNewsArticleEntityAllLinks
-from .journalists import Journalists
+from .breaking_news_article_entity_authors import BreakingNewsArticleEntityAuthors
+from .breaking_news_article_entity_journalists import BreakingNewsArticleEntityJournalists
from .nlp_data_entity import NlpDataEntity
@@ -26,12 +26,12 @@ class BreakingNewsArticleEntity(UniversalBaseModel):
The primary author of the article.
"""
- authors: typing.Optional[Authors] = pydantic.Field(default=None)
+ authors: typing.Optional[BreakingNewsArticleEntityAuthors] = pydantic.Field(default=None)
"""
A list of authors of the article.
"""
- journalists: typing.Optional[Journalists] = pydantic.Field(default=None)
+ journalists: typing.Optional[BreakingNewsArticleEntityJournalists] = pydantic.Field(default=None)
"""
A list of journalists associated with the article.
"""
diff --git a/src/newscatcher/types/breaking_news_article_entity_authors.py b/src/newscatcher/types/breaking_news_article_entity_authors.py
new file mode 100644
index 0000000..63be474
--- /dev/null
+++ b/src/newscatcher/types/breaking_news_article_entity_authors.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+BreakingNewsArticleEntityAuthors = typing.Union[typing.List[str], str]
diff --git a/src/newscatcher/types/breaking_news_article_entity_journalists.py b/src/newscatcher/types/breaking_news_article_entity_journalists.py
new file mode 100644
index 0000000..e541fff
--- /dev/null
+++ b/src/newscatcher/types/breaking_news_article_entity_journalists.py
@@ -0,0 +1,5 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import typing
+
+BreakingNewsArticleEntityJournalists = typing.Union[typing.List[str], str]
diff --git a/src/newscatcher/types/canonical_url.py b/src/newscatcher/types/canonical_url.py
new file mode 100644
index 0000000..862fc95
--- /dev/null
+++ b/src/newscatcher/types/canonical_url.py
@@ -0,0 +1,3 @@
+# This file was auto-generated by Fern from our API Definition.
+
+CanonicalUrl = bool
diff --git a/src/newscatcher/types/failed_authors_response_dto.py b/src/newscatcher/types/failed_authors_response_dto.py
index 7345a65..43f4181 100644
--- a/src/newscatcher/types/failed_authors_response_dto.py
+++ b/src/newscatcher/types/failed_authors_response_dto.py
@@ -13,7 +13,7 @@ class FailedAuthorsResponseDto(BaseSearchResponseDto):
The response model for a failed `Authors` search request.
"""
- articles: typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]] = pydantic.Field(default=None)
+ articles: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic.Field(default=None)
"""
An empty list of articles, as no matches were found.
"""
diff --git a/src/newscatcher/types/failed_search_similar_response_dto.py b/src/newscatcher/types/failed_search_similar_response_dto.py
index 2416b4a..f53ee84 100644
--- a/src/newscatcher/types/failed_search_similar_response_dto.py
+++ b/src/newscatcher/types/failed_search_similar_response_dto.py
@@ -13,7 +13,7 @@ class FailedSearchSimilarResponseDto(BaseSearchResponseDto):
The response model for a failed `Search Similar` request.
"""
- articles: typing.Optional[typing.List[typing.Dict[str, typing.Optional[typing.Any]]]] = pydantic.Field(default=None)
+ articles: typing.Optional[typing.List[typing.Dict[str, typing.Any]]] = pydantic.Field(default=None)
"""
An empty list of articles, as no matches were found.
"""
diff --git a/src/newscatcher/types/search_get_request_from.py b/src/newscatcher/types/search_get_request_from.py
new file mode 100644
index 0000000..7b91efd
--- /dev/null
+++ b/src/newscatcher/types/search_get_request_from.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+SearchGetRequestFrom = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/search_get_request_to.py b/src/newscatcher/types/search_get_request_to.py
new file mode 100644
index 0000000..07ec2a7
--- /dev/null
+++ b/src/newscatcher/types/search_get_request_to.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+SearchGetRequestTo = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/search_response_dto.py b/src/newscatcher/types/search_response_dto.py
index f0d7abb..0d08579 100644
--- a/src/newscatcher/types/search_response_dto.py
+++ b/src/newscatcher/types/search_response_dto.py
@@ -4,7 +4,7 @@
import pydantic
from ..core.pydantic_utilities import IS_PYDANTIC_V2
-from .articles import Articles
+from .articles_dto import ArticlesDto
from .base_search_response_dto import BaseSearchResponseDto
from .user_input_dto import UserInputDto
@@ -18,7 +18,7 @@ class SearchResponseDto(BaseSearchResponseDto):
- The `nlp` property within the article object `articles[n].nlp` is only available with NLP-enabled subscription plans.
"""
- articles: typing.Optional[Articles] = None
+ articles: typing.Optional[ArticlesDto] = None
user_input: typing.Optional[UserInputDto] = None
if IS_PYDANTIC_V2:
diff --git a/src/newscatcher/types/search_similar_get_request_from.py b/src/newscatcher/types/search_similar_get_request_from.py
new file mode 100644
index 0000000..4218be8
--- /dev/null
+++ b/src/newscatcher/types/search_similar_get_request_from.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+SearchSimilarGetRequestFrom = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/search_similar_get_request_to.py b/src/newscatcher/types/search_similar_get_request_to.py
new file mode 100644
index 0000000..9689631
--- /dev/null
+++ b/src/newscatcher/types/search_similar_get_request_to.py
@@ -0,0 +1,6 @@
+# This file was auto-generated by Fern from our API Definition.
+
+import datetime as dt
+import typing
+
+SearchSimilarGetRequestTo = typing.Union[dt.datetime, str]
diff --git a/src/newscatcher/types/source.py b/src/newscatcher/types/source.py
new file mode 100644
index 0000000..ee32d6d
--- /dev/null
+++ b/src/newscatcher/types/source.py
@@ -0,0 +1,3 @@
+# This file was auto-generated by Fern from our API Definition.
+
+Source = str
diff --git a/src/newscatcher/types/sources_response_dto.py b/src/newscatcher/types/sources_response_dto.py
index e06ba3e..1565fa8 100644
--- a/src/newscatcher/types/sources_response_dto.py
+++ b/src/newscatcher/types/sources_response_dto.py
@@ -24,7 +24,7 @@ class SourcesResponseDto(UniversalBaseModel):
A list of news sources that match the specified criteria.
"""
- user_input: typing.Dict[str, typing.Optional[typing.Any]] = pydantic.Field()
+ user_input: typing.Dict[str, typing.Any] = pydantic.Field()
"""
The user input parameters for the request.
"""
diff --git a/src/newscatcher/types/user_input_dto.py b/src/newscatcher/types/user_input_dto.py
index f5da8ea..bec72e4 100644
--- a/src/newscatcher/types/user_input_dto.py
+++ b/src/newscatcher/types/user_input_dto.py
@@ -2,4 +2,4 @@
import typing
-UserInputDto = typing.Dict[str, typing.Optional[typing.Any]]
+UserInputDto = typing.Dict[str, typing.Any]
diff --git a/tests/utils/test_query_encoding.py b/tests/utils/test_query_encoding.py
index 3a3919e..b6a0971 100644
--- a/tests/utils/test_query_encoding.py
+++ b/tests/utils/test_query_encoding.py
@@ -1,6 +1,5 @@
# This file was auto-generated by Fern from our API Definition.
-
from newscatcher.core.query_encoder import encode_query