impectPy 2.5.8__tar.gz → 2.5.9__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.
Files changed (35) hide show
  1. {impectpy-2.5.8 → impectpy-2.5.9}/PKG-INFO +4 -4
  2. {impectpy-2.5.8 → impectpy-2.5.9}/README.md +4 -4
  3. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/formations.py +1 -1
  4. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/helpers.py +4 -2
  5. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/iterations.py +8 -0
  6. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/matches.py +25 -1
  7. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/player_iteration_averages.py +9 -1
  8. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/player_iteration_scores.py +9 -1
  9. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/player_match_scores.py +9 -1
  10. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/player_matchsums.py +9 -1
  11. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/player_profile_scores.py +9 -1
  12. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_coefficients.py +9 -1
  13. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_iteration_averages.py +9 -1
  14. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_iteration_scores.py +9 -1
  15. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_match_scores.py +9 -1
  16. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_matchsums.py +9 -1
  17. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/squad_ratings.py +9 -1
  18. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/starting_positions.py +1 -1
  19. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/substitutions.py +1 -1
  20. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy.egg-info/PKG-INFO +4 -4
  21. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy.egg-info/SOURCES.txt +1 -2
  22. {impectpy-2.5.8 → impectpy-2.5.9}/setup.py +1 -1
  23. impectpy-2.5.8/tests/test_package.py +0 -286
  24. {impectpy-2.5.8 → impectpy-2.5.9}/LICENSE.md +0 -0
  25. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/__init__.py +0 -0
  26. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/access_token.py +0 -0
  27. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/config.py +0 -0
  28. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/events.py +0 -0
  29. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/generate_xml.py +0 -0
  30. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/impect.py +0 -0
  31. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy/set_pieces.py +0 -0
  32. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy.egg-info/dependency_links.txt +0 -0
  33. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy.egg-info/requires.txt +0 -0
  34. {impectpy-2.5.8 → impectpy-2.5.9}/impectPy.egg-info/top_level.txt +0 -0
  35. {impectpy-2.5.8 → impectpy-2.5.9}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: impectPy
3
- Version: 2.5.8
3
+ Version: 2.5.9
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
@@ -25,9 +25,9 @@ Dynamic: summary
25
25
 
26
26
  A package provided by: Impect GmbH
27
27
 
28
- Version: v2.5.8
28
+ Version: v2.5.9
29
29
 
30
- **Updated: March 19th 2026**
30
+ **Updated: April 9th 2026**
31
31
 
32
32
  ---
33
33
 
