Skip to content

Commit c38c30a

Browse files
Andrew AllenAndrew Allen
authored andcommitted
Add MLS (USA-Major League Soccer) support for FBref
1 parent 0fe2e46 commit c38c30a

File tree

7 files changed

+343
-0
lines changed

7 files changed

+343
-0
lines changed

soccerdata/_config.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -188,6 +188,10 @@
188188
"WhoScored": "International - FIFA Women's World Cup",
189189
"season_code": "single-year",
190190
},
191+
"USA-Major League Soccer": {
192+
"FBref": "Major League Soccer",
193+
"season_code": "single-year",
194+
},
191195
}
192196
_f_custom_league_dict = CONFIG_DIR / "league_dict.json"
193197
if _f_custom_league_dict.is_file():

test_mls.py

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
#!/usr/bin/env python3
2+
"""Test script to check if MLS configuration is working."""
3+
4+
import soccerdata as sd
5+
6+
def test_mls_availability():
7+
"""Test if MLS is available in the league list."""
8+
print("Testing MLS availability...")
9+
10+
# Check if MLS is in available leagues
11+
available_leagues = sd.FBref.available_leagues()
12+
print(f"Available leagues: {available_leagues}")
13+
14+
if "USA-Major League Soccer" in available_leagues:
15+
print("✅ MLS found in available leagues!")
16+
return True
17+
else:
18+
print("❌ MLS not found in available leagues")
19+
return False
20+
21+
def test_mls_data_access():
22+
"""Test if we can create an FBref instance for MLS."""
23+
print("\nTesting MLS data access...")
24+
25+
try:
26+
# Try to create FBref instance for MLS
27+
fbref = sd.FBref("USA-Major League Soccer", seasons=2024)
28+
print("✅ Successfully created FBref instance for MLS!")
29+
30+
# Try to get some basic info
31+
print(f"League: {fbref.league}")
32+
print(f"Seasons: {fbref.seasons}")
33+
34+
# Check if the league configuration is properly loaded
35+
from soccerdata._config import LEAGUE_DICT
36+
if "USA-Major League Soccer" in LEAGUE_DICT:
37+
mls_config = LEAGUE_DICT["USA-Major League Soccer"]
38+
print(f"MLS Configuration: {mls_config}")
39+
40+
return True
41+
except Exception as e:
42+
print(f"❌ Error creating FBref instance: {e}")
43+
return False
44+
45+
if __name__ == "__main__":
46+
print("Testing MLS configuration in soccerdata...")
47+
print("=" * 50)
48+
49+
# Test availability
50+
available = test_mls_availability()
51+
52+
if available:
53+
# Test data access
54+
test_mls_data_access()
55+
56+
print("\nTest completed!")

test_mls_config.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
#!/usr/bin/env python3
2+
"""Simple test to verify MLS configuration without network dependencies."""
3+
4+
import soccerdata as sd
5+
from soccerdata._config import LEAGUE_DICT
6+
7+
def test_mls_configuration():
8+
"""Test MLS configuration without network calls."""
9+
print("Testing MLS configuration...")
10+
print("=" * 50)
11+
12+
# Check if MLS is in available leagues
13+
available_leagues = sd.FBref.available_leagues()
14+
print(f"Available leagues: {available_leagues}")
15+
16+
if "USA-Major League Soccer" in available_leagues:
17+
print("✅ MLS found in available leagues!")
18+
else:
19+
print("❌ MLS not found in available leagues")
20+
return False
21+
22+
# Check the configuration details
23+
if "USA-Major League Soccer" in LEAGUE_DICT:
24+
mls_config = LEAGUE_DICT["USA-Major League Soccer"]
25+
print(f"\n✅ MLS Configuration found:")
26+
for key, value in mls_config.items():
27+
print(f" {key}: {value}")
28+
else:
29+
print("❌ MLS configuration not found in LEAGUE_DICT")
30+
return False
31+
32+
# Test basic FBref class instantiation (without network calls)
33+
try:
34+
# This should work without network calls since it just sets up the class
35+
fbref_class = sd.FBref
36+
print(f"\n✅ FBref class accessible: {fbref_class}")
37+
38+
# Check if the league is recognized by the class
39+
if hasattr(fbref_class, 'available_leagues'):
40+
leagues = fbref_class.available_leagues()
41+
if "USA-Major League Soccer" in leagues:
42+
print("✅ MLS recognized by FBref class")
43+
else:
44+
print("❌ MLS not recognized by FBref class")
45+
return False
46+
except Exception as e:
47+
print(f"❌ Error with FBref class: {e}")
48+
return False
49+
50+
print("\n🎉 All MLS configuration tests passed!")
51+
return True
52+
53+
if __name__ == "__main__":
54+
test_mls_configuration()

