@@ -1457,6 +1457,70 @@ def __init__(self, **kwargs) -> None:
1457
1457
self .__dict__ .update (** kwargs )
1458
1458
1459
1459
1460
+ @dataclass
1461
+ class PaperInfo :
1462
+ """
1463
+ Contains information about a paper on the Hub.
1464
+
1465
+ Attributes:
1466
+ id (`str`):
1467
+ arXiv paper ID.
1468
+ authors (`List[str]`, **optional**):
1469
+ Names of paper authors
1470
+ published_at (`datetime`, **optional**):
1471
+ Date paper published.
1472
+ title (`str`, **optional**):
1473
+ Title of the paper.
1474
+ summary (`str`, **optional**):
1475
+ Summary of the paper.
1476
+ upvotes (`int`, **optional**):
1477
+ Number of upvotes for the paper on the Hub.
1478
+ discussion_id (`str`, **optional**):
1479
+ Discussion ID for the paper on the Hub.
1480
+ source (`str`, **optional**):
1481
+ Source of the paper.
1482
+ comments (`int`, **optional**):
1483
+ Number of comments for the paper on the Hub.
1484
+ submitted_at (`datetime`, **optional**):
1485
+ Date paper appeared in daily papers on the Hub.
1486
+ submitted_by (`User`, **optional**):
1487
+ Information about who submitted the daily paper.
1488
+ """
1489
+
1490
+ id : str
1491
+ authors : Optional [List [str ]]
1492
+ published_at : Optional [datetime ]
1493
+ title : Optional [str ]
1494
+ summary : Optional [str ]
1495
+ upvotes : Optional [int ]
1496
+ discussion_id : Optional [str ]
1497
+ source : Optional [str ]
1498
+ comments : Optional [int ]
1499
+ submitted_at : Optional [datetime ]
1500
+ submitted_by : Optional [User ]
1501
+
1502
+ def __init__ (self , ** kwargs ) -> None :
1503
+ paper = kwargs .pop ("paper" , {})
1504
+ self .id = kwargs .pop ("id" , None ) or paper .pop ("id" , None )
1505
+ authors = paper .pop ("authors" , None ) or kwargs .pop ("authors" , None )
1506
+ self .authors = [author .pop ("name" , None ) for author in authors ] if authors else None
1507
+ published_at = paper .pop ("publishedAt" , None ) or kwargs .pop ("publishedAt" , None )
1508
+ self .published_at = parse_datetime (published_at ) if published_at else None
1509
+ self .title = kwargs .pop ("title" , None )
1510
+ self .source = kwargs .pop ("source" , None )
1511
+ self .summary = paper .pop ("summary" , None ) or kwargs .pop ("summary" , None )
1512
+ self .upvotes = paper .pop ("upvotes" , None ) or kwargs .pop ("upvotes" , None )
1513
+ self .discussion_id = paper .pop ("discussionId" , None ) or kwargs .pop ("discussionId" , None )
1514
+ self .comments = kwargs .pop ("numComments" , 0 )
1515
+ submitted_at = kwargs .pop ("publishedAt" , None ) or kwargs .pop ("submittedOnDailyAt" , None )
1516
+ self .submitted_at = parse_datetime (submitted_at ) if submitted_at else None
1517
+ submitted_by = kwargs .pop ("submittedBy" , None ) or kwargs .pop ("submittedOnDailyBy" , None )
1518
+ self .submitted_by = User (** submitted_by ) if submitted_by else None
1519
+
1520
+ # forward compatibility
1521
+ self .__dict__ .update (** kwargs )
1522
+
1523
+
1460
1524
def future_compatible (fn : CallableT ) -> CallableT :
1461
1525
"""Wrap a method of `HfApi` to handle `run_as_future=True`.
1462
1526
@@ -9673,6 +9737,72 @@ def list_user_following(self, username: str, token: Union[bool, str, None] = Non
9673
9737
):
9674
9738
yield User (** followed_user )
9675
9739
9740
+ def list_papers (
9741
+ self ,
9742
+ * ,
9743
+ query : Optional [str ] = None ,
9744
+ token : Union [bool , str , None ] = None ,
9745
+ ) -> Iterable [PaperInfo ]:
9746
+ """
9747
+ List daily papers on the Hugging Face Hub given a search query.
9748
+
9749
+ Args:
9750
+ query (`str`, *optional*):
9751
+ A search query string to find papers.
9752
+ If provided, returns papers that match the query.
9753
+ token (Union[bool, str, None], *optional*):
9754
+ A valid user access token (string). Defaults to the locally saved
9755
+ token, which is the recommended method for authentication (see
9756
+ https://huggingface.co/docs/huggingface_hub/quick-start#authentication).
9757
+ To disable authentication, pass `False`.
9758
+
9759
+ Returns:
9760
+ `Iterable[PaperInfo]`: an iterable of [`huggingface_hub.hf_api.PaperInfo`] objects.
9761
+
9762
+ Example:
9763
+
9764
+ ```python
9765
+ >>> from huggingface_hub import HfApi
9766
+
9767
+ >>> api = HfApi()
9768
+
9769
+ # List all papers with "attention" in their title
9770
+ >>> api.list_papers(query="attention")
9771
+ ```
9772
+ """
9773
+ path = f"{ self .endpoint } /api/papers/search"
9774
+ params = {}
9775
+ if query :
9776
+ params ["q" ] = query
9777
+ r = get_session ().get (
9778
+ path ,
9779
+ params = params ,
9780
+ headers = self ._build_hf_headers (token = token ),
9781
+ )
9782
+ hf_raise_for_status (r )
9783
+ for paper in r .json ():
9784
+ yield PaperInfo (** paper )
9785
+
9786
+ def paper_info (self , id : str ) -> PaperInfo :
9787
+ """
9788
+ Get information for a paper on the Hub.
9789
+
9790
+ Args:
9791
+ id (`str`, **optional**):
9792
+ ArXiv id of the paper.
9793
+
9794
+ Returns:
9795
+ `PaperInfo`: A `PaperInfo` object.
9796
+
9797
+ Raises:
9798
+ [`HTTPError`](https://requests.readthedocs.io/en/latest/api/#requests.HTTPError):
9799
+ HTTP 404 If the paper does not exist on the Hub.
9800
+ """
9801
+ path = f"{ self .endpoint } /api/papers/{ id } "
9802
+ r = get_session ().get (path )
9803
+ hf_raise_for_status (r )
9804
+ return PaperInfo (** r .json ())
9805
+
9676
9806
def auth_check (
9677
9807
self , repo_id : str , * , repo_type : Optional [str ] = None , token : Union [bool , str , None ] = None
9678
9808
) -> None :
@@ -9768,6 +9898,9 @@ def _parse_revision_from_pr_url(pr_url: str) -> str:
9768
9898
list_spaces = api .list_spaces
9769
9899
space_info = api .space_info
9770
9900
9901
+ list_papers = api .list_papers
9902
+ paper_info = api .paper_info
9903
+
9771
9904
repo_exists = api .repo_exists
9772
9905
revision_exists = api .revision_exists
9773
9906
file_exists = api .file_exists
0 commit comments