aiagents4pharma 1.30.2__py3-none-any.whl → 1.30.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. aiagents4pharma/talk2scholars/__init__.py +2 -0
  2. aiagents4pharma/talk2scholars/agents/__init__.py +8 -0
  3. aiagents4pharma/talk2scholars/configs/__init__.py +2 -0
  4. aiagents4pharma/talk2scholars/configs/agents/__init__.py +2 -0
  5. aiagents4pharma/talk2scholars/configs/agents/talk2scholars/__init__.py +2 -0
  6. aiagents4pharma/talk2scholars/configs/app/__init__.py +2 -0
  7. aiagents4pharma/talk2scholars/configs/tools/__init__.py +9 -0
  8. aiagents4pharma/talk2scholars/state/__init__.py +4 -2
  9. aiagents4pharma/talk2scholars/tests/test_s2_multi.py +10 -8
  10. aiagents4pharma/talk2scholars/tests/test_s2_search.py +9 -5
  11. aiagents4pharma/talk2scholars/tests/test_s2_single.py +7 -7
  12. aiagents4pharma/talk2scholars/tests/test_zotero_path.py +25 -11
  13. aiagents4pharma/talk2scholars/tests/test_zotero_read.py +49 -35
  14. aiagents4pharma/talk2scholars/tests/test_zotero_write.py +10 -10
  15. aiagents4pharma/talk2scholars/tools/__init__.py +3 -0
  16. aiagents4pharma/talk2scholars/tools/pdf/__init__.py +4 -2
  17. aiagents4pharma/talk2scholars/tools/s2/__init__.py +9 -0
  18. aiagents4pharma/talk2scholars/tools/s2/multi_paper_rec.py +9 -135
  19. aiagents4pharma/talk2scholars/tools/s2/search.py +8 -114
  20. aiagents4pharma/talk2scholars/tools/s2/single_paper_rec.py +8 -126
  21. aiagents4pharma/talk2scholars/tools/s2/utils/__init__.py +7 -0
  22. aiagents4pharma/talk2scholars/tools/s2/utils/multi_helper.py +194 -0
  23. aiagents4pharma/talk2scholars/tools/s2/utils/search_helper.py +175 -0
  24. aiagents4pharma/talk2scholars/tools/s2/utils/single_helper.py +186 -0
  25. aiagents4pharma/talk2scholars/tools/zotero/__init__.py +2 -0
  26. aiagents4pharma/talk2scholars/tools/zotero/utils/__init__.py +5 -0
  27. aiagents4pharma/talk2scholars/tools/zotero/utils/read_helper.py +167 -0
  28. aiagents4pharma/talk2scholars/tools/zotero/utils/review_helper.py +78 -0
  29. aiagents4pharma/talk2scholars/tools/zotero/utils/write_helper.py +197 -0
  30. aiagents4pharma/talk2scholars/tools/zotero/utils/zotero_path.py +1 -1
  31. aiagents4pharma/talk2scholars/tools/zotero/zotero_read.py +9 -136
  32. aiagents4pharma/talk2scholars/tools/zotero/zotero_review.py +14 -48
  33. aiagents4pharma/talk2scholars/tools/zotero/zotero_write.py +22 -147
  34. {aiagents4pharma-1.30.2.dist-info → aiagents4pharma-1.30.4.dist-info}/METADATA +1 -1
  35. {aiagents4pharma-1.30.2.dist-info → aiagents4pharma-1.30.4.dist-info}/RECORD +38 -31
  36. {aiagents4pharma-1.30.2.dist-info → aiagents4pharma-1.30.4.dist-info}/WHEEL +0 -0
  37. {aiagents4pharma-1.30.2.dist-info → aiagents4pharma-1.30.4.dist-info}/licenses/LICENSE +0 -0
  38. {aiagents4pharma-1.30.2.dist-info → aiagents4pharma-1.30.4.dist-info}/top_level.txt +0 -0