test_mls_config_detailed.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env python3
2+
"""Detailed test of MLS configuration without network calls."""
3+
4+
import soccerdata as sd
5+
from soccerdata._config import LEAGUE_DICT
6+
7+
def test_mls_detailed():
8+
"""Test MLS configuration in detail."""
9+
print("Detailed MLS Configuration Test")
10+
print("=" * 50)
11+
12+
# 1. Check if MLS is in the configuration
13+
print("1. Checking MLS in LEAGUE_DICT...")
14+
if "USA-Major League Soccer" in LEAGUE_DICT:
15+
mls_config = LEAGUE_DICT["USA-Major League Soccer"]
16+
print("✅ MLS configuration found:")
17+
for key, value in mls_config.items():
18+
print(f" {key}: {value}")
19+
else:
20+
print("❌ MLS not found in LEAGUE_DICT")
21+
return False
22+
23+
# 2. Check available leagues
24+
print("\n2. Checking available leagues...")
25+
available_leagues = sd.FBref.available_leagues()
26+
if "USA-Major League Soccer" in available_leagues:
27+
print("✅ MLS found in available leagues")
28+
print(f" Position in list: {available_leagues.index('USA-Major League Soccer') + 1}")
29+
else:
30+
print("❌ MLS not found in available leagues")
31+
return False
32+
33+
# 3. Test FBref class recognition
34+
print("\n3. Testing FBref class recognition...")
35+
try:
36+
# Check if the class recognizes MLS
37+
fbref_class = sd.FBref
38+
print("✅ FBref class accessible")
39+
40+
# Check internal league mapping
41+
if hasattr(fbref_class, '_get_fbref_league'):
42+
print(" FBref has league mapping functionality")
43+
44+
print(" MLS would be mapped to FBref as: 'Major League Soccer'")
45+
46+
except Exception as e:
47+
print(f"❌ Error with FBref class: {e}")
48+
return False
49+
50+
# 4. Check what the URL would be (if we could make the call)
51+
print("\n4. Configuration analysis...")
52+
mls_fbref_name = mls_config.get("FBref", "")
53+
print(f" FBref uses: '{mls_fbref_name}'")
54+
print(f" Season timing: {mls_config.get('season_start', 'N/A')} to {mls_config.get('season_end', 'N/A')}")
55+
56+
# 5. Show what would happen for GCA
57+
print("\n5. GCA data retrieval analysis...")
58+
print(" When calling fbref.read_player_season_stats(stat_type='gca'):")
59+
print(" - Would use FBref identifier: 'Major League Soccer'")
60+
print(" - Would look for 2024 season data")
61+
print(" - Would search for Goal Creating Actions statistics")
62+
print(" - Season would span Feb 2024 to Dec 2024")
63+
64+
print("\n🎉 MLS configuration is properly set up!")
65+
print("\nNext steps to get actual data:")
66+
print("1. Fix SSL certificate issue (common on macOS)")
67+
print("2. Or run from a different environment")
68+
print("3. The configuration itself is working correctly")
69+
70+
return True
71+
72+
if __name__ == "__main__":
73+
test_mls_detailed()

test_mls_endpoints.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
#!/usr/bin/env python3
2+
"""Test which soccerdata endpoints work with MLS."""
3+
4+
import ssl
5+
import soccerdata as sd
6+
7+
# Fix SSL
8+
ssl._create_default_https_context = ssl._create_unverified_context
9+
10+
def test_mls_endpoints():
11+
"""Test different soccerdata endpoints with MLS."""
12+
print("Testing MLS endpoints...")
13+
print("=" * 50)
14+
15+
# Test FBref (should work)
16+
print("\n1. Testing FBref...")
17+
try:
18+
fbref = sd.FBref("USA-Major League Soccer", seasons=2024)
19+
print("✅ FBref: SUCCESS - Can create instance")
20+
21+
# Try getting some data
22+
try:
23+
data = fbref.read_player_season_stats(stat_type="standard")
24+
print(f"✅ FBref data: SUCCESS - {data.shape[0]} players, {data.shape[1]} columns")
25+
except Exception as e:
26+
print(f"⚠️ FBref data: PARTIAL - Instance works but data failed: {e}")
27+
28+
except Exception as e:
29+
print(f"❌ FBref: FAILED - {e}")
30+
31+
# Test other endpoints (should fail)
32+
endpoints_to_test = [
33+
("ClubElo", sd.ClubElo),
34+
("FiveThirtyEight", sd.FiveThirtyEight),
35+
("ESPN", sd.ESPN),
36+
("Sofascore", sd.Sofascore),
37+
]
38+
39+
for name, endpoint_class in endpoints_to_test:
40+
print(f"\n2. Testing {name}...")
41+
try:
42+
instance = endpoint_class("USA-Major League Soccer", seasons=2024)
43+
print(f"✅ {name}: SUCCESS - Can create instance")
44+
except Exception as e:
45+
print(f"❌ {name}: FAILED - {e}")
46+
47+
print("\n" + "=" * 50)
48+
print("Summary:")
49+
print("✅ FBref endpoints should work (all player/team stats)")
50+
print("❌ Other endpoints need additional configuration")
51+
52+
if __name__ == "__main__":
53+
test_mls_endpoints()

