hirundo 0.1.8__py3-none-any.whl → 0.1.16__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 +28 -13
- hirundo/_constraints.py +34 -2
- hirundo/_dataframe.py +43 -0
- hirundo/_env.py +2 -2
- hirundo/_headers.py +18 -2
- hirundo/_http.py +7 -2
- hirundo/_iter_sse_retrying.py +61 -17
- hirundo/_timeouts.py +1 -0
- hirundo/cli.py +52 -0
- hirundo/dataset_enum.py +23 -0
- hirundo/dataset_optimization.py +427 -164
- hirundo/dataset_optimization_results.py +42 -0
- hirundo/git.py +93 -35
- hirundo/storage.py +236 -68
- hirundo/unzip.py +247 -0
- {hirundo-0.1.8.dist-info → hirundo-0.1.16.dist-info}/METADATA +84 -44
- hirundo-0.1.16.dist-info/RECORD +23 -0
- {hirundo-0.1.8.dist-info → hirundo-0.1.16.dist-info}/WHEEL +1 -1
- hirundo/enum.py +0 -20
- hirundo-0.1.8.dist-info/RECORD +0 -20
- {hirundo-0.1.8.dist-info → hirundo-0.1.16.dist-info}/entry_points.txt +0 -0
- {hirundo-0.1.8.dist-info → hirundo-0.1.16.dist-info/licenses}/LICENSE +0 -0
- {hirundo-0.1.8.dist-info → hirundo-0.1.16.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import typing
|
|
2
|
+
from pathlib import Path
|
|
3
|
+
|
|
4
|
+
from pydantic import BaseModel
|
|
5
|
+
from typing_extensions import TypeAliasType
|
|
6
|
+
|
|
7
|
+
from hirundo._dataframe import has_pandas, has_polars
|
|
8
|
+
|
|
9
|
+
DataFrameType = TypeAliasType("DataFrameType", None)
|
|
10
|
+
|
|
11
|
+
if has_pandas:
|
|
12
|
+
from hirundo._dataframe import pd
|
|
13
|
+
|
|
14
|
+
DataFrameType = TypeAliasType("DataFrameType", typing.Union[pd.DataFrame, None])
|
|
15
|
+
if has_polars:
|
|
16
|
+
from hirundo._dataframe import pl
|
|
17
|
+
|
|
18
|
+
DataFrameType = TypeAliasType("DataFrameType", typing.Union[pl.DataFrame, None])
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
T = typing.TypeVar("T")
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DatasetOptimizationResults(BaseModel, typing.Generic[T]):
|
|
25
|
+
model_config = {"arbitrary_types_allowed": True}
|
|
26
|
+
|
|
27
|
+
cached_zip_path: Path
|
|
28
|
+
"""
|
|
29
|
+
The path to the cached zip file of the results
|
|
30
|
+
"""
|
|
31
|
+
suspects: T
|
|
32
|
+
"""
|
|
33
|
+
A polars/pandas DataFrame containing the results of the optimization run
|
|
34
|
+
"""
|
|
35
|
+
object_suspects: typing.Optional[T]
|
|
36
|
+
"""
|
|
37
|
+
A polars/pandas DataFrame containing the object-level results of the optimization run
|
|
38
|
+
"""
|
|
39
|
+
warnings_and_errors: T
|
|
40
|
+
"""
|
|
41
|
+
A polars/pandas DataFrame containing the warnings and errors of the optimization run
|
|
42
|
+
"""
|
hirundo/git.py
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
|
+
import datetime
|
|
1
2
|
import re
|
|
2
3
|
import typing
|
|
3
|
-
from typing import Annotated
|
|
4
4
|
|
|
5
5
|
import pydantic
|
|
6
6
|
import requests
|
|
7
7
|
from pydantic import BaseModel, field_validator
|
|
8
8
|
from pydantic_core import Url
|
|
9
9
|
|
|
10
|
+
from hirundo._constraints import RepoUrl
|
|
10
11
|
from hirundo._env import API_HOST
|
|
11
|
-
from hirundo._headers import
|
|
12
|
+
from hirundo._headers import get_headers
|
|
12
13
|
from hirundo._http import raise_for_status_with_reason
|
|
13
14
|
from hirundo._timeouts import MODIFY_TIMEOUT, READ_TIMEOUT
|
|
14
15
|
from hirundo.logger import get_logger
|
|
@@ -16,7 +17,7 @@ from hirundo.logger import get_logger
|
|
|
16
17
|
logger = get_logger(__name__)
|
|
17
18
|
|
|
18
19
|
|
|
19
|
-
class
|
|
20
|
+
class GitPlainAuth(BaseModel):
|
|
20
21
|
username: str
|
|
21
22
|
"""
|
|
22
23
|
The username for the Git repository
|
|
@@ -27,7 +28,7 @@ class GitPlainAuthBase(BaseModel):
|
|
|
27
28
|
"""
|
|
28
29
|
|
|
29
30
|
|
|
30
|
-
class
|
|
31
|
+
class GitSSHAuth(BaseModel):
|
|
31
32
|
ssh_key: str
|
|
32
33
|
"""
|
|
33
34
|
The SSH key for the Git repository
|
|
@@ -48,10 +49,10 @@ class GitRepo(BaseModel):
|
|
|
48
49
|
"""
|
|
49
50
|
A name to identify the Git repository in the Hirundo system.
|
|
50
51
|
"""
|
|
51
|
-
repository_url:
|
|
52
|
+
repository_url: typing.Union[str, RepoUrl]
|
|
52
53
|
"""
|
|
53
54
|
The URL of the Git repository, it should start with `ssh://` or `https://` or be in the form `user@host:path`.
|
|
54
|
-
If it is in the form `user@host:path`, it will be rewritten to `ssh://user@host
|
|
55
|
+
If it is in the form `user@host:path`, it will be rewritten to `ssh://user@host/path`.
|
|
55
56
|
"""
|
|
56
57
|
organization_id: typing.Optional[int] = None
|
|
57
58
|
"""
|
|
@@ -59,14 +60,14 @@ class GitRepo(BaseModel):
|
|
|
59
60
|
If not provided, it will be assigned to your default organization.
|
|
60
61
|
"""
|
|
61
62
|
|
|
62
|
-
plain_auth: typing.Optional[
|
|
63
|
+
plain_auth: typing.Optional[GitPlainAuth] = pydantic.Field(
|
|
63
64
|
default=None, examples=[None, {"username": "ben", "password": "password"}]
|
|
64
65
|
)
|
|
65
66
|
"""
|
|
66
67
|
The plain authentication details for the Git repository.
|
|
67
68
|
Use this if using a special user with a username and password for authentication.
|
|
68
69
|
"""
|
|
69
|
-
ssh_auth: typing.Optional[
|
|
70
|
+
ssh_auth: typing.Optional[GitSSHAuth] = pydantic.Field(
|
|
70
71
|
default=None,
|
|
71
72
|
examples=[
|
|
72
73
|
{
|
|
@@ -84,34 +85,46 @@ class GitRepo(BaseModel):
|
|
|
84
85
|
|
|
85
86
|
@field_validator("repository_url", mode="before", check_fields=True)
|
|
86
87
|
@classmethod
|
|
87
|
-
def check_valid_repository_url(cls, repository_url: str):
|
|
88
|
-
# Check if the URL
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
88
|
+
def check_valid_repository_url(cls, repository_url: typing.Union[str, RepoUrl]):
|
|
89
|
+
# Check if the URL has the `@` and `:` pattern with a non-numeric section before the next slash
|
|
90
|
+
match = re.match("([^@]+@[^:]+):([^0-9/][^/]*)/(.+)", str(repository_url))
|
|
91
|
+
if match:
|
|
92
|
+
user_host = match.group(1)
|
|
93
|
+
path = match.group(2) + "/" + match.group(3)
|
|
94
|
+
rewritten_url = Url(f"ssh://{user_host}/{path}")
|
|
95
|
+
# Check if the URL already has a protocol
|
|
96
|
+
url_scheme = rewritten_url.scheme
|
|
97
|
+
logger.info(
|
|
98
|
+
"Modified Git repo to replace %s@%s:%s/%s with %s",
|
|
99
|
+
url_scheme,
|
|
100
|
+
match.group(1),
|
|
101
|
+
match.group(2),
|
|
102
|
+
match.group(3),
|
|
103
|
+
rewritten_url,
|
|
104
|
+
)
|
|
105
|
+
return rewritten_url
|
|
106
|
+
if not str(repository_url).startswith("ssh://") and not str(
|
|
107
|
+
repository_url
|
|
108
|
+
).startswith("https://"):
|
|
101
109
|
raise ValueError("Repository URL must start with 'ssh://' or 'https://'")
|
|
110
|
+
if not isinstance(repository_url, Url):
|
|
111
|
+
repository_url = Url(repository_url)
|
|
102
112
|
return repository_url
|
|
103
113
|
|
|
104
|
-
def create(self):
|
|
114
|
+
def create(self, replace_if_exists: bool = False) -> int:
|
|
105
115
|
"""
|
|
106
116
|
Create a Git repository in the Hirundo system.
|
|
117
|
+
|
|
118
|
+
Args:
|
|
119
|
+
replace_if_exists: If a Git repository with the same name already exists, replace it.
|
|
107
120
|
"""
|
|
108
121
|
git_repo = requests.post(
|
|
109
122
|
f"{API_HOST}/git-repo/",
|
|
110
|
-
json=
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
**get_auth_headers(),
|
|
123
|
+
json={
|
|
124
|
+
**self.model_dump(mode="json"),
|
|
125
|
+
"replace_if_exists": replace_if_exists,
|
|
114
126
|
},
|
|
127
|
+
headers=get_headers(),
|
|
115
128
|
timeout=MODIFY_TIMEOUT,
|
|
116
129
|
)
|
|
117
130
|
raise_for_status_with_reason(git_repo)
|
|
@@ -120,19 +133,57 @@ class GitRepo(BaseModel):
|
|
|
120
133
|
return git_repo_id
|
|
121
134
|
|
|
122
135
|
@staticmethod
|
|
123
|
-
def
|
|
136
|
+
def get_by_id(git_repo_id: int) -> "GitRepoOut":
|
|
137
|
+
"""
|
|
138
|
+
Retrieves a `GitRepo` instance from the server by its ID
|
|
139
|
+
|
|
140
|
+
Args:
|
|
141
|
+
git_repo_id: The ID of the `GitRepo` to retrieve
|
|
142
|
+
"""
|
|
143
|
+
git_repo = requests.get(
|
|
144
|
+
f"{API_HOST}/git-repo/{git_repo_id}",
|
|
145
|
+
headers=get_headers(),
|
|
146
|
+
timeout=READ_TIMEOUT,
|
|
147
|
+
)
|
|
148
|
+
raise_for_status_with_reason(git_repo)
|
|
149
|
+
return GitRepoOut(**git_repo.json())
|
|
150
|
+
|
|
151
|
+
@staticmethod
|
|
152
|
+
def get_by_name(
|
|
153
|
+
name: str,
|
|
154
|
+
) -> "GitRepoOut":
|
|
155
|
+
"""
|
|
156
|
+
Retrieves a `GitRepo` instance from the server by its name
|
|
157
|
+
|
|
158
|
+
Args:
|
|
159
|
+
name: The name of the `GitRepo` to retrieve
|
|
160
|
+
"""
|
|
161
|
+
git_repo = requests.get(
|
|
162
|
+
f"{API_HOST}/git-repo/by-name/{name}",
|
|
163
|
+
headers=get_headers(),
|
|
164
|
+
timeout=READ_TIMEOUT,
|
|
165
|
+
)
|
|
166
|
+
raise_for_status_with_reason(git_repo)
|
|
167
|
+
return GitRepoOut(**git_repo.json())
|
|
168
|
+
|
|
169
|
+
@staticmethod
|
|
170
|
+
def list() -> list["GitRepoOut"]:
|
|
124
171
|
"""
|
|
125
172
|
List all Git repositories in the Hirundo system.
|
|
126
173
|
"""
|
|
127
174
|
git_repos = requests.get(
|
|
128
175
|
f"{API_HOST}/git-repo/",
|
|
129
|
-
headers=
|
|
130
|
-
**get_auth_headers(),
|
|
131
|
-
},
|
|
176
|
+
headers=get_headers(),
|
|
132
177
|
timeout=READ_TIMEOUT,
|
|
133
178
|
)
|
|
134
179
|
raise_for_status_with_reason(git_repos)
|
|
135
|
-
|
|
180
|
+
git_repo_json = git_repos.json()
|
|
181
|
+
return [
|
|
182
|
+
GitRepoOut(
|
|
183
|
+
**git_repo,
|
|
184
|
+
)
|
|
185
|
+
for git_repo in git_repo_json
|
|
186
|
+
]
|
|
136
187
|
|
|
137
188
|
@staticmethod
|
|
138
189
|
def delete_by_id(git_repo_id: int):
|
|
@@ -144,9 +195,7 @@ class GitRepo(BaseModel):
|
|
|
144
195
|
"""
|
|
145
196
|
git_repo = requests.delete(
|
|
146
197
|
f"{API_HOST}/git-repo/{git_repo_id}",
|
|
147
|
-
headers=
|
|
148
|
-
**get_auth_headers(),
|
|
149
|
-
},
|
|
198
|
+
headers=get_headers(),
|
|
150
199
|
timeout=MODIFY_TIMEOUT,
|
|
151
200
|
)
|
|
152
201
|
raise_for_status_with_reason(git_repo)
|
|
@@ -158,3 +207,12 @@ class GitRepo(BaseModel):
|
|
|
158
207
|
if not self.id:
|
|
159
208
|
raise ValueError("No GitRepo has been created")
|
|
160
209
|
GitRepo.delete_by_id(self.id)
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
class GitRepoOut(BaseModel):
|
|
213
|
+
id: int
|
|
214
|
+
name: str
|
|
215
|
+
repository_url: RepoUrl
|
|
216
|
+
|
|
217
|
+
created_at: datetime.datetime
|
|
218
|
+
updated_at: datetime.datetime
|