@@ -3,3 +3,5 @@ This file is used to import all the modules in the package.
3
3
  """
4
4
 
5
5
  from . import agents, configs, state, tests, tools
6
+
7
+ __all__ = ["agents", "configs", "state", "tests", "tools"]
@@ -7,3 +7,11 @@ from . import s2_agent
7
7
  from . import paper_download_agent
8
8
  from . import zotero_agent
9
9
  from . import pdf_agent
10
+
11
+ __all__ = [
12
+ "main_agent",
13
+ "s2_agent",
14
+ "paper_download_agent",
15
+ "zotero_agent",
16
+ "pdf_agent",
17
+ ]
@@ -5,3 +5,5 @@ This package contains configuration settings and prompts used by various AI agen
5
5
  from . import agents
6
6
  from . import tools
7
7
  from . import app
8
+
9
+ __all__ = ["agents", "tools", "app"]
@@ -3,3 +3,5 @@ Import all the modules in the package
3
3
  """
4
4
 
5
5
  from . import talk2scholars
6
+
7
+ __all__ = ["talk2scholars"]
@@ -6,3 +6,5 @@ from . import s2_agent
6
6
  from . import main_agent
7
7
  from . import pdf_agent
8
8
  from . import zotero_agent
9
+
10
+ __all__ = ["s2_agent", "main_agent", "pdf_agent", "zotero_agent"]
@@ -3,3 +3,5 @@ Import all the modules in the package
3
3
  """
4
4
 
5
5
  from . import frontend
6
+
7
+ __all__ = ["frontend"]
@@ -8,3 +8,12 @@ from . import multi_paper_recommendation
8
8
  from . import question_and_answer
9
9
  from . import zotero_read
10
10
  from . import zotero_write
11
+
12
+ __all__ = [
13
+ "search",
14
+ "single_paper_recommendation",
15
+ "multi_paper_recommendation",
16
+ "question_and_answer",
17
+ "zotero_read",
18
+ "zotero_write",
19
+ ]
@@ -1,5 +1,7 @@
1
- '''
1
+ """
2
2
  This file is used to import all the modules in the package.