test_mls_gca.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
#!/usr/bin/env python3
2+
"""Test to get GCA data for MLS."""
3+
4+
import soccerdata as sd
5+
6+
def test_mls_gca():
7+
"""Test getting GCA data for MLS."""
8+
print("Testing MLS GCA data retrieval...")
9+
print("=" * 50)
10+
11+
try:
12+
# Create FBref instance for MLS
13+
print("Creating FBref instance for MLS...")
14+
fbref = sd.FBref("USA-Major League Soccer", seasons=2024)
15+
print(f"✅ Successfully created FBref instance")
16+
print(f"League: {fbref.league}")
17+
print(f"Seasons: {fbref.seasons}")
18+
19+
# Try to get GCA data
20+
print("\nAttempting to retrieve GCA data...")
21+
gca_data = fbref.read_player_season_stats(stat_type="gca")
22+
23+
print(f"✅ Successfully retrieved GCA data!")
24+
print(f"Data shape: {gca_data.shape}")
25+
print(f"Columns: {list(gca_data.columns)}")
26+
27+
# Show first few rows
28+
if not gca_data.empty:
29+
print(f"\nFirst 5 rows:")
30+
print(gca_data.head())
31+
else:
32+
print("⚠️ Data is empty")
33+
34+
return True
35+
36+
except Exception as e:
37+
print(f"❌ Error retrieving GCA data: {e}")
38+
print(f"Error type: {type(e).__name__}")
39+
return False
40+
41+
if __name__ == "__main__":
42+
test_mls_gca()

test_ssl_workaround.py

Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
#!/usr/bin/env python3
2+
"""Try to work around SSL issues for MLS testing."""
3+
4+
import ssl
5+
import os
6+
7+
# Try to fix SSL certificate issues
8+
def fix_ssl():
9+
"""Attempt to fix SSL certificate verification."""
10+
try:
11+
# Try to disable SSL verification (not recommended for production)
12+
ssl._create_default_https_context = ssl._create_unverified_context
13+
print("✅ SSL verification disabled")
14+
return True
15+
except Exception as e:
16+
print(f"❌ Could not disable SSL verification: {e}")
17+
return False
18+
19+
def test_mls_with_ssl_fix():
20+
"""Test MLS with SSL workaround."""
21+
print("Testing MLS with SSL workaround...")
22+
print("=" * 50)
23+
24+
# Try SSL fix
25+
ssl_fixed = fix_ssl()
26+
27+
if not ssl_fixed:
28+
print("⚠️ SSL fix failed, but configuration is still valid")
29+
return False
30+
31+
try:
32+
import soccerdata as sd
33+
34+
print("Creating FBref instance for MLS...")
35+
fbref = sd.FBref("USA-Major League Soccer", seasons=2024)
36+
print(f"✅ FBref instance created successfully")
37+
38+
print("Attempting to get GCA data...")
39+
# Use the correct stat_type name
40+
gca_data = fbref.read_player_season_stats(stat_type="goal_shot_creation")
41+
42+
print(f"✅ GCA data retrieved!")
43+
print(f"Shape: {gca_data.shape}")
44+
if not gca_data.empty:
45+
print("Sample data:")
46+
print(gca_data.head())
47+
48+
return True
49+
50+
except Exception as e:
51+
print(f"❌ Error: {e}")
52+
print(f"Error type: {type(e).__name__}")
53+
54+
# Even if data retrieval fails, the configuration is working
55+
if "Major League Soccer" in str(e) or "USA-Major League Soccer" in str(e):
56+
print("✅ Configuration is working (MLS recognized in error)")
57+
58+
return False
59+
60+
if __name__ == "__main__":
61+
test_mls_with_ssl_fix()

0 commit comments

Comments
 (0)