hirundo 0.1.6__py3-none-any.whl → 0.1.8__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.
hirundo/__init__.py CHANGED
@@ -32,4 +32,4 @@ __all__ = [
32
32
  "StorageIntegration",
33
33
  ]
34
34
 
35
- __version__ = "0.1.6"
35
+ __version__ = "0.1.8"
hirundo/_env.py CHANGED
@@ -1,12 +1,26 @@
1
+ import enum
1
2
  import os
3
+ from pathlib import Path
2
4
 
3
5
  from dotenv import load_dotenv
4
6
 
5
- load_dotenv()
7
+
8
+ class EnvLocation(enum.Enum):
9
+ DOTENV = Path.cwd() / ".env"
10
+ HOME = Path.home() / ".hirundo.conf"
11
+
12
+
13
+ if os.path.exists(EnvLocation.DOTENV.value):
14
+ load_dotenv(EnvLocation.DOTENV.value)
15
+ elif os.path.exists(EnvLocation.HOME.value):
16
+ load_dotenv(EnvLocation.HOME.value)
6
17
 
7
18
  API_HOST = os.getenv("API_HOST", "https://api.hirundo.io")
8
19
  API_KEY = os.getenv("API_KEY")
9
- if not API_KEY:
10
- raise ValueError(
11
- "API_KEY is not set. Please run `hirundo setup` to set the API key"
12
- )
20
+
21
+
22
+ def check_api_key():
23
+ if not API_KEY:
24
+ raise ValueError(
25
+ "API_KEY is not set. Please run `hirundo setup` to set the API key"
26
+ )
hirundo/_headers.py CHANGED
@@ -1,9 +1,13 @@
1
- from hirundo._env import API_KEY
1
+ from hirundo._env import API_KEY, check_api_key
2
2
 
3
3
  json_headers = {
4
4
  "Content-Type": "application/json",
5
5
  "Accept": "application/json",
6
6
  }
7
- auth_headers = {
8
- "Authorization": f"Bearer {API_KEY}",
9
- }
7
+
8
+
9
+ def get_auth_headers():
10
+ check_api_key()
11
+ return {
12
+ "Authorization": f"Bearer {API_KEY}",
13
+ }
hirundo/_http.py ADDED
@@ -0,0 +1,14 @@
1
+ from requests import Response
2
+
3
+ import hirundo.logger
4
+
5
+ logger = hirundo.logger.get_logger(__name__)
6
+
7
+
8
+ def raise_for_status_with_reason(response: Response):
9
+ try:
10
+ response.reason = response.json().get("reason", None)
11
+ except Exception as e:
12
+ logger.debug("Failed to parse response as JSON: %s", e)
13
+
14
+ response.raise_for_status()
@@ -1,7 +1,7 @@
1
1
  import asyncio
2
2
  import time
3
+ import typing
3
4
  from collections.abc import AsyncGenerator, Generator
4
- from typing import Union
5
5
 
6
6
  import httpx
7
7
  from httpx_sse import ServerSentEvent, aconnect_sse, connect_sse
@@ -13,7 +13,7 @@ def iter_sse_retrying(
13
13
  client: httpx.Client,
14
14
  method: str,
15
15
  url: str,
16
- headers: Union[dict[str, str], None] = None,
16
+ headers: typing.Optional[dict[str, str]] = None,
17
17
  ) -> Generator[ServerSentEvent, None, None]:
18
18
  if headers is None:
19
19
  headers = {}
hirundo/cli.py CHANGED
@@ -1,11 +1,14 @@
1
+ import os
1
2
  import re
2
3
  import sys
4
+ import typing
5
+ from pathlib import Path
3
6
  from typing import Annotated
4
7
  from urllib.parse import urlparse
5
8
 
6
9
  import typer
7
10
 
8
- from hirundo._env import API_HOST
11
+ from hirundo._env import API_HOST, EnvLocation
9
12
 
10
13
  docs = "sphinx" in sys.modules