3
- '''
3
+ """
4
4
 
5
5
  from . import state_talk2scholars
6
+
7
+ __all__ = ["state_talk2scholars"]
@@ -12,6 +12,7 @@ import hydra
12
12
  from aiagents4pharma.talk2scholars.tools.s2.multi_paper_rec import (
13
13
  get_multi_paper_recommendations,
14
14
  )
15
+ from aiagents4pharma.talk2scholars.tools.s2.utils import multi_helper
15
16
 
16
17
  # --- Dummy Hydra Config Setup ---
17
18
 
@@ -285,20 +286,21 @@ def test_multi_paper_rec_requests_exception(monkeypatch):
285
286
 
286
287
  def test_multi_paper_rec_no_response(monkeypatch):
287
288
  """
288
- Test that get_multi_paper_recommendations raises a RuntimeError when no response is obtained.
289
- This is simulated by patching 'range' in the underlying function's globals to
290
- return an empty iterator,
291
- so that the for loop does not iterate and response remains None.
289
+ Test that get_multi_paper_recommendations raises a RuntimeError
290
+ when no response is obtained. This is simulated by patching 'range'
291
+ in the module namespace of multi_helper to return an empty iterator,
292
+ so that the for loop in _fetch_recommendations never iterates and
293
+ self.response remains None.
292
294
  """
293
- # Patch 'range' in the underlying function's globals (accessed via .func.__globals__)
294
- monkeypatch.setitem(
295
- get_multi_paper_recommendations.func.__globals__, "range", lambda x: iter([])
296
- )
295
+ # Inject a patched 'range' into the multi_helper module's dictionary.
296
+ monkeypatch.setitem(multi_helper.__dict__, "range", lambda x: iter([]))
297
+
297
298
  tool_call_id = "test_tool_call_id"
298
299
  input_data = {
299
300
  "paper_ids": ["p1", "p2"],
300
301
  "tool_call_id": tool_call_id,
301
302
  }
303
+
302
304
  with pytest.raises(
303
305
  RuntimeError, match="Failed to obtain a response from the Semantic Scholar API."
304
306
  ):
@@ -9,6 +9,7 @@ import requests
9
9
  from langgraph.types import Command
10
10
  from langchain_core.messages import ToolMessage
11
11
  from aiagents4pharma.talk2scholars.tools.s2.search import search_tool
12
+ from aiagents4pharma.talk2scholars.tools.s2.utils import search_helper
12
13
 
13
14
  # --- Dummy Hydra Config Setup ---
14
15
 
@@ -269,12 +270,15 @@ def test_search_tool_requests_exception(monkeypatch):
269
270
 
270
271
  def test_search_tool_no_response(monkeypatch):
271
272
  """
272
- Test that search_tool raises a RuntimeError when no response is obtained.
273
- This is simulated by patching 'range' in the original function's globals (a dict)
274
- so that it returns an empty iterator, leaving response as None.
273
+ Test that search_tool raises a RuntimeError when no response
274
+ is obtained. This is simulated by patching 'range' in the
275
+ module namespace of search_helper to return an empty iterator,
276
+ so that the for-loop in _fetch_papers never iterates and self.response
277
+ remains None.
275
278
  """
276
- # Patch 'range' in the original function's globals using setitem.
277
- monkeypatch.setitem(search_tool.func.__globals__, "range", lambda x: iter([]))
279
+ # Patch 'range' in the module globals of search_helper.
280
+ monkeypatch.setitem(search_helper.__dict__, "range", lambda x: iter([]))
281
+
278
282
  tool_call_id = "test_tool_call_id"
279
283
  with pytest.raises(
280
284
  RuntimeError, match="Failed to obtain a response from the Semantic Scholar API."
@@ -11,6 +11,7 @@ from langchain_core.messages import ToolMessage
11
11
  from aiagents4pharma.talk2scholars.tools.s2.single_paper_rec import (
12
12
  get_single_paper_recommendations,
13
13
  )
14
+ from aiagents4pharma.talk2scholars.tools.s2.utils import single_helper
14
15
 
15
16
  # --- Dummy Hydra Config Setup ---
16
17
 
@@ -279,14 +280,13 @@ def test_single_paper_rec_no_response(monkeypatch):
279
280
  """
280
281
  Test that get_single_paper_recommendations raises a RuntimeError
281
282
  when no response is obtained from the API.
282
-
283
- This is simulated by patching 'range' in the underlying function's globals
284
- to return an empty iterator, so the for-loop never iterates and response remains None.
283
+ This is simulated by patching 'range' in the module namespace
284
+ of single_helper to return an empty iterator, so that the for-loop
285
+ in _fetch_recommendations never iterates and response remains None.
285
286
  """
286
- # Patch 'range' in the underlying function's globals (accessed via .func.__globals__)
287
- monkeypatch.setitem(
288
- get_single_paper_recommendations.func.__globals__, "range", lambda x: iter([])
289
- )
287
+ # Patch 'range' in the module globals of single_helper.
288
+ monkeypatch.setitem(single_helper.__dict__, "range", lambda x: iter([]))
289
+
290
290
  tool_call_id = "test_tool_call_id"
291
291
  input_data = {
292
292
  "paper_id": "12345",
@@ -292,7 +292,9 @@ class TestZoteroWrite:
292
292
  @pytest.fixture
293
293
  def mock_hydra(self):
294
294
  """Fixture to mock hydra configuration."""
295
- with patch("hydra.compose") as mock_compose:
295
+ with patch(
296
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose"
297
+ ) as mock_compose:
296
298
  cfg = MagicMock()
297
299
  cfg.tools.zotero_write.user_id = "test_user"
298
300
  cfg.tools.zotero_write.library_type = "user"
@@ -305,13 +307,15 @@ class TestZoteroWrite:
305
307
  @pytest.fixture
306
308
  def mock_zotero(self):
307
309
  """Fixture to mock Zotero client."""
308
- with patch("pyzotero.zotero.Zotero") as mock_zot_class:
310
+ with patch(
311
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.zotero.Zotero"
312
+ ) as mock_zot_class:
309
313
  mock_zot = MagicMock()
310
314
  mock_zot_class.return_value = mock_zot
311
315
  yield mock_zot
312
316
 
313
317
  @patch(
314
- "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.fetch_papers_for_save"
318
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save"
315
319
  )
316
320
  def test_zotero_write_no_papers(self, mock_fetch):
317
321
  """When no papers exist (even after approval), the function raises a ValueError."""
@@ -335,12 +339,14 @@ class TestZoteroWrite:
335
339
  assert "No fetched papers were found to save" in str(excinfo.value)
336
340
 
337
341
  @patch(
338
- "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.fetch_papers_for_save"
342
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save"
339
343
  )
340
344
  @patch(
341
- "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.find_or_create_collection"
345
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection"
342
346
  )
343
- def test_zotero_write_invalid_collection(self, mock_find, mock_fetch, mock_zotero):
347
+ def test_zotero_write_invalid_collection(
348
+ self, mock_find, mock_fetch, mock_zotero
349
+ ):
344
350
  """Saving to a nonexistent Zotero collection returns an error Command."""
345
351
  sample = {"paper1": {"Title": "Test Paper"}}
346
352
  mock_fetch.return_value = sample
@@ -372,12 +378,14 @@ class TestZoteroWrite:
372
378
  assert "Curiosity, Random" in msg
373
379
 
374
380
  @patch(
375
- "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.fetch_papers_for_save"
381
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save"
376
382
  )
377
383
  @patch(
378
- "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.find_or_create_collection"
384
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection"
379
385
  )
380
- def test_zotero_write_success(self, mock_find, mock_fetch, mock_hydra, mock_zotero):
386
+ def test_zotero_write_success(
387
+ self, mock_find, mock_fetch, mock_hydra, mock_zotero
388
+ ):
381
389
  """A valid approved save returns a success Command with summary."""
382
390
  sample = {"paper1": {"Title": "Test Paper", "Authors": ["Test Author"]}}
383
391
  mock_fetch.return_value = sample
@@ -418,7 +426,11 @@ class TestZoteroRead:
418
426
  @pytest.fixture
419
427
  def mock_hydra(self):
420
428
  """Fixture to mock hydra configuration."""
421
- with patch("hydra.initialize"), patch("hydra.compose") as mock_compose:
429
+ with patch(
430
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize"
431
+ ), patch(
432
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose"
433
+ ) as mock_compose:
422
434
  cfg = MagicMock()
423
435
  cfg.tools.zotero_read.user_id = "test_user"
424
436
  cfg.tools.zotero_read.library_type = "user"
@@ -435,7 +447,9 @@ class TestZoteroRead:
435
447
  @pytest.fixture
436
448
  def mock_zotero(self):
437
449
  """Fixture to mock Zotero client."""
438
- with patch("pyzotero.zotero.Zotero") as mock_zot_class:
450
+ with patch(
451
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.zotero.Zotero"
452
+ ) as mock_zot_class:
439
453
  mock_zot = MagicMock()
440
454
  mock_zot_class.return_value = mock_zot
441
455
  yield mock_zot
@@ -6,9 +6,7 @@ from types import SimpleNamespace
6
6
  import unittest
7
7
  from unittest.mock import patch, MagicMock
8
8
  from langgraph.types import Command
9
- from aiagents4pharma.talk2scholars.tools.zotero.zotero_read import (
10
- zotero_read,
11
- )
9
+ from aiagents4pharma.talk2scholars.tools.zotero.zotero_read import zotero_read
12
10
 
13
11
 
14
12
  # Dummy Hydra configuration to be used in tests
@@ -29,11 +27,13 @@ class TestZoteroSearchTool(unittest.TestCase):
29
27
  """Tests for Zotero search tool."""
30
28
 
31
29
  @patch(
32
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
30
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
31
+ )
32
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
33
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
34
+ @patch(
35
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
33
36
  )
34
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
35
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
36
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
37
37
  def test_valid_query(
38
38
  self,
39
39
  mock_hydra_init,
@@ -104,11 +104,13 @@ class TestZoteroSearchTool(unittest.TestCase):
104
104
  self.assertIn("Number of papers found: 2", message_content)
105
105
 
106
106
  @patch(
107
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
107
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
108
+ )
109
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
110
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
111
+ @patch(
112
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
108
113
  )
109
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
110
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
111
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
112
114
  def test_empty_query_fetch_all_items(
113
115
  self,
114
116
  mock_hydra_init,
@@ -154,11 +156,13 @@ class TestZoteroSearchTool(unittest.TestCase):
154
156
  )
155
157
 
156
158
  @patch(
157
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
159
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
160
+ )
161
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
162
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
163
+ @patch(
164
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
158
165
  )
159
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
160
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
161
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
162
166
  def test_no_items_returned(
163
167
  self,
164
168
  mock_hydra_init,
@@ -187,11 +191,13 @@ class TestZoteroSearchTool(unittest.TestCase):
187
191
  self.assertIn("No items returned from Zotero", str(context.exception))
188
192
 
189
193
  @patch(
190
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
194
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
195
+ )
196
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
197
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
198
+ @patch(
199
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
191
200
  )
192
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
193
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
194
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
195
201
  def test_filtering_no_matching_papers(
196
202
  self,
197
203
  mock_hydra_init,
@@ -252,11 +258,13 @@ class TestZoteroSearchTool(unittest.TestCase):
252
258
  self.assertEqual(len(filtered_papers), 2)
253
259
 
254
260
  @patch(
255
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
261
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
262
+ )
263
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
264
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
265
+ @patch(
266
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
256
267
  )
257
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
258
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
259
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
260
268
  def test_items_api_exception(
261
269
  self,
262
270
  mock_hydra_init,
@@ -285,11 +293,13 @@ class TestZoteroSearchTool(unittest.TestCase):
285
293
  self.assertIn("Failed to fetch items from Zotero", str(context.exception))
286
294
 
287
295
  @patch(
288
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
296
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
297
+ )
298
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
299
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
300
+ @patch(
301
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
289
302
  )
290
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
291
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
292
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
293
303
  def test_missing_key_in_item(
294
304
  self,
295
305
  mock_hydra_init,
@@ -344,11 +354,13 @@ class TestZoteroSearchTool(unittest.TestCase):
344
354
  self.assertEqual(len(filtered_papers), 1)
345
355
 
346
356
  @patch(
347
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
357
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
358
+ )
359
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
360
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
361
+ @patch(
362
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
348
363
  )
349
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
350
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
351
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
352
364
  def test_item_not_dict(
353
365
  self,
354
366
  mock_hydra_init,
@@ -382,11 +394,13 @@ class TestZoteroSearchTool(unittest.TestCase):
382
394
  self.assertIn("No matching papers returned from Zotero", str(context.exception))
383
395
 
384
396
  @patch(
385
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_read.get_item_collections"
397
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.zotero_path.get_item_collections"
398
+ )
399
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.zotero.Zotero")
400
+ @patch("aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.compose")
401
+ @patch(
402
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.read_helper.hydra.initialize"
386
403
  )
387
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.zotero.Zotero")
388
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.compose")
389
- @patch("aiagents4pharma.talk2scholars.tools.zotero.zotero_read.hydra.initialize")
390
404
  def test_data_not_dict(
391
405
  self,
392
406
  mock_hydra_init,
@@ -22,14 +22,14 @@ class TestZoteroSaveTool(unittest.TestCase):
22
22
  def setUp(self):
23
23
  """Patch Hydra and Zotero client globally"""
24
24
  self.hydra_init = patch(
25
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.hydra.initialize"
25
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.initialize"
26
26
  ).start()
27
27
  self.hydra_compose = patch(
28
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.hydra.compose",
28
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.hydra.compose",
29
29
  return_value=dummy_cfg,
30
30
  ).start()
31
31
  self.zotero_class = patch(
32
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.zotero.Zotero"
32
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.zotero.Zotero"
33
33
  ).start()
34
34
 
35
35
  self.fake_zot = MagicMock()
@@ -57,7 +57,7 @@ class TestZoteroSaveTool(unittest.TestCase):
57
57
  return state
58
58
 
59
59
  @patch(
60
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.fetch_papers_for_save",
60
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save",
61
61
  return_value=None,
62
62
  )
63
63
  def test_no_papers_after_approval(self, mock_fetch):
@@ -74,11 +74,11 @@ class TestZoteroSaveTool(unittest.TestCase):
74
74
  mock_fetch.assert_called_once()
75
75
 
76
76
  @patch(
77
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.fetch_papers_for_save",
77
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save",
78
78
  return_value={"p1": {"Title": "X"}},
79
79
  )
80
80
  @patch(
81
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.find_or_create_collection",
81
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection",
82
82
  return_value=None,
83
83
  )
84
84
  def test_invalid_collection(self, mock_find, mock_fetch):
@@ -104,11 +104,11 @@ class TestZoteroSaveTool(unittest.TestCase):
104
104
  mock_find.return_value = None
105
105
 
106
106
  @patch(
107
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.fetch_papers_for_save",
107
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save",
108
108
  return_value={"p1": {"Title": "X"}},
109
109
  )
110
110
  @patch(
111
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.find_or_create_collection",
111
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection",
112
112
  return_value="colKey",
113
113
  )
114
114
  def test_save_failure(self, mock_find, mock_fetch):
@@ -131,11 +131,11 @@ class TestZoteroSaveTool(unittest.TestCase):
131
131
  mock_find.return_value = "colKey"
132
132
 
133
133
  @patch(
134
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.fetch_papers_for_save",
134
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.fetch_papers_for_save",
135
135
  return_value={"p1": {"Title": "X"}},
136
136
  )
137
137
  @patch(
138
- "aiagents4pharma.talk2scholars.tools.zotero.zotero_write.find_or_create_collection",
138
+ "aiagents4pharma.talk2scholars.tools.zotero.utils.write_helper.find_or_create_collection",
139
139
  return_value="colKey",
140
140
  )
141
141
  def test_successful_save(self, mock_find, mock_fetch):
@@ -7,3 +7,6 @@ Import statements
7
7
  from . import s2
8
8
  from . import pdf
9
9
  from . import zotero
10
+ from . import paper_download
11
+
12
+ __all__ = ["s2", "pdf", "zotero", "paper_download"]
@@ -1,5 +1,7 @@
1
- '''
1
+ """
2
2
  This file is used to import all the modules in the package.
3
- '''
3
+ """
4
4
 
5
5
  from . import question_and_answer
6
+
7
+ __all__ = ["question_and_answer"]
@@ -8,3 +8,12 @@ from . import search
8
8
  from . import single_paper_rec
9
9
  from . import query_results
10
10
  from . import retrieve_semantic_scholar_paper_id
11
+
12
+ __all__ = [
13
+ "display_results",
14
+ "multi_paper_rec",
15
+ "search",
16
+ "single_paper_rec",
17
+ "query_results",
18
+ "retrieve_semantic_scholar_paper_id",
19
+ ]