impectPy 2.5.0__tar.gz → 2.5.2__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.
- {impectPy-2.5.0 → impectpy-2.5.2}/PKG-INFO +14 -5
- {impectPy-2.5.0 → impectpy-2.5.2}/README.md +3 -3
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/__init__.py +1 -1
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/events.py +41 -24
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/helpers.py +9 -4
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/iteration_averages.py +18 -7
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/matchsums.py +67 -37
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/player_scores.py +34 -19
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/squad_scores.py +34 -19
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy.egg-info/PKG-INFO +14 -5
- {impectPy-2.5.0 → impectpy-2.5.2}/setup.py +1 -1
- {impectPy-2.5.0 → impectpy-2.5.2}/LICENSE.md +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/access_token.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/config.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/impect.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/iterations.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/match_info.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/matches.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/player_profile_scores.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/set_pieces.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/squad_coefficients.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/squad_ratings.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy/xml.py +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy.egg-info/SOURCES.txt +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy.egg-info/dependency_links.txt +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy.egg-info/requires.txt +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/impectPy.egg-info/top_level.txt +0 -0
- {impectPy-2.5.0 → impectpy-2.5.2}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: impectPy
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.2
|
|
4
4
|
Summary: A Python package to facilitate interaction with the Impect customer API
|
|
5
5
|
Home-page: https://github.com/ImpectAPI/impectPy
|
|
6
6
|
Author: Impect
|
|
@@ -11,14 +11,23 @@ License-File: LICENSE.md
|
|
|
11
11
|
Requires-Dist: requests>=2.24.0
|
|
12
12
|
Requires-Dist: pandas>=2.0.0
|
|
13
13
|
Requires-Dist: numpy<2.0,>=1.24.2
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: license
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
14
23
|
|
|
15
24
|
# impectPy <picture><source media="(prefers-color-scheme: dark)" srcset="https://github.com/ImpectAPI/logos/blob/main/impectPy_white.svg"><source media="(prefers-color-scheme: light)" srcset="https://github.com/ImpectAPI/logos/blob/main/impectPy_black.svg"><img alt="ImpectPy Logo" src="https://github.com/ImpectAPI/logos/blob/main/impectPy_black.svg" align="right" height="40"></picture>
|
|
16
25
|
|
|
17
26
|
A package provided by: Impect GmbH
|
|
18
27
|
|
|
19
|
-
Version: v2.5.
|
|
28
|
+
Version: v2.5.2
|
|
20
29
|
|
|
21
|
-
**Updated: October
|
|
30
|
+
**Updated: October 20th 2025**
|
|
22
31
|
|
|
23
32
|
---
|
|
24
33
|
|
|
@@ -49,7 +58,7 @@ pip install impectPy
|
|
|
49
58
|
You can also install it from [GitHub](https://github.com/) with:
|
|
50
59
|
|
|
51
60
|
```cmd
|
|
52
|
-
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.
|
|
61
|
+
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.2
|
|
53
62
|
```
|
|
54
63
|
|
|
55
64
|
## Usage
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
|
|
3
3
|
A package provided by: Impect GmbH
|
|
4
4
|
|
|
5
|
-
Version: v2.5.
|
|
5
|
+
Version: v2.5.2
|
|
6
6
|
|
|
7
|
-
**Updated: October
|
|
7
|
+
**Updated: October 20th 2025**
|
|
8
8
|
|
|
9
9
|
---
|
|
10
10
|
|
|
@@ -35,7 +35,7 @@ pip install impectPy
|
|
|
35
35
|
You can also install it from [GitHub](https://github.com/) with:
|
|
36
36
|
|
|
37
37
|
```cmd
|
|
38
|
-
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.
|
|
38
|
+
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.2
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Usage
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import numpy as np
|
|
3
3
|
import pandas as pd
|
|
4
4
|
import requests
|
|
5
|
-
|
|
5
|
+
import re
|
|
6
|
+
from impectPy.helpers import RateLimitedAPI, ForbiddenError
|
|
6
7
|
from .matches import getMatchesFromHost
|
|
7
8
|
from .iterations import getIterationsFromHost
|
|
8
|
-
import re
|
|
9
9
|
|
|
10
10
|
######
|
|
11
11
|
#
|
|
@@ -119,16 +119,23 @@ def getEventsFromHost(
|
|
|
119
119
|
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
120
120
|
|
|
121
121
|
# get coaches
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
122
|
+
coaches_blacklisted = False
|
|
123
|
+
try:
|
|
124
|
+
coaches = pd.concat(
|
|
125
|
+
map(lambda iteration: connection.make_api_request_limited(
|
|
126
|
+
url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
|
|
127
|
+
method="GET"
|
|
128
|
+
).process_response(
|
|
129
|
+
endpoint="Coaches",
|
|
130
|
+
raise_exception=False
|
|
131
|
+
),
|
|
132
|
+
iterations),
|
|
133
|
+
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
134
|
+
except KeyError:
|
|
135
|
+
# no coaches found, create empty df
|
|
136
|
+
coaches = pd.DataFrame(columns=["id", "name"])
|
|
137
|
+
except ForbiddenError:
|
|
138
|
+
coaches_blacklisted = True
|
|
132
139
|
|
|
133
140
|
# get matches
|
|
134
141
|
matchplan = pd.concat(
|
|
@@ -265,18 +272,6 @@ def getEventsFromHost(
|
|
|
265
272
|
right_on="id",
|
|
266
273
|
how="left",
|
|
267
274
|
suffixes=("", "_right")
|
|
268
|
-
).merge(
|
|
269
|
-
coaches[["id", "name"]].rename(columns={"id": "homeCoachId", "name": "homeCoachName"}),
|
|
270
|
-
left_on="homeSquadCoachId",
|
|
271
|
-
right_on="homeCoachId",
|
|
272
|
-
how="left",
|
|
273
|
-
suffixes=("", "_right")
|
|
274
|
-
).merge(
|
|
275
|
-
coaches[["id", "name"]].rename(columns={"id": "awayCoachId", "name": "awayCoachName"}),
|
|
276
|
-
left_on="awaySquadCoachId",
|
|
277
|
-
right_on="awayCoachId",
|
|
278
|
-
how="left",
|
|
279
|
-
suffixes=("", "_right")
|
|
280
275
|
).merge(
|
|
281
276
|
iterations,
|
|
282
277
|
left_on="iterationId",
|
|
@@ -285,6 +280,25 @@ def getEventsFromHost(
|
|
|
285
280
|
suffixes=("", "_right")
|
|
286
281
|
)
|
|
287
282
|
|
|
283
|
+
if not coaches_blacklisted:
|
|
284
|
+
|
|
285
|
+
# convert coachId to integer if it is None
|
|
286
|
+
events["homeSquadCoachId"] = events["homeSquadCoachId"].astype("Int64")
|
|
287
|
+
events["awaySquadCoachId"] = events["awaySquadCoachId"].astype("Int64")
|
|
288
|
+
events = events.merge(
|
|
289
|
+
coaches[["id", "name"]].rename(columns={"id": "homeCoachId", "name": "homeCoachName"}),
|
|
290
|
+
left_on="homeSquadCoachId",
|
|
291
|
+
right_on="homeCoachId",
|
|
292
|
+
how="left",
|
|
293
|
+
suffixes=("", "_right")
|
|
294
|
+
).merge(
|
|
295
|
+
coaches[["id", "name"]].rename(columns={"id": "awayCoachId", "name": "awayCoachName"}),
|
|
296
|
+
left_on="awaySquadCoachId",
|
|
297
|
+
right_on="awayCoachId",
|
|
298
|
+
how="left",
|
|
299
|
+
suffixes=("", "_right")
|
|
300
|
+
)
|
|
301
|
+
|
|
288
302
|
if include_kpis:
|
|
289
303
|
# unnest scorings and full join with kpi list to ensure all kpis are present
|
|
290
304
|
scorings = scorings.merge(kpis, left_on="kpiId", right_on="id", how="outer") \
|
|
@@ -532,6 +546,9 @@ def getEventsFromHost(
|
|
|
532
546
|
# add kpis
|
|
533
547
|
order = order + kpi_cols
|
|
534
548
|
|
|
549
|
+
if coaches_blacklisted:
|
|
550
|
+
order = [col for col in order if col not in ["homeCoachId", "homeCoachName", "awayCoachId", "awayCoachName"]]
|
|
551
|
+
|
|
535
552
|
# reorder data
|
|
536
553
|
events = events[order]
|
|
537
554
|
|
|
@@ -15,6 +15,11 @@ import math
|
|
|
15
15
|
######
|
|
16
16
|
|
|
17
17
|
|
|
18
|
+
class ForbiddenError(Exception):
|
|
19
|
+
"""Raised when the API returns a 403 Forbidden response."""
|
|
20
|
+
pass
|
|
21
|
+
|
|
22
|
+
|
|
18
23
|
class RateLimitedAPI:
|
|
19
24
|
def __init__(self, session: Optional[requests.Session] = None):
|
|
20
25
|
"""
|
|
@@ -115,10 +120,10 @@ class RateLimitedAPI:
|
|
|
115
120
|
f"Request-ID: {response.headers['x-request-id']} "
|
|
116
121
|
f"(Make sure to include this in any support request.)")
|
|
117
122
|
elif response.status_code == 403:
|
|
118
|
-
raise
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
raise ForbiddenError(f"Received status code {response.status_code} "
|
|
124
|
+
f"(You do not have access to this resource.)\n"
|
|
125
|
+
f"Request-ID: {response.headers['x-request-id']} "
|
|
126
|
+
f"(Make sure to include this in any support request.)")
|
|
122
127
|
# check status code and terminate if other error
|
|
123
128
|
else:
|
|
124
129
|
raise Exception(f"Received status code {response.status_code} "
|
|
@@ -118,13 +118,16 @@ def getPlayerIterationAveragesFromHost(
|
|
|
118
118
|
if len(averages_raw["name"][averages_raw["name"].isnull()]) > 0:
|
|
119
119
|
averages_raw["name"] = averages_raw["name"].fillna("-1")
|
|
120
120
|
|
|
121
|
-
#
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
121
|
+
# get KPIs without a scoring
|
|
122
|
+
mask = (
|
|
123
|
+
averages_raw.iterationId.isnull()
|
|
124
|
+
& averages_raw.squadId.isnull()
|
|
125
|
+
& averages_raw.playerId.isnull()
|
|
126
|
+
& averages_raw.position.isnull()
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# fill join cols with placeholder
|
|
130
|
+
averages_raw.loc[mask] = averages_raw.loc[mask].fillna(-1)
|
|
128
131
|
|
|
129
132
|
# get matchShares
|
|
130
133
|
match_shares_raw = averages_raw[
|
|
@@ -146,6 +149,14 @@ def getPlayerIterationAveragesFromHost(
|
|
|
146
149
|
if "-1" in averages_raw.columns:
|
|
147
150
|
averages_raw.drop(["-1"], inplace=True, axis=1)
|
|
148
151
|
|
|
152
|
+
# drop -1 rows
|
|
153
|
+
averages_raw = averages_raw[
|
|
154
|
+
~(averages_raw.iterationId == -1)
|
|
155
|
+
& ~(averages_raw.squadId == -1)
|
|
156
|
+
& ~(averages_raw.playerId == -1)
|
|
157
|
+
& ~(averages_raw.position == -1)
|
|
158
|
+
]
|
|
159
|
+
|
|
149
160
|
# merge with playDuration and matchShare
|
|
150
161
|
averages_raw = averages_raw.merge(
|
|
151
162
|
match_shares_raw,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# load packages
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import requests
|
|
4
|
-
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df
|
|
4
|
+
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df, ForbiddenError
|
|
5
5
|
from .matches import getMatchesFromHost
|
|
6
6
|
from .iterations import getIterationsFromHost
|
|
7
7
|
|
|
@@ -102,16 +102,23 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
102
102
|
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
103
103
|
|
|
104
104
|
# get coaches
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
105
|
+
coaches_blacklisted = False
|
|
106
|
+
try:
|
|
107
|
+
coaches = pd.concat(
|
|
108
|
+
map(lambda iteration: connection.make_api_request_limited(
|
|
109
|
+
url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
|
|
110
|
+
method="GET"
|
|
111
|
+
).process_response(
|
|
112
|
+
endpoint="Coaches",
|
|
113
|
+
raise_exception=False
|
|
114
|
+
),
|
|
115
|
+
iterations),
|
|
116
|
+
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
117
|
+
except KeyError:
|
|
118
|
+
# no coaches found, create empty df
|
|
119
|
+
coaches = pd.DataFrame(columns=["id", "name"])
|
|
120
|
+
except ForbiddenError:
|
|
121
|
+
coaches_blacklisted = True
|
|
115
122
|
|
|
116
123
|
# get kpis
|
|
117
124
|
kpis = connection.make_api_request_limited(
|
|
@@ -248,14 +255,6 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
248
255
|
right_on="id",
|
|
249
256
|
how="left",
|
|
250
257
|
suffixes=("", "_right")
|
|
251
|
-
).merge(
|
|
252
|
-
coaches[["id", "name"]].rename(
|
|
253
|
-
columns={"id": "coachId", "name": "coachName"}
|
|
254
|
-
),
|
|
255
|
-
left_on="coachId",
|
|
256
|
-
right_on="coachId",
|
|
257
|
-
how="left",
|
|
258
|
-
suffixes=("", "_right")
|
|
259
258
|
).merge(
|
|
260
259
|
countries.rename(columns={"fifaName": "playerCountry"}),
|
|
261
260
|
left_on="countryId",
|
|
@@ -264,6 +263,18 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
264
263
|
suffixes=("", "_right")
|
|
265
264
|
)
|
|
266
265
|
|
|
266
|
+
if not coaches_blacklisted:
|
|
267
|
+
matchsums["coachId"] = matchsums["coachId"].astype("Int64")
|
|
268
|
+
matchsums = matchsums.merge(
|
|
269
|
+
coaches[["id", "name"]].rename(
|
|
270
|
+
columns={"id": "coachId", "name": "coachName"}
|
|
271
|
+
),
|
|
272
|
+
left_on="coachId",
|
|
273
|
+
right_on="coachId",
|
|
274
|
+
how="left",
|
|
275
|
+
suffixes=("", "_right")
|
|
276
|
+
)
|
|
277
|
+
|
|
267
278
|
# rename some columns
|
|
268
279
|
matchsums = matchsums.rename(columns={
|
|
269
280
|
"scheduledDate": "dateTime",
|
|
@@ -304,6 +315,10 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
304
315
|
# add kpiNames to order
|
|
305
316
|
order += kpis['name'].to_list()
|
|
306
317
|
|
|
318
|
+
# check if coaches are blacklisted
|
|
319
|
+
if coaches_blacklisted:
|
|
320
|
+
order = [col for col in order if col not in ["coachId", "coachName"]]
|
|
321
|
+
|
|
307
322
|
# select columns
|
|
308
323
|
matchsums = matchsums[order]
|
|
309
324
|
|
|
@@ -395,16 +410,23 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
|
|
|
395
410
|
ignore_index=True)[["id", "name", "idMappings"]]
|
|
396
411
|
|
|
397
412
|
# get coaches
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
413
|
+
coaches_blacklisted = False
|
|
414
|
+
try:
|
|
415
|
+
coaches = pd.concat(
|
|
416
|
+
map(lambda iteration: connection.make_api_request_limited(
|
|
417
|
+
url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
|
|
418
|
+
method="GET"
|
|
419
|
+
).process_response(
|
|
420
|
+
endpoint="Coaches",
|
|
421
|
+
raise_exception=False
|
|
422
|
+
),
|
|
423
|
+
iterations),
|
|
424
|
+
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
425
|
+
except KeyError:
|
|
426
|
+
# no coaches found, create empty df
|
|
427
|
+
coaches = pd.DataFrame(columns=["id", "name"])
|
|
428
|
+
except ForbiddenError:
|
|
429
|
+
coaches_blacklisted = True
|
|
408
430
|
|
|
409
431
|
# unnest mappings
|
|
410
432
|
squads = unnest_mappings_df(squads, "idMappings").drop(["idMappings"], axis=1).drop_duplicates()
|
|
@@ -502,16 +524,20 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
|
|
|
502
524
|
right_on="squadId",
|
|
503
525
|
how="left",
|
|
504
526
|
suffixes=("", "_home")
|
|
505
|
-
).merge(
|
|
506
|
-
coaches[["id", "name"]].rename(
|
|
507
|
-
columns={"id": "coachId", "name": "coachName"}
|
|
508
|
-
),
|
|
509
|
-
left_on="coachId",
|
|
510
|
-
right_on="coachId",
|
|
511
|
-
how="left",
|
|
512
|
-
suffixes=("", "_right")
|
|
513
527
|
)
|
|
514
528
|
|
|
529
|
+
if not coaches_blacklisted:
|
|
530
|
+
matchsums["coachId"] = matchsums["coachId"].astype("Int64")
|
|
531
|
+
matchsums = matchsums.merge(
|
|
532
|
+
coaches[["id", "name"]].rename(
|
|
533
|
+
columns={"id": "coachId", "name": "coachName"}
|
|
534
|
+
),
|
|
535
|
+
left_on="coachId",
|
|
536
|
+
right_on="coachId",
|
|
537
|
+
how="left",
|
|
538
|
+
suffixes=("", "_right")
|
|
539
|
+
)
|
|
540
|
+
|
|
515
541
|
# rename some columns
|
|
516
542
|
matchsums = matchsums.rename(columns={
|
|
517
543
|
"scheduledDate": "dateTime"
|
|
@@ -549,6 +575,10 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
|
|
|
549
575
|
# reset index
|
|
550
576
|
matchsums = matchsums.reset_index()
|
|
551
577
|
|
|
578
|
+
# check if coaches are blacklisted
|
|
579
|
+
if coaches_blacklisted:
|
|
580
|
+
order = [col for col in order if col not in ["coachId", "coachName"]]
|
|
581
|
+
|
|
552
582
|
# select & order columns
|
|
553
583
|
matchsums = matchsums[order]
|
|
554
584
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# load packages
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import requests
|
|
4
|
-
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df
|
|
4
|
+
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df, ForbiddenError
|
|
5
5
|
from .matches import getMatchesFromHost
|
|
6
6
|
from .iterations import getIterationsFromHost
|
|
7
7
|
|
|
@@ -151,16 +151,23 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
|
|
|
151
151
|
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
152
152
|
|
|
153
153
|
# get coaches
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
154
|
+
coaches_blacklisted = False
|
|
155
|
+
try:
|
|
156
|
+
coaches = pd.concat(
|
|
157
|
+
map(lambda iteration: connection.make_api_request_limited(
|
|
158
|
+
url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
|
|
159
|
+
method="GET"
|
|
160
|
+
).process_response(
|
|
161
|
+
endpoint="Coaches",
|
|
162
|
+
raise_exception=False
|
|
163
|
+
),
|
|
164
|
+
iterations),
|
|
165
|
+
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
166
|
+
except KeyError:
|
|
167
|
+
# no coaches found, create empty df
|
|
168
|
+
coaches = pd.DataFrame(columns=["id", "name"])
|
|
169
|
+
except ForbiddenError:
|
|
170
|
+
coaches_blacklisted = True
|
|
164
171
|
|
|
165
172
|
# get player scores
|
|
166
173
|
scores = connection.make_api_request_limited(
|
|
@@ -350,14 +357,6 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
|
|
|
350
357
|
right_on="id",
|
|
351
358
|
how="left",
|
|
352
359
|
suffixes=("", "_right")
|
|
353
|
-
).merge(
|
|
354
|
-
coaches[["id", "name"]].rename(
|
|
355
|
-
columns={"id": "coachId", "name": "coachName"}
|
|
356
|
-
),
|
|
357
|
-
left_on="coachId",
|
|
358
|
-
right_on="coachId",
|
|
359
|
-
how="left",
|
|
360
|
-
suffixes=("", "_right")
|
|
361
360
|
).merge(
|
|
362
361
|
countries.rename(columns={"fifaName": "playerCountry"}),
|
|
363
362
|
left_on="countryId",
|
|
@@ -366,6 +365,18 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
|
|
|
366
365
|
suffixes=("", "_right")
|
|
367
366
|
)
|
|
368
367
|
|
|
368
|
+
if not coaches_blacklisted:
|
|
369
|
+
player_scores["coachId"] = player_scores["coachId"].astype("Int64")
|
|
370
|
+
player_scores = player_scores.merge(
|
|
371
|
+
coaches[["id", "name"]].rename(
|
|
372
|
+
columns={"id": "coachId", "name": "coachName"}
|
|
373
|
+
),
|
|
374
|
+
left_on="coachId",
|
|
375
|
+
right_on="coachId",
|
|
376
|
+
how="left",
|
|
377
|
+
suffixes=("", "_right")
|
|
378
|
+
)
|
|
379
|
+
|
|
369
380
|
# rename some columns
|
|
370
381
|
player_scores = player_scores.rename(columns={
|
|
371
382
|
"scheduledDate": "dateTime",
|
|
@@ -406,6 +417,10 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
|
|
|
406
417
|
# add kpiNames to order
|
|
407
418
|
order += scores["name"].to_list()
|
|
408
419
|
|
|
420
|
+
# check if coaches are blacklisted
|
|
421
|
+
if coaches_blacklisted:
|
|
422
|
+
order = [col for col in order if col not in ["coachId", "coachName"]]
|
|
423
|
+
|
|
409
424
|
# select columns
|
|
410
425
|
player_scores = player_scores[order]
|
|
411
426
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# load packages
|
|
2
2
|
import pandas as pd
|
|
3
3
|
import requests
|
|
4
|
-
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df
|
|
4
|
+
from impectPy.helpers import RateLimitedAPI, unnest_mappings_df, ForbiddenError
|
|
5
5
|
from .matches import getMatchesFromHost
|
|
6
6
|
from .iterations import getIterationsFromHost
|
|
7
7
|
|
|
@@ -81,16 +81,23 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
81
81
|
ignore_index=True)[["id", "name", "idMappings"]]
|
|
82
82
|
|
|
83
83
|
# get coaches
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
84
|
+
coaches_blacklisted = False
|
|
85
|
+
try:
|
|
86
|
+
coaches = pd.concat(
|
|
87
|
+
map(lambda iteration: connection.make_api_request_limited(
|
|
88
|
+
url=f"{host}/v5/customerapi/iterations/{iteration}/coaches",
|
|
89
|
+
method="GET"
|
|
90
|
+
).process_response(
|
|
91
|
+
endpoint="Coaches",
|
|
92
|
+
raise_exception=False
|
|
93
|
+
),
|
|
94
|
+
iterations),
|
|
95
|
+
ignore_index=True)[["id", "name"]].drop_duplicates()
|
|
96
|
+
except KeyError:
|
|
97
|
+
# no coaches found, create empty df
|
|
98
|
+
coaches = pd.DataFrame(columns=["id", "name"])
|
|
99
|
+
except ForbiddenError:
|
|
100
|
+
coaches_blacklisted = True
|
|
94
101
|
|
|
95
102
|
# unnest mappings
|
|
96
103
|
squads = unnest_mappings_df(squads, "idMappings").drop(["idMappings"], axis=1).drop_duplicates()
|
|
@@ -189,16 +196,20 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
189
196
|
right_on="squadId",
|
|
190
197
|
how="left",
|
|
191
198
|
suffixes=("", "_right")
|
|
192
|
-
).merge(
|
|
193
|
-
coaches[["id", "name"]].rename(
|
|
194
|
-
columns={"id": "coachId", "name": "coachName"}
|
|
195
|
-
),
|
|
196
|
-
left_on="coachId",
|
|
197
|
-
right_on="coachId",
|
|
198
|
-
how="left",
|
|
199
|
-
suffixes=("", "_right")
|
|
200
199
|
)
|
|
201
200
|
|
|
201
|
+
if not coaches_blacklisted:
|
|
202
|
+
squad_scores["coachId"] = squad_scores["coachId"].astype("Int64")
|
|
203
|
+
squad_scores = squad_scores.merge(
|
|
204
|
+
coaches[["id", "name"]].rename(
|
|
205
|
+
columns={"id": "coachId", "name": "coachName"}
|
|
206
|
+
),
|
|
207
|
+
left_on="coachId",
|
|
208
|
+
right_on="coachId",
|
|
209
|
+
how="left",
|
|
210
|
+
suffixes=("", "_right")
|
|
211
|
+
)
|
|
212
|
+
|
|
202
213
|
# rename some columns
|
|
203
214
|
squad_scores = squad_scores.rename(columns={
|
|
204
215
|
"scheduledDate": "dateTime"
|
|
@@ -224,6 +235,10 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
|
|
|
224
235
|
"coachName"
|
|
225
236
|
]
|
|
226
237
|
|
|
238
|
+
# check if coaches are blacklisted
|
|
239
|
+
if coaches_blacklisted:
|
|
240
|
+
order = [col for col in order if col not in ["coachId", "coachName"]]
|
|
241
|
+
|
|
227
242
|
# add scoreNames to order
|
|
228
243
|
order += scores["name"].to_list()
|
|
229
244
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: impectPy
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.2
|
|
4
4
|
Summary: A Python package to facilitate interaction with the Impect customer API
|
|
5
5
|
Home-page: https://github.com/ImpectAPI/impectPy
|
|
6
6
|
Author: Impect
|
|
@@ -11,14 +11,23 @@ License-File: LICENSE.md
|
|
|
11
11
|
Requires-Dist: requests>=2.24.0
|
|
12
12
|
Requires-Dist: pandas>=2.0.0
|
|
13
13
|
Requires-Dist: numpy<2.0,>=1.24.2
|
|
14
|
+
Dynamic: author
|
|
15
|
+
Dynamic: author-email
|
|
16
|
+
Dynamic: description
|
|
17
|
+
Dynamic: description-content-type
|
|
18
|
+
Dynamic: home-page
|
|
19
|
+
Dynamic: license
|
|
20
|
+
Dynamic: license-file
|
|
21
|
+
Dynamic: requires-dist
|
|
22
|
+
Dynamic: summary
|
|
14
23
|
|
|
15
24
|
# impectPy <picture><source media="(prefers-color-scheme: dark)" srcset="https://github.com/ImpectAPI/logos/blob/main/impectPy_white.svg"><source media="(prefers-color-scheme: light)" srcset="https://github.com/ImpectAPI/logos/blob/main/impectPy_black.svg"><img alt="ImpectPy Logo" src="https://github.com/ImpectAPI/logos/blob/main/impectPy_black.svg" align="right" height="40"></picture>
|
|
16
25
|
|
|
17
26
|
A package provided by: Impect GmbH
|
|
18
27
|
|
|
19
|
-
Version: v2.5.
|
|
28
|
+
Version: v2.5.2
|
|
20
29
|
|
|
21
|
-
**Updated: October
|
|
30
|
+
**Updated: October 20th 2025**
|
|
22
31
|
|
|
23
32
|
---
|
|
24
33
|
|
|
@@ -49,7 +58,7 @@ pip install impectPy
|
|
|
49
58
|
You can also install it from [GitHub](https://github.com/) with:
|
|
50
59
|
|
|
51
60
|
```cmd
|
|
52
|
-
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.
|
|
61
|
+
pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.2
|
|
53
62
|
```
|
|
54
63
|
|
|
55
64
|
## Usage
|
|
@@ -17,7 +17,7 @@ setup(
|
|
|
17
17
|
"pandas>=2.0.0",
|
|
18
18
|
"numpy>=1.24.2,<2.0"],
|
|
19
19
|
# *strongly* suggested for sharing
|
|
20
|
-
version="2.5.
|
|
20
|
+
version="2.5.2",
|
|
21
21
|
# The license can be anything you like
|
|
22
22
|
license="MIT",
|
|
23
23
|
description="A Python package to facilitate interaction with the Impect customer API",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|