@@ -58,7 +58,7 @@ pip install impectPy
58
58
  You can also install it from [GitHub](https://github.com/) with:
59
59
 
60
60
  ```cmd
61
- pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.8
61
+ pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.9
62
62
  ```
63
63
 
64
64
  ## Usage
@@ -2,9 +2,9 @@
2
2
 
3
3
  A package provided by: Impect GmbH
4
4
 
5
- Version: v2.5.8
5
+ Version: v2.5.9
6
6
 
7
- **Updated: March 19th 2026**
7
+ **Updated: April 9th 2026**
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.8
38
+ pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.9
39
39
  ```
40
40
 
41
41
  ## Usage
@@ -431,4 +431,4 @@ playerProfileScores = api.getPlayerProfileScores(iteration=iteration, positions=
431
431
  ## Final Notes
432
432
 
433
433
  Further documentation on the data and explanations of variables can be
434
- found in our [Glossary](https://glossary.impect.com/).
434
+ found in our [Glossary](https://glossary.impect.com/).
@@ -134,7 +134,7 @@ def getFormationsFromHost(matches: list, connection: RateLimitedAPI, host: str)
134
134
  # merge with matches info
135
135
  formations = formations.merge(
136
136
  matchplan[[
137
- "id", "skillCornerId", "heimSpielId", "wyscoutId", "matchDayIndex",
137
+ "id", "skillCornerId", "heimSpielId", "wyscoutId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "matchDayIndex",
138
138
  "matchDayName", "scheduledDate", "lastCalculationDate", "iterationId"
139
139
  ]],
140
140
  left_on="id",
@@ -278,7 +278,7 @@ def unnest_mappings_dict(mapping_dict: dict) -> dict:
278
278
 
279
279
  def unnest_mappings_df(df: pd.DataFrame, mapping_col: str) -> pd.DataFrame:
280
280
  # create empty df to store mappings
281
- df_mappings = pd.DataFrame(columns=["wyscoutId", "heimSpielId", "skillCornerId"])
281
+ df_mappings = pd.DataFrame(columns=["wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId"])
282
282
 
283
283
  # iterate over entry and unnest idMappings
284
284
  for index, entry in df.iterrows():
@@ -291,7 +291,9 @@ def unnest_mappings_df(df: pd.DataFrame, mapping_col: str) -> pd.DataFrame:
291
291
  provider = "heimSpiel"
292
292
  elif provider == "skill_corner":
293
293
  provider = "skillCorner"
294
- elif provider == "wyscout":
294
+ elif provider == "stats_perform":
295
+ provider = "statsPerform"
296
+ elif provider in ("wyscout", "opta", "transfermarkt", "soccerdonna"):
295
297
  pass
296
298
  else:
297
299
  raise Exception(f"Unknown provider: {provider}")
@@ -49,6 +49,10 @@ def getIterationsFromHost(connection: RateLimitedAPI, host: str) -> pd.DataFrame
49
49
  df.skillCornerId = df.skillCornerId.apply(lambda x: x[0] if x else None)
50
50
  df.heimSpielId = df.heimSpielId.apply(lambda x: x[0] if x else None)
51
51
  df.wyscoutId = df.wyscoutId.apply(lambda x: x[0] if x else None)
52
+ df.optaId = df.optaId.apply(lambda x: x[0] if x else None)
53
+ df.statsPerformId = df.statsPerformId.apply(lambda x: x[0] if x else None)
54
+ df.transfermarktId = df.transfermarktId.apply(lambda x: x[0] if x else None)
55
+ df.soccerdonnaId = df.soccerdonnaId.apply(lambda x: x[0] if x else None)
52
56
 
53
57
  # get country data
54
58
  countries = connection.make_api_request_limited(
@@ -84,6 +88,10 @@ def getIterationsFromHost(connection: RateLimitedAPI, host: str) -> pd.DataFrame
84
88
  "wyscoutId",
85
89
  "heimSpielId",
86
90
  "skillCornerId",
91
+ "optaId",
92
+ "statsPerformId",
93
+ "transfermarktId",
94
+ "soccerdonnaId",
87
95
  ]
88
96
 
89
97
  # select columns
@@ -69,6 +69,10 @@ def getMatchesFromHost(iteration: int, connection: RateLimitedAPI, host: str) ->
69
69
  "skillCornerId_home": "homeSquadSkillCornerId",
70
70
  "heimSpielId_home": "homeSquadHeimSpielId",
71
71
  "wyscoutId_home": "homeSquadWyscoutId",
72
+ "optaId_home": "homeSquadOptaId",
73
+ "statsPerformId_home": "homeSquadStatsPerformId",
74
+ "transfermarktId_home": "homeSquadTransfermarktId",
75
+ "soccerdonnaId_home": "homeSquadSoccerdonnaId",
72
76
  "countryId": "homeSquadCountryId"
73
77
  })
74
78
  matches = matches.merge(squads,
@@ -81,6 +85,10 @@ def getMatchesFromHost(iteration: int, connection: RateLimitedAPI, host: str) ->
81
85
  "skillCornerId_away": "awaySquadSkillCornerId",
82
86
  "heimSpielId_away": "awaySquadHeimSpielId",
83
87
  "wyscoutId_away": "awaySquadWyscoutId",
88
+ "optaId_away": "awaySquadOptaId",
89
+ "statsPerformId_away": "awaySquadStatsPerformId",
90
+ "transfermarktId_away": "awaySquadTransfermarktId",
91
+ "soccerdonnaId_away": "awaySquadSoccerdonnaId",
84
92
  "countryId": "awaySquadCountryId"
85
93
  })
86
94
 
@@ -107,6 +115,10 @@ def getMatchesFromHost(iteration: int, connection: RateLimitedAPI, host: str) ->
107
115
  "skillCornerId",
108
116
  "heimSpielId",
109
117
  "wyscoutId",
118
+ "optaId",
119
+ "statsPerformId",
120
+ "transfermarktId",
121
+ "soccerdonnaId",
110
122
  "iterationId",
111
123
  "matchDayIndex",
112
124
  "matchDayName",
@@ -118,6 +130,10 @@ def getMatchesFromHost(iteration: int, connection: RateLimitedAPI, host: str) ->
118
130
  "homeSquadSkillCornerId",
119
131
  "homeSquadHeimSpielId",
120
132
  "homeSquadWyscoutId",
133
+ "homeSquadOptaId",
134
+ "homeSquadStatsPerformId",
135
+ "homeSquadTransfermarktId",
136
+ "homeSquadSoccerdonnaId",
121
137
  "awaySquadId",
122
138
  "awaySquadName",
123
139
  "awaySquadType",
@@ -126,6 +142,10 @@ def getMatchesFromHost(iteration: int, connection: RateLimitedAPI, host: str) ->
126
142
  "awaySquadSkillCornerId",
127
143
  "awaySquadHeimSpielId",
128
144
  "awaySquadWyscoutId",
145
+ "awaySquadOptaId",
146
+ "awaySquadStatsPerformId",
147
+ "awaySquadTransfermarktId",
148
+ "awaySquadSoccerdonnaId",
129
149
  "scheduledDate",
130
150
  "lastCalculationDate",
131
151
  "available"
@@ -156,9 +176,13 @@ def clean_df(data: dict) -> pd.DataFrame:
156
176
  # drop idMappings column
157
177
  df = df.drop("idMappings", axis=1)
158
178
 
159
- # keep first entry for skillcorner and heimspiel data
179
+ # keep first entry for skillcorner, heimspiel, wyscout, opta, statsperform, transfermarkt and soccerdonna data
160
180
  df.skillCornerId = df.skillCornerId.apply(lambda x: x[0] if x else None)
161
181
  df.heimSpielId = df.heimSpielId.apply(lambda x: x[0] if x else None)
162
182
  df.wyscoutId = df.wyscoutId.apply(lambda x: x[0] if x else None)
183
+ df.optaId = df.optaId.apply(lambda x: x[0] if x else None)
184
+ df.statsPerformId = df.statsPerformId.apply(lambda x: x[0] if x else None)
185
+ df.transfermarktId = df.transfermarktId.apply(lambda x: x[0] if x else None)
186
+ df.soccerdonnaId = df.soccerdonnaId.apply(lambda x: x[0] if x else None)
163
187
 
164
188
  return df
@@ -198,7 +198,7 @@ def getPlayerIterationAveragesFromHost(
198
198
  suffixes=("", "_squads")
199
199
  ).merge(
200
200
  players[[
201
- "id", "wyscoutId", "heimSpielId", "skillCornerId", "commonname",
201
+ "id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "commonname",
202
202
  "firstname", "lastname", "birthdate", "birthplace", "countryId", "leg"
203
203
  ]].rename(
204
204
  columns={"commonname": "playerName"}
@@ -225,6 +225,10 @@ def getPlayerIterationAveragesFromHost(
225
225
  averages["wyscoutId"] = averages["wyscoutId"].astype("Int64")
226
226
  averages["heimSpielId"] = averages["heimSpielId"].astype("Int64")
227
227
  averages["skillCornerId"] = averages["skillCornerId"].astype("Int64")
228
+ averages["optaId"] = averages["optaId"].astype("string")
229
+ averages["statsPerformId"] = averages["statsPerformId"].astype("string")
230
+ averages["transfermarktId"] = averages["transfermarktId"].astype("string")
231
+ averages["soccerdonnaId"] = averages["soccerdonnaId"].astype("string")
228
232
 
229
233
  # define column order
230
234
  order = [
@@ -237,6 +241,10 @@ def getPlayerIterationAveragesFromHost(
237
241
  "wyscoutId",
238
242
  "heimSpielId",
239
243
  "skillCornerId",
244
+ "optaId",
245
+ "statsPerformId",
246
+ "transfermarktId",
247
+ "soccerdonnaId",
240
248
  "playerName",
241
249
  "firstname",
242
250
  "lastname",
@@ -271,7 +271,7 @@ def getPlayerIterationScoresFromHost(
271
271
  suffixes=("", "_iterations")
272
272
  ).merge(
273
273
  players[[
274
- "id", "wyscoutId", "heimSpielId", "skillCornerId", "commonname",
274
+ "id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "commonname",
275
275
  "firstname", "lastname", "birthdate", "birthplace", "countryId", "leg"
276
276
  ]].rename(
277
277
  columns={"commonname": "playerName"}
@@ -302,6 +302,10 @@ def getPlayerIterationScoresFromHost(
302
302
  "wyscoutId",
303
303
  "heimSpielId",
304
304
  "skillCornerId",
305
+ "optaId",
306
+ "statsPerformId",
307
+ "transfermarktId",
308
+ "soccerdonnaId",
305
309
  "playerName",
306
310
  "firstname",
307
311
  "lastname",
@@ -326,6 +330,10 @@ def getPlayerIterationScoresFromHost(
326
330
  averages["wyscoutId"] = averages["wyscoutId"].astype("Int64")
327
331
  averages["heimSpielId"] = averages["heimSpielId"].astype("Int64")
328
332
  averages["skillCornerId"] = averages["skillCornerId"].astype("Int64")
333
+ averages["optaId"] = averages["optaId"].astype("string")
334
+ averages["statsPerformId"] = averages["statsPerformId"].astype("string")
335
+ averages["transfermarktId"] = averages["transfermarktId"].astype("string")
336
+ averages["soccerdonnaId"] = averages["soccerdonnaId"].astype("string")
329
337
 
330
338
  # return result
331
339
  return averages
@@ -378,7 +378,7 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
378
378
  suffixes=("", "_iterations")
379
379
  ).merge(
380
380
  players[[
381
- "id", "wyscoutId", "heimSpielId", "skillCornerId", "commonname",
381
+ "id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "commonname",
382
382
  "firstname", "lastname", "birthdate", "birthplace", "countryId", "leg"
383
383
  ]].rename(
384
384
  columns={"commonname": "playerName"}
@@ -424,6 +424,10 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
424
424
  "wyscoutId",
425
425
  "heimSpielId",
426
426
  "skillCornerId",
427
+ "optaId",
428
+ "statsPerformId",
429
+ "transfermarktId",
430
+ "soccerdonnaId",
427
431
  "playerName",
428
432
  "firstname",
429
433
  "lastname",
@@ -453,6 +457,10 @@ def getPlayerMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host
453
457
  player_scores["wyscoutId"] = player_scores["wyscoutId"].astype("Int64")
454
458
  player_scores["heimSpielId"] = player_scores["heimSpielId"].astype("Int64")
455
459
  player_scores["skillCornerId"] = player_scores["skillCornerId"].astype("Int64")
460
+ player_scores["optaId"] = player_scores["optaId"].astype("string")
461
+ player_scores["statsPerformId"] = player_scores["statsPerformId"].astype("string")
462
+ player_scores["transfermarktId"] = player_scores["transfermarktId"].astype("string")
463
+ player_scores["soccerdonnaId"] = player_scores["soccerdonnaId"].astype("string")
456
464
 
457
465
  # return data
458
466
  return player_scores
@@ -272,7 +272,7 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
272
272
  suffixes=("", "_iterations")
273
273
  ).merge(
274
274
  players[[
275
- "id", "wyscoutId", "heimSpielId", "skillCornerId", "commonname",
275
+ "id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "commonname",
276
276
  "firstname", "lastname", "birthdate", "birthplace", "countryId", "leg"
277
277
  ]].rename(
278
278
  columns={"commonname": "playerName"}
@@ -318,6 +318,10 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
318
318
  "wyscoutId",
319
319
  "heimSpielId",
320
320
  "skillCornerId",
321
+ "optaId",
322
+ "statsPerformId",
323
+ "transfermarktId",
324
+ "soccerdonnaId",
321
325
  "playerName",
322
326
  "firstname",
323
327
  "lastname",
@@ -347,6 +351,10 @@ def getPlayerMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host:
347
351
  matchsums["wyscoutId"] = matchsums["wyscoutId"].astype("Int64")
348
352
  matchsums["heimSpielId"] = matchsums["heimSpielId"].astype("Int64")
349
353
  matchsums["skillCornerId"] = matchsums["skillCornerId"].astype("Int64")
354
+ matchsums["optaId"] = matchsums["optaId"].astype("string")
355
+ matchsums["statsPerformId"] = matchsums["statsPerformId"].astype("string")
356
+ matchsums["transfermarktId"] = matchsums["transfermarktId"].astype("string")
357
+ matchsums["soccerdonnaId"] = matchsums["soccerdonnaId"].astype("string")
350
358
 
351
359
  # return data
352
360
  return matchsums
@@ -211,7 +211,7 @@ def getPlayerProfileScoresFromHost(
211
211
  suffixes=("", "_squads")
212
212
  ).merge(
213
213
  players[[
214
- "id", "wyscoutId", "heimSpielId", "skillCornerId", "commonname",
214
+ "id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "commonname",
215
215
  "firstname", "lastname", "birthdate", "birthplace", "countryId", "leg"
216
216
  ]].rename(
217
217
  columns={"commonname": "playerName"}
@@ -233,6 +233,10 @@ def getPlayerProfileScoresFromHost(
233
233
  profile_scores["wyscoutId"] = profile_scores["wyscoutId"].astype("Int64")
234
234
  profile_scores["heimSpielId"] = profile_scores["heimSpielId"].astype("Int64")
235
235
  profile_scores["skillCornerId"] = profile_scores["skillCornerId"].astype("Int64")
236
+ profile_scores["optaId"] = profile_scores["optaId"].astype("string")
237
+ profile_scores["statsPerformId"] = profile_scores["statsPerformId"].astype("string")
238
+ profile_scores["transfermarktId"] = profile_scores["transfermarktId"].astype("string")
239
+ profile_scores["soccerdonnaId"] = profile_scores["soccerdonnaId"].astype("string")
236
240
 
237
241
  # define column order
238
242
  order = [
@@ -245,6 +249,10 @@ def getPlayerProfileScoresFromHost(
245
249
  "wyscoutId",
246
250
  "heimSpielId",
247
251
  "skillCornerId",
252
+ "optaId",
253
+ "statsPerformId",
254
+ "transfermarktId",
255
+ "soccerdonnaId",
248
256
  "playerName",
249
257
  "firstname",
250
258
  "lastname",
@@ -87,7 +87,7 @@ def getSquadCoefficientsFromHost(iteration: int, connection: RateLimitedAPI, hos
87
87
 
88
88
  # merge events with squads
89
89
  coefficients = coefficients.merge(
90
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
90
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
91
91
  columns={"id": "squadId", "name": "squadName"}
92
92
  ),
93
93
  left_on="squadId",
@@ -103,6 +103,10 @@ def getSquadCoefficientsFromHost(iteration: int, connection: RateLimitedAPI, hos
103
103
  coefficients["wyscoutId"] = coefficients["wyscoutId"].astype("Int64")
104
104
  coefficients["heimSpielId"] = coefficients["heimSpielId"].astype("Int64")
105
105
  coefficients["skillCornerId"] = coefficients["skillCornerId"].astype("Int64")
106
+ coefficients["optaId"] = coefficients["optaId"].astype("string")
107
+ coefficients["statsPerformId"] = coefficients["statsPerformId"].astype("string")
108
+ coefficients["transfermarktId"] = coefficients["transfermarktId"].astype("string")
109
+ coefficients["soccerdonnaId"] = coefficients["soccerdonnaId"].astype("string")
106
110
 
107
111
  # define desired column order
108
112
  order = [
@@ -120,6 +124,10 @@ def getSquadCoefficientsFromHost(iteration: int, connection: RateLimitedAPI, hos
120
124
  "wyscoutId",
121
125
  "heimSpielId",
122
126
  "skillCornerId",
127
+ "optaId",
128
+ "statsPerformId",
129
+ "transfermarktId",
130
+ "soccerdonnaId",
123
131
  "squadName",
124
132
  "attackCoefficient",
125
133
  "defenseCoefficient",
@@ -110,7 +110,7 @@ def getSquadIterationAveragesFromHost(iteration: int, connection: RateLimitedAPI
110
110
  how="left",
111
111
  suffixes=("", "_iterations")
112
112
  ).merge(
113
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
113
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
114
114
  columns={"id": "squadId", "name": "squadName"}
115
115
  ),
116
116
  left_on="squadId",
@@ -129,6 +129,10 @@ def getSquadIterationAveragesFromHost(iteration: int, connection: RateLimitedAPI
129
129
  averages["wyscoutId"] = averages["wyscoutId"].astype("Int64")
130
130
  averages["heimSpielId"] = averages["heimSpielId"].astype("Int64")
131
131
  averages["skillCornerId"] = averages["skillCornerId"].astype("Int64")
132
+ averages["optaId"] = averages["optaId"].astype("string")
133
+ averages["statsPerformId"] = averages["statsPerformId"].astype("string")
134
+ averages["transfermarktId"] = averages["transfermarktId"].astype("string")
135
+ averages["soccerdonnaId"] = averages["soccerdonnaId"].astype("string")
132
136
 
133
137
  # define column order
134
138
  order = [
@@ -139,6 +143,10 @@ def getSquadIterationAveragesFromHost(iteration: int, connection: RateLimitedAPI
139
143
  "wyscoutId",
140
144
  "heimSpielId",
141
145
  "skillCornerId",
146
+ "optaId",
147
+ "statsPerformId",
148
+ "transfermarktId",
149
+ "soccerdonnaId",
142
150
  "squadName",
143
151
  "matches"
144
152
  ]
@@ -110,7 +110,7 @@ def getSquadIterationScoresFromHost(iteration: int, connection: RateLimitedAPI,
110
110
  how="left",
111
111
  suffixes=("", "_iterations")
112
112
  ).merge(
113
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
113
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
114
114
  columns={"id": "squadId", "name": "squadName"}
115
115
  ),
116
116
  left_on="squadId",
@@ -129,6 +129,10 @@ def getSquadIterationScoresFromHost(iteration: int, connection: RateLimitedAPI,
129
129
  averages["wyscoutId"] = averages["wyscoutId"].astype("Int64")
130
130
  averages["heimSpielId"] = averages["heimSpielId"].astype("Int64")
131
131
  averages["skillCornerId"] = averages["skillCornerId"].astype("Int64")
132
+ averages["optaId"] = averages["optaId"].astype("string")
133
+ averages["statsPerformId"] = averages["statsPerformId"].astype("string")
134
+ averages["transfermarktId"] = averages["transfermarktId"].astype("string")
135
+ averages["soccerdonnaId"] = averages["soccerdonnaId"].astype("string")
132
136
 
133
137
  # define column order
134
138
  order = [
@@ -139,6 +143,10 @@ def getSquadIterationScoresFromHost(iteration: int, connection: RateLimitedAPI,
139
143
  "wyscoutId",
140
144
  "heimSpielId",
141
145
  "skillCornerId",
146
+ "optaId",
147
+ "statsPerformId",
148
+ "transfermarktId",
149
+ "soccerdonnaId",
142
150
  "squadName",
143
151
  "matches"
144
152
  ]
@@ -221,7 +221,7 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
221
221
  how="left",
222
222
  suffixes=("", "_iterations")
223
223
  ).merge(
224
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
224
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
225
225
  columns={"id": "squadId", "name": "squadName"}
226
226
  ),
227
227
  left_on="squadId",
@@ -259,6 +259,10 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
259
259
  "wyscoutId",
260
260
  "heimSpielId",
261
261
  "skillCornerId",
262
+ "optaId",
263
+ "statsPerformId",
264
+ "transfermarktId",
265
+ "soccerdonnaId",
262
266
  "squadName",
263
267
  "coachId",
264
268
  "coachName"
@@ -283,6 +287,10 @@ def getSquadMatchScoresFromHost(matches: list, connection: RateLimitedAPI, host:
283
287
  squad_scores["wyscoutId"] = squad_scores["wyscoutId"].astype("Int64")
284
288
  squad_scores["heimSpielId"] = squad_scores["heimSpielId"].astype("Int64")
285
289
  squad_scores["skillCornerId"] = squad_scores["skillCornerId"].astype("Int64")
290
+ squad_scores["optaId"] = squad_scores["optaId"].astype("string")
291
+ squad_scores["statsPerformId"] = squad_scores["statsPerformId"].astype("string")
292
+ squad_scores["transfermarktId"] = squad_scores["transfermarktId"].astype("string")
293
+ squad_scores["soccerdonnaId"] = squad_scores["soccerdonnaId"].astype("string")
286
294
 
287
295
  # return data
288
296
  return squad_scores
@@ -221,7 +221,7 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
221
221
  how="left",
222
222
  suffixes=("", "_iterations")
223
223
  ).merge(
224
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
224
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
225
225
  columns={"id": "squadId", "name": "squadName"}
226
226
  ),
227
227
  left_on="squadId",
@@ -259,6 +259,10 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
259
259
  "wyscoutId",
260
260
  "heimSpielId",
261
261
  "skillCornerId",
262
+ "optaId",
263
+ "statsPerformId",
264
+ "transfermarktId",
265
+ "soccerdonnaId",
262
266
  "squadName",
263
267
  "coachId",
264
268
  "coachName"
@@ -292,6 +296,10 @@ def getSquadMatchsumsFromHost(matches: list, connection: RateLimitedAPI, host: s
292
296
  matchsums["wyscoutId"] = matchsums["wyscoutId"].astype("Int64")
293
297
  matchsums["heimSpielId"] = matchsums["heimSpielId"].astype("Int64")
294
298
  matchsums["skillCornerId"] = matchsums["skillCornerId"].astype("Int64")
299
+ matchsums["optaId"] = matchsums["optaId"].astype("string")
300
+ matchsums["statsPerformId"] = matchsums["statsPerformId"].astype("string")
301
+ matchsums["transfermarktId"] = matchsums["transfermarktId"].astype("string")
302
+ matchsums["soccerdonnaId"] = matchsums["soccerdonnaId"].astype("string")
295
303
 
296
304
  # return data
297
305
  return matchsums
@@ -85,7 +85,7 @@ def getSquadRatingsFromHost(iteration: int, connection: RateLimitedAPI, host: st
85
85
 
86
86
  # merge events with squads
87
87
  ratings = ratings.merge(
88
- squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "name"]].rename(
88
+ squads[["id", "wyscoutId", "heimSpielId", "skillCornerId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "name"]].rename(
89
89
  columns={"id": "squadId", "name": "squadName"}
90
90
  ),
91
91
  left_on="squadId",
@@ -101,6 +101,10 @@ def getSquadRatingsFromHost(iteration: int, connection: RateLimitedAPI, host: st
101
101
  ratings["wyscoutId"] = ratings["wyscoutId"].astype("Int64")
102
102
  ratings["heimSpielId"] = ratings["heimSpielId"].astype("Int64")
103
103
  ratings["skillCornerId"] = ratings["skillCornerId"].astype("Int64")
104
+ ratings["optaId"] = ratings["optaId"].astype("string")
105
+ ratings["statsPerformId"] = ratings["statsPerformId"].astype("string")
106
+ ratings["transfermarktId"] = ratings["transfermarktId"].astype("string")
107
+ ratings["soccerdonnaId"] = ratings["soccerdonnaId"].astype("string")
104
108
 
105
109
  # define desired column order
106
110
  order = [
@@ -115,6 +119,10 @@ def getSquadRatingsFromHost(iteration: int, connection: RateLimitedAPI, host: st
115
119
  "wyscoutId",
116
120
  "heimSpielId",
117
121
  "skillCornerId",
122
+ "optaId",
123
+ "statsPerformId",
124
+ "transfermarktId",
125
+ "soccerdonnaId",
118
126
  "squadName",
119
127
  "value"
120
128
  ]
@@ -179,7 +179,7 @@ def getStartingPositionsFromHost(matches: list, connection: RateLimitedAPI, host
179
179
  # merge with matches info
180
180
  starting_positions = starting_positions.merge(
181
181
  matchplan[[
182
- "id", "skillCornerId", "heimSpielId", "wyscoutId", "matchDayIndex",
182
+ "id", "skillCornerId", "heimSpielId", "wyscoutId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "matchDayIndex",
183
183
  "matchDayName", "scheduledDate", "lastCalculationDate", "iterationId"
184
184
  ]],
185
185
  left_on="id",
@@ -194,7 +194,7 @@ def getSubstitutionsFromHost(matches: list, connection: RateLimitedAPI, host: st
194
194
  # merge with matches info
195
195
  substitutions = substitutions.merge(
196
196
  matchplan[[
197
- "id", "skillCornerId", "heimSpielId", "wyscoutId", "matchDayIndex",
197
+ "id", "skillCornerId", "heimSpielId", "wyscoutId", "optaId", "statsPerformId", "transfermarktId", "soccerdonnaId", "matchDayIndex",
198
198
  "matchDayName", "scheduledDate", "lastCalculationDate", "iterationId"
199
199
  ]],
200
200
  left_on="id",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: impectPy
3
- Version: 2.5.8
3
+ Version: 2.5.9
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
@@ -25,9 +25,9 @@ Dynamic: summary
25
25
 
26
26
  A package provided by: Impect GmbH
27
27
 
28
- Version: v2.5.8
28
+ Version: v2.5.9
29
29
 
30
- **Updated: March 19th 2026**
30
+ **Updated: April 9th 2026**
31
31
 
32
32
  ---
33
33
 
@@ -58,7 +58,7 @@ pip install impectPy
58
58
  You can also install it from [GitHub](https://github.com/) with:
59
59
 
60
60
  ```cmd
61
- pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.8
61
+ pip install git+https://github.com/ImpectAPI/impectPy.git@v2.5.9
62
62
  ```
63
63
 
64
64
  ## Usage
@@ -29,5 +29,4 @@ impectPy.egg-info/PKG-INFO
29
29
  impectPy.egg-info/SOURCES.txt
30
30
  impectPy.egg-info/dependency_links.txt
31
31
  impectPy.egg-info/requires.txt
32
- impectPy.egg-info/top_level.txt
33
- tests/test_package.py
32
+ impectPy.egg-info/top_level.txt
@@ -17,7 +17,7 @@ setup(
17
17
  "pandas>=2.2.0",
18
18
  "numpy>=1.24.2"],
19
19
  # *strongly* suggested for sharing
20
- version="2.5.8",
20
+ version="2.5.9",
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",
@@ -1,286 +0,0 @@
1
- # load packages
2
- import sys
3
- import importlib
4
- import logging
5
- import os
6
- import re
7
- import subprocess
8
- from pathlib import Path
9
- from tqdm import tqdm
10
- from dotenv import load_dotenv
11
- import pandas as pd
12
-
13
- execute_functions = False
14
-
15
- # branch comparison configuration
16
- BRANCH_A_NAME = "main"
17
- BRANCH_B_NAME = "release"
18
-
19
- REPO_ROOT = Path(__file__).resolve().parents[1]
20
- BRANCH_PATHS = {
21
- BRANCH_A_NAME: REPO_ROOT,
22
- BRANCH_B_NAME: REPO_ROOT,
23
- }
24
-
25
-
26
- def checkout_branch(branch_name: str):
27
- repo_path = BRANCH_PATHS.get(branch_name)
28
- if repo_path is None or not repo_path.exists():
29
- raise ValueError(f"Unknown branch or missing repo path: '{branch_name}'")
30
-
31
- try:
32
- subprocess.run(
33
- ["git", "-C", str(repo_path), "fetch"],
34
- check=True,
35
- stdout=subprocess.DEVNULL
36
- )
37
- subprocess.run(
38
- ["git", "-C", str(repo_path), "checkout", branch_name],
39
- check=True,
40
- stdout=subprocess.DEVNULL
41
- )
42
- except subprocess.CalledProcessError as e:
43
- print(f"Error checking out branch '{branch_name}' in {repo_path}: {e}")
44
-
45
-
46
- def load_impect(env: str):
47
- modules_to_remove = [m for m in sys.modules if m.startswith("impectPy")]
48
-
49
- for module_name in modules_to_remove:
50
- del sys.modules[module_name]
51
-
52
- sys.path = [p for p in sys.path if "impectPy" not in p]
53
-
54
- importlib.invalidate_caches()
55
-
56
- repo_root = BRANCH_PATHS.get(env)
57
- if repo_root is None:
58
- raise ValueError(f"Unknown environment '{env}'. Check BRANCH_PATHS.")
59
-
60
- sys.path.insert(0, str(repo_root))
61
- return importlib.import_module("impectPy")
62
-
63
- if execute_functions:
64
-
65
- # define login credentials
66
- load_dotenv()
67
- username = os.getenv("USERNAME")
68
- password = os.getenv("PASSWORD")
69
-
70
- # define logger
71
- logging.basicConfig(
72
- level=logging.ERROR,
73
- format="%(asctime)s - %(name)s - %(levelname)s - ID=%(id)s - URL=%(url)s - %(message)s"
74
- )
75
-
76
- # define object to be passed onto functions
77
- iteration = 1385
78
-
79
- matches = [
80
- 232434,
81
- 202485
82
- ]
83
-
84
- positions = [
85
- "GOALKEEPER",
86
- "LEFT_WINGBACK_DEFENDER",
87
- "RIGHT_WINGBACK_DEFENDER",
88
- "CENTRAL_DEFENDER",
89
- "DEFENSE_MIDFIELD",
90
- "CENTRAL_MIDFIELD",
91
- "ATTACKING_MIDFIELD",
92
- "LEFT_WINGER",
93
- "RIGHT_WINGER",
94
- "CENTER_FORWARD"
95
- ]
96
-
97
- # define branches
98
- branches = [BRANCH_A_NAME, BRANCH_B_NAME]
99
-
100
- # iterate over envs
101
- for branch in branches:
102
-
103
- os.makedirs(f"files/{branch}", exist_ok=True)
104
-
105
- checkout_branch(branch)
106
- impectPy = load_impect(branch)
107
- print(f"impectPy Version: {impectPy.__version__}")
108
-
109
- config = impectPy.Config()
110
- api = impectPy.Impect(config=config)
111
- api.login(username, password)
112
-
113
- with tqdm(total=20, desc=f"{branch}: Executing functions...", unit="chunk") as pbar:
114
-
115
- # get iterations
116
- iterations = api.getIterations()
117
- iterations.to_csv(f"files/{branch}/iterations.csv")
118
- pbar.update()
119
-
120
- # get squad ratings
121
- ratings = api.getSquadRatings(iteration)
122
- ratings.to_csv(f"files/{branch}/ratings.csv")
123
- pbar.update()
124
-
125
- # get squad coefficients
126
- coefficients = api.getSquadCoefficients(iteration)
127
- coefficients.to_csv(f"files/{branch}/coefficients.csv")
128
- pbar.update()
129
-
130
- # get matches
131
- matchplan = api.getMatches(iteration)
132
- matchplan.to_csv(f"files/{branch}/matchplan.csv")
133
- pbar.update()
134
-
135
- # get match info
136
- formations = api.getFormations(matches)
137
- formations.to_csv(f"files/{branch}/formations.csv")
138
- pbar.update()
139
- substitutions = api.getSubstitutions(matches)
140
- substitutions.to_csv(f"files/{branch}/substitutions.csv")
141
- pbar.update()
142
- startingPositions = api.getStartingPositions(matches)
143
- startingPositions.to_csv(f"files/{branch}/startingPositions.csv")
144
- pbar.update()
145
-
146
- # get match events
147
- events = api.getEvents(matches, include_kpis=True, include_set_pieces=True)
148
- events.to_csv(f"files/{branch}/events.csv")
149
- pbar.update()
150
-
151
- # get set pieces
152
- set_pieces = api.getSetPieces(matches)
153
- set_pieces.to_csv(f"files/{branch}/set_pieces.csv")
154
- pbar.update()
155
-
156
- # get player iteration averages
157
- playerIterationAverages = api.getPlayerIterationAverages(iteration)
158
- playerIterationAverages.to_csv(f"files/{branch}/playerIterationAverages.csv")
159
- pbar.update()
160
-
161
- # get player matchsums
162
- playerMatchsums = api.getPlayerMatchsums(matches)
163
- playerMatchsums.to_csv(f"files/{branch}/playerMatchsums.csv")
164
- pbar.update()
165
-
166
- # get squad iteration averages
167
- squadIterationAverages = api.getSquadIterationAverages(iteration)
168
- squadIterationAverages.to_csv(f"files/{branch}/squadIterationAverages.csv")
169
- pbar.update()
170
-
171
- # get squad matchsums
172
- squadMatchsums = api.getSquadMatchsums(matches)
173
- squadMatchsums.to_csv(f"files/{branch}/squadMatchsums.csv")
174
- pbar.update()
175
-
176
- # get player match scores
177
- playerMatchScores = api.getPlayerMatchScores(matches)
178
- playerMatchScores.to_csv(f"files/{branch}/playerMatchScores.csv")
179
- pbar.update()
180
- playerMatchScores_2 = api.getPlayerMatchScores(matches, positions)
181
- playerMatchScores_2.to_csv(f"files/{branch}/playerMatchScores_2.csv")
182
- pbar.update()
183
-
184
- # get squad match scores
185
- squadMatchScores = api.getSquadMatchScores(matches)
186
- squadMatchScores.to_csv(f"files/{branch}/squadMatchScores.csv")
187
- pbar.update()
188
-
189
- # get player iteration scores
190
- playerIterationScores = api.getPlayerIterationScores(iteration)
191
- playerIterationScores.to_csv(f"files/{branch}/playerIterationScores.csv")
192
- pbar.update()
193
- playerIterationScores_2 = api.getPlayerIterationScores(iteration, positions)
194
- playerIterationScores_2.to_csv(f"files/{branch}/playerIterationScores_2.csv")
195
- pbar.update()
196
-
197
- # get squad iteration scores
198
- squadIterationScores = api.getSquadIterationScores(iteration)
199
- squadIterationScores.to_csv(f"files/{branch}/squadIterationScores.csv")
200
- pbar.update()
201
-
202
- # get player profile scores
203
- playerProfileScores = api.getPlayerProfileScores(iteration, positions)
204
- playerProfileScores.to_csv(f"files/{branch}/playerProfileScores.csv")
205
- pbar.update()
206
-
207
- print("\nRunning auto-diff between source and test outputs...\n")
208
-
209
- base_path = Path(__file__).parent / "files"
210
- source_path = base_path / BRANCH_A_NAME
211
- test_path = base_path / BRANCH_B_NAME
212
-
213
- excluded_columns = [
214
- # "playerCountry"
215
- ]
216
-
217
- failed = False
218
- assertion_error_patterns = {
219
- "column": re.compile(r'column name="([^"]+)"'),
220
- "percentage": re.compile(r'values are different \(([\d.]+)\s*%\)'),
221
- "first_diff": re.compile(
222
- r'At positional index (\d+), first diff:\s*(.*?)\s*!=\s*(.*)'
223
- ),
224
- }
225
-
226
- for src_file in source_path.glob("*.csv"):
227
- test_file = test_path / src_file.name
228
-
229
- if not test_file.exists():
230
- print(f"[MISSING] {src_file.name} not found in test/")
231
- failed = True
232
- continue
233
-
234
- src_df = pd.read_csv(src_file, low_memory=False)
235
- test_df = pd.read_csv(test_file, low_memory=False)
236
-
237
- src_df = src_df[[col for col in src_df.columns if col not in excluded_columns]]
238
- test_df = test_df[[col for col in test_df.columns if col not in excluded_columns]]
239
-
240
- try:
241
- pd.testing.assert_frame_equal(
242
- src_df,
243
- test_df,
244
- check_dtype=False,
245
- check_like=True
246
- )
247
- print(f"[OK] {src_file.name}")
248
- except AssertionError as e:
249
- parsed_error = str(e)
250
-
251
- column = assertion_error_patterns["column"].search(parsed_error).group(1)
252
- percentage = float(assertion_error_patterns["percentage"].search(parsed_error).group(1))
253
-
254
- first_diff_match = assertion_error_patterns["first_diff"].search(parsed_error)
255
- if first_diff_match:
256
- first_diff = {
257
- "index": int(first_diff_match.group(1)),
258
- "left": first_diff_match.group(2),
259
- "right": first_diff_match.group(3),
260
- }
261
- else:
262
- # pandas uses [index]/[left]/[right] array format when all values differ
263
- idx_match = re.search(r'\[index\]:\s*\[([^]]+)', parsed_error)
264
- left_match = re.search(r'\[left\]:\s*\[([^]]+)', parsed_error)
265
- right_match = re.search(r'\[right\]:\s*\[([^]]+)', parsed_error)
266
- first_diff = {
267
- "index": idx_match.group(1).split(",")[0].strip() if idx_match else "?",
268
- "left": left_match.group(1).split(",")[0].strip() if left_match else "?",
269
- "right": right_match.group(1).split(",")[0].strip() if right_match else "?",
270
- }
271
-
272
- result = {
273
- "column": column,
274
- "percentage_diff": percentage,
275
- "first_diff": first_diff,
276
- }
277
-
278
- print(f"[DIFF] {src_file.name} : Column '{result['column']}‘ (Delta: {result['percentage_diff']:.2f}%)') : "
279
- f"First Diff at index {result['first_diff']['index']} "
280
- f"({result['first_diff']['left']} != {result['first_diff']['right']})")
281
- failed = True
282
-
283
- if failed:
284
- raise AssertionError("Auto-diff failed: source and test outputs differ")
285
-
286
- print("\nAll source vs test outputs are identical ✅")
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes