-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 6bd2b5e
Showing
15 changed files
with
661 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.idea | ||
*.env | ||
__pycache__ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
Release History | ||
=============== | ||
|
||
0.0.1 (2022-01-29) | ||
------------------ | ||
|
||
- Soccer: get_elo_season, get_elo_match | ||
- Database: data_query, command_query, write_dataframe, get_engine | ||
- Credentials: set_credentials | ||
- Datasets: list_datasets, load_dataset. copa_rayados.2021.csv dataset |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
""" | ||
KonoPyUtil Library | ||
~~~~~~~~~~~~~~~~~~ | ||
KonoPyUtil is a library of convenience fuctions, written in Python, for Kono Analytics and anyone else who wants to use it. | ||
Basic usage: | ||
>>> import KonoPyUtil as kpu | ||
>>> credentials = kpu.set_credentials('.env') | ||
>>> query = "SELECT TOP 10 * FROM [mytable];" | ||
>>> df = kpu.data_query(query) | ||
:license: Apache 2.0, see LICENSE for more details. | ||
""" | ||
|
||
|
||
from .__version__ import ( | ||
__title__, | ||
__description__, | ||
__url__, | ||
__version__, | ||
__author__, | ||
__author_email__, | ||
__license__, | ||
__copyright__, | ||
) | ||
|
||
from .dbutils import ( | ||
data_query, | ||
command_query, | ||
write_dataframe, | ||
get_engine, | ||
) | ||
from .credentials import ( | ||
set_credentials, | ||
) | ||
from .datasets import list_datasets, load_dataset | ||
from .soccer import get_elo_season, get_elo_match | ||
import logging | ||
|
||
logging.getLogger(__name__).addHandler(logging.NullHandler()) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
__title__ = "KonoPyUtil" | ||
__description__ = "Python Utilities for Kono Analytics" | ||
__url__ = "https://konoanalytics.com" | ||
__version__ = "0.0.1" | ||
__author__ = "Jonathan Bennett" | ||
__author_email__ = "[email protected]" | ||
__license__ = "Apache 2.0" | ||
__copyright__ = "Copyright 2022 Jonathan Bennett" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
import os | ||
import json | ||
from environs import Env | ||
|
||
|
||
def set_credentials(file_and_path_to_credential_file=".env", recurse=False): | ||
""" | ||
Loads credential file into O/S environment if a file_and_path_to_credential_file is not None | ||
overwrites DB_CREDENTIALS O/S environment variable | ||
returns DB_CREDENTIALS as a dictionary | ||
credential_file should be formatted as follows: | ||
DB_CREDENTIALS='{"DBNAME": "postgres", "SCHEMA": "public", "USERID": "useridhere", "PASSWORD": "passwordhere", "HOST": "path_to_database_here", "PORT": "port_here"}' | ||
:param file_and_path_to_dot_env: defaults to .env, uf yi | ||
:param recurse: Boolean = if True recursively search upward for a .env file | ||
:return: dictionary of database credentials if present, or empty dictionary otherwise | ||
""" | ||
if file_and_path_to_credential_file: | ||
# clear existing "DB_CREDENTIALS" environment variable | ||
try: | ||
del os.environ["DB_CREDENTIALS"] | ||
except KeyError: | ||
pass | ||
finally: | ||
env = Env() | ||
file_and_path_formatted = os.path.abspath(file_and_path_to_credential_file) | ||
env.read_env(file_and_path_formatted, recurse=recurse) | ||
if "DB_CREDENTIALS" in os.environ: | ||
return dict(json.loads(os.environ["DB_CREDENTIALS"])) | ||
else: | ||
return {} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,60 @@ | ||
match,game_time,home_name,away_name,home_score,away_score,game_description | ||
527,11/24/2021 11:00,TEXAS TIGRES 09',CHELSEA EAST 09,2,2, | ||
561,11/24/2021 11:00,EP LOCOMOTIVE FC EP LOCOMOT,HOUSTONIANS FC 09B,0,0, | ||
562,11/24/2021 11:00,AZTECAS FUTBOL AZTECAS FC 09B Blue,MSK RAYADOS 09B,1,0, | ||
536,11/24/2021 11:30,BARÇA ACADEMY NASHVILLE BAR,SPORTS GROUP 1 SG1 09B,0,0, | ||
537,11/24/2021 11:30,PRIMOS FC,AVANTI SOCCER ACADEMY 09B,0,1, | ||
546,11/24/2021 12:15,RAPIDS SOUTH 09B ELITE,ALBION HURRICANES AHFC 09B,1,2, | ||
547,11/24/2021 12:15,AVANTI SOCCER ACADEMY 09B WEST,ASPIRE FC 09 YELLOW,4,0, | ||
526,11/24/2021 13:30,CADENCE SFC 2009 ACADEMY,RISE SC RISE U13B ECNL,0,1, | ||
559,11/24/2021 14:45,AZTECAS FUTBOL AZTECAS FC 09B Blue,HOUSTONIANS FC 09B,0,2, | ||
560,11/24/2021 15:15,IMPERIAL SC 09B,ID CHELSEA JR 09B Q,2,3, | ||
525,11/24/2021 16:00,CHELSEA EAST 09,ID REAL HOUSTON 09B Q,0,2, | ||
544,11/24/2021 16:00,AVANTI SOCCER ACADEMY 09B WEST,ALBION HURRICANES AHFC 09B,2,0, | ||
535,11/24/2021 16:30,AVANTI SOCCER ACADEMY 09B,DYNAMO WOODLANDS 09 PA,1,1, | ||
545,11/24/2021 17:15,SOCCER CENTRO 09,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,1,1, | ||
528,11/25/2021 08:15,CADENCE SFC 2009 ACADEMY,CHELSEA EAST 09,0,1, | ||
530,11/25/2021 08:15,RISE SC RISE U13B ECNL,ID REAL HOUSTON 09B Q,1,4, | ||
541,11/25/2021 08:15,BARÇA ACADEMY NASHVILLE BAR,PRIMOS FC,0,1, | ||
563,11/25/2021 08:15,EP LOCOMOTIVE FC EP LOCOMOT,ID CHELSEA JR 09B Q,0,2, | ||
564,11/25/2021 09:00,AZTECAS FUTBOL AZTECAS FC 09B Blue,IMPERIAL SC 09B,1,1, | ||
551,11/25/2021 11:30,SOCCER CENTRO 09,RAPIDS SOUTH 09B ELITE,0,3, | ||
566,11/25/2021 11:30,EP LOCOMOTIVE FC EP LOCOMOT,IMPERIAL SC 09B,3,0, | ||
538,11/26/2021 08:00,BARÇA ACADEMY NASHVILLE BAR,AVANTI SOCCER ACADEMY 09B,1,1, | ||
552,11/26/2021 08:00,AVANTI SOCCER ACADEMY 09B WEST,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,1,0, | ||
554,11/26/2021 08:00,SOCCER CENTRO 09,ALBION HURRICANES AHFC 09B,0,4, | ||
540,11/26/2021 08:30,DYNAMO WOODLANDS 09 PA,SPORTS GROUP 1 SG1 09B,1,1, | ||
572,11/26/2021 08:30,ID CHELSEA JR 09B Q,MSK RAYADOS 09B,0,1, | ||
531,11/26/2021 09:00,CADENCE SFC 2009 ACADEMY,TEXAS TIGRES 09',1,5, | ||
548,11/26/2021 09:00,RAPIDS SOUTH 09B ELITE,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,1,0, | ||
550,11/26/2021 09:00,ALBION HURRICANES AHFC 09B,ASPIRE FC 09 YELLOW,3,0, | ||
568,11/26/2021 09:00,EP LOCOMOTIVE FC EP LOCOMOT,AZTECAS FUTBOL AZTECAS FC 09B Blue,6,0, | ||
539,11/26/2021 09:45,PRIMOS FC,DYNAMO WOODLANDS 09 PA,1,0, | ||
553,11/26/2021 11:00,SOCCER CENTRO 09,ASPIRE FC 09 YELLOW,3,0, | ||
532,11/26/2021 11:10,CHELSEA EAST 09,RISE SC RISE U13B ECNL,0,0, | ||
569,11/26/2021 12:15,IMPERIAL SC 09B,MSK RAYADOS 09B,5,0, | ||
529,11/26/2021 12:20,TEXAS TIGRES 09',ID REAL HOUSTON 09B Q,0,4, | ||
570,11/26/2021 12:30,ID CHELSEA JR 09B Q,HOUSTONIANS FC 09B,4,0, | ||
542,11/26/2021 13:30,AVANTI SOCCER ACADEMY 09B,SPORTS GROUP 1 SG1 09B,0,1, | ||
556,11/26/2021 13:45,RAPIDS SOUTH 09B ELITE,AVANTI SOCCER ACADEMY 09B WEST,0,0, | ||
557,11/26/2021 15:00,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,ASPIRE FC 09 YELLOW,2,1, | ||
534,11/26/2021 17:15,PRIMOS FC,SPORTS GROUP 1 SG1 09B,0,1, | ||
533,11/26/2021 17:45,BARÇA ACADEMY NASHVILLE BAR,DYNAMO WOODLANDS 09 PA,1,1, | ||
523,11/26/2021 19:20,CADENCE SFC 2009 ACADEMY,ID REAL HOUSTON 09B Q,0,4, | ||
524,11/26/2021 19:20,TEXAS TIGRES 09',RISE SC RISE U13B ECNL,0,0, | ||
565,11/26/2021 21:45,MSK RAYADOS 09B,HOUSTONIANS FC 09B,0,1, | ||
574,11/27/2021 08:15,SPORTS GROUP 1 SG1 09B,AVANTI SOCCER ACADEMY 09B WEST,0,4,gold semi | ||
580,11/27/2021 08:15,AVANTI SOCCER ACADEMY 09B,RAPIDS SOUTH 09B ELITE,0,4,bronze semi | ||
585,11/27/2021 08:30,CADENCE SFC 2009 ACADEMY,AZTECAS FUTBOL AZTECAS FC 09B Blue,1,5,quartz semi | ||
586,11/27/2021 08:30,DYNAMO WOODLANDS 09 PA,SOCCER CENTRO 09,5,4,quartz semi | ||
573,11/27/2021 10:00,ID REAL HOUSTON 09B Q,ID CHELSEA JR 09B Q,1,2,gold semi | ||
579,11/27/2021 10:00,CHELSEA EAST 09,HOUSTONIANS FC 09B,1,3,bronze semi | ||
582,11/27/2021 10:00,RISE SC RISE U13B ECNL,IMPERIAL SC 09B,1,2,copper semi | ||
583,11/27/2021 10:00,BARÇA ACADEMY NASHVILLE BAR,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,2,4,copper semi | ||
576,11/27/2021 11:45,TEXAS TIGRES 09',EP LOCOMOTIVE FC EP LOCOMOT,0,2,silver semi | ||
577,11/27/2021 12:00,PRIMOS FC,ALBION HURRICANES AHFC 09B,0,8,silver semi | ||
581,11/28/2021 13:15,HOUSTONIANS FC 09B,RAPIDS SOUTH 09B ELITE,0,3,bronze final | ||
575,11/28/2021 13:30,ID CHELSEA JR 09B Q,AVANTI SOCCER ACADEMY 09B WEST,0,1,gold final | ||
587,11/28/2021 14:40,AZTECAS FUTBOL AZTECAS FC 09B Blue,DYNAMO WOODLANDS 09 PA,3,1,quartz final | ||
578,11/28/2021 15:15,EP LOCOMOTIVE FC EP LOCOMOT,ALBION HURRICANES AHFC 09B,1,0,silver final | ||
584,11/28/2021 15:15,IMPERIAL SC 09B,DDYSC HOUSTON DYNAMO YOUTH ECNL RL 09,2,0,copper final |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import os | ||
import pandas as pd | ||
|
||
|
||
def list_datasets(): | ||
""" | ||
List all datasets in KonoPyUtil library | ||
:return: a list of filenames corresponding to datasets | ||
""" | ||
_here = os.path.abspath(os.path.dirname(__file__)) | ||
data_directory = os.path.join(_here, "data") | ||
return os.listdir(data_directory) | ||
|
||
|
||
def load_dataset(dataset): | ||
""" | ||
Loads a specific dataset in KonoPyUtil library | ||
:param dataset: name of dataset (options can be found via list_datasets() | ||
:return: a Pandas dataframe of the requested dataset | ||
""" | ||
_here = os.path.abspath(os.path.dirname(__file__)) | ||
file_and_path = os.path.join(_here, "data", dataset) | ||
if dataset in list_datasets(): | ||
return pd.read_csv(file_and_path) | ||
return pd.DataFrame() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,86 @@ | ||
import sqlalchemy as sa | ||
import pandas as pd | ||
from .credentials import set_credentials | ||
from .exceptions import MissingCredentialsError | ||
|
||
|
||
def data_query(query, engine=None, **kwargs): | ||
""" | ||
consumes a select query and returns a dataframe with the results | ||
:param query: string of query | ||
:param engine: sql alchemy engine | ||
:param **kwargs: remaining parameters for pandas.read_sql() | ||
:return: dataframe of results of query | ||
""" | ||
close_engine = False | ||
if engine is None: | ||
close_engine = True | ||
engine = get_engine(**kwargs) | ||
df = pd.read_sql(query, engine) | ||
if close_engine: | ||
engine.dispose() | ||
return df | ||
|
||
|
||
def command_query(query, engine=None, **kwargs): | ||
""" | ||
consumes a command query (update, drop, etc) | ||
:param query: string of query | ||
:param engine: sql alchemy engine | ||
:return: returns result of query execution | ||
""" | ||
close_engine = False | ||
if engine is None: | ||
close_engine = True | ||
engine = get_engine(**kwargs) | ||
if close_engine: | ||
engine.dispose() | ||
return engine.execute(sa.text(query).execution_options(autocommit=True)) | ||
|
||
|
||
def write_dataframe(df, tablename, engine, if_exists="append", index=False, **kwargs): | ||
""" | ||
Appends dataframe records to a database. (Creates table if it doesn't exist) | ||
:param df: dataframe | ||
:param tablename: table name | ||
:param engine: engine | ||
:param if_exists: {‘fail’, ‘replace’, ‘append’}, default ‘append’ | ||
:param **kwargs: remaining parameters for pandas.to_sql() | ||
:return: True if success, False otherwise | ||
""" | ||
|
||
close_engine = False | ||
if engine is None: | ||
close_engine = True | ||
engine = get_engine(**kwargs) | ||
try: | ||
df.to_sql(name=tablename, con=engine, if_exists=if_exists, index=index) | ||
engine.dispose() | ||
success = True | ||
except Exception as ex: | ||
template = "An exception of type {0} occurred. Arguments:\n{1!r}" | ||
message = template.format(type(ex).__name__, ex.args) | ||
print(message) | ||
success = False | ||
finally: | ||
if close_engine: | ||
engine.dispose() | ||
return success | ||
|
||
|
||
def get_engine(credentials=None, **kwargs): | ||
""" | ||
Returns a sqlalchemy engine given appropriate inputs | ||
:param **kwargs: remaining parameters for sqlalchemy.create_engine() | ||
""" | ||
if not credentials: | ||
os_credentials = set_credentials() | ||
if not os_credentials: | ||
raise (MissingCredentialsError()) | ||
userid = os_credentials.get("USERID", "db_userid") | ||
password = os_credentials.get("PASSWORD", "db_password") | ||
host = os_credentials.get("HOST", "db_host") | ||
port = int(os_credentials.get("PORT", "0")) | ||
dbname = os_credentials.get("DBNAME", "db_name") | ||
cstring = f"postgresql://{userid}:{password}@{host}:{port}/{dbname}" | ||
return sa.create_engine(cstring, **kwargs) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,19 @@ | ||
class ParameterError(Exception): | ||
def __init__(self, valid_parameters, bad_parameter): | ||
self.valid_parameters = valid_parameters | ||
self.bad_parameter = bad_parameter | ||
|
||
def __str__(self): | ||
return repr(f"""Valid Option: {self.valid_parameters}. Option Provided: {self.bad_parameter}""") | ||
|
||
|
||
class MissingCredentialsError(Exception): | ||
def __init__( | ||
self, | ||
): | ||
pass | ||
|
||
def __str__(self): | ||
return repr( | ||
f"""Your credentials are missing. Try KonoPyUtil.set_credentials() to set an environment variable named DB_CREDENTIALS.""" | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
from .elo import get_elo_season, get_elo_match |
Oops, something went wrong.