python-easyverein 0.2.4__tar.gz → 0.2.7__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.
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/PKG-INFO +1 -1
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/__init__.py +1 -1
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/api.py +5 -1
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/client.py +19 -4
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/protocol.py +5 -10
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/types.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/contact_details.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/custom_field.py +10 -6
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/invoice.py +13 -3
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/invoice_item.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/member.py +5 -4
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/mixins/empty_strings_mixin.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/mixins/required_attributes.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/contact_details.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/custom_field.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/invoice.py +9 -1
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/invoice_item.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/member.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/member_custom_field.py +1 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/pyproject.toml +1 -1
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/LICENSE +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/README.md +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/__init__.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/exceptions.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/core/validators.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/__init__.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/base.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/member_custom_field.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/mixins/__init__.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/__init__.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/mixins/__init__.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/mixins/crud.py +0 -0
- {python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/mixins/recycle_bin.py +0 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Main EasyVerein API class
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
import logging
|
|
5
6
|
|
|
6
7
|
from .core.client import EasyvereinClient
|
|
@@ -19,6 +20,7 @@ class EasyvereinAPI:
|
|
|
19
20
|
api_version="v1.7",
|
|
20
21
|
base_url: str = "https://hexa.easyverein.com/api/",
|
|
21
22
|
logger: logging.Logger = None,
|
|
23
|
+
auto_retry=False,
|
|
22
24
|
):
|
|
23
25
|
"""
|
|
24
26
|
Constructor setting API key and logger. Test
|
|
@@ -31,7 +33,9 @@ class EasyvereinAPI:
|
|
|
31
33
|
else:
|
|
32
34
|
self.logger = logging.getLogger("easyverein")
|
|
33
35
|
|
|
34
|
-
self.c = EasyvereinClient(
|
|
36
|
+
self.c = EasyvereinClient(
|
|
37
|
+
api_key, api_version, base_url, self.logger, self, auto_retry
|
|
38
|
+
)
|
|
35
39
|
|
|
36
40
|
# Add methods
|
|
37
41
|
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Main EasyVerein API class
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
import logging
|
|
7
8
|
from pathlib import Path
|
|
9
|
+
from time import sleep
|
|
8
10
|
from typing import TYPE_CHECKING, Any, TypeVar
|
|
9
11
|
|
|
10
12
|
import requests
|
|
@@ -35,6 +37,7 @@ class EasyvereinClient:
|
|
|
35
37
|
base_url,
|
|
36
38
|
logger: logging.Logger,
|
|
37
39
|
instance: EasyvereinAPI,
|
|
40
|
+
auto_retry=False,
|
|
38
41
|
):
|
|
39
42
|
"""
|
|
40
43
|
Constructor setting API key and logger
|
|
@@ -44,6 +47,7 @@ class EasyvereinClient:
|
|
|
44
47
|
self.api_version = api_version
|
|
45
48
|
self.logger = logger
|
|
46
49
|
self.api_instance = instance
|
|
50
|
+
self.auto_retry = auto_retry
|
|
47
51
|
|
|
48
52
|
def _get_header(self):
|
|
49
53
|
"""
|
|
@@ -118,10 +122,21 @@ class EasyvereinClient:
|
|
|
118
122
|
"Request returned status code 429, too many requests. Wait %d seconds",
|
|
119
123
|
retry_after,
|
|
120
124
|
)
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
retry_after
|
|
124
|
-
|
|
125
|
+
if self.auto_retry:
|
|
126
|
+
self.logger.warning("Retrying after %d seconds sleep.", retry_after)
|
|
127
|
+
sleep(retry_after)
|
|
128
|
+
if files:
|
|
129
|
+
for v in files.values():
|
|
130
|
+
v.seek(
|
|
131
|
+
0
|
|
132
|
+
) # reset file seek, as it has been moved by the previous call
|
|
133
|
+
|
|
134
|
+
return self._do_request(method, url, binary, data, headers, files)
|
|
135
|
+
else:
|
|
136
|
+
raise EasyvereinAPITooManyRetriesException(
|
|
137
|
+
f"Too many requests, please wait {retry_after} seconds and try again.",
|
|
138
|
+
retry_after=retry_after,
|
|
139
|
+
)
|
|
125
140
|
|
|
126
141
|
if res.status_code == 404:
|
|
127
142
|
self.logger.warning("Request returned status code 404, resource not found")
|
|
@@ -9,21 +9,16 @@ from .client import EasyvereinClient
|
|
|
9
9
|
# noinspection PyPropertyDefinition
|
|
10
10
|
class IsEVClientProtocol(Protocol):
|
|
11
11
|
@property
|
|
12
|
-
def logger(self) -> logging.Logger:
|
|
13
|
-
...
|
|
12
|
+
def logger(self) -> logging.Logger: ...
|
|
14
13
|
|
|
15
14
|
@property
|
|
16
|
-
def c(self) -> EasyvereinClient:
|
|
17
|
-
...
|
|
15
|
+
def c(self) -> EasyvereinClient: ...
|
|
18
16
|
|
|
19
17
|
@property
|
|
20
|
-
def endpoint_name(self) -> str:
|
|
21
|
-
...
|
|
18
|
+
def endpoint_name(self) -> str: ...
|
|
22
19
|
|
|
23
20
|
@property
|
|
24
|
-
def model_class(self) -> TypeVar:
|
|
25
|
-
...
|
|
21
|
+
def model_class(self) -> TypeVar: ...
|
|
26
22
|
|
|
27
23
|
@property
|
|
28
|
-
def return_type(self) -> Type[BaseModel]:
|
|
29
|
-
...
|
|
24
|
+
def return_type(self) -> Type[BaseModel]: ...
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Member related models
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
from typing import Literal
|
|
@@ -36,9 +37,9 @@ class CustomFieldBase(EasyVereinBase):
|
|
|
36
37
|
color: HexColor = None
|
|
37
38
|
short: str | None = Field(default=None, max_length=4)
|
|
38
39
|
orderSequence: PositiveIntWithZero | None = None
|
|
39
|
-
settings_type: Literal[
|
|
40
|
-
|
|
41
|
-
|
|
40
|
+
settings_type: Literal["t", "f", "z", "d", "c", "r", "s", "a", "b", "m"] | None = (
|
|
41
|
+
None
|
|
42
|
+
)
|
|
42
43
|
"""
|
|
43
44
|
Settings type defines which type of field this custom field should be. Possible values:
|
|
44
45
|
|
|
@@ -55,9 +56,12 @@ class CustomFieldBase(EasyVereinBase):
|
|
|
55
56
|
|
|
56
57
|
If type is set to s or a, the possible options need to be defined in the additional field
|
|
57
58
|
"""
|
|
58
|
-
kind:
|
|
59
|
-
|
|
60
|
-
|
|
59
|
+
kind: (
|
|
60
|
+
Literal[
|
|
61
|
+
"a", "b", "ba", "ca", "iv", "t", "u", "ic", "c", "e", "h", "j", "i", "k"
|
|
62
|
+
]
|
|
63
|
+
| None
|
|
64
|
+
) = None
|
|
61
65
|
"""
|
|
62
66
|
Kind defines in which context this custom field is used. Unfortunately only some possible values are
|
|
63
67
|
documented in the API spec:
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Invoice related models
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
from typing import Literal
|
|
@@ -42,9 +43,18 @@ class InvoiceBase(EasyVereinBase):
|
|
|
42
43
|
taxName: str | None = None
|
|
43
44
|
relatedAddress: ContactDetails | EasyVereinReference | None = None
|
|
44
45
|
path: EasyVereinReference | None = None
|
|
45
|
-
kind:
|
|
46
|
-
|
|
47
|
-
|
|
46
|
+
kind: (
|
|
47
|
+
Literal[
|
|
48
|
+
"balance",
|
|
49
|
+
"donation",
|
|
50
|
+
"membership",
|
|
51
|
+
"revenue",
|
|
52
|
+
"expense",
|
|
53
|
+
"cancel",
|
|
54
|
+
"credit",
|
|
55
|
+
]
|
|
56
|
+
| None
|
|
57
|
+
) = None
|
|
48
58
|
# TODO: Add reference to BillingAccount once implemented
|
|
49
59
|
selectionAcc: EasyVereinReference | None = None
|
|
50
60
|
refNumber: str | None = None
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Member related models
|
|
3
3
|
"""
|
|
4
|
+
|
|
4
5
|
from __future__ import annotations
|
|
5
6
|
|
|
6
7
|
from typing import Literal
|
|
@@ -73,7 +74,7 @@ class MemberBase(EasyVereinBase):
|
|
|
73
74
|
"""
|
|
74
75
|
Alias for `_applicationDate` field. See [Pydantic Models](../usage.md#pydantic-models) for details.
|
|
75
76
|
"""
|
|
76
|
-
applicationWasAcceptedAt:
|
|
77
|
+
applicationWasAcceptedAt: Date | None = Field(
|
|
77
78
|
default=None, alias="_applicationWasAcceptedAt"
|
|
78
79
|
)
|
|
79
80
|
"""
|
|
@@ -178,13 +179,13 @@ class MemberFilter(BaseModel):
|
|
|
178
179
|
applicationDate__isnull: Date = Field(
|
|
179
180
|
default=None, serialization_alias="_applicationDate__isnull"
|
|
180
181
|
)
|
|
181
|
-
applicationWasAcceptedAt:
|
|
182
|
+
applicationWasAcceptedAt: Date = Field(
|
|
182
183
|
default=None, serialization_alias="_applicationWasAcceptedAt"
|
|
183
184
|
)
|
|
184
|
-
applicationWasAcceptedAt__gte:
|
|
185
|
+
applicationWasAcceptedAt__gte: Date = Field(
|
|
185
186
|
default=None, serialization_alias="_applicationWasAcceptedAt__gte"
|
|
186
187
|
)
|
|
187
|
-
applicationWasAcceptedAt__lte:
|
|
188
|
+
applicationWasAcceptedAt__lte: Date = Field(
|
|
188
189
|
default=None, serialization_alias="_applicationWasAcceptedAt__lte"
|
|
189
190
|
)
|
|
190
191
|
applicationWasAcceptedAt__isnull: bool = Field(
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import logging
|
|
2
|
+
import re
|
|
3
|
+
import urllib
|
|
2
4
|
from pathlib import Path
|
|
3
5
|
from typing import List
|
|
4
6
|
|
|
@@ -169,4 +171,10 @@ class InvoiceMixin(
|
|
|
169
171
|
"Unable to obtain a valid path for given invoice."
|
|
170
172
|
)
|
|
171
173
|
|
|
172
|
-
|
|
174
|
+
# Fix for unencoded characters - should probably be fixed in easyverein API
|
|
175
|
+
m = re.fullmatch(r"^(.*\&path=)(.*)(&storedInS3=True)$", path.unicode_string())
|
|
176
|
+
url_components = list(m.groups())
|
|
177
|
+
if "%" not in url_components[1]:
|
|
178
|
+
url_components[1] = urllib.parse.quote(url_components[1])
|
|
179
|
+
|
|
180
|
+
return self.c.fetch_file("".join(url_components))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/models/member_custom_field.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{python_easyverein-0.2.4 → python_easyverein-0.2.7}/easyverein/modules/mixins/recycle_bin.py
RENAMED
|
File without changes
|