diff --git a/app.py b/app.py index f033f91..3e337bd 100644 --- a/app.py +++ b/app.py @@ -6,21 +6,33 @@ app = Dash(__name__, use_pages=True) app.layout = html.Div( [ - html.H1("MonkeyPox Radar", style={'display':'inline-block'}), - - html.Img(src=r'assets/hpi_logo.png',alt='Img_HPI', style={'float':'right', 'height':'15%', 'width':'15%'}), - html.Img(src=r'assets/rki_logo.png',alt='Img_RKI', style={'float':'right', 'height':'15%', 'width':'15%'}), - html.Img(src=r'assets/DAKI-FWS_logo.png',alt='Img_DAKI-FWS', style={'float':'right', 'height':'15%', 'width':'15%'}), - + html.H1("MonkeyPox Radar", style={"display": "inline-block"}), + html.Img( + src=r"assets/hpi_logo.png", + alt="Img_HPI", + style={"float": "right", "height": "15%", "width": "15%"}, + ), + html.Img( + src=r"assets/rki_logo.png", + alt="Img_RKI", + style={"float": "right", "height": "15%", "width": "15%"}, + ), + html.Img( + src=r"assets/DAKI-FWS_logo.png", + alt="Img_DAKI-FWS", + style={"float": "right", "height": "15%", "width": "15%"}, + ), html.Div("A genomic surveiillance dashboard for MonkeyPox."), html.Br(), html.Div( [ html.Div( dcc.Link( - html.A(f"{page['name']}"), href=page["relative_path"], style={'color':'black', 'display':'inline-block'} + html.A(f"{page['name']}"), + href=page["relative_path"], + style={"color": "black", "display": "inline-block"}, ) - #f"{page['name']}", href=page["relative_path"] + # f"{page['name']}", href=page["relative_path"] ) for page in dash.page_registry.values() ] @@ -31,24 +43,39 @@ html.Hr(), html.Br(), # style={'height':'99999999px;', 'width':'100%', 'bottom':'0', 'left':'0', 'position':'absolute'} - html.Footer([ - html.A("About MPXRadar", href="About", style={'color':'black', 'display':'inline-block'}), - html.Div(children="Supported by:", style={'float':'right', "margin-right": "250px"}), - html.Br(), - html.A("Contact Us", href="Contact", style={'color':'black'}), - html.Br(), - html.A("Imprint", href="Home", style={'color':'black'}), - html.Br(), - html.A("App:", href="Tool", style={'color':'black'}), - - - - html.Img(src=r'assets/denbi_cloud_logo.png',alt='Img_RKI', style={'float':'right', 'height':'15%', 'width':'15%'}), - html.Div(children="on the basis of a decision"), - html.Div(children="by the German Bundestag"), - html.Img(src=r'assets/Bundesministerium_für_Wirtschaft_und_Energie_Logo.svg.png',alt='Img_RKI', style={'float':'right', 'height':'15%', 'width':'15%'}),]), + html.Footer( + [ + html.A( + "About MPXRadar", + href="About", + style={"color": "black", "display": "inline-block"}, + ), + html.Div( + children="Supported by:", + style={"float": "right", "margin-right": "250px"}, + ), + html.Br(), + html.A("Contact Us", href="Contact", style={"color": "black"}), + html.Br(), + html.A("Imprint", href="Home", style={"color": "black"}), + html.Br(), + html.A("App:", href="Tool", style={"color": "black"}), + html.Img( + src=r"assets/denbi_cloud_logo.png", + alt="Img_RKI", + style={"float": "right", "height": "15%", "width": "15%"}, + ), + html.Div(children="on the basis of a decision"), + html.Div(children="by the German Bundestag"), + html.Img( + src=r"assets/Bundesministerium_für_Wirtschaft_und_Energie_Logo.svg.png", + alt="Img_RKI", + style={"float": "right", "height": "15%", "width": "15%"}, + ), + ] + ), ] ) if __name__ == "__main__": - app.run_server(debug=True, host="0.0.0.0") \ No newline at end of file + app.run_server(debug=True, host="0.0.0.0") diff --git a/assets/style.css b/assets/style.css index 5192d03..1ed310f 100644 --- a/assets/style.css +++ b/assets/style.css @@ -2,4 +2,4 @@ width: 100%; max-width: 400px; height: auto; - } \ No newline at end of file + } diff --git a/example.app.py b/example_app.py similarity index 68% rename from example.app.py rename to example_app.py index d70fe2e..bc3386f 100644 --- a/example.app.py +++ b/example_app.py @@ -10,8 +10,11 @@ from dash import State import dash_bootstrap_components as dbc from dotenv import load_dotenv +import pandas as pd +from pages.app_controller import get_all_references from pages.app_controller import get_freq_mutation +from pages.app_controller import get_value_by_reference from pages.app_controller import match_controller from pages.app_controller import sonarBasicsChild from pages.libs.mpxsonar.src.mpxsonar.sonar import parse_args @@ -20,6 +23,53 @@ # stylesheet with the .dbc class dbc_css = "https://cdn.jsdelivr.net/gh/AnnMarieW/dash-bootstrap-templates/dbc.min.css" app = Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP, dbc_css]) +df = pd.DataFrame( + { + "First Name": ["Arthur", "Ford", "Zaphod", "Trillian"], + "Last Name": ["Dent", "Prefect", "Beeblebrox", "Astra"], + } +) +# preload +dat_checkbox_list_of_dict = get_all_references() + + +tool_checkbox_cards = html.Div( + [ + dbc.Card( + [ + dbc.CardBody( + [ + dbc.CardHeader("FILTER"), + dbc.Row( + [ + html.H3("Reference", className="card-title"), + dbc.Col( + [ + dcc.Checklist( + id="reference-selection", + options=dat_checkbox_list_of_dict, + labelStyle={"display": "block"}, + style={ + "height": 100, + "width": 200, + "overflow": "auto", + }, + ) + ] + ), + dbc.Spinner(html.Div(id="loading-output")), + html.Div(id="display-selected-values"), + html.Hr(), + html.Div(id="table1-results"), + ] + ), + ] + ), + ] + ), + ] +) + custom_cmd_cards = html.Div( [ dbc.Card( @@ -113,7 +163,7 @@ "1.The output will be showed in the below section." ), html.Ul( - "2. Available reference: NC_063383.1, NC_003310.1, ON563414.3, MN648051.1, MT903344.1, ON585033.1, and ON568298.1 " + "2. Available reference: NC_063383.1, ON563414.3 and MT903344.1" ), ], title="Note>", @@ -131,10 +181,32 @@ id="cmd-1", ), dbc.Badge( - "match --profile del:1-6", + "match --profile del:1-60", + color="white", + text_color="primary", + className="border me-1", + id="cmd-3", + ), + dbc.Badge( + "match --profile ^C162331T", color="white", text_color="primary", className="border me-1", + id="cmd-4", + ), + dbc.Badge( + "match --profile OPG188:L246F --profile MPXV-UK_P2-164:L246F ", + color="white", + text_color="primary", + className="border me-1", + id="cmd-5", + ), + dbc.Badge( + "match --profile A151461C del:=1-=6", + color="white", + text_color="primary", + className="border me-1", + id="cmd-8", ), dbc.Badge( "match --LENGTH >197120 <197200", @@ -148,6 +220,7 @@ color="white", text_color="primary", className="border me-1", + id="cmd-9", ), dbc.Badge( "list-prop", @@ -168,6 +241,30 @@ "List all properties", target="cmd-7", ), + dbc.Tooltip( + "Select all samples that have or in range 1-60 deletion mutation (e.g., del:1-60, del:1-6, del:11-20)", + target="cmd-3", + ), + dbc.Tooltip( + "Select all samples except samples contain C162331T mutation (^ = exclude)", + target="cmd-4", + ), + dbc.Tooltip( + "Combine with 'OR'; for example, get all samples that have mutation at 'OPG188:L246F' OR 'MPXV-UK_P2-164:L246F' (format, GENE/TAG:protien mutation)", + target="cmd-5", + ), + dbc.Tooltip( + "Get all samples ", + target="cmd-6", + ), + dbc.Tooltip( + "'AND' operation; for example, get all samples that have mutation at A151461C and exact 1-6 deletion", + target="cmd-8", + ), + dbc.Tooltip( + "Get sample by name", + target="cmd-9", + ), ], title="Example commands...", ), @@ -209,6 +306,10 @@ style_data={ "whiteSpace": "normal", "height": "auto", + # all three widths are needed + "minWidth": "300px", + "width": "300px", + "maxWidth": "300px", }, style_table={"overflowX": "auto"}, export_format="csv", @@ -227,7 +328,7 @@ app.layout = dbc.Container( [ - dbc.Row([]), + dbc.Row([tool_checkbox_cards]), html.Hr(), dbc.Row( [ @@ -239,6 +340,29 @@ ) +@app.callback( + Output("loading-output", "children"), + Output("display-selected-values", "children"), + Output("table1-results", "children"), + Input(component_id="reference-selection", component_property="value"), +) +def checkbox(checked_value): + output_df = "" + print(checked_value) + if len(checked_value) == 0: + return "", "", output_df + else: + output_df = get_value_by_reference(checked_value) + print(len(output_df)) + return ( + "", + "{}".format(checked_value), + dbc.Table.from_dataframe( + output_df[0:5], striped=True, bordered=True, hover=True + ), + ) + + @app.callback( Output(component_id="my-command", component_property="children"), Input(component_id="my-input", component_property="value"), diff --git a/mpx-project.ini b/mpx-project.ini new file mode 100644 index 0000000..e69de29 diff --git a/pages/DBManager.py b/pages/DBManager.py index d89062b..46dff32 100644 --- a/pages/DBManager.py +++ b/pages/DBManager.py @@ -1 +1,140 @@ # just in case for some query we can use a direct connect to database. +import sys +from urllib.parse import urlparse + +import mariadb + +from .config import DB_URL +from .config import logging_radar + + +class DBManager(object): + """ + This object provides a DB manager handler managing connections and + providing context-safe transaction control. + """ + + def __init__(self, db_url=None, readonly=True): + + if db_url is None: + db_url = DB_URL + + # public attributes + self.connection = None + self.dbfile = db_url # os.path.abspath(dbfile) + self.cursor = None + self.__references = {} + self.__uri = self.get_uri(db_url) + self.__mode = "ro" if readonly else "rwc" + self.db_user = self.__uri.username + self.db_pass = self.__uri.password + self.db_url = self.__uri.hostname + self.db_port = self.__uri.port + self.db_database = self.__uri.path.replace("/", "") + + def __enter__(self): + """establish connection and start transaction when class is initialized""" + self.connection, self.cursor = self.connect() + self.start_transaction() + return self + + def __exit__(self, exc_type, exc_value, exc_traceback): + """close connection and - if errors occured - rollback when class is exited""" + if [exc_type, exc_value, exc_traceback].count(None) != 3: + if self.__mode == "rwc": + print("Rollback database", file=sys.stderr) + self.rollback() + elif self.__mode == "rwc": + self.commit() + self.close() + + def __del__(self): + """close connection when class is deleted""" + if self.connection: + # self.close() + self.conection = None + # logging.debug("Connection Closed") + + def connect(self): + """connect to database""" + # con = sqlite3.connect( + # self.__uri + "?mode=" + self.__mode, + # self.__timeout, + # isolation_level=None, + # uri=True, + # ) + try: + db_user = self.db_user + db_pass = self.db_pass + db_url = self.db_url + db_port = self.db_port + db_database = self.db_database + # logging.debug(f"{db_user}, {db_url}, {db_port}, {db_database}") + con = mariadb.connect( + user=db_user, + password=db_pass, + host=db_url, + port=db_port, + database=db_database, + ) + except mariadb.Error as e: + logging_radar.error(f"Error connecting to MariaDB Platform: {e}") + sys.exit(1) + + # if self.debug: + # con.set_trace_callback(logging.debug) + con.row_factory = self.dict_factory + cur = con.cursor(dictionary=True) + return con, cur + + @staticmethod + def dict_factory(cursor, row): + d = {} # OrderedDict() + for idx, col in enumerate(cursor.description): + d[col[0]] = row[idx] + return d + + def get_uri(self, db_url): + """ + returns username password host port + + """ + parsed_obj = urlparse(db_url) + return parsed_obj + + def start_transaction(self): + self.cursor.execute("START TRANSACTION;") + + def new_transaction(self): + """commit and start new transaction""" + self.commit() + self.start_transaction() + + def commit(self): + """commit""" + self.connection.commit() + + def rollback(self): + """roll back""" + self.connection.rollback() + + def close(self): + """close database connection""" + self.cursor.close() + self.connection.close() + + @property + def references(self): + """ + return all references + + """ + if self.__references == {}: + sql = "SELECT `id`, `accession`, `description`, `organism` FROM reference;" + self.cursor.execute(sql) + rows = self.cursor.fetchall() + if rows: + self.__references = rows + else: + self.__references = {} + return self.__references diff --git a/pages/about.py b/pages/about.py index d69c8ac..3056988 100644 --- a/pages/about.py +++ b/pages/about.py @@ -1,12 +1,12 @@ -import dash_bootstrap_components as dbc import dash -from dash import html, dcc +from dash import dcc +from dash import html +import dash_bootstrap_components as dbc -dash.register_page(__name__, path='/About') +dash.register_page(__name__, path="/About") layout = html.Div( children=[ - html.H1(children="Project Description"), html.Div( children=""" @@ -16,142 +16,222 @@ Therefore, the Robert Koch Institute (RKI) together with the Hasso Platter Institute (HPI) joined forces to and adapted the tool covSonar - a database framework developed at the RKI for SARS-CoV-2 - to Monkeypox. """ ), - html.H1(children="Who are we?"), dbc.Card( [ - dbc.CardImg(src="assets/Prof. Dr. Bernhard Renard.jpeg", - top=True, style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Prof. Dr. Bernhard Renard.jpeg", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Prof. Dr. Bernhard Renard", className="card-title" - ), + html.P("Prof. Dr. Bernhard Renard", className="card-title"), ] ), - ], style={"width": "15rem", "margin-left": "2rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-left": "2rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ - dbc.CardImg(src="assets/Dr. Stephan Fuchs.png", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Dr. Stephan Fuchs.png", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Dr. Stephan Fuchs", className="card-text" - ), + html.P("Dr. Stephan Fuchs", className="card-text"), ] ), - ], style={"width": "15rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={"width": "15rem", "margin-right": "5rem", "display": "inline-block"}, + ), dbc.Card( [ - dbc.CardImg(src="assets/Dr. Anna-Juliane Schmachtenberg.jpeg", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Dr. Anna-Juliane Schmachtenberg.jpeg", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Dr. Anna-Juliane Schmachtenberg" - ), + html.P("Dr. Anna-Juliane Schmachtenberg"), ] ), - ], style={"width": "15rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={"width": "15rem", "margin-right": "5rem", "display": "inline-block"}, + ), dbc.Card( [ - dbc.CardImg(src="assets/Alice Wittig.jpeg", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Alice Wittig.jpeg", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Alice Wittig" - ), + html.P("Alice Wittig"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-left": "2rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-left": "2rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ - dbc.CardImg(src="assets/Ferdous Nasri.jpeg", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Ferdous Nasri.jpeg", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Ferdous Nasri" - ), + html.P("Ferdous Nasri"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ dbc.CardImg( - src="https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png", top=True, style={"width": "238px", "height": "300px"}, className='align-self-center'), + src="https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Kunaphas Kongkitimanon" - ), + html.P("Kunaphas Kongkitimanon"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ dbc.CardImg( - src="https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png", top=True, style={"width": "238px", "height": "300px"}, className='align-self-center'), + src="https://upload.wikimedia.org/wikipedia/commons/9/99/Sample_User_Icon.png", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Jorge Sanchez-Cortes" - ), + html.P("Jorge Sanchez-Cortes"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-left": "2rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-left": "2rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ - dbc.CardImg(src="assets/Injun Park.jpeg", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Injun Park.jpeg", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Injun Park" - ), + html.P("Injun Park"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ - dbc.CardImg(src="assets/Ivan Tunov.png", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Ivan Tunov.png", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Ivan Tunov" - ), + html.P("Ivan Tunov"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-right": "5rem", 'display': 'inline-block'},), + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), dbc.Card( [ - dbc.CardImg(src="assets/Pavlo Konoplev.png", top=True, - style={"width": "238px", "height": "300px"}, className='align-self-center'), + dbc.CardImg( + src="assets/Pavlo Konoplev.png", + top=True, + style={"width": "238px", "height": "300px"}, + className="align-self-center", + ), dbc.CardBody( [ - html.P( - "Pavlo Konoplev" - ), + html.P("Pavlo Konoplev"), ] ), - ], style={"width": "15rem", "margin-top": "1rem", "margin-left": "2rem", "margin-right": "5rem", 'display': 'inline-block'},), - - - + ], + style={ + "width": "15rem", + "margin-top": "1rem", + "margin-left": "2rem", + "margin-right": "5rem", + "display": "inline-block", + }, + ), html.H1(children="Data sources:"), html.Div( children=""" ... """ ), - html.H1(children="Link to code:"), - dcc.Link(html.A('Link to Github'), href=( - 'https://github.com/ferbsx/MPXRadar-frontend'), target='_blank'), - + dcc.Link( + html.A("Link to Github"), + href=("https://github.com/ferbsx/MPXRadar-frontend"), + target="_blank", + ), html.H1(children="Acknowledgements:"), html.Div( children=""" diff --git a/pages/app_controller.py b/pages/app_controller.py index 11db6b8..151a290 100644 --- a/pages/app_controller.py +++ b/pages/app_controller.py @@ -2,12 +2,13 @@ # -*- coding: utf-8 -*- # DEPENDENCIES - import sys from textwrap import fill import pandas as pd +from .config import DB_URL +from .DBManager import DBManager from .libs.mpxsonar.src.mpxsonar.basics import sonarBasics from .libs.mpxsonar.src.mpxsonar.dbm import sonarDBManager @@ -100,12 +101,23 @@ def list_prop(db=None): rows[-1].append(dt) rows[-1].append(dbm.properties[prop]["querytype"]) rows[-1].append(dbm.properties[prop]["standard"]) - # output = tabulate(rows, headers=cols, tablefmt="orgtbl") # output = output + "\n" # output = output + "DATE FORMAT" + "\n" output = pd.DataFrame(rows, columns=cols) - print(output) + # remove some column + output = output[ + ~output["name"].isin( + [ + "AA_PROFILE", + "AA_X_PROFILE", + "NUC_N_PROFILE", + "NUC_PROFILE", + "IMPORTED", + "MODIFIED", + ] + ) + ] return output @@ -170,3 +182,26 @@ def match_controller(args): # noqa: C901 reference=args.reference, ) return output + + +def get_all_references(): + _list = [] + with DBManager() as dbm: + list_dict = dbm.references + for _dict in list_dict: + # print(_dict) + _list.append({"value": _dict["accession"], "label": _dict["accession"]}) + # logging_radar.info(_dict) + return _list + + +def get_value_by_reference(checked_ref): + output_df = pd.DataFrame() + for ref in checked_ref: + print("Query " + ref) + _df = sonarBasicsChild.match(DB_URL, reference=ref, debug="False") + if type(_df) == str: + continue + output_df = pd.concat([output_df, _df], ignore_index=True) + + return output_df diff --git a/pages/config.py b/pages/config.py index d75d4b5..f2fea2b 100644 --- a/pages/config.py +++ b/pages/config.py @@ -1,7 +1,33 @@ -# +import logging +import os +from dotenv import load_dotenv + +load_dotenv() # CONFIG +DB_URL = os.getenv("DB_URL") +LOG_LEVEL = os.getenv("LOG_LEVEL") + + +def get_module_logger(mod_name): + """ + format="MPXRadar:%(asctime)s %(levelname)-4s: %(message)s", + level=LOG_LEVEL, + datefmt="%Y-%m-%d %H:%M:%S", + """ + logger = logging.getLogger(mod_name) + handler = logging.StreamHandler() + formatter = logging.Formatter( + "MPXRadar:%(asctime)s %(levelname)-4s: %(message)s", "%Y-%m-%d %H:%M:%S" + ) + handler.setFormatter(formatter) + logger.addHandler(handler) + logger.setLevel(LOG_LEVEL) + return logger + + +logging_radar = get_module_logger("MPXRADAR") # STRING diff --git a/pages/contact.py b/pages/contact.py index 9138535..fc71e55 100644 --- a/pages/contact.py +++ b/pages/contact.py @@ -3,27 +3,27 @@ dash.register_page(__name__, path="/Contact") -layout = html.Div( - children=[ - html.H1(children="Contact us"), - html.Div( - children=""" - Please open an issue on our GitHub repository. if you find a bug or if something is unclear. +layout = ( + html.Div( + children=[ + html.H1(children="Contact us"), + html.Div( + children=""" + Please open an issue on our GitHub repository. if you find a bug or if something is unclear. """ - ), - html.Br(), - html.Div( - children=""" - GitHub repository link: [github-repo-link] + ), + html.Br(), + html.Div( + children=""" + GitHub repository link: [github-repo-link] """ - ), - html.Br(), - html.Div( - children=""" + ), + html.Br(), + html.Div( + children=""" You can also email us using the following address: monkeyporadar-team@xx.xx """ - ), - ], - -), - + ), + ], + ), +) diff --git a/pages/libs/mpxsonar/.env.template b/pages/libs/mpxsonar/.env.template index a4b482f..4efc85a 100644 --- a/pages/libs/mpxsonar/.env.template +++ b/pages/libs/mpxsonar/.env.template @@ -8,6 +8,15 @@ DEBUG=True # https://USERNAME:PASSWORD@IP:PORT/DBNAME DB_URL="https://super_user:123456@localhost:3306/mpx" -# Logging +# Logging for MPXSonar # DEBUG, INFO, WARNING, ERROR, CRITICAL LOG_LEVEL=DEBUG + +# NCBI API-KEY +# To get API key https://ncbiinsights.ncbi.nlm.nih.gov/2017/11/02/new-api-keys-for-the-e-utilities/ +NCBI_API_KEY="" +NCBI_TOOL="MPXSonar" +NCBI_EMAIL="" + +# For NCBI downloader +SAVE_PATH = "" diff --git a/pages/libs/mpxsonar/.gitignore b/pages/libs/mpxsonar/.gitignore index 0ff244c..e15f06b 100644 --- a/pages/libs/mpxsonar/.gitignore +++ b/pages/libs/mpxsonar/.gitignore @@ -164,3 +164,9 @@ cython_debug/ # Test data !tests/data/cache-test/var + +# NCBI +epost.dtd + +# pipeline +pipeline.sh diff --git a/pages/libs/mpxsonar/197120 b/pages/libs/mpxsonar/197120 new file mode 100644 index 0000000..e69de29 diff --git a/pages/libs/mpxsonar/NCBI.downloader.py b/pages/libs/mpxsonar/NCBI.downloader.py new file mode 100644 index 0000000..0dba7ae --- /dev/null +++ b/pages/libs/mpxsonar/NCBI.downloader.py @@ -0,0 +1,345 @@ +#!/usr/bin/env python3 +# Author: K2. +# Step in this File +# 1. Search query term and then get total count +# 2. load with batch size and save into tmp file. +# 3. Parse the record and save into tsv and fasta +# ---- +# 4. log.log file to keep track process +# 5. .success to indicate this folder is ready to import. + +import argparse +import datetime +import logging +import os +import sys +import time +import traceback +from urllib.error import HTTPError + +from Bio import Entrez +from Bio import SeqIO +import dateparser +from dotenv import load_dotenv + +load_dotenv() +LOG_LEVEL = os.getenv("LOG_LEVEL", "DEBUG") +REF_LIST = [ + "NC_063383.1", + "ON563414.3", + "MT903344.1", +] + +Entrez.api_key = os.getenv("NCBI_API_KEY", "") +Entrez.tool = os.getenv("NCBI_TOOL", "") +Entrez.email = os.getenv("NCBI_EMAIL", "") # Always tell NCBI who you are + + +def download(save_path): # noqa: C901 + # nucleotide nuccore + DB = "nucleotide" + QUERY = "Monkeypox virus[Organism] AND complete[prop]" + BATCH_SIZE = 10 + # 1 + # retmax=1 just returns first result of possibly many. + attempt = 0 + success = False + while attempt < 3 and not success: + attempt += 1 + try: + handle = Entrez.esearch( + db=DB, + term=QUERY, + usehistory="y", + idtype="acc", + ) + + record = Entrez.read(handle) + total_count = record["Count"] + logging.info("Total sample to download: %s " % (total_count)) + + handle = Entrez.esearch( + db=DB, + term=QUERY, + retmax=total_count, + usehistory="y", + idtype="acc", + ) + record = Entrez.read(handle) + # setup cache + time.sleep(1) + # print(record) + id_list = record["IdList"] + search_results = Entrez.read(Entrez.epost(DB, id=",".join(id_list))) + webenv = search_results["WebEnv"] + query_key = search_results["QueryKey"] + time.sleep(1) + success = True + except Exception as e: + logging.error("Error at %s", "getting ID", exc_info=e) + handle.close() + if attempt == 3 and not success: + return False + + if not os.path.exists(os.path.join(save_path, ".download.log")): + file_log_handler = open(os.path.join(save_path, ".download.log"), "w+") + else: + file_log_handler = open(os.path.join(save_path, ".download.log"), "r+") + try: + _start = int(file_log_handler.read()) + logging.info(f"Resume previous download: start at {_start}") + except Exception: + logging.warning( + "Cannot resume previous download, we will start a new download." + ) + _start = 0 + # 2 + for start in range(_start, int(total_count), BATCH_SIZE): + end = min(int(total_count), start + BATCH_SIZE) + logging.info("Going to download record %i to %i" % (start + 1, end)) + + save_filename = os.path.join(save_path, f"MPX.{start}-{end}.GB") + file_handler = open(save_filename, "w") + attempt = 0 + success = False + while attempt < 3 and not success: + attempt += 1 + try: + fetch_handle = Entrez.efetch( + db=DB, + rettype="gb", + retmode="text", + retstart=start, + retmax=BATCH_SIZE, + webenv=webenv, + query_key=query_key, + idtype="acc", + ) + success = True + except HTTPError as err: + if 500 <= err.code <= 599: + logging.warning(f"Received error from server {err}") + logging.warning("Attempt {attempt} of 3") + time.sleep(5) + if 400 == err.code: + logging.warning(f"Received error from server {err}") + logging.warning("Attempt {attempt} of 3") + time.sleep(5) + else: + raise + except Exception as e: + logging.error("Error at %s", "download sample", exc_info=e) + + if attempt == 3 and not success: + fetch_handle.close() + file_handler.close() + file_log_handler.close() + return False + + data = fetch_handle.read() + fetch_handle.close() + + file_handler.write(data) + file_handler.close() + # save end .log + file_log_handler.seek(0) + file_log_handler.write(str(end)) + file_log_handler.truncate() + time.sleep(2) + + with open(os.path.join(save_path, ".download.success"), "w") as f: + f.writelines("done") + + file_log_handler.close() + return True + + +def generate_outputfiles(save_download_path, save_final_path): # noqa: C901 + + list_of_GB = [] + for x in os.listdir(save_download_path): + if x.endswith(".GB"): + # Prints only text file present in My Folder + list_of_GB.append(os.path.join(save_download_path, x)) + # TODO: remove reference genome from the list. + + # fasta & meta + fasta_out_handler = open(os.path.join(save_final_path, "seq.fasta"), "w") + meta_out_handler = open(os.path.join(save_final_path, "meta.tsv"), "w") + header = [ + "ID", + "ISOLATE", + "LENGTH", + "COUNTRY", + "GEO_LOCATION", + "RELEASE_DATE", + "COLLECTION_DATE", + "SEQ_TECH", + ] + meta_out_handler.write("\t".join(header) + "\n") # Write the header line + try: + for _file in list_of_GB: + logging.info("Load:" + _file) + seq_GBrecords = list(SeqIO.parse(_file, "genbank")) + for seq_record in seq_GBrecords: + if seq_record.id in REF_LIST: + continue + + _isolate = "" + _country = "" + _geo_location = "" + _NCBI_release_date = "" + _collection_date = "" + _seq_tech = "" + # print("Dealing with GenBank record %s" % seq_record.id) + + fasta_out_handler.write( + ">%s |%s\n%s\n" + % (seq_record.id, seq_record.description, seq_record.seq) + ) + + # assume all keys are exit. + if "isolate" in seq_record.features[0].qualifiers: + _isolate = seq_record.features[0].qualifiers["isolate"][0] + if "country" in seq_record.features[0].qualifiers: + _geo_location = seq_record.features[0].qualifiers["country"][0] + # extract country only + _country = _geo_location.split(":")[0] + + if "collection_date" in seq_record.features[0].qualifiers: + _collection_date = seq_record.features[0].qualifiers[ + "collection_date" + ][0] + # 1.) need to fix date Nov-2017 -> 2017-11-01, 09-Nov-2017 -> 2017-11-09 + # 1995 -> 1995-01-01 set default value with first day of + # the month and first month of the year + # 2.) Year needs to be present in the format. + + d = dateparser.parse( + _collection_date, + settings={ + "PREFER_DAY_OF_MONTH": "first", + "DATE_ORDER": "YMD", + "REQUIRE_PARTS": ["year"], + "RELATIVE_BASE": datetime.datetime(2022, 1, 1), + }, + ) + _collection_date = d.strftime("%Y-%m-%d") + + if ( + "structured_comment" in seq_record.annotations + and "Assembly-Data" in seq_record.annotations["structured_comment"] + and "Sequencing Technology" + in seq_record.annotations["structured_comment"]["Assembly-Data"] + ): + _seq_tech = seq_record.annotations["structured_comment"][ + "Assembly-Data" + ]["Sequencing Technology"] + + if "date" in seq_record.annotations: + _NCBI_release_date = seq_record.annotations["date"] + # need to fix date 18-NOV-2022 -> 2022-11-18 + d = dateparser.parse( + _NCBI_release_date, + settings={"PREFER_DAY_OF_MONTH": "first", "DATE_ORDER": "YMD"}, + ) + _NCBI_release_date = d.strftime("%Y-%m-%d") + + meta_out_handler.write( + "%s\t%s\t%s\t%s\t%s\t%s\t%s\t%s\n" + % ( + seq_record.id, + _isolate, + len(seq_record), + _country, + _geo_location, + _NCBI_release_date, + _collection_date, + _seq_tech, + ) + ) + except Exception: + fasta_out_handler.close() + meta_out_handler.close() + logging.exception(f"Error in {seq_record.id} !!") + traceback.print_exc() + return False + + fasta_out_handler.close() + meta_out_handler.close() + return True + + +def run(args): + # logging.info("api_key:" + Entrez.api_key) + # logging.info("tool:" + Entrez.tool) + # logging.info("email:" + Entrez.email) + if args.date: + TODAY_DATE = args.date + else: + TODAY_DATE = datetime.datetime.now().strftime("%Y-%m-%d") + + if args.output: + SAVE_PATH = args.output + else: + SAVE_PATH = os.path.join(os.getenv("SAVE_PATH", ""), TODAY_DATE) + if not os.path.exists(SAVE_PATH): + os.makedirs(SAVE_PATH) + + logging.basicConfig( + format="NCBI-DL:%(asctime)s %(levelname)-4s: %(message)s", + level=LOG_LEVEL, + datefmt="%Y-%m-%d %H:%M:%S", + handlers=[ + logging.FileHandler(os.path.join(SAVE_PATH, "debug.log")), + logging.StreamHandler(), + ], + ) + logging.info("Script version: 1") + logging.info("Save output to:" + SAVE_PATH) + + save_download_path = os.path.join(SAVE_PATH, "GB") + if not os.path.exists(save_download_path): + os.makedirs(save_download_path) + + save_final_path = os.path.join(SAVE_PATH, "output") + if not os.path.exists(save_final_path): + os.makedirs(save_final_path) + # + logging.info("--- Download samples ---") + if not os.path.exists(os.path.join(SAVE_PATH, "GB", ".download.success")): + if download(save_download_path): + logging.info("Download completed") + else: + logging.error("Download stop before it is finished") + sys.exit("Please rerun it again later.") + else: + logging.info("Download completed, continue to process on GeneBank files.") + + # 3 + logging.info("--- Convert GeneBank to fasta and meta file ---") + if not os.path.exists(os.path.join(SAVE_PATH, ".success")): + if generate_outputfiles(save_download_path, save_final_path): + + logging.info("Processing completed") + else: + logging.error("Process stop before it is finished") + sys.exit("Please rerun it again later.") + + with open(os.path.join(SAVE_PATH, ".success"), "w+") as f: + f.write("done") + logging.info("--- Done ---") + + +if __name__ == "__main__": + parser = argparse.ArgumentParser() + + parser.add_argument( + "-d", + "--date", + type=lambda s: datetime.datetime.strptime(s, "%Y-%m-%d"), + help="Date use for download.", + ) + parser.add_argument("-o", "--output", type=str, help="Output") + args = parser.parse_args() + run(args) diff --git a/pages/libs/mpxsonar/example-dash/app_controller.py b/pages/libs/mpxsonar/example-dash/app_controller.py index 68f2809..a7fb46c 100644 --- a/pages/libs/mpxsonar/example-dash/app_controller.py +++ b/pages/libs/mpxsonar/example-dash/app_controller.py @@ -105,7 +105,19 @@ def list_prop(db=None): # output = output + "\n" # output = output + "DATE FORMAT" + "\n" output = pd.DataFrame(rows, columns=cols) - print(output) + # tmp fix. + output = output[ + ~output["name"].isin( + [ + "AA_PROFILE", + "AA_X_PROFILE", + "NUC_N_PROFILE", + "NUC_PROFILE", + "IMPORTED", + "MODIFIED", + ] + ) + ] return output diff --git a/pages/libs/mpxsonar/example-dash/example.app.py b/pages/libs/mpxsonar/example-dash/exampleApp.py similarity index 77% rename from pages/libs/mpxsonar/example-dash/example.app.py rename to pages/libs/mpxsonar/example-dash/exampleApp.py index 56991dc..9d4a1d1 100644 --- a/pages/libs/mpxsonar/example-dash/example.app.py +++ b/pages/libs/mpxsonar/example-dash/exampleApp.py @@ -120,7 +120,7 @@ "1.The output will be showed in the below section." ), html.Ul( - "2. Available reference: NC_063383.1, NC_003310.1, ON563414.3, MN648051.1, MT903344.1, ON585033.1, and ON568298.1 " + "2. Available reference: NC_063383.1, ON563414.3 and MT903344.1" ), ], title="Note>", @@ -138,10 +138,32 @@ id="cmd-1", ), dbc.Badge( - "match --profile del:1-6", + "match --profile del:1-60", color="white", text_color="primary", className="border me-1", + id="cmd-3", + ), + dbc.Badge( + "match --profile ^C162331T", + color="white", + text_color="primary", + className="border me-1", + id="cmd-4", + ), + dbc.Badge( + "match --profile OPG188:L246F --profile MPXV-UK_P2-164:L246F ", + color="white", + text_color="primary", + className="border me-1", + id="cmd-5", + ), + dbc.Badge( + "match --profile A151461C del:=1-=6", + color="white", + text_color="primary", + className="border me-1", + id="cmd-8", ), dbc.Badge( "match --LENGTH >197120 <197200", @@ -155,6 +177,7 @@ color="white", text_color="primary", className="border me-1", + id="cmd-9", ), dbc.Badge( "list-prop", @@ -175,6 +198,30 @@ "List all properties", target="cmd-7", ), + dbc.Tooltip( + "Select all samples that have or in range 1-60 deletion mutation (e.g., del:1-60, del:1-6, del:11-20)", + target="cmd-3", + ), + dbc.Tooltip( + "Select all samples except samples contain C162331T mutation (^ = exclude)", + target="cmd-4", + ), + dbc.Tooltip( + "Combine with 'OR'; for example, get all samples that have mutation at 'OPG188:L246F' OR 'MPXV-UK_P2-164:L246F' (format, GENE/TAG:protien mutation)", + target="cmd-5", + ), + dbc.Tooltip( + "Get all samples ", + target="cmd-6", + ), + dbc.Tooltip( + "'AND' operation; for example, get all samples that have mutation at A151461C and exact 1-6 deletion", + target="cmd-8", + ), + dbc.Tooltip( + "Get sameple by name", + target="cmd-9", + ), ], title="Example commands...", ), @@ -216,6 +263,10 @@ style_data={ "whiteSpace": "normal", "height": "auto", + # all three widths are needed + "minWidth": "300px", + "width": "300px", + "maxWidth": "300px", }, style_table={"overflowX": "auto"}, export_format="csv", diff --git a/pages/libs/mpxsonar/pipeline.sh.template b/pages/libs/mpxsonar/pipeline.sh.template new file mode 100644 index 0000000..b21214a --- /dev/null +++ b/pages/libs/mpxsonar/pipeline.sh.template @@ -0,0 +1,28 @@ +#!/bin/bash +# version 1 +# 0/50 0 0 ? * * * pipeline.sh >/dev/null 2>&1 + +# OUTPUT DIR +CACHE_DIR=/mnt/c/data/cache +DOWNLOAD_DIR=/mnt/c/data/prod_mpx +# +ANALYSIS_DATE=$(date +'%Y-%m-%d') # 2022-11-22 +INPUT_FASTA=/mnt/c/data/prod_mpx/${ANALYSIS_DATE}/output/seq.min.fasta +INPUT_META=/mnt/c/data/prod_mpx/${ANALYSIS_DATE}/output/meta.tsv + +CPUS=8 +source /home/note/miniconda3/etc/profile.d/conda.sh + +conda activate mpxsonar-dev +# 1. +# TODO: need to adjust the script to handle the parameters or arguments +# Right now just assume, there is the .env file in the same directory. +python NCBI.downloader.py --date $ANALYSIS_DATE -o ${DOWNLOAD_DIR}/${ANALYSIS_DATE} + +# 2. +# Load into database +#sonar import -r MT903344.1 --fasta $INPUT_FASTA --tsv $INPUT_META --cols sample=ID --cache $CACHE_DIR/cache_MT903 --threads $CPUS +#sonar import -r ON563414.3 --fasta $INPUT_FASTA --tsv $INPUT_META --cols sample=ID --cache $CACHE_DIR/cache_ON563 --threads $CPUS +# sonar import -r ON585033.1 --fasta $INPUT_FASTA --tsv $INPUT_META --cols sample=ID --cache $CACHE_DIR/cache_ON585 --threads $CPUS +#sonar import -r NC_063383.1 --fasta $INPUT_FASTA --tsv $INPUT_META --cols sample=ID --cache $CACHE_DIR/cache_NC063 --threads $CPUS +# sonar import -r ON568298.1 --fasta $INPUT_FASTA --tsv $INPUT_META --cols sample=ID --cache $CACHE_DIR/cache_ON568 --threads $CPUS diff --git a/pages/libs/mpxsonar/poetry.lock b/pages/libs/mpxsonar/poetry.lock index 3e32e41..5ad23b1 100644 --- a/pages/libs/mpxsonar/poetry.lock +++ b/pages/libs/mpxsonar/poetry.lock @@ -1,24 +1,16 @@ -[[package]] -name = "atomicwrites" -version = "1.4.0" -description = "Atomic file writes." -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" - [[package]] name = "attrs" -version = "21.4.0" +version = "22.1.0" description = "Classes Without Boilerplate" category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = ">=3.5" [package.extras] -dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "sphinx", "sphinx-notfound-page", "zope.interface"] +dev = ["cloudpickle", "coverage[toml] (>=5.0.2)", "furo", "hypothesis", "mypy (>=0.900,!=0.940)", "pre-commit", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "sphinx", "sphinx-notfound-page", "zope.interface"] docs = ["furo", "sphinx", "sphinx-notfound-page", "zope.interface"] -tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six", "zope.interface"] -tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "six"] +tests = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins", "zope.interface"] +tests_no_zope = ["cloudpickle", "coverage[toml] (>=5.0.2)", "hypothesis", "mypy (>=0.900,!=0.940)", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins"] [[package]] name = "bandit" @@ -52,11 +44,11 @@ numpy = "*" [[package]] name = "black" -version = "22.6.0" +version = "22.10.0" description = "The uncompromising code formatter." category = "dev" optional = false -python-versions = ">=3.6.2" +python-versions = ">=3.7" [package.dependencies] click = ">=8.0.0" @@ -74,7 +66,7 @@ uvloop = ["uvloop (>=0.15.2)"] [[package]] name = "certifi" -version = "2022.6.15" +version = "2022.9.24" description = "Python package for providing Mozilla's CA Bundle." category = "main" optional = false @@ -82,7 +74,7 @@ python-versions = ">=3.6" [[package]] name = "charset-normalizer" -version = "2.1.0" +version = "2.1.1" description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." category = "main" optional = false @@ -104,11 +96,11 @@ colorama = {version = "*", markers = "platform_system == \"Windows\""} [[package]] name = "colorama" -version = "0.4.5" +version = "0.4.6" description = "Cross-platform colored terminal text." category = "dev" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" [[package]] name = "coverage" @@ -185,9 +177,28 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "dateparser" +version = "1.1.4" +description = "Date parsing library designed to parse dates from HTML pages" +category = "main" +optional = false +python-versions = ">=3.7" + +[package.dependencies] +python-dateutil = "*" +pytz = "*" +regex = "<2019.02.19 || >2019.02.19,<2021.8.27 || >2021.8.27" +tzlocal = "*" + +[package.extras] +calendars = ["convertdate", "hijri-converter"] +fasttext = ["fasttext"] +langdetect = ["langdetect"] + [[package]] name = "dparse" -version = "0.5.1" +version = "0.6.2" description = "A parser for Python dependency files" category = "dev" optional = false @@ -195,12 +206,23 @@ python-versions = ">=3.5" [package.dependencies] packaging = "*" -pyyaml = "*" toml = "*" [package.extras] +conda = ["pyyaml"] pipenv = ["pipenv"] +[[package]] +name = "exceptiongroup" +version = "1.0.4" +description = "Backport of PEP 654 (exception groups)" +category = "dev" +optional = false +python-versions = ">=3.7" + +[package.extras] +test = ["pytest (>=6)"] + [[package]] name = "flake8" version = "4.0.1" @@ -230,7 +252,7 @@ pycodestyle = "*" [[package]] name = "flake8-black" -version = "0.3.3" +version = "0.3.5" description = "flake8 plugin to call black as a code style validator" category = "dev" optional = false @@ -238,23 +260,26 @@ python-versions = ">=3.7" [package.dependencies] black = ">=22.1.0" -flake8 = ">=3.0.0" +flake8 = ">=3" tomli = "*" +[package.extras] +develop = ["build", "twine"] + [[package]] name = "flake8-bugbear" -version = "22.7.1" +version = "22.10.27" description = "A plugin for flake8 finding likely bugs and design problems in your program. Contains warnings that don't belong in pyflakes and pycodestyle." category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] attrs = ">=19.2.0" flake8 = ">=3.0.0" [package.extras] -dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit"] +dev = ["coverage", "hypothesis", "hypothesmith (>=0.2)", "pre-commit", "tox"] [[package]] name = "flake8-import-order" @@ -299,18 +324,18 @@ dotenv = ["python-dotenv"] [[package]] name = "gitdb" -version = "4.0.9" +version = "4.0.10" description = "Git Object Database" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.7" [package.dependencies] smmap = ">=3.0.1,<6" [[package]] name = "gitpython" -version = "3.1.27" +version = "3.1.29" description = "GitPython is a python library used to interact with Git repositories" category = "dev" optional = false @@ -321,7 +346,7 @@ gitdb = ">=4.0.1,<5" [[package]] name = "idna" -version = "3.3" +version = "3.4" description = "Internationalized Domain Names in Applications (IDNA)" category = "main" optional = false @@ -329,7 +354,7 @@ python-versions = ">=3.5" [[package]] name = "importlib-metadata" -version = "5.0.0" +version = "5.1.0" description = "Read metadata from Python packages" category = "dev" optional = false @@ -375,12 +400,15 @@ i18n = ["Babel (>=2.7)"] [[package]] name = "mariadb" -version = "1.1.4" +version = "1.1.5.post3" description = "Python MariaDB extension" category = "main" optional = false python-versions = ">=3.7" +[package.dependencies] +packaging = "*" + [[package]] name = "markupsafe" version = "2.1.1" @@ -434,7 +462,7 @@ python-versions = "*" [[package]] name = "numpy" -version = "1.23.0" +version = "1.23.5" description = "NumPy is the fundamental package for array computing with Python." category = "main" optional = false @@ -444,7 +472,7 @@ python-versions = ">=3.8" name = "packaging" version = "21.3" description = "Core utilities for Python packages" -category = "dev" +category = "main" optional = false python-versions = ">=3.6" @@ -453,7 +481,7 @@ pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" [[package]] name = "pandas" -version = "1.4.3" +version = "1.4.4" description = "Powerful data structures for data analysis, time series, and statistics" category = "main" optional = false @@ -474,15 +502,15 @@ test = ["hypothesis (>=5.5.3)", "pytest (>=6.0)", "pytest-xdist (>=1.31)"] [[package]] name = "pathspec" -version = "0.9.0" +version = "0.10.2" description = "Utility library for gitignore style pattern matching of file paths." category = "dev" optional = false -python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,>=2.7" +python-versions = ">=3.7" [[package]] name = "pbr" -version = "5.9.0" +version = "5.11.0" description = "Python Build Reasonableness" category = "dev" optional = false @@ -490,15 +518,15 @@ python-versions = ">=2.6" [[package]] name = "platformdirs" -version = "2.5.2" -description = "A small Python module for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." +version = "2.5.4" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a \"user data dir\"." category = "dev" optional = false python-versions = ">=3.7" [package.extras] -docs = ["furo (>=2021.7.5b38)", "proselint (>=0.10.2)", "sphinx (>=4)", "sphinx-autodoc-typehints (>=1.12)"] -test = ["appdirs (==1.4.4)", "pytest (>=6)", "pytest-cov (>=2.7)", "pytest-mock (>=3.6)"] +docs = ["furo (>=2022.9.29)", "proselint (>=0.13)", "sphinx (>=5.3)", "sphinx-autodoc-typehints (>=1.19.4)"] +test = ["appdirs (==1.4.4)", "pytest (>=7.2)", "pytest-cov (>=4)", "pytest-mock (>=3.10)"] [[package]] name = "plotly" @@ -525,7 +553,7 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "psutil" -version = "5.9.3" +version = "5.9.4" description = "Cross-platform lib for process and system monitoring in Python." category = "main" optional = false @@ -534,14 +562,6 @@ python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" [package.extras] test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"] -[[package]] -name = "py" -version = "1.11.0" -description = "library with cross-python path, ini-parsing, io, code, log facilities" -category = "dev" -optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" - [[package]] name = "pyaml" version = "20.4.0" @@ -584,7 +604,7 @@ plugins = ["importlib-metadata"] name = "pyparsing" version = "3.0.9" description = "pyparsing module - Classes and methods to define and execute parsing grammars" -category = "dev" +category = "main" optional = false python-versions = ">=3.6.8" @@ -593,21 +613,20 @@ diagrams = ["jinja2", "railroad-diagrams"] [[package]] name = "pytest" -version = "7.1.2" +version = "7.2.0" description = "pytest: simple powerful testing with Python" category = "dev" optional = false python-versions = ">=3.7" [package.dependencies] -atomicwrites = {version = ">=1.0", markers = "sys_platform == \"win32\""} attrs = ">=19.2.0" colorama = {version = "*", markers = "sys_platform == \"win32\""} +exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" pluggy = ">=0.12,<2.0" -py = ">=1.8.2" -tomli = ">=1.0.0" +tomli = {version = ">=1.0.0", markers = "python_version < \"3.11\""} [package.extras] testing = ["argcomplete", "hypothesis (>=3.56)", "mock", "nose", "pygments (>=2.7.2)", "requests", "xmlschema"] @@ -629,7 +648,7 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-sugar" -version = "0.9.5" +version = "0.9.6" description = "pytest-sugar is a plugin for pytest that changes the default look and feel of pytest (e.g. progressbar, show tests that fail instantly)." category = "dev" optional = false @@ -664,12 +683,23 @@ cli = ["click (>=5.0)"] [[package]] name = "pytz" -version = "2022.1" +version = "2022.6" description = "World timezone definitions, modern and historical" category = "main" optional = false python-versions = "*" +[[package]] +name = "pytz-deprecation-shim" +version = "0.1.0.post0" +description = "Shims to make deprecation of pytz easier" +category = "main" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" + +[package.dependencies] +tzdata = {version = "*", markers = "python_version >= \"3.6\""} + [[package]] name = "pywin32" version = "305" @@ -686,6 +716,14 @@ category = "main" optional = false python-versions = ">=3.6" +[[package]] +name = "regex" +version = "2022.10.31" +description = "Alternative regular expression module, to replace re." +category = "main" +optional = false +python-versions = ">=3.6" + [[package]] name = "requests" version = "2.28.1" @@ -721,7 +759,7 @@ jinja2 = ["ruamel.yaml.jinja2 (>=0.2)"] [[package]] name = "ruamel.yaml.clib" -version = "0.2.6" +version = "0.2.7" description = "C version of reader, parser and emitter for ruamel.yaml derived from libyaml" category = "dev" optional = false @@ -729,7 +767,7 @@ python-versions = ">=3.5" [[package]] name = "safety" -version = "2.0.0" +version = "2.3.2" description = "Checks installed dependencies for known vulnerabilities and licenses." category = "dev" optional = false @@ -737,11 +775,15 @@ python-versions = "*" [package.dependencies] Click = ">=8.0.2" -dparse = ">=0.5.1" +dparse = ">=0.6.2" packaging = ">=21.0" requests = "*" "ruamel.yaml" = ">=0.17.21" +[package.extras] +github = ["jinja2 (>=3.1.0)", "pygithub (>=1.43.3)"] +gitlab = ["python-gitlab (>=1.3.0)"] + [[package]] name = "six" version = "1.16.0" @@ -760,11 +802,11 @@ python-versions = ">=3.6" [[package]] name = "stevedore" -version = "3.5.0" +version = "4.1.1" description = "Manage dynamic plugins for Python applications" category = "dev" optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" [package.dependencies] pbr = ">=2.0.0,<2.1.0 || >2.1.0" @@ -793,11 +835,14 @@ doc = ["reno", "sphinx", "tornado (>=4.5)"] [[package]] name = "termcolor" -version = "1.1.0" -description = "ANSII Color formatting for output in terminal." +version = "2.1.1" +description = "ANSI color formatting for output in terminal" category = "dev" optional = false -python-versions = "*" +python-versions = ">=3.7" + +[package.extras] +tests = ["pytest", "pytest-cov"] [[package]] name = "toml" @@ -830,23 +875,47 @@ telegram = ["requests"] [[package]] name = "typing-extensions" -version = "4.3.0" +version = "4.4.0" description = "Backported and Experimental Type Hints for Python 3.7+" category = "dev" optional = false python-versions = ">=3.7" +[[package]] +name = "tzdata" +version = "2022.6" +description = "Provider of IANA time zone data" +category = "main" +optional = false +python-versions = ">=2" + +[[package]] +name = "tzlocal" +version = "4.2" +description = "tzinfo object for the local timezone" +category = "main" +optional = false +python-versions = ">=3.6" + +[package.dependencies] +pytz-deprecation-shim = "*" +tzdata = {version = "*", markers = "platform_system == \"Windows\""} + +[package.extras] +devenv = ["black", "pyroma", "pytest-cov", "zest.releaser"] +test = ["pytest (>=4.3)", "pytest-mock (>=3.3)"] + [[package]] name = "urllib3" -version = "1.26.9" +version = "1.26.13" description = "HTTP library with thread-safe connection pooling, file post, and more." category = "main" optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <4" +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" [package.extras] brotli = ["brotli (>=1.0.9)", "brotlicffi (>=0.8.0)", "brotlipy (>=0.6.0)"] -secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)"] +secure = ["certifi", "cryptography (>=1.3.4)", "idna (>=2.0.0)", "ipaddress", "pyOpenSSL (>=0.14)", "urllib3-secure-extra"] socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] @@ -891,16 +960,12 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "5b827199d04ec3c6993185dd6474b52a2dbffeda59b0bb1065d6eb58235ec4eb" +content-hash = "b8efcfdb4e77a41d2a788a7752bc75ade6a91c9177a67f7211ef2946ba217a07" [metadata.files] -atomicwrites = [ - {file = "atomicwrites-1.4.0-py2.py3-none-any.whl", hash = "sha256:6d1784dea7c0c8d4a5172b6c620f40b6e4cbfdf96d783691f2e1302a7b88e197"}, - {file = "atomicwrites-1.4.0.tar.gz", hash = "sha256:ae70396ad1a434f9c7046fd2dd196fc04b12f9e91ffb859164193be8b6168a7a"}, -] attrs = [ - {file = "attrs-21.4.0-py2.py3-none-any.whl", hash = "sha256:2d27e3784d7a565d36ab851fe94887c5eccd6a463168875832a1be79c82828b4"}, - {file = "attrs-21.4.0.tar.gz", hash = "sha256:626ba8234211db98e869df76230a137c4c40a12d72445c45d5f5b716f076e2fd"}, + {file = "attrs-22.1.0-py2.py3-none-any.whl", hash = "sha256:86efa402f67bf2df34f51a335487cf46b1ec130d02b8d39fd248abfd30da551c"}, + {file = "attrs-22.1.0.tar.gz", hash = "sha256:29adc2665447e5191d0e7c568fde78b21f9672d344281d0c6e1ab085429b22b6"}, ] bandit = [ {file = "bandit-1.7.4-py3-none-any.whl", hash = "sha256:412d3f259dab4077d0e7f0c11f50f650cc7d10db905d98f6520a95a18049658a"}, @@ -944,45 +1009,43 @@ biopython = [ {file = "biopython-1.79.tar.gz", hash = "sha256:edb07eac99d3b8abd7ba56ff4bedec9263f76dfc3c3f450e7d2e2bcdecf8559b"}, ] black = [ - {file = "black-22.6.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:f586c26118bc6e714ec58c09df0157fe2d9ee195c764f630eb0d8e7ccce72e69"}, - {file = "black-22.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b270a168d69edb8b7ed32c193ef10fd27844e5c60852039599f9184460ce0807"}, - {file = "black-22.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6797f58943fceb1c461fb572edbe828d811e719c24e03375fd25170ada53825e"}, - {file = "black-22.6.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c85928b9d5f83b23cee7d0efcb310172412fbf7cb9d9ce963bd67fd141781def"}, - {file = "black-22.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:f6fe02afde060bbeef044af7996f335fbe90b039ccf3f5eb8f16df8b20f77666"}, - {file = "black-22.6.0-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:cfaf3895a9634e882bf9d2363fed5af8888802d670f58b279b0bece00e9a872d"}, - {file = "black-22.6.0-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:94783f636bca89f11eb5d50437e8e17fbc6a929a628d82304c80fa9cd945f256"}, - {file = "black-22.6.0-cp36-cp36m-win_amd64.whl", hash = "sha256:2ea29072e954a4d55a2ff58971b83365eba5d3d357352a07a7a4df0d95f51c78"}, - {file = "black-22.6.0-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e439798f819d49ba1c0bd9664427a05aab79bfba777a6db94fd4e56fae0cb849"}, - {file = "black-22.6.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:187d96c5e713f441a5829e77120c269b6514418f4513a390b0499b0987f2ff1c"}, - {file = "black-22.6.0-cp37-cp37m-win_amd64.whl", hash = "sha256:074458dc2f6e0d3dab7928d4417bb6957bb834434516f21514138437accdbe90"}, - {file = "black-22.6.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:a218d7e5856f91d20f04e931b6f16d15356db1c846ee55f01bac297a705ca24f"}, - {file = "black-22.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:568ac3c465b1c8b34b61cd7a4e349e93f91abf0f9371eda1cf87194663ab684e"}, - {file = "black-22.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6c1734ab264b8f7929cef8ae5f900b85d579e6cbfde09d7387da8f04771b51c6"}, - {file = "black-22.6.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c9a3ac16efe9ec7d7381ddebcc022119794872abce99475345c5a61aa18c45ad"}, - {file = "black-22.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:b9fd45787ba8aa3f5e0a0a98920c1012c884622c6c920dbe98dbd05bc7c70fbf"}, - {file = "black-22.6.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:7ba9be198ecca5031cd78745780d65a3f75a34b2ff9be5837045dce55db83d1c"}, - {file = "black-22.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:a3db5b6409b96d9bd543323b23ef32a1a2b06416d525d27e0f67e74f1446c8f2"}, - {file = "black-22.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:560558527e52ce8afba936fcce93a7411ab40c7d5fe8c2463e279e843c0328ee"}, - {file = "black-22.6.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b154e6bbde1e79ea3260c4b40c0b7b3109ffcdf7bc4ebf8859169a6af72cd70b"}, - {file = "black-22.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:4af5bc0e1f96be5ae9bd7aaec219c901a94d6caa2484c21983d043371c733fc4"}, - {file = "black-22.6.0-py3-none-any.whl", hash = "sha256:ac609cf8ef5e7115ddd07d85d988d074ed00e10fbc3445aee393e70164a2219c"}, - {file = "black-22.6.0.tar.gz", hash = "sha256:6c6d39e28aed379aec40da1c65434c77d75e65bb59a1e1c283de545fb4e7c6c9"}, + {file = "black-22.10.0-1fixedarch-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:5cc42ca67989e9c3cf859e84c2bf014f6633db63d1cbdf8fdb666dcd9e77e3fa"}, + {file = "black-22.10.0-1fixedarch-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:5d8f74030e67087b219b032aa33a919fae8806d49c867846bfacde57f43972ef"}, + {file = "black-22.10.0-1fixedarch-cp37-cp37m-macosx_10_16_x86_64.whl", hash = "sha256:197df8509263b0b8614e1df1756b1dd41be6738eed2ba9e9769f3880c2b9d7b6"}, + {file = "black-22.10.0-1fixedarch-cp38-cp38-macosx_10_16_x86_64.whl", hash = "sha256:2644b5d63633702bc2c5f3754b1b475378fbbfb481f62319388235d0cd104c2d"}, + {file = "black-22.10.0-1fixedarch-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:e41a86c6c650bcecc6633ee3180d80a025db041a8e2398dcc059b3afa8382cd4"}, + {file = "black-22.10.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2039230db3c6c639bd84efe3292ec7b06e9214a2992cd9beb293d639c6402edb"}, + {file = "black-22.10.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:14ff67aec0a47c424bc99b71005202045dc09270da44a27848d534600ac64fc7"}, + {file = "black-22.10.0-cp310-cp310-win_amd64.whl", hash = "sha256:819dc789f4498ecc91438a7de64427c73b45035e2e3680c92e18795a839ebb66"}, + {file = "black-22.10.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5b9b29da4f564ba8787c119f37d174f2b69cdfdf9015b7d8c5c16121ddc054ae"}, + {file = "black-22.10.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8b49776299fece66bffaafe357d929ca9451450f5466e997a7285ab0fe28e3b"}, + {file = "black-22.10.0-cp311-cp311-win_amd64.whl", hash = "sha256:21199526696b8f09c3997e2b4db8d0b108d801a348414264d2eb8eb2532e540d"}, + {file = "black-22.10.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1e464456d24e23d11fced2bc8c47ef66d471f845c7b7a42f3bd77bf3d1789650"}, + {file = "black-22.10.0-cp37-cp37m-win_amd64.whl", hash = "sha256:9311e99228ae10023300ecac05be5a296f60d2fd10fff31cf5c1fa4ca4b1988d"}, + {file = "black-22.10.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:fba8a281e570adafb79f7755ac8721b6cf1bbf691186a287e990c7929c7692ff"}, + {file = "black-22.10.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915ace4ff03fdfff953962fa672d44be269deb2eaf88499a0f8805221bc68c87"}, + {file = "black-22.10.0-cp38-cp38-win_amd64.whl", hash = "sha256:444ebfb4e441254e87bad00c661fe32df9969b2bf224373a448d8aca2132b395"}, + {file = "black-22.10.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:974308c58d057a651d182208a484ce80a26dac0caef2895836a92dd6ebd725e0"}, + {file = "black-22.10.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72ef3925f30e12a184889aac03d77d031056860ccae8a1e519f6cbb742736383"}, + {file = "black-22.10.0-cp39-cp39-win_amd64.whl", hash = "sha256:432247333090c8c5366e69627ccb363bc58514ae3e63f7fc75c54b1ea80fa7de"}, + {file = "black-22.10.0-py3-none-any.whl", hash = "sha256:c957b2b4ea88587b46cf49d1dc17681c1e672864fd7af32fc1e9664d572b3458"}, + {file = "black-22.10.0.tar.gz", hash = "sha256:f513588da599943e0cde4e32cc9879e825d58720d6557062d1098c5ad80080e1"}, ] certifi = [ - {file = "certifi-2022.6.15-py3-none-any.whl", hash = "sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412"}, - {file = "certifi-2022.6.15.tar.gz", hash = "sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d"}, + {file = "certifi-2022.9.24-py3-none-any.whl", hash = "sha256:90c1a32f1d68f940488354e36370f6cca89f0f106db09518524c88d6ed83f382"}, + {file = "certifi-2022.9.24.tar.gz", hash = "sha256:0d9c601124e5a6ba9712dbc60d9c53c21e34f5f641fe83002317394311bdce14"}, ] charset-normalizer = [ - {file = "charset-normalizer-2.1.0.tar.gz", hash = "sha256:575e708016ff3a5e3681541cb9d79312c416835686d054a23accb873b254f413"}, - {file = "charset_normalizer-2.1.0-py3-none-any.whl", hash = "sha256:5189b6f22b01957427f35b6a08d9a0bc45b46d3788ef5a92e978433c7a35f8a5"}, + {file = "charset-normalizer-2.1.1.tar.gz", hash = "sha256:5a3d016c7c547f69d6f81fb0db9449ce888b418b5b9952cc5e6e66843e9dd845"}, + {file = "charset_normalizer-2.1.1-py3-none-any.whl", hash = "sha256:83e9a75d1911279afd89352c68b45348559d1fc0506b054b346651b5e7fee29f"}, ] click = [ {file = "click-8.1.3-py3-none-any.whl", hash = "sha256:bb4d8133cb15a609f44e8213d9b391b0809795062913b383c62be0ee95b1db48"}, {file = "click-8.1.3.tar.gz", hash = "sha256:7682dc8afb30297001674575ea00d1814d808d6a36af415a82bd481d37ba7b8e"}, ] colorama = [ - {file = "colorama-0.4.5-py2.py3-none-any.whl", hash = "sha256:854bf444933e37f5824ae7bfc1e98d5bce2ebe4160d46b5edf346a89358e99da"}, - {file = "colorama-0.4.5.tar.gz", hash = "sha256:e6c6b4334fc50988a639d9b98aa429a0b57da6e17b9a44f0451f930b6967b7a4"}, + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, ] coverage = [ {file = "coverage-6.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ef8674b0ee8cc11e2d574e3e2998aea5df5ab242e012286824ea3c6970580e53"}, @@ -1056,9 +1119,17 @@ dash-table = [ {file = "dash_table-5.0.0-py3-none-any.whl", hash = "sha256:19036fa352bb1c11baf38068ec62d172f0515f73ca3276c79dee49b95ddc16c9"}, {file = "dash_table-5.0.0.tar.gz", hash = "sha256:18624d693d4c8ef2ddec99a6f167593437a7ea0bf153aa20f318c170c5bc7308"}, ] +dateparser = [ + {file = "dateparser-1.1.4-py2.py3-none-any.whl", hash = "sha256:4431159799b63d8acec5d7d844c5e06edf3d1b0eb2bda6d4cac87134ddddd01c"}, + {file = "dateparser-1.1.4.tar.gz", hash = "sha256:73ec6e44a133c54076ecf9f9dc0fbe3dd4831f154f977ff06f53114d57c5425e"}, +] dparse = [ - {file = "dparse-0.5.1-py3-none-any.whl", hash = "sha256:e953a25e44ebb60a5c6efc2add4420c177f1d8404509da88da9729202f306994"}, - {file = "dparse-0.5.1.tar.gz", hash = "sha256:a1b5f169102e1c894f9a7d5ccf6f9402a836a5d24be80a986c7ce9eaed78f367"}, + {file = "dparse-0.6.2-py3-none-any.whl", hash = "sha256:8097076f1dd26c377f30d4745e6ec18fef42f3bf493933b842ac5bafad8c345f"}, + {file = "dparse-0.6.2.tar.gz", hash = "sha256:d45255bda21f998bc7ddf2afd5e62505ba6134756ba2d42a84c56b0826614dfe"}, +] +exceptiongroup = [ + {file = "exceptiongroup-1.0.4-py3-none-any.whl", hash = "sha256:542adf9dea4055530d6e1279602fa5cb11dab2395fa650b8674eaec35fc4a828"}, + {file = "exceptiongroup-1.0.4.tar.gz", hash = "sha256:bd14967b79cd9bdb54d97323216f8fdf533e278df937aa2a90089e7d6e06e5ec"}, ] flake8 = [ {file = "flake8-4.0.1-py2.py3-none-any.whl", hash = "sha256:479b1304f72536a55948cb40a32dce8bb0ffe3501e26eaf292c7e60eb5e0428d"}, @@ -1069,12 +1140,12 @@ flake8-bandit = [ {file = "flake8_bandit-3.0.0.tar.gz", hash = "sha256:54d19427e6a8d50322a7b02e1841c0a7c22d856975f3459803320e0e18e2d6a1"}, ] flake8-black = [ - {file = "flake8-black-0.3.3.tar.gz", hash = "sha256:8211f5e20e954cb57c709acccf2f3281ce27016d4c4b989c3e51f878bb7ce12a"}, - {file = "flake8_black-0.3.3-py3-none-any.whl", hash = "sha256:7d667d0059fd1aa468de1669d77cc934b7f1feeac258d57bdae69a8e73c4cd90"}, + {file = "flake8-black-0.3.5.tar.gz", hash = "sha256:9e93252b1314a8eb3c2f55dec54a07239e502b12f57567f2c105f2202714b15e"}, + {file = "flake8_black-0.3.5-py3-none-any.whl", hash = "sha256:4948a579fdddd98fbf935fd94255dfcfce560c4ddc1ceee08e3f12d6114c8619"}, ] flake8-bugbear = [ - {file = "flake8-bugbear-22.7.1.tar.gz", hash = "sha256:e450976a07e4f9d6c043d4f72b17ec1baf717fe37f7997009c8ae58064f88305"}, - {file = "flake8_bugbear-22.7.1-py3-none-any.whl", hash = "sha256:db5d7a831ef4412a224b26c708967ff816818cabae415e76b8c58df156c4b8e5"}, + {file = "flake8-bugbear-22.10.27.tar.gz", hash = "sha256:a6708608965c9e0de5fff13904fed82e0ba21ac929fe4896459226a797e11cd5"}, + {file = "flake8_bugbear-22.10.27-py3-none-any.whl", hash = "sha256:6ad0ab754507319060695e2f2be80e6d8977cfcea082293089a9226276bd825d"}, ] flake8-import-order = [ {file = "flake8-import-order-0.18.1.tar.gz", hash = "sha256:a28dc39545ea4606c1ac3c24e9d05c849c6e5444a50fb7e9cdd430fc94de6e92"}, @@ -1089,20 +1160,20 @@ flask = [ {file = "Flask-2.2.2.tar.gz", hash = "sha256:642c450d19c4ad482f96729bd2a8f6d32554aa1e231f4f6b4e7e5264b16cca2b"}, ] gitdb = [ - {file = "gitdb-4.0.9-py3-none-any.whl", hash = "sha256:8033ad4e853066ba6ca92050b9df2f89301b8fc8bf7e9324d412a63f8bf1a8fd"}, - {file = "gitdb-4.0.9.tar.gz", hash = "sha256:bac2fd45c0a1c9cf619e63a90d62bdc63892ef92387424b855792a6cabe789aa"}, + {file = "gitdb-4.0.10-py3-none-any.whl", hash = "sha256:c286cf298426064079ed96a9e4a9d39e7f3e9bf15ba60701e95f5492f28415c7"}, + {file = "gitdb-4.0.10.tar.gz", hash = "sha256:6eb990b69df4e15bad899ea868dc46572c3f75339735663b81de79b06f17eb9a"}, ] gitpython = [ - {file = "GitPython-3.1.27-py3-none-any.whl", hash = "sha256:5b68b000463593e05ff2b261acff0ff0972df8ab1b70d3cdbd41b546c8b8fc3d"}, - {file = "GitPython-3.1.27.tar.gz", hash = "sha256:1c885ce809e8ba2d88a29befeb385fcea06338d3640712b59ca623c220bb5704"}, + {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, + {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, ] idna = [ - {file = "idna-3.3-py3-none-any.whl", hash = "sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff"}, - {file = "idna-3.3.tar.gz", hash = "sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d"}, + {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, + {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, ] importlib-metadata = [ - {file = "importlib_metadata-5.0.0-py3-none-any.whl", hash = "sha256:ddb0e35065e8938f867ed4928d0ae5bf2a53b7773871bfe6bcc7e4fcdc7dea43"}, - {file = "importlib_metadata-5.0.0.tar.gz", hash = "sha256:da31db32b304314d044d3c12c79bd59e307889b287ad12ff387b3500835fc2ab"}, + {file = "importlib_metadata-5.1.0-py3-none-any.whl", hash = "sha256:d84d17e21670ec07990e1044a99efe8d615d860fd176fc29ef5c306068fda313"}, + {file = "importlib_metadata-5.1.0.tar.gz", hash = "sha256:d5059f9f1e8e41f80e9c56c2ee58811450c31984dfa625329ffd7c0dad88a73b"}, ] iniconfig = [ {file = "iniconfig-1.1.1-py2.py3-none-any.whl", hash = "sha256:011e24c64b7f47f6ebd835bb12a743f2fbe9a26d4cecaa7f53bc4f35ee9da8b3"}, @@ -1117,15 +1188,17 @@ jinja2 = [ {file = "Jinja2-3.1.2.tar.gz", hash = "sha256:31351a702a408a9e7595a8fc6150fc3f43bb6bf7e319770cbc0db9df9437e852"}, ] mariadb = [ - {file = "mariadb-1.1.4-cp310-cp310-win32.whl", hash = "sha256:eccdfd2579fc311578d5b938ec0d18f7b5f77ec5adcdb60bc001d462d78965e5"}, - {file = "mariadb-1.1.4-cp310-cp310-win_amd64.whl", hash = "sha256:b48d81a90b89532051e5aa12848bcd3973107a8eb9462ba857369d319a1a0217"}, - {file = "mariadb-1.1.4-cp37-cp37m-win32.whl", hash = "sha256:9a5d62eae145014a93c1d109233b071049e99b244eb58ab942891f47cb3012e1"}, - {file = "mariadb-1.1.4-cp37-cp37m-win_amd64.whl", hash = "sha256:97831f1cea8c611b7bbc101ca1a4679b376fd6a2cd365c3826beba39f0dc260f"}, - {file = "mariadb-1.1.4-cp38-cp38-win32.whl", hash = "sha256:c974750b5ac92da2af092897509808fc221dc2ebcc8688b5be4c5446b76489fe"}, - {file = "mariadb-1.1.4-cp38-cp38-win_amd64.whl", hash = "sha256:059a2e0b1f319284a618651fb3dc246e0657f4b9560accf7f9a4e9ec1802c7ec"}, - {file = "mariadb-1.1.4-cp39-cp39-win32.whl", hash = "sha256:086afe3f37c282c0d4f5d96e688ce1e3cc601dfdf045568b8f82d6d7b5f12910"}, - {file = "mariadb-1.1.4-cp39-cp39-win_amd64.whl", hash = "sha256:ce6093dedebe4d9e0ca4f802422f084ed8a6848080210474ab4195c69f323e48"}, - {file = "mariadb-1.1.4.zip", hash = "sha256:73a0acbd2ace381ec1bcfc61ced7a79a519e66c02c24e12ae6d27baa03717876"}, + {file = "mariadb-1.1.5.post3-cp310-cp310-win32.whl", hash = "sha256:85a76359a746aac09e87f666d2bc22e33c4bfc6324a4c13d2593c2a91a184f80"}, + {file = "mariadb-1.1.5.post3-cp310-cp310-win_amd64.whl", hash = "sha256:ae44fd1aec97ff873b25420f48220da4e5a688dbd327ec145acad41e8ba8fea2"}, + {file = "mariadb-1.1.5.post3-cp311-cp311-win32.whl", hash = "sha256:4cf132556c3be86f235fa4849ccf36a09ecc34c277d894cfd7fafd8b2b370446"}, + {file = "mariadb-1.1.5.post3-cp311-cp311-win_amd64.whl", hash = "sha256:60e7c1bc55b297accb1d423e922a1131dcc5c03ba0035ea961889c72541d3662"}, + {file = "mariadb-1.1.5.post3-cp37-cp37m-win32.whl", hash = "sha256:ea6890ada88efd6ae8a7ca3152753c2853fcd65105e03ecbc79e5104f1ef4a97"}, + {file = "mariadb-1.1.5.post3-cp37-cp37m-win_amd64.whl", hash = "sha256:78b597c598c4bec0e0e44885fd06545dd80ca2ed445e77d72a75342658afa290"}, + {file = "mariadb-1.1.5.post3-cp38-cp38-win32.whl", hash = "sha256:e78d05532197728e4cf9d1a28cdf86bf8e9e3f5eef52c9321800a2c7644b9781"}, + {file = "mariadb-1.1.5.post3-cp38-cp38-win_amd64.whl", hash = "sha256:a7bc81f750128d069c850153f582d512f6a67b42af44ab668ce35ccf069be0e6"}, + {file = "mariadb-1.1.5.post3-cp39-cp39-win32.whl", hash = "sha256:fa5f0f42bfb87013f179f9c3bc3deefa13398cae1e027a869b367db9dc8dd285"}, + {file = "mariadb-1.1.5.post3-cp39-cp39-win_amd64.whl", hash = "sha256:0f805d6e5406318438df4923cc01bea80cfdddeee5f53dd22057b94f75391545"}, + {file = "mariadb-1.1.5.post3.tar.gz", hash = "sha256:f9336dd4cb3207e621933bb5221f33fac0d7184db64dc44c70531430f4ecdcee"}, ] markupsafe = [ {file = "MarkupSafe-2.1.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:86b1f75c4e7c2ac2ccdaec2b9022845dbb81880ca318bb7a0a01fbf7813e3812"}, @@ -1186,67 +1259,73 @@ mypy-extensions = [ {file = "mypy_extensions-0.4.3.tar.gz", hash = "sha256:2d82818f5bb3e369420cb3c4060a7970edba416647068eb4c5343488a6c604a8"}, ] numpy = [ - {file = "numpy-1.23.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:58bfd40eb478f54ff7a5710dd61c8097e169bc36cc68333d00a9bcd8def53b38"}, - {file = "numpy-1.23.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:196cd074c3f97c4121601790955f915187736f9cf458d3ee1f1b46aff2b1ade0"}, - {file = "numpy-1.23.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f1d88ef79e0a7fa631bb2c3dda1ea46b32b1fe614e10fedd611d3d5398447f2f"}, - {file = "numpy-1.23.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d54b3b828d618a19779a84c3ad952e96e2c2311b16384e973e671aa5be1f6187"}, - {file = "numpy-1.23.0-cp310-cp310-win32.whl", hash = "sha256:2b2da66582f3a69c8ce25ed7921dcd8010d05e59ac8d89d126a299be60421171"}, - {file = "numpy-1.23.0-cp310-cp310-win_amd64.whl", hash = "sha256:97a76604d9b0e79f59baeca16593c711fddb44936e40310f78bfef79ee9a835f"}, - {file = "numpy-1.23.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d8cc87bed09de55477dba9da370c1679bd534df9baa171dd01accbb09687dac3"}, - {file = "numpy-1.23.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f0f18804df7370571fb65db9b98bf1378172bd4e962482b857e612d1fec0f53e"}, - {file = "numpy-1.23.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ac86f407873b952679f5f9e6c0612687e51547af0e14ddea1eedfcb22466babd"}, - {file = "numpy-1.23.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ae8adff4172692ce56233db04b7ce5792186f179c415c37d539c25de7298d25d"}, - {file = "numpy-1.23.0-cp38-cp38-win32.whl", hash = "sha256:fe8b9683eb26d2c4d5db32cd29b38fdcf8381324ab48313b5b69088e0e355379"}, - {file = "numpy-1.23.0-cp38-cp38-win_amd64.whl", hash = "sha256:5043bcd71fcc458dfb8a0fc5509bbc979da0131b9d08e3d5f50fb0bbb36f169a"}, - {file = "numpy-1.23.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1c29b44905af288b3919803aceb6ec7fec77406d8b08aaa2e8b9e63d0fe2f160"}, - {file = "numpy-1.23.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:98e8e0d8d69ff4d3fa63e6c61e8cfe2d03c29b16b58dbef1f9baa175bbed7860"}, - {file = "numpy-1.23.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:79a506cacf2be3a74ead5467aee97b81fca00c9c4c8b3ba16dbab488cd99ba10"}, - {file = "numpy-1.23.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:092f5e6025813e64ad6d1b52b519165d08c730d099c114a9247c9bb635a2a450"}, - {file = "numpy-1.23.0-cp39-cp39-win32.whl", hash = "sha256:d6ca8dabe696c2785d0c8c9b0d8a9b6e5fdbe4f922bde70d57fa1a2848134f95"}, - {file = "numpy-1.23.0-cp39-cp39-win_amd64.whl", hash = "sha256:fc431493df245f3c627c0c05c2bd134535e7929dbe2e602b80e42bf52ff760bc"}, - {file = "numpy-1.23.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:f9c3fc2adf67762c9fe1849c859942d23f8d3e0bee7b5ed3d4a9c3eeb50a2f07"}, - {file = "numpy-1.23.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0d2094e8f4d760500394d77b383a1b06d3663e8892cdf5df3c592f55f3bff66"}, - {file = "numpy-1.23.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:94b170b4fa0168cd6be4becf37cb5b127bd12a795123984385b8cd4aca9857e5"}, - {file = "numpy-1.23.0.tar.gz", hash = "sha256:bd3fa4fe2e38533d5336e1272fc4e765cabbbde144309ccee8675509d5cd7b05"}, + {file = "numpy-1.23.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9c88793f78fca17da0145455f0d7826bcb9f37da4764af27ac945488116efe63"}, + {file = "numpy-1.23.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:e9f4c4e51567b616be64e05d517c79a8a22f3606499941d97bb76f2ca59f982d"}, + {file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7903ba8ab592b82014713c491f6c5d3a1cde5b4a3bf116404e08f5b52f6daf43"}, + {file = "numpy-1.23.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e05b1c973a9f858c74367553e236f287e749465f773328c8ef31abe18f691e1"}, + {file = "numpy-1.23.5-cp310-cp310-win32.whl", hash = "sha256:522e26bbf6377e4d76403826ed689c295b0b238f46c28a7251ab94716da0b280"}, + {file = "numpy-1.23.5-cp310-cp310-win_amd64.whl", hash = "sha256:dbee87b469018961d1ad79b1a5d50c0ae850000b639bcb1b694e9981083243b6"}, + {file = "numpy-1.23.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ce571367b6dfe60af04e04a1834ca2dc5f46004ac1cc756fb95319f64c095a96"}, + {file = "numpy-1.23.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:56e454c7833e94ec9769fa0f86e6ff8e42ee38ce0ce1fa4cbb747ea7e06d56aa"}, + {file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5039f55555e1eab31124a5768898c9e22c25a65c1e0037f4d7c495a45778c9f2"}, + {file = "numpy-1.23.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:58f545efd1108e647604a1b5aa809591ccd2540f468a880bedb97247e72db387"}, + {file = "numpy-1.23.5-cp311-cp311-win32.whl", hash = "sha256:b2a9ab7c279c91974f756c84c365a669a887efa287365a8e2c418f8b3ba73fb0"}, + {file = "numpy-1.23.5-cp311-cp311-win_amd64.whl", hash = "sha256:0cbe9848fad08baf71de1a39e12d1b6310f1d5b2d0ea4de051058e6e1076852d"}, + {file = "numpy-1.23.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f063b69b090c9d918f9df0a12116029e274daf0181df392839661c4c7ec9018a"}, + {file = "numpy-1.23.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:0aaee12d8883552fadfc41e96b4c82ee7d794949e2a7c3b3a7201e968c7ecab9"}, + {file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:92c8c1e89a1f5028a4c6d9e3ccbe311b6ba53694811269b992c0b224269e2398"}, + {file = "numpy-1.23.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d208a0f8729f3fb790ed18a003f3a57895b989b40ea4dce4717e9cf4af62c6bb"}, + {file = "numpy-1.23.5-cp38-cp38-win32.whl", hash = "sha256:06005a2ef6014e9956c09ba07654f9837d9e26696a0470e42beedadb78c11b07"}, + {file = "numpy-1.23.5-cp38-cp38-win_amd64.whl", hash = "sha256:ca51fcfcc5f9354c45f400059e88bc09215fb71a48d3768fb80e357f3b457e1e"}, + {file = "numpy-1.23.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8969bfd28e85c81f3f94eb4a66bc2cf1dbdc5c18efc320af34bffc54d6b1e38f"}, + {file = "numpy-1.23.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a7ac231a08bb37f852849bbb387a20a57574a97cfc7b6cabb488a4fc8be176de"}, + {file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bf837dc63ba5c06dc8797c398db1e223a466c7ece27a1f7b5232ba3466aafe3d"}, + {file = "numpy-1.23.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33161613d2269025873025b33e879825ec7b1d831317e68f4f2f0f84ed14c719"}, + {file = "numpy-1.23.5-cp39-cp39-win32.whl", hash = "sha256:af1da88f6bc3d2338ebbf0e22fe487821ea4d8e89053e25fa59d1d79786e7481"}, + {file = "numpy-1.23.5-cp39-cp39-win_amd64.whl", hash = "sha256:09b7847f7e83ca37c6e627682f145856de331049013853f344f37b0c9690e3df"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:abdde9f795cf292fb9651ed48185503a2ff29be87770c3b8e2a14b0cd7aa16f8"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f9a909a8bae284d46bbfdefbdd4a262ba19d3bc9921b1e76126b1d21c3c34135"}, + {file = "numpy-1.23.5-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:01dd17cbb340bf0fc23981e52e1d18a9d4050792e8fb8363cecbf066a84b827d"}, + {file = "numpy-1.23.5.tar.gz", hash = "sha256:1b1766d6f397c18153d40015ddfc79ddb715cabadc04d2d228d4e5a8bc4ded1a"}, ] packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] pandas = [ - {file = "pandas-1.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d51674ed8e2551ef7773820ef5dab9322be0828629f2cbf8d1fc31a0c4fed640"}, - {file = "pandas-1.4.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:16ad23db55efcc93fa878f7837267973b61ea85d244fc5ff0ccbcfa5638706c5"}, - {file = "pandas-1.4.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:958a0588149190c22cdebbc0797e01972950c927a11a900fe6c2296f207b1d6f"}, - {file = "pandas-1.4.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e48fbb64165cda451c06a0f9e4c7a16b534fcabd32546d531b3c240ce2844112"}, - {file = "pandas-1.4.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6f803320c9da732cc79210d7e8cc5c8019aad512589c910c66529eb1b1818230"}, - {file = "pandas-1.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:2893e923472a5e090c2d5e8db83e8f907364ec048572084c7d10ef93546be6d1"}, - {file = "pandas-1.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:24ea75f47bbd5574675dae21d51779a4948715416413b30614c1e8b480909f81"}, - {file = "pandas-1.4.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d5ebc990bd34f4ac3c73a2724c2dcc9ee7bf1ce6cf08e87bb25c6ad33507e318"}, - {file = "pandas-1.4.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d6c0106415ff1a10c326c49bc5dd9ea8b9897a6ca0c8688eb9c30ddec49535ef"}, - {file = "pandas-1.4.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:78b00429161ccb0da252229bcda8010b445c4bf924e721265bec5a6e96a92e92"}, - {file = "pandas-1.4.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dfbf16b1ea4f4d0ee11084d9c026340514d1d30270eaa82a9f1297b6c8ecbf0"}, - {file = "pandas-1.4.3-cp38-cp38-win32.whl", hash = "sha256:48350592665ea3cbcd07efc8c12ff12d89be09cd47231c7925e3b8afada9d50d"}, - {file = "pandas-1.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:605d572126eb4ab2eadf5c59d5d69f0608df2bf7bcad5c5880a47a20a0699e3e"}, - {file = "pandas-1.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a3924692160e3d847e18702bb048dc38e0e13411d2b503fecb1adf0fcf950ba4"}, - {file = "pandas-1.4.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:07238a58d7cbc8a004855ade7b75bbd22c0db4b0ffccc721556bab8a095515f6"}, - {file = "pandas-1.4.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:755679c49460bd0d2f837ab99f0a26948e68fa0718b7e42afbabd074d945bf84"}, - {file = "pandas-1.4.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41fc406e374590a3d492325b889a2686b31e7a7780bec83db2512988550dadbf"}, - {file = "pandas-1.4.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1d9382f72a4f0e93909feece6fef5500e838ce1c355a581b3d8f259839f2ea76"}, - {file = "pandas-1.4.3-cp39-cp39-win32.whl", hash = "sha256:0daf876dba6c622154b2e6741f29e87161f844e64f84801554f879d27ba63c0d"}, - {file = "pandas-1.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:721a3dd2f06ef942f83a819c0f3f6a648b2830b191a72bbe9451bcd49c3bd42e"}, - {file = "pandas-1.4.3.tar.gz", hash = "sha256:2ff7788468e75917574f080cd4681b27e1a7bf36461fe968b49a87b5a54d007c"}, + {file = "pandas-1.4.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:799e6a25932df7e6b1f8dabf63de064e2205dc309abb75956126a0453fd88e97"}, + {file = "pandas-1.4.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7cd1d69a387f7d5e1a5a06a87574d9ef2433847c0e78113ab51c84d3a8bcaeaa"}, + {file = "pandas-1.4.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:94f2ed1fd51e545ebf71da1e942fe1822ee01e10d3dd2a7276d01351333b7c6b"}, + {file = "pandas-1.4.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4591cadd06fbbbd16fafc2de6e840c1aaefeae3d5864b688004777ef1bbdede3"}, + {file = "pandas-1.4.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d0022fe6a313df1c4869b5edc012d734c6519a6fffa3cf70930f32e6a1078e49"}, + {file = "pandas-1.4.4-cp310-cp310-win_amd64.whl", hash = "sha256:785e878a6e6d8ddcdb8c181e600855402750052497d7fc6d6b508894f6b8830b"}, + {file = "pandas-1.4.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:c4bb8b0ab9f94207d07e401d24baebfc63057246b1a5e0cd9ee50df85a656871"}, + {file = "pandas-1.4.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:51c424ca134fdaeac9a4acd719d1ab48046afc60943a489028f0413fdbe9ef1c"}, + {file = "pandas-1.4.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ce35f947202b0b99c660221d82beb91d2e6d553d55a40b30128204e3e2c63848"}, + {file = "pandas-1.4.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ee6f1848148ed3204235967613b0a32be2d77f214e9623f554511047705c1e04"}, + {file = "pandas-1.4.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7cc960959be28d064faefc0cb2aef854d46b827c004ebea7e79b5497ed83e7d"}, + {file = "pandas-1.4.4-cp38-cp38-win32.whl", hash = "sha256:9d805bce209714b1c1fa29bfb1e42ad87e4c0a825e4b390c56a3e71593b7e8d8"}, + {file = "pandas-1.4.4-cp38-cp38-win_amd64.whl", hash = "sha256:afbddad78a98ec4d2ce08b384b81730de1ccc975b99eb663e6dac43703f36d98"}, + {file = "pandas-1.4.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a08ceb59db499864c58a9bf85ab6219d527d91f14c0240cc25fa2c261032b2a7"}, + {file = "pandas-1.4.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0959c41004e3d2d16f39c828d6da66ebee329836a7ecee49fb777ac9ad8a7501"}, + {file = "pandas-1.4.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87b4194f344dcd14c0f885cecb22005329b38bda10f1aaf7b9596a00ec8a4768"}, + {file = "pandas-1.4.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d2a7a3c1fea668d56bd91edbd5f2732e0af8feb9d2bf8d9bfacb2dea5fa9536"}, + {file = "pandas-1.4.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a981cfabf51c318a562deb4ae7deec594c07aee7cf18b4594a92c23718ec8275"}, + {file = "pandas-1.4.4-cp39-cp39-win32.whl", hash = "sha256:050aada67a5ec6699a7879e769825b510018a95fb9ac462bb1867483d0974a97"}, + {file = "pandas-1.4.4-cp39-cp39-win_amd64.whl", hash = "sha256:8d4d2fe2863ecddb0ba1979bdda26c8bc2ea138f5a979abe3ba80c0fa4015c91"}, + {file = "pandas-1.4.4.tar.gz", hash = "sha256:ab6c0d738617b675183e5f28db32b5148b694ad9bba0a40c3ea26d96b431db67"}, ] pathspec = [ - {file = "pathspec-0.9.0-py2.py3-none-any.whl", hash = "sha256:7d15c4ddb0b5c802d161efc417ec1a2558ea2653c2e8ad9c19098201dc1c993a"}, - {file = "pathspec-0.9.0.tar.gz", hash = "sha256:e564499435a2673d586f6b2130bb5b95f04a3ba06f81b8f895b651a3c76aabb1"}, + {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, + {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, ] pbr = [ - {file = "pbr-5.9.0-py2.py3-none-any.whl", hash = "sha256:e547125940bcc052856ded43be8e101f63828c2d94239ffbe2b327ba3d5ccf0a"}, - {file = "pbr-5.9.0.tar.gz", hash = "sha256:e8dca2f4b43560edef58813969f52a56cef023146cbb8931626db80e6c1c4308"}, + {file = "pbr-5.11.0-py2.py3-none-any.whl", hash = "sha256:db2317ff07c84c4c63648c9064a79fe9d9f5c7ce85a9099d4b6258b3db83225a"}, + {file = "pbr-5.11.0.tar.gz", hash = "sha256:b97bc6695b2aff02144133c2e7399d5885223d42b7912ffaec2ca3898e673bfe"}, ] platformdirs = [ - {file = "platformdirs-2.5.2-py3-none-any.whl", hash = "sha256:027d8e83a2d7de06bbac4e5ef7e023c02b863d7ea5d079477e722bb41ab25788"}, - {file = "platformdirs-2.5.2.tar.gz", hash = "sha256:58c8abb07dcb441e6ee4b11d8df0ac856038f944ab98b7be6b27b2a3c7feef19"}, + {file = "platformdirs-2.5.4-py3-none-any.whl", hash = "sha256:af0276409f9a02373d540bf8480021a048711d572745aef4b7842dad245eba10"}, + {file = "platformdirs-2.5.4.tar.gz", hash = "sha256:1006647646d80f16130f052404c6b901e80ee4ed6bef6792e1f238a8969106f7"}, ] plotly = [ {file = "plotly-5.11.0-py2.py3-none-any.whl", hash = "sha256:52fd74b08aa4fd5a55b9d3034a30dbb746e572d7ed84897422f927fdf687ea5f"}, @@ -1257,46 +1336,20 @@ pluggy = [ {file = "pluggy-1.0.0.tar.gz", hash = "sha256:4224373bacce55f955a878bf9cfa763c1e360858e330072059e10bad68531159"}, ] psutil = [ - {file = "psutil-5.9.3-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:b4a247cd3feaae39bb6085fcebf35b3b8ecd9b022db796d89c8f05067ca28e71"}, - {file = "psutil-5.9.3-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:5fa88e3d5d0b480602553d362c4b33a63e0c40bfea7312a7bf78799e01e0810b"}, - {file = "psutil-5.9.3-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:767ef4fa33acda16703725c0473a91e1832d296c37c63896c7153ba81698f1ab"}, - {file = "psutil-5.9.3-cp27-cp27m-win32.whl", hash = "sha256:9a4af6ed1094f867834f5f07acd1250605a0874169a5fcadbcec864aec2496a6"}, - {file = "psutil-5.9.3-cp27-cp27m-win_amd64.whl", hash = "sha256:fa5e32c7d9b60b2528108ade2929b115167fe98d59f89555574715054f50fa31"}, - {file = "psutil-5.9.3-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:fe79b4ad4836e3da6c4650cb85a663b3a51aef22e1a829c384e18fae87e5e727"}, - {file = "psutil-5.9.3-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:db8e62016add2235cc87fb7ea000ede9e4ca0aa1f221b40cef049d02d5d2593d"}, - {file = "psutil-5.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:941a6c2c591da455d760121b44097781bc970be40e0e43081b9139da485ad5b7"}, - {file = "psutil-5.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:71b1206e7909792d16933a0d2c1c7f04ae196186c51ba8567abae1d041f06dcb"}, - {file = "psutil-5.9.3-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f57d63a2b5beaf797b87024d018772439f9d3103a395627b77d17a8d72009543"}, - {file = "psutil-5.9.3-cp310-cp310-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7507f6c7b0262d3e7b0eeda15045bf5881f4ada70473b87bc7b7c93b992a7d7"}, - {file = "psutil-5.9.3-cp310-cp310-win32.whl", hash = "sha256:1b540599481c73408f6b392cdffef5b01e8ff7a2ac8caae0a91b8222e88e8f1e"}, - {file = "psutil-5.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:547ebb02031fdada635452250ff39942db8310b5c4a8102dfe9384ee5791e650"}, - {file = "psutil-5.9.3-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d8c3cc6bb76492133474e130a12351a325336c01c96a24aae731abf5a47fe088"}, - {file = "psutil-5.9.3-cp36-cp36m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07d880053c6461c9b89cd5d4808f3b8336665fa3acdefd6777662c5ed73a851a"}, - {file = "psutil-5.9.3-cp36-cp36m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5e8b50241dd3c2ed498507f87a6602825073c07f3b7e9560c58411c14fe1e1c9"}, - {file = "psutil-5.9.3-cp36-cp36m-win32.whl", hash = "sha256:828c9dc9478b34ab96be75c81942d8df0c2bb49edbb481f597314d92b6441d89"}, - {file = "psutil-5.9.3-cp36-cp36m-win_amd64.whl", hash = "sha256:ed15edb14f52925869250b1375f0ff58ca5c4fa8adefe4883cfb0737d32f5c02"}, - {file = "psutil-5.9.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:d266cd05bd4a95ca1c2b9b5aac50d249cf7c94a542f47e0b22928ddf8b80d1ef"}, - {file = "psutil-5.9.3-cp37-cp37m-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7e4939ff75149b67aef77980409f156f0082fa36accc475d45c705bb00c6c16a"}, - {file = "psutil-5.9.3-cp37-cp37m-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:68fa227c32240c52982cb931801c5707a7f96dd8927f9102d6c7771ea1ff5698"}, - {file = "psutil-5.9.3-cp37-cp37m-win32.whl", hash = "sha256:beb57d8a1ca0ae0eb3d08ccaceb77e1a6d93606f0e1754f0d60a6ebd5c288837"}, - {file = "psutil-5.9.3-cp37-cp37m-win_amd64.whl", hash = "sha256:12500d761ac091f2426567f19f95fd3f15a197d96befb44a5c1e3cbe6db5752c"}, - {file = "psutil-5.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:ba38cf9984d5462b506e239cf4bc24e84ead4b1d71a3be35e66dad0d13ded7c1"}, - {file = "psutil-5.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:46907fa62acaac364fff0b8a9da7b360265d217e4fdeaca0a2397a6883dffba2"}, - {file = "psutil-5.9.3-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a04a1836894c8279e5e0a0127c0db8e198ca133d28be8a2a72b4db16f6cf99c1"}, - {file = "psutil-5.9.3-cp38-cp38-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a4e07611997acf178ad13b842377e3d8e9d0a5bac43ece9bfc22a96735d9a4f"}, - {file = "psutil-5.9.3-cp38-cp38-win32.whl", hash = "sha256:6ced1ad823ecfa7d3ce26fe8aa4996e2e53fb49b7fed8ad81c80958501ec0619"}, - {file = "psutil-5.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:35feafe232d1aaf35d51bd42790cbccb882456f9f18cdc411532902370d660df"}, - {file = "psutil-5.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:538fcf6ae856b5e12d13d7da25ad67f02113c96f5989e6ad44422cb5994ca7fc"}, - {file = "psutil-5.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a3d81165b8474087bb90ec4f333a638ccfd1d69d34a9b4a1a7eaac06648f9fbe"}, - {file = "psutil-5.9.3-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3a7826e68b0cf4ce2c1ee385d64eab7d70e3133171376cac53d7c1790357ec8f"}, - {file = "psutil-5.9.3-cp39-cp39-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ec296f565191f89c48f33d9544d8d82b0d2af7dd7d2d4e6319f27a818f8d1cc"}, - {file = "psutil-5.9.3-cp39-cp39-win32.whl", hash = "sha256:9ec95df684583b5596c82bb380c53a603bb051cf019d5c849c47e117c5064395"}, - {file = "psutil-5.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:4bd4854f0c83aa84a5a40d3b5d0eb1f3c128f4146371e03baed4589fe4f3c931"}, - {file = "psutil-5.9.3.tar.gz", hash = "sha256:7ccfcdfea4fc4b0a02ca2c31de7fcd186beb9cff8207800e14ab66f79c773af6"}, -] -py = [ - {file = "py-1.11.0-py2.py3-none-any.whl", hash = "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378"}, - {file = "py-1.11.0.tar.gz", hash = "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719"}, + {file = "psutil-5.9.4-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:c1ca331af862803a42677c120aff8a814a804e09832f166f226bfd22b56feee8"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:68908971daf802203f3d37e78d3f8831b6d1014864d7a85937941bb35f09aefe"}, + {file = "psutil-5.9.4-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:3ff89f9b835100a825b14c2808a106b6fdcc4b15483141482a12c725e7f78549"}, + {file = "psutil-5.9.4-cp27-cp27m-win32.whl", hash = "sha256:852dd5d9f8a47169fe62fd4a971aa07859476c2ba22c2254d4a1baa4e10b95ad"}, + {file = "psutil-5.9.4-cp27-cp27m-win_amd64.whl", hash = "sha256:9120cd39dca5c5e1c54b59a41d205023d436799b1c8c4d3ff71af18535728e94"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6b92c532979bafc2df23ddc785ed116fced1f492ad90a6830cf24f4d1ea27d24"}, + {file = "psutil-5.9.4-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:efeae04f9516907be44904cc7ce08defb6b665128992a56957abc9b61dca94b7"}, + {file = "psutil-5.9.4-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:54d5b184728298f2ca8567bf83c422b706200bcbbfafdc06718264f9393cfeb7"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:16653106f3b59386ffe10e0bad3bb6299e169d5327d3f187614b1cb8f24cf2e1"}, + {file = "psutil-5.9.4-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:54c0d3d8e0078b7666984e11b12b88af2db11d11249a8ac8920dd5ef68a66e08"}, + {file = "psutil-5.9.4-cp36-abi3-win32.whl", hash = "sha256:149555f59a69b33f056ba1c4eb22bb7bf24332ce631c44a319cec09f876aaeff"}, + {file = "psutil-5.9.4-cp36-abi3-win_amd64.whl", hash = "sha256:fd8522436a6ada7b4aad6638662966de0d61d241cb821239b2ae7013d41a43d4"}, + {file = "psutil-5.9.4-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:6001c809253a29599bc0dfd5179d9f8a5779f9dffea1da0f13c53ee568115e1e"}, + {file = "psutil-5.9.4.tar.gz", hash = "sha256:3d7f9739eb435d4b1338944abe23f49584bde5395f27487d2ee25ad9a8774a62"}, ] pyaml = [ {file = "pyaml-20.4.0-py2.py3-none-any.whl", hash = "sha256:67081749a82b72c45e5f7f812ee3a14a03b3f5c25ff36ec3b290514f8c4c4b99"}, @@ -1319,16 +1372,16 @@ pyparsing = [ {file = "pyparsing-3.0.9.tar.gz", hash = "sha256:2b020ecf7d21b687f219b71ecad3631f644a47f01403fa1d1036b0c6416d70fb"}, ] pytest = [ - {file = "pytest-7.1.2-py3-none-any.whl", hash = "sha256:13d0e3ccfc2b6e26be000cb6568c832ba67ba32e719443bfe725814d3c42433c"}, - {file = "pytest-7.1.2.tar.gz", hash = "sha256:a06a0425453864a270bc45e71f783330a7428defb4230fb5e6a731fde06ecd45"}, + {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, + {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, ] pytest-cov = [ {file = "pytest-cov-3.0.0.tar.gz", hash = "sha256:e7f0f5b1617d2210a2cabc266dfe2f4c75a8d32fb89eafb7ad9d06f6d076d470"}, {file = "pytest_cov-3.0.0-py3-none-any.whl", hash = "sha256:578d5d15ac4a25e5f961c938b85a05b09fdaae9deef3bb6de9a6e766622ca7a6"}, ] pytest-sugar = [ - {file = "pytest-sugar-0.9.5.tar.gz", hash = "sha256:eea78b6f15b635277d3d90280cd386d8feea1cab0f9be75947a626e8b02b477d"}, - {file = "pytest_sugar-0.9.5-py2.py3-none-any.whl", hash = "sha256:3da42de32ce4e1e95b448d61c92804433f5d4058c0a765096991c2e93d5a289f"}, + {file = "pytest-sugar-0.9.6.tar.gz", hash = "sha256:c4793495f3c32e114f0f5416290946c316eb96ad5a3684dcdadda9267e59b2b8"}, + {file = "pytest_sugar-0.9.6-py2.py3-none-any.whl", hash = "sha256:30e5225ed2b3cc988a8a672f8bda0fc37bcd92d62e9273937f061112b3f2186d"}, ] python-dateutil = [ {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, @@ -1339,8 +1392,12 @@ python-dotenv = [ {file = "python_dotenv-0.21.0-py3-none-any.whl", hash = "sha256:1684eb44636dd462b66c3ee016599815514527ad99965de77f43e0944634a7e5"}, ] pytz = [ - {file = "pytz-2022.1-py2.py3-none-any.whl", hash = "sha256:e68985985296d9a66a881eb3193b0906246245294a881e7c8afe623866ac6a5c"}, - {file = "pytz-2022.1.tar.gz", hash = "sha256:1e760e2fe6a8163bc0b3d9a19c4f84342afa0a2affebfaa84b01b978a02ecaa7"}, + {file = "pytz-2022.6-py2.py3-none-any.whl", hash = "sha256:222439474e9c98fced559f1709d89e6c9cbf8d79c794ff3eb9f8800064291427"}, + {file = "pytz-2022.6.tar.gz", hash = "sha256:e89512406b793ca39f5971bc999cc538ce125c0e51c27941bef4568b460095e2"}, +] +pytz-deprecation-shim = [ + {file = "pytz_deprecation_shim-0.1.0.post0-py2.py3-none-any.whl", hash = "sha256:8314c9692a636c8eb3bda879b9f119e350e93223ae83e70e80c31675a0fdc1a6"}, + {file = "pytz_deprecation_shim-0.1.0.post0.tar.gz", hash = "sha256:af097bae1b616dde5c5744441e2ddc69e74dfdcb0c263129610d85b87445a59d"}, ] pywin32 = [ {file = "pywin32-305-cp310-cp310-win32.whl", hash = "sha256:421f6cd86e84bbb696d54563c48014b12a23ef95a14e0bdba526be756d89f116"}, @@ -1400,6 +1457,96 @@ pyyaml = [ {file = "PyYAML-6.0-cp39-cp39-win_amd64.whl", hash = "sha256:b3d267842bf12586ba6c734f89d1f5b871df0273157918b0ccefa29deb05c21c"}, {file = "PyYAML-6.0.tar.gz", hash = "sha256:68fb519c14306fec9720a2a5b45bc9f0c8d1b9c72adf45c37baedfcd949c35a2"}, ] +regex = [ + {file = "regex-2022.10.31-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a8ff454ef0bb061e37df03557afda9d785c905dab15584860f982e88be73015f"}, + {file = "regex-2022.10.31-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1eba476b1b242620c266edf6325b443a2e22b633217a9835a52d8da2b5c051f9"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0e5af9a9effb88535a472e19169e09ce750c3d442fb222254a276d77808620b"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d03fe67b2325cb3f09be029fd5da8df9e6974f0cde2c2ac6a79d2634e791dd57"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a9d0b68ac1743964755ae2d89772c7e6fb0118acd4d0b7464eaf3921c6b49dd4"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8a45b6514861916c429e6059a55cf7db74670eaed2052a648e3e4d04f070e001"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8b0886885f7323beea6f552c28bff62cbe0983b9fbb94126531693ea6c5ebb90"}, + {file = "regex-2022.10.31-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:5aefb84a301327ad115e9d346c8e2760009131d9d4b4c6b213648d02e2abe144"}, + {file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:702d8fc6f25bbf412ee706bd73019da5e44a8400861dfff7ff31eb5b4a1276dc"}, + {file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a3c1ebd4ed8e76e886507c9eddb1a891673686c813adf889b864a17fafcf6d66"}, + {file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:50921c140561d3db2ab9f5b11c5184846cde686bb5a9dc64cae442926e86f3af"}, + {file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7db345956ecce0c99b97b042b4ca7326feeec6b75facd8390af73b18e2650ffc"}, + {file = "regex-2022.10.31-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:763b64853b0a8f4f9cfb41a76a4a85a9bcda7fdda5cb057016e7706fde928e66"}, + {file = "regex-2022.10.31-cp310-cp310-win32.whl", hash = "sha256:44136355e2f5e06bf6b23d337a75386371ba742ffa771440b85bed367c1318d1"}, + {file = "regex-2022.10.31-cp310-cp310-win_amd64.whl", hash = "sha256:bfff48c7bd23c6e2aec6454aaf6edc44444b229e94743b34bdcdda2e35126cf5"}, + {file = "regex-2022.10.31-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4b4b1fe58cd102d75ef0552cf17242705ce0759f9695334a56644ad2d83903fe"}, + {file = "regex-2022.10.31-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:542e3e306d1669b25936b64917285cdffcd4f5c6f0247636fec037187bd93542"}, + {file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c27cc1e4b197092e50ddbf0118c788d9977f3f8f35bfbbd3e76c1846a3443df7"}, + {file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8e38472739028e5f2c3a4aded0ab7eadc447f0d84f310c7a8bb697ec417229e"}, + {file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:76c598ca73ec73a2f568e2a72ba46c3b6c8690ad9a07092b18e48ceb936e9f0c"}, + {file = "regex-2022.10.31-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c28d3309ebd6d6b2cf82969b5179bed5fefe6142c70f354ece94324fa11bf6a1"}, + {file = "regex-2022.10.31-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9af69f6746120998cd9c355e9c3c6aec7dff70d47247188feb4f829502be8ab4"}, + {file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a5f9505efd574d1e5b4a76ac9dd92a12acb2b309551e9aa874c13c11caefbe4f"}, + {file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5ff525698de226c0ca743bfa71fc6b378cda2ddcf0d22d7c37b1cc925c9650a5"}, + {file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:4fe7fda2fe7c8890d454f2cbc91d6c01baf206fbc96d89a80241a02985118c0c"}, + {file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2cdc55ca07b4e70dda898d2ab7150ecf17c990076d3acd7a5f3b25cb23a69f1c"}, + {file = "regex-2022.10.31-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:44a6c2f6374e0033873e9ed577a54a3602b4f609867794c1a3ebba65e4c93ee7"}, + {file = "regex-2022.10.31-cp311-cp311-win32.whl", hash = "sha256:d8716f82502997b3d0895d1c64c3b834181b1eaca28f3f6336a71777e437c2af"}, + {file = "regex-2022.10.31-cp311-cp311-win_amd64.whl", hash = "sha256:61edbca89aa3f5ef7ecac8c23d975fe7261c12665f1d90a6b1af527bba86ce61"}, + {file = "regex-2022.10.31-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:0a069c8483466806ab94ea9068c34b200b8bfc66b6762f45a831c4baaa9e8cdd"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d26166acf62f731f50bdd885b04b38828436d74e8e362bfcb8df221d868b5d9b"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac741bf78b9bb432e2d314439275235f41656e189856b11fb4e774d9f7246d81"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:75f591b2055523fc02a4bbe598aa867df9e953255f0b7f7715d2a36a9c30065c"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6b30bddd61d2a3261f025ad0f9ee2586988c6a00c780a2fb0a92cea2aa702c54"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ef4163770525257876f10e8ece1cf25b71468316f61451ded1a6f44273eedeb5"}, + {file = "regex-2022.10.31-cp36-cp36m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7b280948d00bd3973c1998f92e22aa3ecb76682e3a4255f33e1020bd32adf443"}, + {file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_aarch64.whl", hash = "sha256:d0213671691e341f6849bf33cd9fad21f7b1cb88b89e024f33370733fec58742"}, + {file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_i686.whl", hash = "sha256:22e7ebc231d28393dfdc19b185d97e14a0f178bedd78e85aad660e93b646604e"}, + {file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_ppc64le.whl", hash = "sha256:8ad241da7fac963d7573cc67a064c57c58766b62a9a20c452ca1f21050868dfa"}, + {file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_s390x.whl", hash = "sha256:586b36ebda81e6c1a9c5a5d0bfdc236399ba6595e1397842fd4a45648c30f35e"}, + {file = "regex-2022.10.31-cp36-cp36m-musllinux_1_1_x86_64.whl", hash = "sha256:0653d012b3bf45f194e5e6a41df9258811ac8fc395579fa82958a8b76286bea4"}, + {file = "regex-2022.10.31-cp36-cp36m-win32.whl", hash = "sha256:144486e029793a733e43b2e37df16a16df4ceb62102636ff3db6033994711066"}, + {file = "regex-2022.10.31-cp36-cp36m-win_amd64.whl", hash = "sha256:c14b63c9d7bab795d17392c7c1f9aaabbffd4cf4387725a0ac69109fb3b550c6"}, + {file = "regex-2022.10.31-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:4cac3405d8dda8bc6ed499557625585544dd5cbf32072dcc72b5a176cb1271c8"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23cbb932cc53a86ebde0fb72e7e645f9a5eec1a5af7aa9ce333e46286caef783"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74bcab50a13960f2a610cdcd066e25f1fd59e23b69637c92ad470784a51b1347"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:78d680ef3e4d405f36f0d6d1ea54e740366f061645930072d39bca16a10d8c93"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce6910b56b700bea7be82c54ddf2e0ed792a577dfaa4a76b9af07d550af435c6"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:659175b2144d199560d99a8d13b2228b85e6019b6e09e556209dfb8c37b78a11"}, + {file = "regex-2022.10.31-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:1ddf14031a3882f684b8642cb74eea3af93a2be68893901b2b387c5fd92a03ec"}, + {file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:b683e5fd7f74fb66e89a1ed16076dbab3f8e9f34c18b1979ded614fe10cdc4d9"}, + {file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2bde29cc44fa81c0a0c8686992c3080b37c488df167a371500b2a43ce9f026d1"}, + {file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:4919899577ba37f505aaebdf6e7dc812d55e8f097331312db7f1aab18767cce8"}, + {file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:9c94f7cc91ab16b36ba5ce476f1904c91d6c92441f01cd61a8e2729442d6fcf5"}, + {file = "regex-2022.10.31-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ae1e96785696b543394a4e3f15f3f225d44f3c55dafe3f206493031419fedf95"}, + {file = "regex-2022.10.31-cp37-cp37m-win32.whl", hash = "sha256:c670f4773f2f6f1957ff8a3962c7dd12e4be54d05839b216cb7fd70b5a1df394"}, + {file = "regex-2022.10.31-cp37-cp37m-win_amd64.whl", hash = "sha256:8e0caeff18b96ea90fc0eb6e3bdb2b10ab5b01a95128dfeccb64a7238decf5f0"}, + {file = "regex-2022.10.31-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:131d4be09bea7ce2577f9623e415cab287a3c8e0624f778c1d955ec7c281bd4d"}, + {file = "regex-2022.10.31-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:e613a98ead2005c4ce037c7b061f2409a1a4e45099edb0ef3200ee26ed2a69a8"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:052b670fafbe30966bbe5d025e90b2a491f85dfe5b2583a163b5e60a85a321ad"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aa62a07ac93b7cb6b7d0389d8ef57ffc321d78f60c037b19dfa78d6b17c928ee"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5352bea8a8f84b89d45ccc503f390a6be77917932b1c98c4cdc3565137acc714"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f61c9944f0be2dc2b75689ba409938c14876c19d02f7585af4460b6a21403e"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:29c04741b9ae13d1e94cf93fca257730b97ce6ea64cfe1eba11cf9ac4e85afb6"}, + {file = "regex-2022.10.31-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:543883e3496c8b6d58bd036c99486c3c8387c2fc01f7a342b760c1ea3158a318"}, + {file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b7a8b43ee64ca8f4befa2bea4083f7c52c92864d8518244bfa6e88c751fa8fff"}, + {file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:6a9a19bea8495bb419dc5d38c4519567781cd8d571c72efc6aa959473d10221a"}, + {file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6ffd55b5aedc6f25fd8d9f905c9376ca44fcf768673ffb9d160dd6f409bfda73"}, + {file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4bdd56ee719a8f751cf5a593476a441c4e56c9b64dc1f0f30902858c4ef8771d"}, + {file = "regex-2022.10.31-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:8ca88da1bd78990b536c4a7765f719803eb4f8f9971cc22d6ca965c10a7f2c4c"}, + {file = "regex-2022.10.31-cp38-cp38-win32.whl", hash = "sha256:5a260758454580f11dd8743fa98319bb046037dfab4f7828008909d0aa5292bc"}, + {file = "regex-2022.10.31-cp38-cp38-win_amd64.whl", hash = "sha256:5e6a5567078b3eaed93558842346c9d678e116ab0135e22eb72db8325e90b453"}, + {file = "regex-2022.10.31-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5217c25229b6a85049416a5c1e6451e9060a1edcf988641e309dbe3ab26d3e49"}, + {file = "regex-2022.10.31-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4bf41b8b0a80708f7e0384519795e80dcb44d7199a35d52c15cc674d10b3081b"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cf0da36a212978be2c2e2e2d04bdff46f850108fccc1851332bcae51c8907cc"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d403d781b0e06d2922435ce3b8d2376579f0c217ae491e273bab8d092727d244"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a37d51fa9a00d265cf73f3de3930fa9c41548177ba4f0faf76e61d512c774690"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4f781ffedd17b0b834c8731b75cce2639d5a8afe961c1e58ee7f1f20b3af185"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d243b36fbf3d73c25e48014961e83c19c9cc92530516ce3c43050ea6276a2ab7"}, + {file = "regex-2022.10.31-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:370f6e97d02bf2dd20d7468ce4f38e173a124e769762d00beadec3bc2f4b3bc4"}, + {file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:597f899f4ed42a38df7b0e46714880fb4e19a25c2f66e5c908805466721760f5"}, + {file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:7dbdce0c534bbf52274b94768b3498abdf675a691fec5f751b6057b3030f34c1"}, + {file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:22960019a842777a9fa5134c2364efaed5fbf9610ddc5c904bd3a400973b0eb8"}, + {file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:7f5a3ffc731494f1a57bd91c47dc483a1e10048131ffb52d901bfe2beb6102e8"}, + {file = "regex-2022.10.31-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:7ef6b5942e6bfc5706301a18a62300c60db9af7f6368042227ccb7eeb22d0892"}, + {file = "regex-2022.10.31-cp39-cp39-win32.whl", hash = "sha256:395161bbdbd04a8333b9ff9763a05e9ceb4fe210e3c7690f5e68cedd3d65d8e1"}, + {file = "regex-2022.10.31-cp39-cp39-win_amd64.whl", hash = "sha256:957403a978e10fb3ca42572a23e6f7badff39aa1ce2f4ade68ee452dc6807692"}, + {file = "regex-2022.10.31.tar.gz", hash = "sha256:a3a98921da9a1bf8457aeee6a551948a83601689e5ecdd736894ea9bbec77e83"}, +] requests = [ {file = "requests-2.28.1-py3-none-any.whl", hash = "sha256:8fefa2a1a1365bf5520aac41836fbee479da67864514bdb821f31ce07ce65349"}, {file = "requests-2.28.1.tar.gz", hash = "sha256:7c5599b102feddaa661c826c56ab4fee28bfd17f5abca1ebbe3e7f19d7c97983"}, @@ -1409,40 +1556,43 @@ requests = [ {file = "ruamel.yaml-0.17.21.tar.gz", hash = "sha256:8b7ce697a2f212752a35c1ac414471dc16c424c9573be4926b56ff3f5d23b7af"}, ] "ruamel.yaml.clib" = [ - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:6e7be2c5bcb297f5b82fee9c665eb2eb7001d1050deaba8471842979293a80b0"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:066f886bc90cc2ce44df8b5f7acfc6a7e2b2e672713f027136464492b0c34d7c"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:221eca6f35076c6ae472a531afa1c223b9c29377e62936f61bc8e6e8bdc5f9e7"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win32.whl", hash = "sha256:1070ba9dd7f9370d0513d649420c3b362ac2d687fe78c6e888f5b12bf8bc7bee"}, - {file = "ruamel.yaml.clib-0.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:77df077d32921ad46f34816a9a16e6356d8100374579bc35e15bab5d4e9377de"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-macosx_10_6_intel.whl", hash = "sha256:cfdb9389d888c5b74af297e51ce357b800dd844898af9d4a547ffc143fa56751"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-manylinux1_x86_64.whl", hash = "sha256:7b2927e92feb51d830f531de4ccb11b320255ee95e791022555971c466af4527"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win32.whl", hash = "sha256:ada3f400d9923a190ea8b59c8f60680c4ef8a4b0dfae134d2f2ff68429adfab5"}, - {file = "ruamel.yaml.clib-0.2.6-cp35-cp35m-win_amd64.whl", hash = "sha256:de9c6b8a1ba52919ae919f3ae96abb72b994dd0350226e28f3686cb4f142165c"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:d67f273097c368265a7b81e152e07fb90ed395df6e552b9fa858c6d2c9f42502"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux1_x86_64.whl", hash = "sha256:72a2b8b2ff0a627496aad76f37a652bcef400fd861721744201ef1b45199ab78"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:d3c620a54748a3d4cf0bcfe623e388407c8e85a4b06b8188e126302bcab93ea8"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win32.whl", hash = "sha256:9efef4aab5353387b07f6b22ace0867032b900d8e91674b5d8ea9150db5cae94"}, - {file = "ruamel.yaml.clib-0.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:846fc8336443106fe23f9b6d6b8c14a53d38cef9a375149d61f99d78782ea468"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:0847201b767447fc33b9c235780d3aa90357d20dd6108b92be544427bea197dd"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux1_x86_64.whl", hash = "sha256:78988ed190206672da0f5d50c61afef8f67daa718d614377dcd5e3ed85ab4a99"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:210c8fcfeff90514b7133010bf14e3bad652c8efde6b20e00c43854bf94fa5a6"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win32.whl", hash = "sha256:a49e0161897901d1ac9c4a79984b8410f450565bbad64dbfcbf76152743a0cdb"}, - {file = "ruamel.yaml.clib-0.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:bf75d28fa071645c529b5474a550a44686821decebdd00e21127ef1fd566eabe"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:a32f8d81ea0c6173ab1b3da956869114cae53ba1e9f72374032e33ba3118c233"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux1_x86_64.whl", hash = "sha256:7f7ecb53ae6848f959db6ae93bdff1740e651809780822270eab111500842a84"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:61bc5e5ca632d95925907c569daa559ea194a4d16084ba86084be98ab1cec1c6"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win32.whl", hash = "sha256:89221ec6d6026f8ae859c09b9718799fea22c0e8da8b766b0b2c9a9ba2db326b"}, - {file = "ruamel.yaml.clib-0.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:31ea73e564a7b5fbbe8188ab8b334393e06d997914a4e184975348f204790277"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:dc6a613d6c74eef5a14a214d433d06291526145431c3b964f5e16529b1842bed"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux1_x86_64.whl", hash = "sha256:1866cf2c284a03b9524a5cc00daca56d80057c5ce3cdc86a52020f4c720856f0"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:1b4139a6ffbca8ef60fdaf9b33dec05143ba746a6f0ae0f9d11d38239211d335"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win32.whl", hash = "sha256:3fb9575a5acd13031c57a62cc7823e5d2ff8bc3835ba4d94b921b4e6ee664104"}, - {file = "ruamel.yaml.clib-0.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:825d5fccef6da42f3c8eccd4281af399f21c02b32d98e113dbc631ea6a6ecbc7"}, - {file = "ruamel.yaml.clib-0.2.6.tar.gz", hash = "sha256:4ff604ce439abb20794f05613c374759ce10e3595d1867764dd1ae675b85acbd"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:d5859983f26d8cd7bb5c287ef452e8aacc86501487634573d260968f753e1d71"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-macosx_12_0_arm64.whl", hash = "sha256:debc87a9516b237d0466a711b18b6ebeb17ba9f391eb7f91c649c5c4ec5006c7"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux2014_aarch64.whl", hash = "sha256:df5828871e6648db72d1c19b4bd24819b80a755c4541d3409f0f7acd0f335c80"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:efa08d63ef03d079dcae1dfe334f6c8847ba8b645d08df286358b1f5293d24ab"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win32.whl", hash = "sha256:763d65baa3b952479c4e972669f679fe490eee058d5aa85da483ebae2009d231"}, + {file = "ruamel.yaml.clib-0.2.7-cp310-cp310-win_amd64.whl", hash = "sha256:d000f258cf42fec2b1bbf2863c61d7b8918d31ffee905da62dede869254d3b8a"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:045e0626baf1c52e5527bd5db361bc83180faaba2ff586e763d3d5982a876a9e"}, + {file = "ruamel.yaml.clib-0.2.7-cp311-cp311-macosx_12_6_arm64.whl", hash = "sha256:721bc4ba4525f53f6a611ec0967bdcee61b31df5a56801281027a3a6d1c2daf5"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_10_9_x86_64.whl", hash = "sha256:4b3a93bb9bc662fc1f99c5c3ea8e623d8b23ad22f861eb6fce9377ac07ad6072"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-macosx_12_0_arm64.whl", hash = "sha256:a234a20ae07e8469da311e182e70ef6b199d0fbeb6c6cc2901204dd87fb867e8"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux2014_aarch64.whl", hash = "sha256:15910ef4f3e537eea7fe45f8a5d19997479940d9196f357152a09031c5be59f3"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:370445fd795706fd291ab00c9df38a0caed0f17a6fb46b0f607668ecb16ce763"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win32.whl", hash = "sha256:ecdf1a604009bd35c674b9225a8fa609e0282d9b896c03dd441a91e5f53b534e"}, + {file = "ruamel.yaml.clib-0.2.7-cp36-cp36m-win_amd64.whl", hash = "sha256:f34019dced51047d6f70cb9383b2ae2853b7fc4dce65129a5acd49f4f9256646"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:2aa261c29a5545adfef9296b7e33941f46aa5bbd21164228e833412af4c9c75f"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-macosx_12_0_arm64.whl", hash = "sha256:f01da5790e95815eb5a8a138508c01c758e5f5bc0ce4286c4f7028b8dd7ac3d0"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux2014_aarch64.whl", hash = "sha256:40d030e2329ce5286d6b231b8726959ebbe0404c92f0a578c0e2482182e38282"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:c3ca1fbba4ae962521e5eb66d72998b51f0f4d0f608d3c0347a48e1af262efa7"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win32.whl", hash = "sha256:7bdb4c06b063f6fd55e472e201317a3bb6cdeeee5d5a38512ea5c01e1acbdd93"}, + {file = "ruamel.yaml.clib-0.2.7-cp37-cp37m-win_amd64.whl", hash = "sha256:be2a7ad8fd8f7442b24323d24ba0b56c51219513cfa45b9ada3b87b76c374d4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:91a789b4aa0097b78c93e3dc4b40040ba55bef518f84a40d4442f713b4094acb"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-macosx_12_0_arm64.whl", hash = "sha256:99e77daab5d13a48a4054803d052ff40780278240a902b880dd37a51ba01a307"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux2014_aarch64.whl", hash = "sha256:3243f48ecd450eddadc2d11b5feb08aca941b5cd98c9b1db14b2fd128be8c697"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:8831a2cedcd0f0927f788c5bdf6567d9dc9cc235646a434986a852af1cb54b4b"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win32.whl", hash = "sha256:3110a99e0f94a4a3470ff67fc20d3f96c25b13d24c6980ff841e82bafe827cac"}, + {file = "ruamel.yaml.clib-0.2.7-cp38-cp38-win_amd64.whl", hash = "sha256:92460ce908546ab69770b2e576e4f99fbb4ce6ab4b245345a3869a0a0410488f"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5bc0667c1eb8f83a3752b71b9c4ba55ef7c7058ae57022dd9b29065186a113d9"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-macosx_12_0_arm64.whl", hash = "sha256:4a4d8d417868d68b979076a9be6a38c676eca060785abaa6709c7b31593c35d1"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux2014_aarch64.whl", hash = "sha256:bf9a6bc4a0221538b1a7de3ed7bca4c93c02346853f44e1cd764be0023cd3640"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:a7b301ff08055d73223058b5c46c55638917f04d21577c95e00e0c4d79201a6b"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win32.whl", hash = "sha256:d5e51e2901ec2366b79f16c2299a03e74ba4531ddcfacc1416639c557aef0ad8"}, + {file = "ruamel.yaml.clib-0.2.7-cp39-cp39-win_amd64.whl", hash = "sha256:184faeaec61dbaa3cace407cffc5819f7b977e75360e8d5ca19461cd851a5fc5"}, + {file = "ruamel.yaml.clib-0.2.7.tar.gz", hash = "sha256:1f08fd5a2bea9c4180db71678e850b995d2a5f4537be0e94557668cf0f5f9497"}, ] safety = [ - {file = "safety-2.0.0-py3-none-any.whl", hash = "sha256:77cebdd128ce47b941e68a1b3bbc29fbbd2b9e98d11f179c5def64c1d05da295"}, - {file = "safety-2.0.0.tar.gz", hash = "sha256:d739d00a9e4203cfaba34540c822a73ca1d327159ed7776b3dce09391f81c35d"}, + {file = "safety-2.3.2-py3-none-any.whl", hash = "sha256:d824cccd76fcf451c745d0a280dabc5176903878a68b9b9a2ec7dbfc2f8d03ff"}, + {file = "safety-2.3.2.tar.gz", hash = "sha256:7ed8d71f5ba7590d1c9abfa22c72a64de389ae2e07c6732b1c90955a168c55bf"}, ] six = [ {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, @@ -1453,8 +1603,8 @@ smmap = [ {file = "smmap-5.0.0.tar.gz", hash = "sha256:c840e62059cd3be204b0c9c9f74be2c09d5648eddd4580d9314c3ecde0b30936"}, ] stevedore = [ - {file = "stevedore-3.5.0-py3-none-any.whl", hash = "sha256:a547de73308fd7e90075bb4d301405bebf705292fa90a90fc3bcf9133f58616c"}, - {file = "stevedore-3.5.0.tar.gz", hash = "sha256:f40253887d8712eaa2bb0ea3830374416736dc8ec0e22f5a65092c1174c44335"}, + {file = "stevedore-4.1.1-py3-none-any.whl", hash = "sha256:aa6436565c069b2946fe4ebff07f5041e0c8bf18c7376dd29edf80cf7d524e4e"}, + {file = "stevedore-4.1.1.tar.gz", hash = "sha256:7f8aeb6e3f90f96832c301bff21a7eb5eefbe894c88c506483d355565d88cc1a"}, ] tabulate = [ {file = "tabulate-0.8.10-py3-none-any.whl", hash = "sha256:0ba055423dbaa164b9e456abe7920c5e8ed33fcc16f6d1b2f2d152c8e1e8b4fc"}, @@ -1466,7 +1616,8 @@ tenacity = [ {file = "tenacity-8.1.0.tar.gz", hash = "sha256:e48c437fdf9340f5666b92cd7990e96bc5fc955e1298baf4a907e3972067a445"}, ] termcolor = [ - {file = "termcolor-1.1.0.tar.gz", hash = "sha256:1d6d69ce66211143803fbc56652b41d73b4a400a2891d7bf7a1cdf4c02de613b"}, + {file = "termcolor-2.1.1-py3-none-any.whl", hash = "sha256:fa852e957f97252205e105dd55bbc23b419a70fec0085708fc0515e399f304fd"}, + {file = "termcolor-2.1.1.tar.gz", hash = "sha256:67cee2009adc6449c650f6bcf3bdeed00c8ba53a8cda5362733c53e0a39fb70b"}, ] toml = [ {file = "toml-0.10.2-py2.py3-none-any.whl", hash = "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b"}, @@ -1481,12 +1632,20 @@ tqdm = [ {file = "tqdm-4.59.0.tar.gz", hash = "sha256:d666ae29164da3e517fcf125e41d4fe96e5bb375cd87ff9763f6b38b5592fe33"}, ] typing-extensions = [ - {file = "typing_extensions-4.3.0-py3-none-any.whl", hash = "sha256:25642c956049920a5aa49edcdd6ab1e06d7e5d467fc00e0506c44ac86fbfca02"}, - {file = "typing_extensions-4.3.0.tar.gz", hash = "sha256:e6d2677a32f47fc7eb2795db1dd15c1f34eff616bcaf2cfb5e997f854fa1c4a6"}, + {file = "typing_extensions-4.4.0-py3-none-any.whl", hash = "sha256:16fa4864408f655d35ec496218b85f79b3437c829e93320c7c9215ccfd92489e"}, + {file = "typing_extensions-4.4.0.tar.gz", hash = "sha256:1511434bb92bf8dd198c12b1cc812e800d4181cfcb867674e0f8279cc93087aa"}, +] +tzdata = [ + {file = "tzdata-2022.6-py2.py3-none-any.whl", hash = "sha256:04a680bdc5b15750c39c12a448885a51134a27ec9af83667663f0b3a1bf3f342"}, + {file = "tzdata-2022.6.tar.gz", hash = "sha256:91f11db4503385928c15598c98573e3af07e7229181bee5375bd30f1695ddcae"}, +] +tzlocal = [ + {file = "tzlocal-4.2-py3-none-any.whl", hash = "sha256:89885494684c929d9191c57aa27502afc87a579be5cdd3225c77c463ea043745"}, + {file = "tzlocal-4.2.tar.gz", hash = "sha256:ee5842fa3a795f023514ac2d801c4a81d1743bbe642e3940143326b3a00addd7"}, ] urllib3 = [ - {file = "urllib3-1.26.9-py2.py3-none-any.whl", hash = "sha256:44ece4d53fb1706f667c9bd1c648f5469a2ec925fcf3a776667042d645472c14"}, - {file = "urllib3-1.26.9.tar.gz", hash = "sha256:aabaf16477806a5e1dd19aa41f8c2b7950dd3c746362d7e3223dbe6de6ac448e"}, + {file = "urllib3-1.26.13-py2.py3-none-any.whl", hash = "sha256:47cc05d99aaa09c9e72ed5809b60e7ba354e64b59c9c173ac3018642d8bb41fc"}, + {file = "urllib3-1.26.13.tar.gz", hash = "sha256:c083dd0dce68dbfbe1129d5271cb90f9447dea7d52097c6e0126120c521ddea8"}, ] werkzeug = [ {file = "Werkzeug-2.2.2-py3-none-any.whl", hash = "sha256:f979ab81f58d7318e064e99c4506445d60135ac5cd2e177a2de0089bfd4c9bd5"}, diff --git a/pages/libs/mpxsonar/pyproject.toml b/pages/libs/mpxsonar/pyproject.toml index 82e11ca..7e7954f 100644 --- a/pages/libs/mpxsonar/pyproject.toml +++ b/pages/libs/mpxsonar/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "mpxsonar" -version = "0.3.8" +version = "0.4.3" description = "A database-driven system for handling genomic sequences and screening genomic profiles." authors = ["Stephan Fuchs ", "Kunaphas Kongkitimanon ", "Matthew Huska "] license = "GPL3" @@ -21,6 +21,7 @@ requests = "^2.28.0" python-dotenv = "^0.21.0" mariadb = "^1.1.4" psutil = "^5.9.3" +dateparser = "^1.1.4" [tool.poetry.dev-dependencies] pytest = "^7.1.2" diff --git a/pages/libs/mpxsonar/setup-database.sh.template b/pages/libs/mpxsonar/setup-database.sh.template new file mode 100644 index 0000000..953c841 --- /dev/null +++ b/pages/libs/mpxsonar/setup-database.sh.template @@ -0,0 +1,25 @@ +#!/bin/bash + +conda activate mpxsonar-dev + +sonar setup + +sonar add-ref --gbk refs/NC_063383.1.gb +sonar add-ref --gbk refs/NC_003310.1.gb +sonar add-ref --gbk refs/ON563414.3.gb +sonar add-ref --gbk refs/ON568298.1.gb +sonar add-ref --gbk refs/ON585033.1.gb +sonar add-ref --gbk refs/MN648051.1.gb +sonar add-ref --gbk refs/MT903344.1.gb + + +# ------------------------------ +sonar add-prop --name COLLECTION_DATE --dtype text --descr "collection date" +sonar add-prop --name RELEASE_DATE --dtype date --descr "A release date" +sonar add-prop --name ISOLATE --dtype text --descr "isolate from where" +sonar add-prop --name SEQ_TECH --dtype text --descr "sequencing technologies" +sonar add-prop --name LENGTH --dtype integer --descr "dna length" +sonar add-prop --name COUNTRY --dtype text --descr "A country" +sonar add-prop --name GEO_LOCATION --dtype text --descr "A GEO_LOCATION" +# sonar add-prop --name HOST --dtype text --descr "A host" +# sonar add-prop --name FAMILY --dtype text --descr "A Family" diff --git a/pages/libs/mpxsonar/src/mpxsonar/align.py b/pages/libs/mpxsonar/src/mpxsonar/align.py index 2aa82f6..f1635c0 100644 --- a/pages/libs/mpxsonar/src/mpxsonar/align.py +++ b/pages/libs/mpxsonar/src/mpxsonar/align.py @@ -39,8 +39,8 @@ def log(self, msg, die=False, errtype="error"): exit(errtype + ": " + msg) def cal_seq_length(self, seq, msg=""): - lower_bound = int((len(seq) * 97) / 100) - upper_bound = int((len(seq) * 103) / 100) + lower_bound = (len(seq) * 97) / 100 + upper_bound = (len(seq) * 103) / 100 self.log(seq) self.log(msg + "=" + " LO:" + str(lower_bound) + "UP:" + str(upper_bound)) self.log("#----------#") @@ -61,7 +61,7 @@ def align(self, qry, ref, gapopen=16, gapextend=4): # datafile="EDNAFULL", auto set by strecher ) stdout, stderr = cline() - self.cal_seq_length(stdout[0:20], msg="stdout") + # self.cal_seq_length(stdout[0:20], msg="stdout") # find the fist position of '\n' to get seq1 s1 = stdout.find("\n") + 1 # find the start of second sequence position diff --git a/pages/libs/mpxsonar/src/mpxsonar/basics.py b/pages/libs/mpxsonar/src/mpxsonar/basics.py index eed83c4..49b8eed 100644 --- a/pages/libs/mpxsonar/src/mpxsonar/basics.py +++ b/pages/libs/mpxsonar/src/mpxsonar/basics.py @@ -6,6 +6,7 @@ # DEPENDENCIES import collections import csv +from datetime import datetime import os import sys @@ -477,10 +478,11 @@ def import_data( # noqa: C901 ): pbar.update(1) # insert into DB - cache.import_cached_samples() + cache.import_cached_samples(threads) # importing properties if tsv: + logging.info("Import meta data.") with sonarDBManager(db, readonly=False, debug=debug) as dbm: for sample_name in tqdm( properties, @@ -496,6 +498,8 @@ def import_data( # noqa: C901 for property_name, value in properties[sample_name].items(): dbm.insert_property(sample_id, property_name, value) + cache.log(f"//Done:--{datetime.now().strftime('%m/%d/%Y, %H:%M:%S')}--") + # matching @staticmethod def match( diff --git a/pages/libs/mpxsonar/src/mpxsonar/cache.py b/pages/libs/mpxsonar/src/mpxsonar/cache.py index 59a828b..35d5c01 100644 --- a/pages/libs/mpxsonar/src/mpxsonar/cache.py +++ b/pages/libs/mpxsonar/src/mpxsonar/cache.py @@ -15,6 +15,7 @@ from tempfile import mkdtemp import traceback +from mpire import WorkerPool import pandas as pd from tqdm import tqdm @@ -115,13 +116,15 @@ def __init__( self.algn_dir = os.path.join(self.basedir, "algn") self.var_dir = os.path.join(self.basedir, "var") self.ref_dir = os.path.join(self.basedir, "ref") - + self.error_dir = os.path.join(self.basedir, "error") os.makedirs(self.basedir, exist_ok=True) os.makedirs(self.seq_dir, exist_ok=True) os.makedirs(self.ref_dir, exist_ok=True) # os.makedirs(self.algn_dir, exist_ok=True) os.makedirs(self.var_dir, exist_ok=True) os.makedirs(self.sample_dir, exist_ok=True) + os.makedirs(self.error_dir, exist_ok=True) + self._samplefiles = set() self._samplefiles_to_profile = set() self._refs = set() @@ -575,7 +578,7 @@ def add_fasta(self, *fnames, propdict=defaultdict(dict)): # noqa: C901 self.cache_sample(**data) if failed_list: self.log( - "Sample will not be processed due to viloate max/min seq lenght rule (+-3%):" + "Sample will not be processed due to violate max/min seq lenght rule (+-3%):" + str(failed_list), ) logging.warn("Fail max/min seq lenght rule:" + str(failed_list)) @@ -638,7 +641,8 @@ def assign_data(self, data, seqhash, refseq_id, dbm): data["varfile"] = None return data - def import_cached_samples(self): # noqa: C901 + def import_cached_samples(self, threads): # noqa: C901 + list_fail_samples = [] refseqs = {} count_sample = 0 with sonarDBManager(self.db, readonly=False, debug=self.debug) as dbm: @@ -650,9 +654,9 @@ def import_cached_samples(self): # noqa: C901 bar_format="{desc} {percentage:3.0f}% [{n_fmt}/{total_fmt}, {elapsed}<{remaining}, {rate_fmt}{postfix}]", disable=self.disable_progress, ): - print("\n") - print("-----####------ sample_data -----####------") - print(sample_data) + # print("\n") + # print("-----####------ sample_data -----####------") + # print(sample_data) try: # nucleotide level import @@ -660,8 +664,8 @@ def import_cached_samples(self): # noqa: C901 dbm.insert_sample(sample_data["name"], sample_data["seqhash"]) # self.log("sample_data:" + str(sample_data)) # sample_data["refmolid"] - print("-----####------ insert_alignment -----####------") - print(sample_data["seqhash"], sample_data["sourceid"]) + # print("-----####------ insert_alignment -----####------") + # print(sample_data["seqhash"], sample_data["sourceid"]) algnid = dbm.insert_alignment( sample_data["seqhash"], sample_data["sourceid"] ) @@ -689,9 +693,10 @@ def import_cached_samples(self): # noqa: C901 ) # paranoia test if not sample_data["seqhash"] is None: - if self.paranoid_test(refseqs, sample_data, dbm): - count_sample = count_sample + 1 - + paranoid_dict = self.paranoid_check(refseqs, sample_data, dbm) + if paranoid_dict: + list_fail_samples.append(paranoid_dict) + count_sample = count_sample + 1 except Exception as e: logging.error("\n------- Fatal Error ---------") print(traceback.format_exc()) @@ -700,7 +705,128 @@ def import_cached_samples(self): # noqa: C901 print("\n During insert:") pp.pprint(sample_data) sys.exit("Unknown import error") - logging.info("Total sample insert:" + str(count_sample)) + if list_fail_samples: + logging.info( + f"Start paranoid alignment on {len(list_fail_samples)} sample." + ) + self.paranoid_align_multi(list_fail_samples, threads) + count_sample = count_sample - len(list_fail_samples) + logging.info("Total sample insert: " + str(count_sample)) + + def _align(self, output_paranoid, qryfile, reffile, sample_name): + # print(output_paranoid, qryfile, reffile, sample_name) + + if not os.path.exists(output_paranoid): + aligner = sonarAligner(outdir=self.basedir) + + qry, ref = aligner.align(qryfile, reffile) + with open(output_paranoid, "w+") as handle: + handle.write( + ">original_" + + sample_name + + "\n" + + ref + + "\n>restored_" + + sample_name + + "\n" + + qry + + "\n" + ) + logging.warn(f"See {output_paranoid} for alignment comparison.") + + def paranoid_align_multi(self, list_fail_samples, threads): # noqa: C901 + l = len(list_fail_samples) + with WorkerPool(n_jobs=threads, start_method="fork") as pool, tqdm( + position=0, + leave=True, + desc="paranoid align...", + total=l, + unit="seqs", + bar_format="{desc} {percentage:3.0f}% [{n_fmt}/{total_fmt}, {elapsed}<{remaining}, {rate_fmt}{postfix}]", + ) as pbar: + for _ in pool.imap_unordered(self._align, list_fail_samples): + pbar.update(1) + + def paranoid_check(self, refseqs, sample_data, dbm): # noqa: C901 + """link to import_cached_samples + + return dict. + """ + try: + seq = list(refseqs[sample_data["sourceid"]]) + except Exception: + refseqs[sample_data["sourceid"]] = list( + dbm.get_sequence(sample_data["sourceid"]) + ) + seq = list(refseqs[sample_data["sourceid"]]) + prefix = "" + + sample_name = sample_data["name"] + for vardata in dbm.iter_dna_variants(sample_name, sample_data["sourceid"]): + if vardata["variant.alt"] == " ": + for i in range(vardata["variant.start"], vardata["variant.end"]): + seq[i] = "" + elif vardata["variant.start"] >= 0: + seq[vardata["variant.start"]] = vardata["variant.alt"] + else: + prefix = vardata["variant.alt"] + ref_name = sample_data["refmol"] + # seq is now a restored version from variant dict. + seq = prefix + "".join(seq) + with open(sample_data["seq_file"], "r") as handle: + orig_seq = handle.read() + + if seq != orig_seq: + self.log("[Paranoid-test] Fail sample:" + sample_name) + logging.warn( + f"Fail in sanity check: This {sample_name} sample will not be inserted to the database...," + + "keeps an error log under the given cache directory." + ) + if not os.path.exists(self.error_dir): + os.makedirs(self.error_dir) + with open( + os.path.join(self.error_dir, f"{sample_name}.error.var"), "w+" + ) as handle: + for vardata in dbm.iter_dna_variants( + sample_name, sample_data["sourceid"] + ): + handle.write(str(vardata) + "\n") + + qryfile = os.path.join( + self.error_dir, sample_name + ".error.restored_sam.fa" + ) + reffile = os.path.join( + self.error_dir, sample_name + ".error.original_sam.fa" + ) + + with open(qryfile, "w+") as handle: + handle.write(">seq\n" + seq) + with open(reffile, "w+") as handle: + handle.write(">ref\n" + orig_seq) + output_paranoid = os.path.join( + self.basedir, f"{sample_name}.withref.{ref_name}.fail-paranoid.fna" + ) + + dbm.delete_alignment( + seqhash=sample_data["seqhash"], element_id=sample_data["sourceid"] + ) + # delete sample if this sample didnt have any alignment and variant??. + _return_ali_id = dbm.get_alignment_by_seqhash( + seqhash=sample_data["seqhash"] + ) + if len(_return_ali_id) == 0: + logging.warn("Sonar will delete a sample with empty alignment") + dbm.delete_samples(sample_name) + dbm.delete_seqhash(sample_data["seqhash"]) + + return { + "sample_name": sample_name, + "qryfile": qryfile, + "reffile": reffile, + "output_paranoid": output_paranoid, + } + else: + return {} def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 """link to import_cached_samples @@ -768,8 +894,9 @@ def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 seq[vardata["variant.start"]] = vardata["variant.alt"] else: prefix = vardata["variant.alt"] - print("-----####------ prefix -----####------") - print(prefix) + # print("-----####------ prefix -----####------") + # print(prefix) + ref_name = sample_data["refmol"] # seq is now a restored version from variant dict. seq = prefix + "".join(seq) @@ -780,7 +907,7 @@ def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 if seq != orig_seq: logging.warn( f"Fail in sanity check: This {sample_name} sample will not be inserted to the database...," - + "keeping an error log under the given cache directory." + + "keeps an error log under the given cache directory." ) try: mismatch = [i for i, (a, b) in enumerate(zip(seq, orig_seq)) if a != b] @@ -788,7 +915,7 @@ def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 # if orig_seq[i] != seq[i]: # _lin.append(i) self.log("-----") - self.log("Fail:" + sample_name) + self.log("Fail sample:" + sample_name) self.log("First position of mismatch:" + str(mismatch[0])) self.log(seq[mismatch[0]]) self.log(orig_seq[mismatch[0]]) @@ -811,7 +938,7 @@ def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 handle.write(">seq\n" + seq) with open(reffile, "w+") as handle: handle.write(">ref\n" + orig_seq) - output_paranoid = f"{sample_name}.fail-paranoid-alignment.fna" + output_paranoid = f"{sample_name}.withref.{ref_name}.fail-paranoid.fna" if not os.path.exists(output_paranoid): aligner = sonarAligner(outdir=self.basedir) @@ -828,12 +955,20 @@ def paranoid_test(self, refseqs, sample_data, dbm): # noqa: C901 + qry + "\n" ) - logging.warn("See fail-paranoid-alignment.fna for alignment comparison") - # delete alignment + logging.warn(f"See {output_paranoid} for alignment comparison.") + # delete alignment, sourceid = reference id dbm.delete_alignment( seqhash=sample_data["seqhash"], element_id=sample_data["sourceid"] ) - # delete variant. + # delete sample if this sample didnt have any alignment and variant??. + # + _return_ali_id = dbm.get_alignment_by_seqhash( + seqhash=sample_data["seqhash"] + ) + if len(_return_ali_id) == 0: + logging.warn("Sonar will delete a sample with empty alignment") + dbm.delete_samples(sample_name) + dbm.delete_seqhash(sample_data["seqhash"]) # """ sys.exit( diff --git a/pages/libs/mpxsonar/src/mpxsonar/dbm.py b/pages/libs/mpxsonar/src/mpxsonar/dbm.py index 953fd64..934d7a2 100644 --- a/pages/libs/mpxsonar/src/mpxsonar/dbm.py +++ b/pages/libs/mpxsonar/src/mpxsonar/dbm.py @@ -781,6 +781,20 @@ def get_sample_data(self, sample_name): row = self.cursor.fetchone() return (row["id"], row["seqhash"]) if row else (None, None) + def get_alignment_by_seqhash(self, seqhash): + """ + Returns the rowid of a sample based on the respective seqhash If no + alignment of the given sequence hash, it will return empty list. + + Check if there is a sample that doesn't align to any reference. + """ + sql = "SELECT id FROM alignment WHERE seqhash = ? ;" + self.cursor.execute(sql, [seqhash]) + row = self.cursor.fetchall() + if not row: + return [] + return [x["id"] for x in row] + def get_alignment_id(self, seqhash, element_id): """ Returns the rowid of a sample based on the respective seqhash and element. If no @@ -1405,6 +1419,204 @@ def query_metadata(self, name, *vals): valueList, ) + def get_ref_ID_base_query_profile( # noqa: 901 + self, *vars, reference_accession=None + ): + iupac_nt_code = { + "A": set("A"), + "C": set("C"), + "G": set("G"), + "T": set("T"), + "R": set("AGR"), + "Y": set("CTY"), + "S": set("GCS"), + "W": set("ATW"), + "K": set("GTK"), + "M": set("ACM"), + "B": set("CGTB"), + "D": set("AGTD"), + "H": set("ACTH"), + "V": set("ACGV"), + "N": set("ACGTRYSWKMBDHVN"), + "n": set("N"), + } + iupac_aa_code = { + "A": set("A"), + "R": set("R"), + "N": set("N"), + "D": set("D"), + "C": set("C"), + "Q": set("Q"), + "E": set("E"), + "G": set("G"), + "H": set("H"), + "I": set("I"), + "L": set("L"), + "K": set("K"), + "M": set("M"), + "F": set("F"), + "P": set("P"), + "S": set("S"), + "T": set("T"), + "W": set("W"), + "Y": set("Y"), + "V": set("V"), + "U": set("U"), + "O": set("O"), + "B": set("DNB"), + "Z": set("EQZ"), + "J": set("ILJ"), + "Φ": set("VILFWYMΦ"), + "Ω": set("FWYHΩ"), + "Ψ": set("VILMΨ"), + "π": set("PGASπ"), + "ζ": set("STHNQEDKRζ"), + "+": set("KRH+"), + "-": set("DE-"), + "X": set("ARNDCQEGHILKMFPSTWYVUOBZJΦΩΨπζ+-X"), + "x": set("X"), + } + del_regex = re.compile(r"^(|[^:]+:)?([^:]+:)?del:(=?[0-9]+)(|-=?[0-9]+)?$") + snv_regex = re.compile(r"^(|[^:]+:)?([^:]+:)?([A-Z]+)([0-9]+)(=?[A-Zxn]+)$") + + # set variants and generate sql + base_sql = "SELECT DISTINCT(`reference.id`) AS id FROM variantView WHERE " + intersect_sqls = [] + intersect_vals = [] + except_sqls = [] + except_vals = [] + for var in vars: + c = [] # condition + v = [] # variable + + if var.startswith("^"): + var = var[1:] + negate = True + else: + negate = False + + # variant typing + if match := snv_regex.match(var): + snv = True + elif match := del_regex.match(var): + snv = False + else: + logging.error("'" + var + "' is not a valid variant definition.") + sys.exit( + "Please check the query statement,(IUPAC AA/NT codes, NT format(e.g. A3451T), AA format(e.g. S:N501Y))" + ) + # set molecule + if match.group(1): + c.append("`molecule.symbol` = ?") + v.append(match.group(1)[:-1]) + else: + c.append("`molecule.standard` = ?") + v.append(1) + + # set element + if match.group(2): + c.append("`element.type` = ?") + v.append("cds") + c.append("`element.symbol` = ?") + v.append(match.group(2)[:-1]) + code = iupac_aa_code + else: + c.append("`element.standard` = ?") + v.append(1) + code = iupac_nt_code + + # snp handling + if snv: + c.append("`variant.start` = ?") + v.append(int(match.group(4)) - 1) + c.append("`variant.end` = ?") + v.append(int(match.group(4))) + c.append("`variant.ref` = ?") + v.append(match.group(3)) + try: + # explicit alternate allele + if match.group(5).startswith("="): + c.append("`variant.alt` = ?") + v.append(match.group(5)[1:]) + + # potentially ambiguous alternate snp + elif len(match.group(5)) == 1: + l = len(code[match.group(5)]) + if l == 1: + match_group5 = ( + match.group(5).upper() + if match.group(5) == "n" or match.group(5) == "x" + else match.group(5) + ) + c.append("`variant.alt` = ?") + v.append(match_group5) + else: + c.append("`variant.alt` IN (" + ", ".join(["?"] * l) + ")") + v.extend(code[match.group(5)]) + + # potentially ambiguous alternate insert + else: + a = [ + "".join(x) + for x in itertools.product( + *[code[x] for x in match.group(5)] + ) + ] + l = len(a) + if l == 1: + a = a.upper() if a == "n" or a == "x" else a + c.append("`variant.alt` = ?") + v.extend(a) + else: + c.append("`variant.alt` IN (" + ", ".join(["?"] * l) + ")") + v.extend(a) + except KeyError: + logging.error("'" + var + "' is not a valid input") + sys.exit( + "Please check the query statement,(IUPAC AA/NT codes, NT format(e.g. A3451T), AA format(e.g. S:N501Y))" + ) + # deletion handling + else: + s = match.group(3) + e = match.group(4)[1:] + # if del:=1-=60 meanse exact search del:1-60 + # del:1-60 means range search--> it could be del:1-11 or del:1-60 + if s.startswith("="): + s = s[1:] + c.append("`variant.start` = ?") + else: + c.append("`variant.start` >= ?") + + if e.startswith("="): + e = e[1:] + c.append("`variant.end` = ?") + else: + c.append("`variant.end` <= ?") + v.append(int(s) - 1) + v.append(int(e)) + + c.append("`variant.alt` = ?") + v.append(" ") + + # assemble sub-sql + if negate: + except_sqls.append(base_sql + " AND ".join(c)) + except_vals.extend(v) + else: + intersect_sqls.append(base_sql + " AND ".join(c)) + intersect_vals.extend(v) + + # assemble final sql + if not intersect_sqls: + intersect_sqls = [base_sql + "1"] + # Change this + sql = " INTERSECT ".join(intersect_sqls) + + if except_sqls: + sql += " EXCEPT " + " EXCEPT ".join(except_sqls) + + return sql, intersect_vals + except_vals + def query_profile(self, *vars, reference_accession=None): # noqa: C901 iupac_nt_code = { "A": set("A"), @@ -1563,18 +1775,19 @@ def query_profile(self, *vars, reference_accession=None): # noqa: C901 else: s = match.group(3) e = match.group(4)[1:] - + # if del:=1-=60 meanse exact search del:1-60 + # del:1-60 means range search--> it could be del:1-11 or del:1-60 if s.startswith("="): s = s[1:] c.append("`variant.start` = ?") else: - c.append("`variant.start` <= ?") + c.append("`variant.start` >= ?") if e.startswith("="): e = e[1:] c.append("`variant.end` = ?") else: - c.append("`variant.end` >= ?") + c.append("`variant.end` <= ?") v.append(int(s) - 1) v.append(int(e)) @@ -1600,6 +1813,53 @@ def query_profile(self, *vars, reference_accession=None): # noqa: C901 return sql, intersect_vals + except_vals + def get_ref_variant_ID(self, profiles, reference_accession=None): # noqa: 901 + """Tmp patch + Get reference ID based on variant profile. + + Return string of selected; + """ + + profile_sqls = [] + profile_vals = [] + for profile in profiles: + + sql, val = self.get_ref_ID_base_query_profile( + *profile, reference_accession=reference_accession + ) + profile_sqls.append(sql) + profile_vals.extend(val) + + if len(profiles) == 1: + profile_sqls = profile_sqls[0] + elif len(profiles) > 1: + profile_sqls = " UNION ".join( + [ + "SELECT * FROM (" + x + ") t" + str(i) + for i, x in enumerate(profile_sqls) + ] + ) + else: + profile_sqls = "" + if self.debug: + logging.info(f"Reference sqls: {profile_sqls}") + logging.info(f"Reference vals: {profile_vals}") + if profile_sqls == "": + logging.info("Filtered Reference ID: none") + return [] + + self.cursor.execute(profile_sqls, profile_vals) + variant_ids = self.cursor.fetchall() + if not variant_ids: + logging.info("Filtered Reference ID: none") + return [] + + # TODO: deduplicate IDs + # print(variant_ids) + # remove None value incase there is the one, however, we should fix it at sql command. + variant_ids = [str(i["id"]) for i in variant_ids if i["id"] is not None] + return variant_ids + def match( # noqa: 901 self, *profiles, @@ -1611,8 +1871,9 @@ def match( # noqa: 901 format="csv", ): """ - # TODO check if reference is not exit. - # get all alignment + # TODO: 1. check if reference is not exit then we get all alignment. + # 2. Match query or sql or step can improve. + # 3. Note: If reference accession is None, we will query all varaints with all references. Return: @@ -1672,7 +1933,7 @@ def match( # noqa: 901 include_lin = _tmp_include_lin properties[lineage_col] = include_lin if self.debug: - logging.info(f"list all prop.:{properties}") + logging.info(f"List all prop.:{properties}") # if properties are present in query if properties: for pname, vals in properties.items(): @@ -1683,7 +1944,7 @@ def match( # noqa: 901 property_sqls = " INTERSECT ".join(property_sqls) if self.debug: - logging.info(f"SQL Properties:{property_sqls}") + logging.info(f"Properties in Query: {property_sqls}") # collecting sqls for genomic profile based filtering profile_sqls = [] @@ -1700,13 +1961,27 @@ def match( # noqa: 901 profile_sqls = profile_sqls[0] elif len(profiles) > 1: profile_sqls = " UNION ".join( - ["SELECT * FROM (" + x + ")" for x in profile_sqls] + [ + "SELECT * FROM (" + x + ") t" + str(i) + for i, x in enumerate(profile_sqls) + ] ) else: profile_sqls = "" if self.debug: - logging.info(f"profile_sqls:{profile_sqls}") - + logging.info(f"Profile sqls: {profile_sqls}") + logging.info(f"Profile vals: {profile_vals}") + + variant_id_list = self.get_ref_variant_ID(profiles) + if len(variant_id_list) > 0: + selected_variant_ids = ", ".join([str(x) for x in variant_id_list]) + logging.info(f"Selected Reference ID: {selected_variant_ids}") + varinat_condition_stm = ( + " AND `reference.id` IN (" + selected_variant_ids + ")" + ) + else: + varinat_condition_stm = "" + # ------ if property_sqls and profile_sqls: if len(profiles) > 1: sample_selection_sql = ( @@ -1738,14 +2013,16 @@ def match( # noqa: 901 # we need to check if ref accession number is given. if reference_accession: - sample_selection_sql = "SELECT DISTINCT(`sample.id`) AS id FROM alignmentView WHERE `reference.accession`={}".format( + sample_selection_sql = "SELECT DISTINCT(`sample.id`) AS id FROM alignmentView WHERE `reference.accession`={}".format( '"' + reference_accession + '"' ) else: # should we use only sample or all alignment sample_selection_sql = "SELECT id FROM sample" - if self.debug: - logging.info(f"sample_selection_sql: {sample_selection_sql}") + + if self.debug: + logging.info(f"Sample selection in sql: {sample_selection_sql}") + genome_element_condition = [ str(x) for x in self.get_element_ids(reference_accession, "source") ] @@ -1760,6 +2037,8 @@ def match( # noqa: 901 m = "" # CurrentSolution: we add reference column instead # m = ' `molecule.symbol`, "@" , ' + if self.debug: + logging.info(f"Genome element in sql: {genome_element_condition}") if not showNX: nn = ' AND `variant.alt` != "N" ' @@ -1793,22 +2072,32 @@ def match( # noqa: 901 # select samples sql = sample_selection_sql - + if self.debug: + logging.info( + f"Before execute 'Select Samples': {sql} with {property_vals + profile_vals}" + ) + # this execution is based on the samples and given profiles. self.cursor.execute(sql, property_vals + profile_vals) sample_ids = self.cursor.fetchall() if not sample_ids: return [] + # TODO: deduplicate IDs selected_sample_ids = ", ".join([str(x["id"]) for x in sample_ids]) + if self.debug: + logging.info(f" 'Selected Samples': {selected_sample_ids}") # rows = {x['id']: {"id": x['id']} for x in sample_ids} # print(len(sample_ids)) # # Current solution: - # After we got the selected IDs + # After we got the selected IDs (filter by profiles) # We use two-stage query and then combine both results together to produce final result - # 1. Query properties - # 2. Query AA/NT profile + # 1. Query: get all properties based on selected IDs + # 2. Query: get all AA/NT profile based on selected IDs and reference IDs + # Finally, we combine 1. and 2. based on outer join. + + # output columns fields = ["`sample.name`"] + ["`" + x + "`" for x in self.properties] sql = "SELECT name as " + ", ".join(fields) + "FROM sample " @@ -1839,43 +2128,75 @@ def match( # noqa: 901 self.cursor.execute(_1_final_sql) _1_rows = self.cursor.fetchall() + # since some samples didn't return AA mutation., so we use LEFT JOIN to NT. + # ... and also remove unnecessay 'WHERE IN SAMPLE_IDs' _2_final_sql = ( - " SELECT name AS `sample.name`, nt_profile.reference_accession AS REFERENCE_ACCESSION, nt_profile._profile AS NUC_PROFILE, aa_profile._profile AS AA_PROFILE \ - FROM ( SELECT `sample.id`, `reference.accession` AS reference_accession, group_concat(" + " SELECT name AS `sample.name`, nt_profile.reference_accession AS REFERENCE_ACCESSION, nt_profile._profile AS NUC_PROFILE, aa_profile._profile AS AA_PROFILE " + + " FROM ( SELECT `sample.id`, `reference.accession` AS reference_accession, group_concat(" + + m + + " `variant.label`) AS _profile, `variant.id`" + + "FROM variantView WHERE `sample.id` IN (" + + selected_sample_ids + + ") AND " + + genome_element_condition + + nn + + varinat_condition_stm + + " GROUP BY `sample.id`, reference_accession) nt_profile " + + " LEFT JOIN " + + "( SELECT `sample.id`, `reference.accession` AS reference_accession , group_concat(" + + m + + ' `element.symbol`, ":" ,`variant.label`) AS _profile, `variant.id`' + + " FROM variantView WHERE `sample.id` IN ( " + + selected_sample_ids + + ")" + + cds_element_condition + + nx + + varinat_condition_stm + + " GROUP BY `sample.id`, reference_accession ) aa_profile " + + " ON nt_profile.`sample.id` = aa_profile.`sample.id` AND nt_profile.reference_accession =aa_profile.reference_accession " + + ", `sample` " + + " WHERE nt_profile.`sample.id` = `sample`.id " + ) + """ + 2_final_sql = ( + " SELECT name AS `sample.name`, nt_profile.reference_accession AS REFERENCE_ACCESSION, nt_profile._profile AS NUC_PROFILE, aa_profile._profile AS AA_PROFILE " + + " FROM ( SELECT `sample.id`, `reference.accession` AS reference_accession, group_concat(" + m - + "`variant.label`) AS _profile \ - FROM variantView WHERE `sample.id` IN (" + + " `variant.label`) AS _profile, `variant.id`" + + "FROM variantView WHERE `sample.id` IN (" + selected_sample_ids + ") AND " + genome_element_condition + nn - + " GROUP BY `sample.id`, reference_accession) nt_profile, \ - ( SELECT `sample.id`, `reference.accession` AS reference_accession , group_concat(" + + varinat_condition_stm + + " GROUP BY `sample.id`, reference_accession) nt_profile, " + + " ( SELECT `sample.id`, `reference.accession` AS reference_accession , group_concat(" + m - + '`element.symbol`, ":" ,`variant.label`) AS _profile \ - FROM variantView WHERE `sample.id` IN (' + + ' `element.symbol`, ":" ,`variant.label`) AS _profile, `variant.id`' + + " FROM variantView WHERE `sample.id` IN ( " + selected_sample_ids - + ") " + + ")" + cds_element_condition + nx - + " GROUP BY `sample.id`, reference_accession \ - ) aa_profile, \ - `sample` \ - WHERE nt_profile.`sample.id` = aa_profile.`sample.id` AND nt_profile.`sample.id` = `sample`.id \ - AND nt_profile.reference_accession = aa_profile.reference_accession \ - AND `sample`.id IN (" + + varinat_condition_stm + + " GROUP BY `sample.id`, reference_accession ) aa_profile, `sample` " + + " WHERE nt_profile.`sample.id` = aa_profile.`sample.id` AND nt_profile.`sample.id` = `sample`.id " + + " AND nt_profile.reference_accession = aa_profile.reference_accession " + + " AND `sample`.id IN (" + selected_sample_ids + ")" ) + """ if self.debug: logging.info("Second SQL") logging.info(_2_final_sql) + self.cursor.execute(_2_final_sql) _2_rows = self.cursor.fetchall() if len(_1_rows) != len(_2_rows): - logging.warning("Detects something suspicious in matching process.") + # logging.warning("Detects something suspicious in matching process.") logging.warning( - "Mismatch records; %d and %d between meta-info and fasta" + "Return records; between %d meta-info and %d sequence alignment" % (len(_1_rows), len(_2_rows)) ) logging.warning( @@ -1906,6 +2227,7 @@ def match( # noqa: 901 # ) # _1_rows = list(filter(None, _1_rows)) + # ------ alternative solution convert to df df_1 = pd.DataFrame(_1_rows) df_1.sort_values(by=["sample.name"], inplace=True) @@ -1915,7 +2237,9 @@ def match( # noqa: 901 df_2 = pd.DataFrame(_2_rows) df_2.sort_values(by=["sample.name"], inplace=True) if self.debug: + logging.debug(df_2.columns) logging.debug(df_2["sample.name"]) + """ merge_df = pd.merge( df_1, @@ -1959,6 +2283,7 @@ def match( # noqa: 901 return _1_rows # list(rows.values()) elif format == "count": + # TODO: currently we count only samples not the sample-aligned wise. logging.info("'--count' will return only unique sample.") sql = ( "SELECT COUNT(DISTINCT s2p.id) AS `count` FROM (" @@ -1976,6 +2301,10 @@ def match( # noqa: 901 ) else: sys.exit("error: '" + format + "' is not a valid output format") + if self.debug: + logging.info( + f"Before execute 'Select Samples': {sql} with {property_vals + profile_vals}" + ) self.cursor.execute(sql, property_vals + profile_vals) return self.cursor diff --git a/pages/tool.py b/pages/tool.py index 270f0ec..e289bac 100644 --- a/pages/tool.py +++ b/pages/tool.py @@ -1,112 +1,105 @@ import dash -from dash import html -from dash import dcc -from dash import State from dash import dash_table -from dash import callback_context - -import dash_bootstrap_components as dbc -import dash_mantine_components as dmc - -import plotly.express as px +from dash import dcc +from dash import html import pandas as pd +import plotly.express as px from pages.tool_page_components import user_query_input -#from src.covsonar.app_controller import get_freq_mutation -#from src.covsonar.app_controller import match_controller -#from src.covsonar.app_controller import sonarBasics -#from src.covsonar.sonar import parse_args +# from src.covsonar.app_controller import get_freq_mutation +# from src.covsonar.app_controller import match_controller +# from src.covsonar.app_controller import sonarBasics +# from src.covsonar.sonar import parse_args dash.register_page(__name__, path="/Tool") -############## TEST DATA EXPERIMENT ################ -note_data = pd.read_csv('data/Data.csv') -coord_data = pd.read_csv('data/location_coordinates.csv') +# TEST DATA EXPERIMENT +note_data = pd.read_csv("data/Data.csv") +coord_data = pd.read_csv("data/location_coordinates.csv") -result = pd.merge(note_data, coord_data, left_on='COUNTRY', right_on='name') +result = pd.merge(note_data, coord_data, left_on="COUNTRY", right_on="name") -mutation_list = ['del:3-9', 'del:2-20', 'del:16', 'del:20'] +mutation_list = ["del:3-9", "del:2-20", "del:16", "del:20"] -result['number'] = [len(x.split(',')) for x in result['NUC_PROFILE']] -new_res = result.groupby(['COUNTRY', 'lon', 'lat', 'RELEASE_DATE'])['number'].sum().reset_index() +result["number"] = [len(x.split(",")) for x in result["NUC_PROFILE"]] +new_res = ( + result.groupby(["COUNTRY", "lon", "lat", "RELEASE_DATE"])["number"] + .sum() + .reset_index() +) fig0 = px.scatter_mapbox( new_res, lat="lat", lon="lon", size="number", - #size_max=15, + # size_max=15, animation_frame="RELEASE_DATE", zoom=10, - mapbox_style="carto-positron" + mapbox_style="carto-positron", ) -#################################################### - +# layout = html.Div( [ - #check box with references + # check box with references html.Div( - style={'width':'10%', 'height':'100%','float':'left'}, + style={"width": "10%", "height": "100%", "float": "left"}, children=[ dcc.Checklist( - className ='checkbox_1', - id='references-list', + className="checkbox_1", + id="references-list", options=[ - {'label': 'MT903344.1', 'value': 'MT903344.1'}, - {'label': 'NC_063383.1', 'value': 'NC_063383.1'}, - {'label': 'ON563414.3', 'value': 'ON563414.3'}, + {"label": "MT903344.1", "value": "MT903344.1"}, + {"label": "NC_063383.1", "value": "NC_063383.1"}, + {"label": "ON563414.3", "value": "ON563414.3"}, ], - labelStyle={'display': 'block'} - ) - ] - ), - - #checkbox with mutations + labelStyle={"display": "block"}, + ) + ], + ), + # checkbox with mutations html.Div( - style={'width':'10%', 'height':'100%','float':'left'}, + style={"width": "10%", "height": "100%", "float": "left"}, children=[ dcc.Checklist( - className ='checkbox_1', - id='mutation-list', + className="checkbox_1", + id="mutation-list", options=[ - {'label': 'some mutation', 'value': 'I1ST2'}, - {'label': 'some mutation', 'value': 'I2ST2'}, - {'label': 'some mutation', 'value': 'I3ST2'}, - {'label': 'some mutation', 'value': 'I4ST2'}, + {"label": "some mutation", "value": "I1ST2"}, + {"label": "some mutation", "value": "I2ST2"}, + {"label": "some mutation", "value": "I3ST2"}, + {"label": "some mutation", "value": "I4ST2"}, ], - labelStyle={'display': 'block'} - ) - ] - ), - + labelStyle={"display": "block"}, + ) + ], + ), html.Div( - style={'width':'15%', 'height':'190%','float':'left'}, + style={"width": "15%", "height": "190%", "float": "left"}, children=[ dcc.Checklist( - className ='checkbox_1', - id='vizual-method-list', + className="checkbox_1", + id="vizual-method-list", options=[ - {'label': 'Frequencies', 'value': 'freq'}, - {'label': 'Increasing Trend', 'value': 'trend-inc'}, - {'label': 'Decreasing Trend', 'value': 'trend-dec'}, - {'label': 'Constant Trend', 'value': 'trend-const'} + {"label": "Frequencies", "value": "freq"}, + {"label": "Increasing Trend", "value": "trend-inc"}, + {"label": "Decreasing Trend", "value": "trend-dec"}, + {"label": "Constant Trend", "value": "trend-const"}, ], - value=['I1MT'], - labelStyle={'display': 'block'} + value=["I1MT"], + labelStyle={"display": "block"}, ) - ] + ], ), - - html.Br(style={'line-height': '10'}), - html.Br(style={'line-height': '10'}), + html.Br(style={"line-height": "10"}), + html.Br(style={"line-height": "10"}), user_query_input, - html.Br(style={'line-height': '10'}), - + html.Br(style={"line-height": "10"}), html.Div(id="user-output", children=""), html.Div( [ @@ -115,11 +108,11 @@ page_current=0, page_size=10, style_table={ - 'maxHeight': '50ex', - 'overfrlowY': 'scroll', - 'width': '40%', - 'minWidth': '40%' - } + "maxHeight": "50ex", + "overfrlowY": "scroll", + "width": "40%", + "minWidth": "40%", + }, ), ] ), @@ -131,17 +124,17 @@ html.Br(), html.Div( [ - html.Button('Download CSV', id='csv-download'), - dcc.Download(id='df-download') + html.Button("Download CSV", id="csv-download"), + dcc.Download(id="df-download"), ] - ) + ), ] - ) + ), ] ) -''' +""" @app.callback( Output(component_id="user-output", component_property="children"), Output(component_id="my-output-df", component_property="data"), @@ -181,4 +174,4 @@ def update_output_sonar(n_clicks, commands): except SystemExit: output = "error: unrecognized arguments/commands" return output, data, columns -''' +""" diff --git a/pages/tool_page_components.py b/pages/tool_page_components.py index 83a9081..10b8cef 100644 --- a/pages/tool_page_components.py +++ b/pages/tool_page_components.py @@ -1,27 +1,25 @@ -import dash -from dash import html from dash import dcc +from dash import html import dash_bootstrap_components as dbc -import dash_mantine_components as dmc references_box = dbc.Card( dbc.CardBody( [ html.Div( - style={'width': '10%', 'height': '100%', 'float': 'left'}, + style={"width": "10%", "height": "100%", "float": "left"}, children=[ dcc.Checklist( - className='checkbox_1', - id='references-list', + className="checkbox_1", + id="references-list", options=[ - {'label': 'MT903344.1', 'value': 'MT903344.1'}, - {'label': 'NC_063383.1', 'value': 'NC_063383.1'}, - {'label': 'ON563414.3', 'value': 'ON563414.3'}, + {"label": "MT903344.1", "value": "MT903344.1"}, + {"label": "NC_063383.1", "value": "NC_063383.1"}, + {"label": "ON563414.3", "value": "ON563414.3"}, ], - labelStyle={'display': 'block'} + labelStyle={"display": "block"}, ) - ] + ], ) ] ), @@ -33,20 +31,20 @@ dbc.CardBody( [ html.Div( - style={'width': '10%', 'height': '100%', 'float': 'left'}, + style={"width": "10%", "height": "100%", "float": "left"}, children=[ dcc.Checklist( - className='checkbox_1', - id='mutation-list', + className="checkbox_1", + id="mutation-list", options=[ - {'label': 'some mutation', 'value': 'I1ST2'}, - {'label': 'some mutation', 'value': 'I2ST2'}, - {'label': 'some mutation', 'value': 'I3ST2'}, - {'label': 'some mutation', 'value': 'I4ST2'}, + {"label": "some mutation", "value": "I1ST2"}, + {"label": "some mutation", "value": "I2ST2"}, + {"label": "some mutation", "value": "I3ST2"}, + {"label": "some mutation", "value": "I4ST2"}, ], - labelStyle={'display': 'block'} + labelStyle={"display": "block"}, ) - ] + ], ) ] ), @@ -58,21 +56,21 @@ dbc.CardBody( [ html.Div( - style={'width': '45%', 'height': '100%', 'float': 'left'}, + style={"width": "45%", "height": "100%", "float": "left"}, children=[ dcc.Checklist( - className='checkbox_1', - id='vizual-method-list', + className="checkbox_1", + id="vizual-method-list", options=[ - {'label': 'Frequencies', 'value': 'freq'}, - {'label': 'Increasing Trend', 'value': 'trend-inc'}, - {'label': 'Decreasing Trend', 'value': 'trend-dec'}, - {'label': 'Constant Trend', 'value': 'trend-const'} + {"label": "Frequencies", "value": "freq"}, + {"label": "Increasing Trend", "value": "trend-inc"}, + {"label": "Decreasing Trend", "value": "trend-dec"}, + {"label": "Constant Trend", "value": "trend-const"}, ], - value=['I1MT'], - labelStyle={'display': 'block'} + value=["I1MT"], + labelStyle={"display": "block"}, ) - ] + ], ) ] ), @@ -80,7 +78,6 @@ ) - user_query_input = dbc.Card( dbc.CardBody( [ @@ -90,10 +87,10 @@ [ "direct MPXSonar query: ", html.Br(), - dcc.Input( - id="my-input", type="text", size="100" + dcc.Input(id="my-input", type="text", size="100"), + html.Button( + "Run direct MPXSonar query", id="btn-1", n_clicks=0 ), - html.Button('Run direct MPXSonar query', id='btn-1', n_clicks=0), ] ) ] @@ -101,4 +98,4 @@ ] ), style={"width": "18rem"}, -) \ No newline at end of file +) diff --git a/poetry.lock b/poetry.lock index 56d94c3..5b586ed 100644 --- a/poetry.lock +++ b/poetry.lock @@ -169,6 +169,14 @@ category = "main" optional = false python-versions = "*" +[[package]] +name = "dash-mantine-components" +version = "0.11.0" +description = "Plotly Dash Components based on Mantine" +category = "main" +optional = false +python-versions = "*" + [[package]] name = "dash-table" version = "5.0.0" @@ -322,6 +330,20 @@ python-versions = ">=3.7" [package.dependencies] gitdb = ">=4.0.1,<5" +[[package]] +name = "gunicorn" +version = "20.1.0" +description = "WSGI HTTP Server for UNIX" +category = "main" +optional = false +python-versions = ">=3.5" + +[package.extras] +eventlet = ["eventlet (>=0.24.1)"] +gevent = ["gevent (>=1.4.0)"] +setproctitle = ["setproctitle"] +tornado = ["tornado (>=0.2)"] + [[package]] name = "idna" version = "3.4" @@ -895,7 +917,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = "^3.9" -content-hash = "c6c92b7e8185fe1ff714963c602688bcaa174c59d2596e89b57c6e14d0b3c3c6" +content-hash = "d04fa4e192d4fce7305a33d902518ad1544c585e93efd507c928f4208be23fe0" [metadata.files] attrs = [ @@ -1050,6 +1072,9 @@ dash-html-components = [ {file = "dash_html_components-2.0.0-py3-none-any.whl", hash = "sha256:b42cc903713c9706af03b3f2548bda4be7307a7cf89b7d6eae3da872717d1b63"}, {file = "dash_html_components-2.0.0.tar.gz", hash = "sha256:8703a601080f02619a6390998e0b3da4a5daabe97a1fd7a9cebc09d015f26e50"}, ] +dash-mantine-components = [ + {file = "dash_mantine_components-0.11.0-py3-none-any.whl", hash = "sha256:e2fa1a089926e7f7c9bc29a02ee06f8ce6cfb4d867b3e9bcd55d8a74cd27664c"}, +] dash-table = [ {file = "dash_table-5.0.0-py3-none-any.whl", hash = "sha256:19036fa352bb1c11baf38068ec62d172f0515f73ca3276c79dee49b95ddc16c9"}, {file = "dash_table-5.0.0.tar.gz", hash = "sha256:18624d693d4c8ef2ddec99a6f167593437a7ea0bf153aa20f318c170c5bc7308"}, @@ -1098,6 +1123,10 @@ gitpython = [ {file = "GitPython-3.1.29-py3-none-any.whl", hash = "sha256:41eea0deec2deea139b459ac03656f0dd28fc4a3387240ec1d3c259a2c47850f"}, {file = "GitPython-3.1.29.tar.gz", hash = "sha256:cc36bfc4a3f913e66805a28e84703e419d9c264c1077e537b54f0e1af85dbefd"}, ] +gunicorn = [ + {file = "gunicorn-20.1.0-py3-none-any.whl", hash = "sha256:9dcc4547dbb1cb284accfb15ab5667a0e5d1881cc443e0677b4882a4067a807e"}, + {file = "gunicorn-20.1.0.tar.gz", hash = "sha256:e0a968b5ba15f8a328fdfd7ab1fcb5af4470c28aaf7e55df02a99bc13138e6e8"}, +] idna = [ {file = "idna-3.4-py3-none-any.whl", hash = "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2"}, {file = "idna-3.4.tar.gz", hash = "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4"}, diff --git a/pyproject.toml b/pyproject.toml index be82507..183ae92 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,6 +19,8 @@ mariadb = "^1.1.4" psutil = "^5.9.3" dash-bootstrap-components = "^1.2.1" dash = "^2.7.0" +gunicorn = "^20.1.0" +dash-mantine-components = "^0.11.0" [tool.poetry.dev-dependencies] pytest = "^7.1.2"