hh-applicant-tool 0.1.9__tar.gz → 0.2.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.
Potentially problematic release.
This version of hh-applicant-tool might be problematic. Click here for more details.
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/PKG-INFO +13 -12
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/README.md +12 -11
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/api/client.py +14 -8
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/api/errors.py +7 -3
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/constants.py +2 -2
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/apply_similar.py +5 -4
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/call_api.py +11 -5
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/clear_negotiations.py +2 -3
- hh_applicant_tool-0.2.1/hh_applicant_tool/operations/refresh_token.py +42 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/update_resumes.py +2 -2
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/whoami.py +2 -2
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/utils.py +4 -9
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/pyproject.toml +1 -1
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/__init__.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/__main__.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/api/__init__.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/color_log.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/main.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/__init__.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/add_handler.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/authorize.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/list_resumes.py +0 -0
- {hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/types.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: hh-applicant-tool
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary:
|
|
5
5
|
Author: Senior YAML Developer
|
|
6
6
|
Author-email: yamldeveloper@proton.me
|
|
@@ -110,16 +110,17 @@ https://hh.ru/employer/1918903
|
|
|
110
110
|
- `-v` используется для вывода отладочной информации. Два таких флага, например, выводят запросы к **API**.
|
|
111
111
|
- `-c <path>` можно создать путь до конфига. С помощью этого флага можно одновременно использовать несколько профилей.
|
|
112
112
|
|
|
113
|
-
| Операция | Описание
|
|
114
|
-
| ---------------------- |
|
|
115
|
-
| **add-handler** | Добавляет обработчик протокола `hhandroid`
|
|
116
|
-
| **authorize** | Открывает сайт hh.ru для авторизации и перехватывает перенаправление на `hhadnroid://oauthresponse`
|
|
117
|
-
| **whoami** | Выводит информацию об авторизованном пользователе
|
|
118
|
-
| **list-resumes** | Список резюме
|
|
119
|
-
| **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату».
|
|
120
|
-
| **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день
|
|
121
|
-
| **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят
|
|
122
|
-
| **call-api** |
|
|
113
|
+
| Операция | Описание |
|
|
114
|
+
| ---------------------- | --------------------------------------------------------------------------------------------------- |
|
|
115
|
+
| **add-handler** | Добавляет обработчик протокола `hhandroid` |
|
|
116
|
+
| **authorize** | Открывает сайт hh.ru для авторизации и перехватывает перенаправление на `hhadnroid://oauthresponse` |
|
|
117
|
+
| **whoami** | Выводит информацию об авторизованном пользователе |
|
|
118
|
+
| **list-resumes** | Список резюме |
|
|
119
|
+
| **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату». |
|
|
120
|
+
| **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день |
|
|
121
|
+
| **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят |
|
|
122
|
+
| **call-api** | Вызов произвольного метода API с вводом результата. |
|
|
123
|
+
| **refresh-token** | Обновляет access_token. |
|
|
123
124
|
|
|
124
125
|
Для начала нужно добавить обработчик протокола `hhandroid`, который используется Android-приложением для усложнения жизни честным автоматизаторам:
|
|
125
126
|
|
|
@@ -223,7 +224,7 @@ datetime.datetime(2023, 3, 23, 6, 36, 15, 596290)
|
|
|
223
224
|
>>>
|
|
224
225
|
```
|
|
225
226
|
|
|
226
|
-
После нужно
|
|
227
|
+
После нужно вызвать `refresh-token`.
|
|
227
228
|
|
|
228
229
|

|
|
229
230
|
|
|
@@ -96,16 +96,17 @@ https://hh.ru/employer/1918903
|
|
|
96
96
|
- `-v` используется для вывода отладочной информации. Два таких флага, например, выводят запросы к **API**.
|
|
97
97
|
- `-c <path>` можно создать путь до конфига. С помощью этого флага можно одновременно использовать несколько профилей.
|
|
98
98
|
|
|
99
|
-
| Операция | Описание
|
|
100
|
-
| ---------------------- |
|
|
101
|
-
| **add-handler** | Добавляет обработчик протокола `hhandroid`
|
|
102
|
-
| **authorize** | Открывает сайт hh.ru для авторизации и перехватывает перенаправление на `hhadnroid://oauthresponse`
|
|
103
|
-
| **whoami** | Выводит информацию об авторизованном пользователе
|
|
104
|
-
| **list-resumes** | Список резюме
|
|
105
|
-
| **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату».
|
|
106
|
-
| **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день
|
|
107
|
-
| **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят
|
|
108
|
-
| **call-api** |
|
|
99
|
+
| Операция | Описание |
|
|
100
|
+
| ---------------------- | --------------------------------------------------------------------------------------------------- |
|
|
101
|
+
| **add-handler** | Добавляет обработчик протокола `hhandroid` |
|
|
102
|
+
| **authorize** | Открывает сайт hh.ru для авторизации и перехватывает перенаправление на `hhadnroid://oauthresponse` |
|
|
103
|
+
| **whoami** | Выводит информацию об авторизованном пользователе |
|
|
104
|
+
| **list-resumes** | Список резюме |
|
|
105
|
+
| **update-resumes** | Обновить все резюме. Аналогично нажатию кнопки «Обновить дату». |
|
|
106
|
+
| **apply-similar** | Откликнуться на все подходящие вакансии. Лимит = 200 в день |
|
|
107
|
+
| **clear-negotiations** | Удаляет отказы и отменяет заявки, которые долго висят |
|
|
108
|
+
| **call-api** | Вызов произвольного метода API с вводом результата. |
|
|
109
|
+
| **refresh-token** | Обновляет access_token. |
|
|
109
110
|
|
|
110
111
|
Для начала нужно добавить обработчик протокола `hhandroid`, который используется Android-приложением для усложнения жизни честным автоматизаторам:
|
|
111
112
|
|
|
@@ -209,7 +210,7 @@ datetime.datetime(2023, 3, 23, 6, 36, 15, 596290)
|
|
|
209
210
|
>>>
|
|
210
211
|
```
|
|
211
212
|
|
|
212
|
-
После нужно
|
|
213
|
+
После нужно вызвать `refresh-token`.
|
|
213
214
|
|
|
214
215
|

|
|
215
216
|
|
|
@@ -14,8 +14,8 @@ import requests
|
|
|
14
14
|
from requests import Response, Session
|
|
15
15
|
|
|
16
16
|
from ..constants import (
|
|
17
|
-
|
|
18
|
-
|
|
17
|
+
ANDROID_CLIENT_ID,
|
|
18
|
+
ANDROID_CLIENT_SECRET,
|
|
19
19
|
DEFAULT_USER_AGENT,
|
|
20
20
|
)
|
|
21
21
|
from ..types import AccessToken
|
|
@@ -99,11 +99,12 @@ class BaseClient:
|
|
|
99
99
|
"%d %-6s %s",
|
|
100
100
|
response.status_code,
|
|
101
101
|
method,
|
|
102
|
-
url
|
|
102
|
+
url
|
|
103
|
+
+ (
|
|
103
104
|
"?" + urlencode(params)
|
|
104
105
|
if not has_body and params
|
|
105
106
|
else ""
|
|
106
|
-
)
|
|
107
|
+
),
|
|
107
108
|
)
|
|
108
109
|
self.previous_request_time = time.monotonic()
|
|
109
110
|
self.raise_for_status(response, rv)
|
|
@@ -143,8 +144,8 @@ class BaseClient:
|
|
|
143
144
|
|
|
144
145
|
@dataclass
|
|
145
146
|
class OAuthClient(BaseClient):
|
|
146
|
-
client_id: str =
|
|
147
|
-
client_secret: str =
|
|
147
|
+
client_id: str = ANDROID_CLIENT_ID
|
|
148
|
+
client_secret: str = ANDROID_CLIENT_SECRET
|
|
148
149
|
_: dataclasses.KW_ONLY
|
|
149
150
|
base_url: str = "https://hh.ru/oauth"
|
|
150
151
|
state: str = ""
|
|
@@ -181,7 +182,8 @@ class OAuthClient(BaseClient):
|
|
|
181
182
|
|
|
182
183
|
@dataclass
|
|
183
184
|
class ApiClient(BaseClient):
|
|
184
|
-
|
|
185
|
+
# Например, для просмотра информации о компании токен не нужен
|
|
186
|
+
access_token: str | None = None
|
|
185
187
|
refresh_token: str | None = None
|
|
186
188
|
_: dataclasses.KW_ONLY
|
|
187
189
|
base_url: str = "https://api.hh.ru/"
|
|
@@ -196,7 +198,11 @@ class ApiClient(BaseClient):
|
|
|
196
198
|
def additional_headers(
|
|
197
199
|
self,
|
|
198
200
|
) -> dict[str, str]:
|
|
199
|
-
return
|
|
201
|
+
return (
|
|
202
|
+
{"Authorization": f"Bearer {self.access_token}"}
|
|
203
|
+
if self.access_token
|
|
204
|
+
else {}
|
|
205
|
+
)
|
|
200
206
|
|
|
201
207
|
# def refresh_access(self) -> AccessToken:
|
|
202
208
|
# tok = self.oauth_client.refresh_access(self.refresh_token)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
#from copy import deepcopy
|
|
1
|
+
# from copy import deepcopy
|
|
2
2
|
from typing import Any
|
|
3
3
|
|
|
4
|
-
from requests import
|
|
4
|
+
from requests import Request, Response
|
|
5
5
|
from requests.adapters import CaseInsensitiveDict
|
|
6
6
|
|
|
7
7
|
__all__ = (
|
|
@@ -20,7 +20,11 @@ class ApiError(Exception):
|
|
|
20
20
|
def __init__(self, response: Response, data: dict[str, Any]) -> None:
|
|
21
21
|
self._response = response
|
|
22
22
|
self._raw = data
|
|
23
|
-
|
|
23
|
+
|
|
24
|
+
@property
|
|
25
|
+
def data(self) -> dict:
|
|
26
|
+
return self._raw
|
|
27
|
+
|
|
24
28
|
@property
|
|
25
29
|
def request(self) -> Request:
|
|
26
30
|
return self._response.request
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
DEFAULT_USER_AGENT = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36"
|
|
2
|
-
|
|
2
|
+
ANDROID_CLIENT_ID = (
|
|
3
3
|
"HIOMIAS39CA9DICTA7JIO64LQKQJF5AGIK74G9ITJKLNEDAOH5FHS5G1JI7FOEGD"
|
|
4
4
|
)
|
|
5
|
-
|
|
5
|
+
ANDROID_CLIENT_SECRET = (
|
|
6
6
|
"V9M870DE342BGHFRUJ5FTCGCUA1482AN0DI8C5TFI9ULMA89H10N60NOP8I4JMVS"
|
|
7
7
|
)
|
|
8
8
|
HHANDROID_SOCKET_PATH = "/tmp/hhandroid.sock"
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/apply_similar.py
RENAMED
|
@@ -8,7 +8,7 @@ from ..api import ApiClient, ApiError, BadRequest
|
|
|
8
8
|
from ..main import BaseOperation
|
|
9
9
|
from ..main import Namespace as BaseNamespace
|
|
10
10
|
from ..types import ApiListResponse, VacancyItem
|
|
11
|
-
from ..utils import truncate_string
|
|
11
|
+
from ..utils import print_err, truncate_string
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger(__package__)
|
|
14
14
|
|
|
@@ -74,8 +74,9 @@ class Operation(BaseOperation):
|
|
|
74
74
|
page=page,
|
|
75
75
|
per_page=per_page,
|
|
76
76
|
# Мне кажется, что так поисковая выдача можно забиться неадекватами, которые по полгода кого-то ищут
|
|
77
|
-
#
|
|
78
|
-
order_by="publication_time",
|
|
77
|
+
# Но так откликается на что-то уж совсем нерелевантное
|
|
78
|
+
# order_by="publication_time",
|
|
79
|
+
order_by="relevance",
|
|
79
80
|
)
|
|
80
81
|
rv.extend(res["items"])
|
|
81
82
|
if page >= res["pages"] - 1:
|
|
@@ -117,7 +118,7 @@ class Operation(BaseOperation):
|
|
|
117
118
|
")",
|
|
118
119
|
)
|
|
119
120
|
except ApiError as ex:
|
|
120
|
-
|
|
121
|
+
print_err("❗ Ошибка:", ex)
|
|
121
122
|
if isinstance(ex, BadRequest) and ex.limit_exceeded:
|
|
122
123
|
break
|
|
123
124
|
print("📝 Отклики на вакансии разосланы!")
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/call_api.py
RENAMED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Этот модуль можно использовать как образец для других
|
|
2
2
|
import argparse
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
5
|
+
import sys
|
|
4
6
|
|
|
5
|
-
from ..api import ApiClient
|
|
7
|
+
from ..api import ApiClient, ApiError
|
|
6
8
|
from ..main import BaseOperation
|
|
7
9
|
from ..main import Namespace as BaseNamespace
|
|
8
|
-
from ..utils import dumps
|
|
9
10
|
|
|
10
11
|
logger = logging.getLogger(__package__)
|
|
11
12
|
|
|
@@ -14,6 +15,7 @@ class Namespace(BaseNamespace):
|
|
|
14
15
|
method: str
|
|
15
16
|
endpoint: str
|
|
16
17
|
params: list[str]
|
|
18
|
+
pretty_print: bool
|
|
17
19
|
|
|
18
20
|
|
|
19
21
|
class Operation(BaseOperation):
|
|
@@ -24,7 +26,7 @@ class Operation(BaseOperation):
|
|
|
24
26
|
parser.add_argument(
|
|
25
27
|
"param",
|
|
26
28
|
nargs="*",
|
|
27
|
-
help="PARAM=VALUE
|
|
29
|
+
help="PARAM=VALUE",
|
|
28
30
|
default=[],
|
|
29
31
|
)
|
|
30
32
|
parser.add_argument(
|
|
@@ -38,5 +40,9 @@ class Operation(BaseOperation):
|
|
|
38
40
|
user_agent=args.config["user_agent"],
|
|
39
41
|
)
|
|
40
42
|
params = dict(x.split("=", 1) for x in args.param)
|
|
41
|
-
|
|
42
|
-
|
|
43
|
+
try:
|
|
44
|
+
result = api.request(args.method, args.endpoint, params=params)
|
|
45
|
+
print(json.dumps(result, ensure_ascii=True))
|
|
46
|
+
except ApiError as ex:
|
|
47
|
+
json.dump(ex.data, sys.stderr, ensure_ascii=True)
|
|
48
|
+
return 1
|
|
@@ -8,7 +8,7 @@ from ..constants import INVALID_ISO8601_FORMAT
|
|
|
8
8
|
from ..main import BaseOperation
|
|
9
9
|
from ..main import Namespace as BaseNamespace
|
|
10
10
|
from ..types import ApiListResponse
|
|
11
|
-
from ..utils import truncate_string
|
|
11
|
+
from ..utils import print_err, truncate_string
|
|
12
12
|
|
|
13
13
|
logger = logging.getLogger(__package__)
|
|
14
14
|
|
|
@@ -100,6 +100,5 @@ class Operation(BaseOperation):
|
|
|
100
100
|
")",
|
|
101
101
|
)
|
|
102
102
|
except ClientError as ex:
|
|
103
|
-
|
|
104
|
-
|
|
103
|
+
print_err("❗ Ошибка:", ex)
|
|
105
104
|
print("🧹 Чистка заявок завершена!")
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Этот модуль можно использовать как образец для других
|
|
2
|
+
import argparse
|
|
3
|
+
import logging
|
|
4
|
+
|
|
5
|
+
from ..api import ApiError, OAuthClient
|
|
6
|
+
from ..main import BaseOperation
|
|
7
|
+
from ..main import Namespace as BaseNamespace
|
|
8
|
+
from ..utils import print_err
|
|
9
|
+
|
|
10
|
+
logger = logging.getLogger(__package__)
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class Namespace(BaseNamespace):
|
|
14
|
+
pass
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class Operation(BaseOperation):
|
|
18
|
+
"""Получает новый access_token."""
|
|
19
|
+
|
|
20
|
+
def setup_parser(self, parser: argparse.ArgumentParser) -> None:
|
|
21
|
+
pass
|
|
22
|
+
|
|
23
|
+
def run(self, args: Namespace) -> None:
|
|
24
|
+
if (
|
|
25
|
+
not args.config["token"]
|
|
26
|
+
or not args.config["token"]["refresh_token"]
|
|
27
|
+
):
|
|
28
|
+
print_err("❗ Необходим refresh_token!")
|
|
29
|
+
return 1
|
|
30
|
+
try:
|
|
31
|
+
oauth = OAuthClient(
|
|
32
|
+
user_agent=(
|
|
33
|
+
args.config["oauth_user_agent"]
|
|
34
|
+
or args.config["user_agent"]
|
|
35
|
+
),
|
|
36
|
+
)
|
|
37
|
+
token = oauth.refresh_access(args.config["token"]["refresh_token"])
|
|
38
|
+
args.config.save(token=token)
|
|
39
|
+
print("✅ Токен обновлен!")
|
|
40
|
+
except ApiError as ex:
|
|
41
|
+
print_err("❗ Ошибка:", ex)
|
|
42
|
+
return 1
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/update_resumes.py
RENAMED
|
@@ -6,7 +6,7 @@ from ..api import ApiClient, ApiError
|
|
|
6
6
|
from ..main import BaseOperation
|
|
7
7
|
from ..main import Namespace as BaseNamespace
|
|
8
8
|
from ..types import ApiListResponse
|
|
9
|
-
from ..utils import truncate_string
|
|
9
|
+
from ..utils import print_err, truncate_string
|
|
10
10
|
|
|
11
11
|
logger = logging.getLogger(__package__)
|
|
12
12
|
|
|
@@ -34,4 +34,4 @@ class Operation(BaseOperation):
|
|
|
34
34
|
assert res == {}
|
|
35
35
|
print("✅ Обновлено", truncate_string(resume["title"]))
|
|
36
36
|
except ApiError as ex:
|
|
37
|
-
|
|
37
|
+
print_err("❗ Ошибка:", ex)
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
# Этот модуль можно использовать как образец для других
|
|
2
2
|
import argparse
|
|
3
|
+
import json
|
|
3
4
|
import logging
|
|
4
5
|
|
|
5
6
|
from ..api import ApiClient
|
|
6
7
|
from ..main import BaseOperation
|
|
7
8
|
from ..main import Namespace as BaseNamespace
|
|
8
|
-
from ..utils import dumps
|
|
9
9
|
|
|
10
10
|
logger = logging.getLogger(__package__)
|
|
11
11
|
|
|
@@ -27,4 +27,4 @@ class Operation(BaseOperation):
|
|
|
27
27
|
user_agent=args.config["user_agent"],
|
|
28
28
|
)
|
|
29
29
|
result = api.get("/me")
|
|
30
|
-
print(dumps(result))
|
|
30
|
+
print(json.dumps(result, ensure_ascii=True, indent=2, sort_keys=True))
|
|
@@ -9,13 +9,6 @@ from typing import Any
|
|
|
9
9
|
|
|
10
10
|
print_err = partial(print, file=sys.stderr)
|
|
11
11
|
|
|
12
|
-
json_dump_kwargs = dict(
|
|
13
|
-
indent=2, ensure_ascii=False, sort_keys=True, default=str
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
dump = partial(json.dump, **json_dump_kwargs)
|
|
17
|
-
dumps = partial(json.dumps, **json_dump_kwargs)
|
|
18
|
-
|
|
19
12
|
|
|
20
13
|
class AttrDict(dict):
|
|
21
14
|
__getattr__ = dict.get
|
|
@@ -43,8 +36,10 @@ class Config(dict):
|
|
|
43
36
|
self.update(*args, **kwargs)
|
|
44
37
|
self._config_path.parent.mkdir(exist_ok=True, parents=True)
|
|
45
38
|
with self._lock:
|
|
46
|
-
with self._config_path.open("w+") as
|
|
47
|
-
dump(
|
|
39
|
+
with self._config_path.open("w+") as fp:
|
|
40
|
+
json.dump(
|
|
41
|
+
self, fp, ensure_ascii=True, indent=2, sort_keys=True
|
|
42
|
+
)
|
|
48
43
|
|
|
49
44
|
__getitem__ = dict.get
|
|
50
45
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/__init__.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/add_handler.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/authorize.py
RENAMED
|
File without changes
|
{hh_applicant_tool-0.1.9 → hh_applicant_tool-0.2.1}/hh_applicant_tool/operations/list_resumes.py
RENAMED
|
File without changes
|
|
File without changes
|