11
14
  hirundo_epilog = (
@@ -14,12 +17,18 @@ hirundo_epilog = (
14
17
  else "Made with ❤️ by Hirundo. Visit https://www.hirundo.io for more information."
15
18
  )
16
19
 
20
+
17
21
  app = typer.Typer(
18
- name="hirundo", no_args_is_help=True, rich_markup_mode="rich", epilog=hirundo_epilog
22
+ name="hirundo",
23
+ no_args_is_help=True,
24
+ rich_markup_mode="rich",
25
+ epilog=hirundo_epilog,
19
26
  )
20
27
 
21
28
 
22
- def upsert_env(var_name: str, var_value: str):
29
+ def _upsert_env(
30
+ dotenv_filepath: typing.Union[str, Path], var_name: str, var_value: str
31
+ ):
23
32
  """
24
33
  Change an environment variable in the .env file.
25
34
  If the variable does not exist, it will be added.
@@ -28,18 +37,30 @@ def upsert_env(var_name: str, var_value: str):
28
37
  var_name: The name of the environment variable to change.
29
38
  var_value: The new value of the environment variable.
30
39
  """
31
- dotenv = "./.env"
32
40
  regex = re.compile(rf"^{var_name}=.*$")
33
- with open(dotenv) as f:
34
- lines = f.readlines()
41
+ lines = []
42
+ if os.path.exists(dotenv_filepath):
43
+ with open(dotenv_filepath) as f:
44
+ lines = f.readlines()
35
45
 
36
- with open(dotenv, "w") as f:
46
+ with open(dotenv_filepath, "w") as f:
37
47
  f.writelines(line for line in lines if not regex.search(line) and line != "\n")
38
48
 
39
- with open(dotenv, "a") as f:
49
+ with open(dotenv_filepath, "a") as f:
40
50
  f.writelines(f"\n{var_name}={var_value}")
41
51
 
42
52
 
53
+ def upsert_env(var_name: str, var_value: str):
54
+ if os.path.exists(EnvLocation.DOTENV.value):
55
+ # If a `.env` file exists, re-use it
56
+ _upsert_env(EnvLocation.DOTENV.value, var_name, var_value)
57
+ return EnvLocation.DOTENV.name
58
+ else:
59
+ # Create a `.hirundo.conf` file with environment variables in the home directory
60
+ _upsert_env(EnvLocation.HOME.value, var_name, var_value)
61
+ return EnvLocation.HOME.name
62
+
63
+
43
64
  def fix_api_host(api_host: str):
44
65
  if not api_host.startswith("http") and not api_host.startswith("https"):
45
66
  api_host = f"https://{api_host}"
@@ -68,8 +89,15 @@ def setup_api_key(
68
89
  Setup the API key for the Hirundo client library.
69
90
  Values are saved to a .env file in the current directory for use by the library in requests.
70
91
  """
71
- upsert_env("API_KEY", api_key)
72
- print("API key saved to .env for future use. Please do not share the .env file")
92
+ saved_to = upsert_env("API_KEY", api_key)
93
+ if saved_to == EnvLocation.HOME.name:
94
+ print(
95
+ "API key saved to ~/.hirundo.conf for future use. Please do not share the ~/.hirundo.conf file since it contains your secret API key."
96
+ )
97
+ elif saved_to == EnvLocation.DOTENV.name:
98
+ print(
99
+ "API key saved to local .env file for future use. Please do not share the .env file since it contains your secret API key."
100
+ )
73
101
 
74
102
 
75
103
  @app.command("change-remote", epilog=hirundo_epilog)
@@ -90,8 +118,13 @@ def change_api_remote(
90
118
  """
91
119
  api_host = fix_api_host(api_host)
92
120
 
93
- upsert_env("API_HOST", api_host)
94
- print("API host saved to .env for future use. Please do not share this file")
121
+ saved_to = upsert_env("API_HOST", api_host)
122
+ if saved_to == EnvLocation.HOME.name:
123
+ print(
124
+ "API host saved to ~/.hirundo.conf for future use. Please do not share the ~/.hirundo.conf file"
125
+ )
126
+ elif saved_to == EnvLocation.DOTENV.name:
127
+ print("API host saved to .env for future use. Please do not share this file")
95
128
 
96
129
 
97
130
  @app.command("setup", epilog=hirundo_epilog)
@@ -119,11 +152,41 @@ def setup(
119
152
  Setup the Hirundo client library.
120
153
  """
121
154
  api_host = fix_api_host(api_host)
122
- upsert_env("API_HOST", api_host)
123
- upsert_env("API_KEY", api_key)
124
- print(
125
- "API host and API key saved to .env for future use. Please do not share this file"
126
- )
155
+ api_host_saved_to = upsert_env("API_HOST", api_host)
156
+ api_key_saved_to = upsert_env("API_KEY", api_key)
157
+ if api_host_saved_to != api_key_saved_to:
158
+ print(
159
+ "API host and API key saved to different locations. This should not happen. Please report this issue."
160
+ )
161
+ if (
162
+ api_host_saved_to == EnvLocation.HOME.name
163
+ and api_key_saved_to == EnvLocation.DOTENV.name
164
+ ):
165
+ print(
166
+ "API host saved to ~/.hirundo.conf for future use. Please do not share the ~/.hirundo.conf file"
167
+ )
168
+ print(
169
+ "API key saved to local .env file for future use. Please do not share the .env file since it contains your secret API key."
170
+ )
171
+ elif (
172
+ api_host_saved_to == EnvLocation.DOTENV.name
173
+ and api_key_saved_to == EnvLocation.HOME.name
174
+ ):
175
+ print(
176
+ "API host saved to .env for future use. Please do not share this file"
177
+ )
178
+ print(
179
+ "API key saved to ~/.hirundo.conf for future use. Please do not share the ~/.hirundo.conf file since it contains your secret API key."
180
+ )
181
+ return
182
+ if api_host_saved_to == EnvLocation.HOME.name:
183
+ print(
184
+ "API host and API key saved to ~/.hirundo.conf for future use. Please do not share the ~/.hirundo.conf file since it contains your secret API key."
185
+ )
186
+ elif api_host_saved_to == EnvLocation.DOTENV.name:
187
+ print(
188
+ "API host and API key saved to .env for future use. Please do not share this file since it contains your secret API key."
189
+ )
127
190
 
128
191
 
129
192
  typer_click_object = typer.main.get_command(app)