gemini-webapi 1.10.2__tar.gz → 1.11.1__tar.gz

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 (37) hide show
  1. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/PKG-INFO +3 -2
  2. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/README.md +2 -1
  3. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/client.py +35 -6
  4. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/constants.py +17 -2
  5. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/exceptions.py +24 -0
  6. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi.egg-info/PKG-INFO +3 -2
  7. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/tests/test_client_features.py +16 -9
  8. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.github/dependabot.yml +0 -0
  9. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.github/workflows/github-release.yml +0 -0
  10. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.github/workflows/pypi-publish.yml +0 -0
  11. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.gitignore +0 -0
  12. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.vscode/launch.json +0 -0
  13. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/.vscode/settings.json +0 -0
  14. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/LICENSE +0 -0
  15. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/assets/banner.png +0 -0
  16. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/assets/favicon.png +0 -0
  17. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/assets/logo.svg +0 -0
  18. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/assets/sample.pdf +0 -0
  19. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/pyproject.toml +0 -0
  20. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/setup.cfg +0 -0
  21. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/__init__.py +0 -0
  22. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/types/__init__.py +0 -0
  23. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/types/candidate.py +0 -0
  24. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/types/image.py +0 -0
  25. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/types/modeloutput.py +0 -0
  26. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/__init__.py +0 -0
  27. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/get_access_token.py +0 -0
  28. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/load_browser_cookies.py +0 -0
  29. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/logger.py +0 -0
  30. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/rotate_1psidts.py +0 -0
  31. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi/utils/upload_file.py +0 -0
  32. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi.egg-info/SOURCES.txt +0 -0
  33. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi.egg-info/dependency_links.txt +0 -0
  34. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi.egg-info/requires.txt +0 -0
  35. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/src/gemini_webapi.egg-info/top_level.txt +0 -0
  36. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/tests/test_rotate_cookies.py +0 -0
  37. {gemini_webapi-1.10.2 → gemini_webapi-1.11.1}/tests/test_save_image.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.10.2
3
+ Version: 1.11.1
4
4
  Summary: ✨ An elegant async Python wrapper for Google Gemini web app
5
5
  Author: UZQueen
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -822,9 +822,10 @@ You can specify which language model to use by passing `model` argument to `Gemi
822
822
 
823
823
  Currently available models (as of Feb 5, 2025):
824
824
 
825
- - `unspecified` - Default model (same as `gemini-2.0-flash` if account does NOT have Gemini Advanced subscription)
825
+ - `unspecified` - Default model
826
826
  - `gemini-2.0-flash` - Gemini 2.0 Flash
827
827
  - `gemini-2.0-flash-thinking` - Gemini 2.0 Flash Thinking Experimental
828
+ - `gemini-2.5-flash` - Gemini 2.5 Flash
828
829
  - `gemini-2.5-pro` - Gemini 2.5 Pro (daily usage limit imposed)
829
830
 
830
831
  Models pending update (may not work as expected):
@@ -139,9 +139,10 @@ You can specify which language model to use by passing `model` argument to `Gemi
139
139
 
140
140
  Currently available models (as of Feb 5, 2025):
141
141
 
142
- - `unspecified` - Default model (same as `gemini-2.0-flash` if account does NOT have Gemini Advanced subscription)
142
+ - `unspecified` - Default model
143
143
  - `gemini-2.0-flash` - Gemini 2.0 Flash
144
144
  - `gemini-2.0-flash-thinking` - Gemini 2.0 Flash Thinking Experimental
145
+ - `gemini-2.5-flash` - Gemini 2.5 Flash
145
146
  - `gemini-2.5-pro` - Gemini 2.5 Pro (daily usage limit imposed)
146
147
 
147
148
  Models pending update (may not work as expected):
@@ -8,8 +8,16 @@ from typing import Any, Optional
8
8
 
9
9
  from httpx import AsyncClient, ReadTimeout
10
10
 
11
- from .constants import Endpoint, Headers, Model
12
- from .exceptions import AuthError, APIError, TimeoutError, GeminiError
11
+ from .constants import Endpoint, ErrorCode, Headers, Model
12
+ from .exceptions import (
13
+ AuthError,
14
+ APIError,
15
+ TimeoutError,
16
+ GeminiError,
17
+ UsageLimitExceeded,
18
+ ModelInvalid,
19
+ TemporarilyBlocked,
20
+ )
13
21
  from .types import WebImage, GeneratedImage, Candidate, ModelOutput
