@@ -1457,6 +1457,70 @@ def __init__(self, **kwargs) -> None:
14571457 self .__dict__ .update (** kwargs )
14581458
14591459
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+
14601524def future_compatible (fn : CallableT ) -> CallableT :
14611525 """Wrap a method of `HfApi` to handle `run_as_future=True`.
14621526
@@ -9673,6 +9737,72 @@ def list_user_following(self, username: str, token: Union[bool, str, None] = Non
96739737 ):
96749738 yield User (** followed_user )
96759739
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+
96769806 def auth_check (
96779807 self , repo_id : str , * , repo_type : Optional [str ] = None , token : Union [bool , str , None ] = None
96789808 ) -> None :
@@ -9768,6 +9898,9 @@ def _parse_revision_from_pr_url(pr_url: str) -> str:
97689898list_spaces = api .list_spaces
97699899space_info = api .space_info
97709900
9901+ list_papers = api .list_papers
9902+ paper_info = api .paper_info
9903+
97719904repo_exists = api .repo_exists
97729905revision_exists = api .revision_exists
97739906file_exists = api .file_exists
0 commit comments