Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
tenacity
httpx
nest_asyncio
10 changes: 8 additions & 2 deletions semanticscholar/PaginatedResults.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from typing import Any, Union, List
import asyncio
import concurrent.futures

from semanticscholar.ApiRequester import ApiRequester
from semanticscholar.SemanticScholarException import NoMorePagesException
Expand Down Expand Up @@ -156,8 +157,13 @@ def _get_next_page(self) -> list:

self._build_params()

loop = asyncio.get_event_loop()
results = loop.run_until_complete(self._request_data())
try:
asyncio.get_running_loop()
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
future = pool.submit(asyncio.run, self._request_data())
results = future.result()
except RuntimeError:
results = asyncio.run(self._request_data())

return self._update_params(results)

Expand Down
66 changes: 30 additions & 36 deletions semanticscholar/SemanticScholar.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from typing import List, Literal, Tuple, Union
import asyncio
import nest_asyncio
import concurrent.futures

from semanticscholar.PaginatedResults import PaginatedResults
from semanticscholar.AsyncSemanticScholar import AsyncSemanticScholar
Expand All @@ -12,6 +12,18 @@
from semanticscholar.Autocomplete import Autocomplete


def _run_async(coro):
'''Run an async coroutine from synchronous code, even if an event
loop is already running (e.g. Jupyter notebooks).'''
try:
asyncio.get_running_loop()
with concurrent.futures.ThreadPoolExecutor(max_workers=1) as pool:
future = pool.submit(asyncio.run, coro)
return future.result()
except RuntimeError:
return asyncio.run(coro)


class SemanticScholar():
'''
Main class to retrieve data from Semantic Scholar Graph API synchronously.
Expand All @@ -33,7 +45,6 @@ def __init__(
:param bool debug: (optional) enable debug mode.
:param bool retry: enable retry mode.
'''
nest_asyncio.apply()
self._timeout = timeout
self._retry = retry
self._AsyncSemanticScholar = AsyncSemanticScholar(
Expand Down Expand Up @@ -126,8 +137,7 @@ def get_paper(
:raises: ObjectNotFoundException: if Paper ID not found.
'''

loop = asyncio.get_event_loop()
paper = loop.run_until_complete(
paper = _run_async(
self._AsyncSemanticScholar.get_paper(
paper_id=paper_id,
fields=fields
Expand Down Expand Up @@ -169,8 +179,7 @@ def get_papers(
:raises: BadQueryParametersException: if no paper was found.
'''

loop = asyncio.get_event_loop()
papers = loop.run_until_complete(
papers = _run_async(
self._AsyncSemanticScholar.get_papers(
paper_ids=paper_ids,
fields=fields,
Expand Down Expand Up @@ -207,8 +216,7 @@ def get_paper_authors(
(must be <= 1000).
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.get_paper_authors(
paper_id=paper_id,
fields=fields,
Expand Down Expand Up @@ -245,8 +253,7 @@ def get_paper_citations(
(must be <= 1000).
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.get_paper_citations(
paper_id=paper_id,
fields=fields,
Expand Down Expand Up @@ -283,8 +290,7 @@ def get_paper_references(
(must be <= 1000).
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.get_paper_references(
paper_id=paper_id,
fields=fields,
Expand Down Expand Up @@ -358,8 +364,7 @@ def search_paper(
:class:`semanticscholar.Paper.Paper`
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.search_paper(
query=query,
year=year,
Expand Down Expand Up @@ -397,8 +402,7 @@ def get_author(
:raises: ObjectNotFoundException: if Author ID not found.
'''

loop = asyncio.get_event_loop()
author = loop.run_until_complete(
author = _run_async(
self._AsyncSemanticScholar.get_author(
author_id=author_id,
fields=fields
Expand Down Expand Up @@ -429,8 +433,7 @@ def get_authors(
:raises: BadQueryParametersException: if no author was found.
'''

loop = asyncio.get_event_loop()
authors = loop.run_until_complete(
authors = _run_async(
self._AsyncSemanticScholar.get_authors(
author_ids=author_ids,
fields=fields,
Expand Down Expand Up @@ -467,8 +470,7 @@ def get_author_papers(
(must be <= 1000).
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.get_author_papers(
author_id=author_id,
fields=fields,
Expand Down Expand Up @@ -499,8 +501,7 @@ def search_author(
:rtype: :class:`semanticscholar.PaginatedResults.PaginatedResults`
'''

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.search_author(
query=query,
fields=fields,
Expand Down Expand Up @@ -542,8 +543,7 @@ def get_recommended_papers(
:rtype: :class:`List` of :class:`semanticscholar.Paper.Paper`
'''

loop = asyncio.get_event_loop()
papers = loop.run_until_complete(
papers = _run_async(
self._AsyncSemanticScholar.get_recommended_papers(
paper_id=paper_id,
fields=fields,
Expand Down Expand Up @@ -579,8 +579,7 @@ def get_recommended_papers_from_lists(
:rtype: :class:`List` of :class:`semanticscholar.Paper.Paper`
'''

loop = asyncio.get_event_loop()
papers = loop.run_until_complete(
papers = _run_async(
self._AsyncSemanticScholar.get_recommended_papers_from_lists(
positive_paper_ids=positive_paper_ids,
negative_paper_ids=negative_paper_ids,
Expand All @@ -605,8 +604,7 @@ def get_autocomplete(self, query: str) -> List[Autocomplete]:
:class:`semanticscholar.Autocomplete.Autocomplete`
"""

loop = asyncio.get_event_loop()
results = loop.run_until_complete(
results = _run_async(
self._AsyncSemanticScholar.get_autocomplete(query=query)
)

Expand All @@ -624,8 +622,7 @@ def get_available_releases(self) -> List[str]:
:rtype: :class:`List` of :class:`str`
"""

loop = asyncio.get_event_loop()
releases = loop.run_until_complete(
releases = _run_async(
self._AsyncSemanticScholar.get_available_releases()
)

Expand All @@ -644,8 +641,7 @@ def get_release(self, release_id: str) -> Release:
:rtype: :class:`semanticscholar.Release.Release`
"""

loop = asyncio.get_event_loop()
release = loop.run_until_complete(
release = _run_async(
self._AsyncSemanticScholar.get_release(release_id=release_id)
)

Expand All @@ -669,8 +665,7 @@ def get_dataset_download_links(
:rtype: :class:`semanticscholar.Dataset.Dataset`
"""

loop = asyncio.get_event_loop()
dataset = loop.run_until_complete(
dataset = _run_async(
self._AsyncSemanticScholar.get_dataset_download_links(
release_id=release_id,
dataset_name=dataset_name
Expand Down Expand Up @@ -703,8 +698,7 @@ def get_dataset_diffs(
:rtype: :class:`semanticscholar.DatasetDiff.DatasetDiff`
"""

loop = asyncio.get_event_loop()
result = loop.run_until_complete(
result = _run_async(
self._AsyncSemanticScholar.get_dataset_diffs(
dataset_name=dataset_name,
start_release_id=start_release_id,
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
license='MIT',
packages=['semanticscholar'],
python_requires='>=3.10',
install_requires=['tenacity', 'httpx', 'nest_asyncio'],
install_requires=['tenacity', 'httpx'],
test_suite='tests',
tests_require=['vcrpy>=8.0'],
classifiers=[
Expand Down