14
22
  from .utils import (
15
23
  upload_file,
@@ -376,10 +384,31 @@ class GeminiClient:
376
384
  raise Exception
377
385
  except Exception:
378
386
  await self.close()
379
- logger.debug(f"Invalid response: {response.text}")
380
- raise APIError(
381
- "Failed to generate contents. Invalid response data received. Client will try to re-initialize on next request."
382
- )
387
+
388
+ try:
389
+ match ErrorCode(response_json[0][5][2][0][1][0]):
390
+ case ErrorCode.USAGE_LIMIT_EXCEEDED:
391
+ raise UsageLimitExceeded(
392
+ f"Failed to generate contents. Usage limit of {model.model_name} model has exceeded. Please try switching to another model."
393
+ )
394
+ case ErrorCode.MODEL_HEADER_INVALID:
395
+ raise ModelInvalid(
396
+ "Failed to generate contents. The specified model is not available. Please update gemini_webapi to the latest version. "
397
+ "If the error persists and is caused by the package, please report it on GitHub."
398
+ )
399
+ case ErrorCode.IP_TEMPORARILY_BLOCKED:
400
+ raise TemporarilyBlocked(
401
+ "Failed to generate contents. Your IP address is temporarily blocked by Google. Please try using a proxy or waiting for a while."
402
+ )
403
+ case _:
404
+ raise Exception
405
+ except GeminiError:
406
+ raise
407
+ except Exception:
408
+ logger.debug(f"Invalid response: {response.text}")
409
+ raise APIError(
410
+ "Failed to generate contents. Invalid response data received. Client will try to re-initialize on next request."
411
+ )
383
412
 
384
413
  try:
385
414
  candidates = []
@@ -27,17 +27,22 @@ class Model(Enum):
27
27
  UNSPECIFIED = ("unspecified", {}, False)
28
28
  G_2_0_FLASH = (
29
29
  "gemini-2.0-flash",
30
- {"x-goog-ext-525001261-jspb": '[null,null,null,null,"f299729663a2343f"]'},
30
+ {"x-goog-ext-525001261-jspb": '[1,null,null,null,"f299729663a2343f"]'},
31
31
  False,
32
32
  )
33
33
  G_2_0_FLASH_THINKING = (
34
34
  "gemini-2.0-flash-thinking",
35
35
  {"x-goog-ext-525001261-jspb": '[null,null,null,null,"7ca48d02d802f20a"]'},
36
36
  False,
37
+ ) # Deprecated
38
+ G_2_5_FLASH = (
39
+ "gemini-2.5-flash",
40
+ {"x-goog-ext-525001261-jspb": '[1,null,null,null,"35609594dbe934d8"]'},
41
+ False,
37
42
  )
38
43
  G_2_5_PRO = (
39
44
  "gemini-2.5-pro",
40
- {"x-goog-ext-525001261-jspb": '[null,null,null,null,"2525e3954d185b3c"]'},
45
+ {"x-goog-ext-525001261-jspb": '[1,null,null,null,"2525e3954d185b3c"]'},
41
46
  False,
42
47
  )
43
48
  G_2_0_EXP_ADVANCED = (
@@ -64,3 +69,13 @@ class Model(Enum):
64
69
  raise ValueError(
65
70
  f"Unknown model name: {name}. Available models: {', '.join([model.model_name for model in cls])}"
66
71
  )
72
+
73
+
74
+ class ErrorCode(Enum):
75
+ """
76
+ Known error codes returned from server.
77
+ """
78
+
79
+ USAGE_LIMIT_EXCEEDED = 1037
80
+ MODEL_HEADER_INVALID = 1052
81
+ IP_TEMPORARILY_BLOCKED = 1060
@@ -28,3 +28,27 @@ class TimeoutError(GeminiError):
28
28
  """
29
29
 
30
30
  pass
31
+
32
+
33
+ class UsageLimitExceeded(GeminiError):
34
+ """
35
+ Exception for model usage limit exceeded errors.
36
+ """
37
+
38
+ pass
39
+
40
+
41
+ class ModelInvalid(GeminiError):
42
+ """
43
+ Exception for invalid model header string errors.
44
+ """
45
+
46
+ pass
47
+
48
+
49
+ class TemporarilyBlocked(GeminiError):
50
+ """
51
+ Exception for 429 Too Many Requests when IP is temporarily blocked.
52
+ """
53
+
54
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gemini-webapi
3
- Version: 1.10.2
3
+ Version: 1.11.1
4
4
  Summary: ✨ An elegant async Python wrapper for Google Gemini web app
5
5
  Author: UZQueen
6
6
  License: GNU AFFERO GENERAL PUBLIC LICENSE
@@ -822,9 +822,10 @@ You can specify which language model to use by passing `model` argument to `Gemi
822
822
 
823
823
  Currently available models (as of Feb 5, 2025):
824
824
 
825
- - `unspecified` - Default model (same as `gemini-2.0-flash` if account does NOT have Gemini Advanced subscription)
825
+ - `unspecified` - Default model
826
826
  - `gemini-2.0-flash` - Gemini 2.0 Flash
827
827
  - `gemini-2.0-flash-thinking` - Gemini 2.0 Flash Thinking Experimental
828
+ - `gemini-2.5-flash` - Gemini 2.5 Flash
828
829
  - `gemini-2.5-pro` - Gemini 2.5 Pro (daily usage limit imposed)
829
830
 
830
831
  Models pending update (may not work as expected):
@@ -7,6 +7,7 @@ from loguru import logger
7
7
 
8
8
  from gemini_webapi import GeminiClient, AuthError, set_log_level
9
9
  from gemini_webapi.constants import Model
10
+ from gemini_webapi.exceptions import UsageLimitExceeded, ModelInvalid
10
11
 
11
12
  logging.getLogger("asyncio").setLevel(logging.ERROR)
12
13
  set_log_level("DEBUG")
@@ -19,22 +20,23 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
19
20
  )
20
21
 
21
22
  try:
22
- await self.geminiclient.init()
23
+ await self.geminiclient.init(timeout=60)
23
24
  except AuthError as e:
24
25
  self.skipTest(e)
25
26
 
26
27
  @logger.catch(reraise=True)
27
28
  async def test_successful_request(self):
28
29
  response = await self.geminiclient.generate_content(
29
- "Hello World!", model=Model.G_2_5_PRO
30
+ "Tell me a fact about today in history and illustrate it with a youtube video",
31
+ model=Model.G_2_5_FLASH,
30
32
  )
31
33
  logger.debug(response.text)
32
34
 
33
35
  @logger.catch(reraise=True)
34
36
  async def test_thinking_model(self):
35
37
  response = await self.geminiclient.generate_content(
36
- "Tell me a fact about today in history and illustrate it with a youtube video",
37
- model=Model.G_2_0_FLASH_THINKING,
38
+ "1+1=?",
39
+ model=Model.G_2_5_FLASH,
38
40
  )
39
41
  logger.debug(response.thoughts)
40
42
  logger.debug(response.text)
@@ -46,11 +48,16 @@ class TestGeminiClient(unittest.IsolatedAsyncioTestCase):
46
48
  logger.debug(f"Model {model.model_name} requires an advanced account")
47
49
  continue
48
50
 
49
- response = await self.geminiclient.generate_content(
50
- "What's you language model version? Reply version number only.",
51
- model=model,
52
- )
53
- logger.debug(f"Model version ({model.model_name}): {response.text}")
51
+ try:
52
+ response = await self.geminiclient.generate_content(
53
+ "What's you language model version? Reply version number only.",
54
+ model=model,
55
+ )
56
+ logger.debug(f"Model version ({model.model_name}): {response.text}")
57
+ except UsageLimitExceeded:
58
+ logger.debug(f"Model {model.model_name} usage limit exceeded")
59
+ except ModelInvalid:
60
+ logger.debug(f"Model {model.model_name} is not available anymore")
54
61
 
55
62
  @logger.catch(reraise=True)
56
63
  async def test_upload_files(self):
File without changes
File without changes