From ac8f4d18cf80e5b42bcc6e0ddc521a4ba3806634 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Fri, 17 Feb 2023 15:44:53 -0500 Subject: [PATCH 01/31] Add: param argument --- src/sql/magic.py | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/src/sql/magic.py b/src/sql/magic.py index d281a8c66..c698010f1 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -114,7 +114,6 @@ class SqlMagic(Magics, Configurable): @telemetry.log_call("init") def __init__(self, shell): - self._store = store Configurable.__init__(self, config=shell.config) @@ -191,6 +190,21 @@ def __init__(self, shell): type=str, help="Assign an alias to the connection", ) + # @argument( + # "-G", + # "--use-globals", + # action="use_globals", + # help="use global namespace" + # ) + @argument( + "-o", + "--param", + type=str, + nargs=2, + action="append", + metavar=("NAME", "VALUE"), + help="stroe a param", + ) @telemetry.log_call("execute") def execute(self, line="", cell="", local_ns={}): """ @@ -230,6 +244,7 @@ def execute(self, line="", cell="", local_ns={}): # {cell} # save globals and locals so they can be referenced in bind vars + print("execute") user_ns = self.shell.user_ns.copy() user_ns.update(local_ns) @@ -297,6 +312,14 @@ def execute(self, line="", cell="", local_ns={}): print("Skipping execution...") return + if args.param: + print("I have param") + self._persist_parameter(command.sql) + + print("args: ", args) + # print ("command: ", conn) + # print ("user_ns", user_ns) + # print ("test_x: ", user_ns["test_y"]) try: result = sql.run.run(conn, command.sql, self, user_ns) @@ -323,7 +346,6 @@ def execute(self, line="", cell="", local_ns={}): return None else: - if command.result_var: self.shell.user_ns.update({command.result_var: result}) return None @@ -369,6 +391,9 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): frame.to_sql(table_name, conn.session.engine, if_exists=if_exists, index=index) return "Persisted %s" % table_name + def _persist_parameter(self, raw): + print("Raw: ", raw) + def load_ipython_extension(ip): """Load the extension in IPython.""" From f52af0a2adbb3841c7668f3051a5b36f0fd66be1 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Mon, 20 Feb 2023 10:27:07 -0500 Subject: [PATCH 02/31] Add: param arguments --- src/sql/magic.py | 35 ++++++++++++++++++++++------------- 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/src/sql/magic.py b/src/sql/magic.py index c698010f1..6114b2105 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -190,14 +190,14 @@ def __init__(self, shell): type=str, help="Assign an alias to the connection", ) - # @argument( - # "-G", - # "--use-globals", - # action="use_globals", - # help="use global namespace" - # ) @argument( - "-o", + "-G", + "--use-globals", + action="store_true", + help="use global namespace" + ) + @argument( + "-P", "--param", type=str, nargs=2, @@ -313,14 +313,15 @@ def execute(self, line="", cell="", local_ns={}): return if args.param: - print("I have param") - self._persist_parameter(command.sql) + self.parse_sql_clause_by_parameters(raw = command.sql, user_ns = user_ns, use_globals=False) + # self._persist_parameter(command.sql) + + if args.use_globals: + # Gotta replace the sql clause variable from namespace + self.parse_sql_clause_by_parameters(raw = command.sql, user_ns = user_ns, use_globals=True) - print("args: ", args) - # print ("command: ", conn) - # print ("user_ns", user_ns) - # print ("test_x: ", user_ns["test_y"]) try: + print ("before run: ", command.sql) result = sql.run.run(conn, command.sql, self, user_ns) if ( @@ -370,6 +371,8 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): if not DataFrame: raise ImportError("Must `pip install pandas` to use DataFrames") + # print ("raw: ", raw) + # print ("user_ns: ", user_ns) frame_name = raw.strip(";") # Get the DataFrame from the user namespace @@ -391,9 +394,15 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): frame.to_sql(table_name, conn.session.engine, if_exists=if_exists, index=index) return "Persisted %s" % table_name + def _persist_parameter(self, raw): print("Raw: ", raw) + def parse_sql_clause_by_parameters(self, raw, user_ns, use_globals = False): + if use_globals: + print ("Parse: {} with use_globals".format(raw)) + else: + print ("Parse: {} with param".format(raw)) def load_ipython_extension(ip): """Load the extension in IPython.""" From f24edf242a767bdd9d1ccb491cb8f9d22ac37da0 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Mon, 20 Feb 2023 10:27:40 -0500 Subject: [PATCH 03/31] Format --- src/sql/magic.py | 25 ++++++++++++------------- 1 file changed, 12 insertions(+), 13 deletions(-) diff --git a/src/sql/magic.py b/src/sql/magic.py index 6114b2105..3bbd87fe5 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -190,12 +190,7 @@ def __init__(self, shell): type=str, help="Assign an alias to the connection", ) - @argument( - "-G", - "--use-globals", - action="store_true", - help="use global namespace" - ) + @argument("-G", "--use-globals", action="store_true", help="use global namespace") @argument( "-P", "--param", @@ -313,15 +308,19 @@ def execute(self, line="", cell="", local_ns={}): return if args.param: - self.parse_sql_clause_by_parameters(raw = command.sql, user_ns = user_ns, use_globals=False) + self.parse_sql_clause_by_parameters( + raw=command.sql, user_ns=user_ns, use_globals=False + ) # self._persist_parameter(command.sql) if args.use_globals: # Gotta replace the sql clause variable from namespace - self.parse_sql_clause_by_parameters(raw = command.sql, user_ns = user_ns, use_globals=True) + self.parse_sql_clause_by_parameters( + raw=command.sql, user_ns=user_ns, use_globals=True + ) try: - print ("before run: ", command.sql) + print("before run: ", command.sql) result = sql.run.run(conn, command.sql, self, user_ns) if ( @@ -394,15 +393,15 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): frame.to_sql(table_name, conn.session.engine, if_exists=if_exists, index=index) return "Persisted %s" % table_name - def _persist_parameter(self, raw): print("Raw: ", raw) - def parse_sql_clause_by_parameters(self, raw, user_ns, use_globals = False): + def parse_sql_clause_by_parameters(self, raw, user_ns, use_globals=False): if use_globals: - print ("Parse: {} with use_globals".format(raw)) + print("Parse: {} with use_globals".format(raw)) else: - print ("Parse: {} with param".format(raw)) + print("Parse: {} with param".format(raw)) + def load_ipython_extension(ip): """Load the extension in IPython.""" From 34081f451340a4cf877384f07e82eed62387767c Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 15:32:26 -0500 Subject: [PATCH 04/31] Add: legacy support --- src/sql/command.py | 55 +++++++++++++++++++++++++++++++++++++++++----- src/sql/magic.py | 43 +++++++++++------------------------- 2 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 319f0b646..de0723406 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -1,4 +1,5 @@ from IPython.core.magic_arguments import parse_argstring +from jinja2 import Template from sqlalchemy.engine import Engine @@ -19,12 +20,9 @@ class SQLCommand: """ def __init__(self, magic, user_ns, line, cell) -> None: - # Parse variables (words wrapped in {}) for %%sql magic - # (for %sql this is done automatically) - cell = magic.shell.var_expand(cell) - + # Support for the variable substition in the SQL clause + line, cell = self._var_expand(magic, user_ns, line, cell) self.args = parse.magic_args(magic.execute, line) - # self.args.line (everything that appears after %sql/%%sql in the first line) # is splited in tokens (delimited by spaces), this checks if we have one arg one_arg = len(self.args.line) == 1 @@ -45,7 +43,6 @@ def __init__(self, magic, user_ns, line, cell) -> None: add_alias = True else: add_alias = False - self.command_text = " ".join(line_for_command) + "\n" + cell if self.args.file: @@ -89,3 +86,49 @@ def connection(self): def result_var(self): """Returns the result_var""" return self.parsed["result_var"] + + def _params_helper(self, params): + def is_float(element): + if element is None: + return False + try: + float(element) + return True + except ValueError: + return False + + params_dict = {} + if not params: + return params_dict + # Throw some exception + + for key, value in params: + if is_float(value): + params_dict[key] = int(value) + else: + params_dict[key] = value + return params_dict + + def _var_expand(self, magic, user_ns, line, cell): + """ + Support for the variable substition in the SQL clause, for now we have two ways: + 1. Latest format, {{a}}, we use jinja2 to parse the string with {{a}} format + 2. Legacy format, {a}, $a, and :a format. + + We will deprecate the legacy format feature in next major version + """ + self.is_legacy_var_expand_parsed = False + # Latest format + # TODO: support --param and --use-global logic here + line = Template(line).render(user_ns) + cell = Template(cell).render(user_ns) + # Legacy + parsed_cell = magic.shell.var_expand(cell) + parsed_line = magic.shell.var_expand(line) + has_SQLAlchemy_var_expand = ":" in line or ":" in cell + + if parsed_line != line or parsed_cell != cell or has_SQLAlchemy_var_expand: + self.is_legacy_var_expand_parsed = True + print("You should not use this feature") + + return parsed_line, parsed_cell diff --git a/src/sql/magic.py b/src/sql/magic.py index 3bbd87fe5..b238af787 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -7,6 +7,7 @@ line_magic, magics_class, needs_local_scope, + no_var_expand, ) from IPython.core.magic_arguments import argument, magic_arguments, parse_argstring from sqlalchemy.exc import OperationalError, ProgrammingError, DatabaseError @@ -19,6 +20,7 @@ from sql.magic_plot import SqlPlotMagic from sql.magic_cmd import SqlCmdMagic + try: from traitlets.config.configurable import Configurable from traitlets import Bool, Int, Unicode @@ -122,6 +124,7 @@ def __init__(self, shell): # Add ourself to the list of module configurable via %config self.shell.configurables.append(self) + @no_var_expand @needs_local_scope @line_magic("sql") @cell_magic("sql") @@ -190,16 +193,16 @@ def __init__(self, shell): type=str, help="Assign an alias to the connection", ) - @argument("-G", "--use-globals", action="store_true", help="use global namespace") - @argument( - "-P", - "--param", - type=str, - nargs=2, - action="append", - metavar=("NAME", "VALUE"), - help="stroe a param", - ) + # @argument("-G", "--use-globals", action="store_true", help="use global namespace") + # @argument( + # "-P", + # "--param", + # type=str, + # nargs=2, + # action="append", + # metavar=("NAME", "VALUE"), + # help="stroe a param", + # ) @telemetry.log_call("execute") def execute(self, line="", cell="", local_ns={}): """ @@ -239,7 +242,6 @@ def execute(self, line="", cell="", local_ns={}): # {cell} # save globals and locals so they can be referenced in bind vars - print("execute") user_ns = self.shell.user_ns.copy() user_ns.update(local_ns) @@ -307,20 +309,7 @@ def execute(self, line="", cell="", local_ns={}): print("Skipping execution...") return - if args.param: - self.parse_sql_clause_by_parameters( - raw=command.sql, user_ns=user_ns, use_globals=False - ) - # self._persist_parameter(command.sql) - - if args.use_globals: - # Gotta replace the sql clause variable from namespace - self.parse_sql_clause_by_parameters( - raw=command.sql, user_ns=user_ns, use_globals=True - ) - try: - print("before run: ", command.sql) result = sql.run.run(conn, command.sql, self, user_ns) if ( @@ -396,12 +385,6 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): def _persist_parameter(self, raw): print("Raw: ", raw) - def parse_sql_clause_by_parameters(self, raw, user_ns, use_globals=False): - if use_globals: - print("Parse: {} with use_globals".format(raw)) - else: - print("Parse: {} with param".format(raw)) - def load_ipython_extension(ip): """Load the extension in IPython.""" From d92c313ce94c79e59a786f4edc66b7938a9a09b7 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 15:34:26 -0500 Subject: [PATCH 05/31] Revert: magic --- src/sql/magic.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sql/magic.py b/src/sql/magic.py index b238af787..0291a236c 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -359,8 +359,6 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): if not DataFrame: raise ImportError("Must `pip install pandas` to use DataFrames") - # print ("raw: ", raw) - # print ("user_ns: ", user_ns) frame_name = raw.strip(";") # Get the DataFrame from the user namespace @@ -382,9 +380,6 @@ def _persist_dataframe(self, raw, conn, user_ns, append=False, index=True): frame.to_sql(table_name, conn.session.engine, if_exists=if_exists, index=index) return "Persisted %s" % table_name - def _persist_parameter(self, raw): - print("Raw: ", raw) - def load_ipython_extension(ip): """Load the extension in IPython.""" From 662ce22972048225ec7b8b9dd822e35e98c6b174 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 15:51:38 -0500 Subject: [PATCH 06/31] Comment --- src/sql/command.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index de0723406..167c6cea6 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -111,24 +111,29 @@ def is_float(element): def _var_expand(self, magic, user_ns, line, cell): """ - Support for the variable substition in the SQL clause, for now we have two ways: + Support for the variable substition in the SQL clause + For now, we have enabled two ways: 1. Latest format, {{a}}, we use jinja2 to parse the string with {{a}} format 2. Legacy format, {a}, $a, and :a format. We will deprecate the legacy format feature in next major version """ self.is_legacy_var_expand_parsed = False - # Latest format + # Latest format parsing # TODO: support --param and --use-global logic here line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) - # Legacy + # Legacy format parsing parsed_cell = magic.shell.var_expand(cell) parsed_line = magic.shell.var_expand(line) has_SQLAlchemy_var_expand = ":" in line or ":" in cell if parsed_line != line or parsed_cell != cell or has_SQLAlchemy_var_expand: self.is_legacy_var_expand_parsed = True - print("You should not use this feature") + print( + "Please aware the variable substition" + " as {a}, $a, and :a format has been deprecated." + ) + print("Use {{a}} instead.") return parsed_line, parsed_cell From 3e15aeea5127f1be0a242da60c5463a57a76682a Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 16:35:08 -0500 Subject: [PATCH 07/31] Move: var_expand func --- src/sql/command.py | 23 +++++++++++------------ src/tests/test_command.py | 28 ++++++++++++++++++++++++++++ 2 files changed, 39 insertions(+), 12 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 167c6cea6..995b3c864 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -21,7 +21,7 @@ class SQLCommand: def __init__(self, magic, user_ns, line, cell) -> None: # Support for the variable substition in the SQL clause - line, cell = self._var_expand(magic, user_ns, line, cell) + # line, cell = self._var_expand(magic, user_ns, line, cell) self.args = parse.magic_args(magic.execute, line) # self.args.line (everything that appears after %sql/%%sql in the first line) # is splited in tokens (delimited by spaces), this checks if we have one arg @@ -50,6 +50,8 @@ def __init__(self, magic, user_ns, line, cell) -> None: self.command_text = infile.read() + "\n" + self.command_text self.parsed = parse.parse(self.command_text, magic) + # Variable substition + self.parsed["sql"] = self._var_expand(magic, user_ns, self.parsed["sql"]) self.parsed["sql_original"] = self.parsed["sql"] @@ -109,7 +111,7 @@ def is_float(element): params_dict[key] = value return params_dict - def _var_expand(self, magic, user_ns, line, cell): + def _var_expand(self, magic, user_ns, sql): """ Support for the variable substition in the SQL clause For now, we have enabled two ways: @@ -121,19 +123,16 @@ def _var_expand(self, magic, user_ns, line, cell): self.is_legacy_var_expand_parsed = False # Latest format parsing # TODO: support --param and --use-global logic here - line = Template(line).render(user_ns) - cell = Template(cell).render(user_ns) + sql = Template(sql).render(user_ns) # Legacy format parsing - parsed_cell = magic.shell.var_expand(cell) - parsed_line = magic.shell.var_expand(line) - has_SQLAlchemy_var_expand = ":" in line or ":" in cell + parsed_sql = magic.shell.var_expand(sql) + has_SQLAlchemy_var_expand = ":" in sql - if parsed_line != line or parsed_cell != cell or has_SQLAlchemy_var_expand: + if parsed_sql != sql or has_SQLAlchemy_var_expand: self.is_legacy_var_expand_parsed = True print( - "Please aware the variable substition" + "Warning: The variable substition" " as {a}, $a, and :a format has been deprecated." ) - print("Use {{a}} instead.") - - return parsed_line, parsed_cell + print("Instead, use {{a}} format.") + return parsed_sql diff --git a/src/tests/test_command.py b/src/tests/test_command.py index a0aaabeb0..f7ba2606e 100644 --- a/src/tests/test_command.py +++ b/src/tests/test_command.py @@ -181,3 +181,31 @@ def test_variable_substitution_cell_magic(ip, sql_magic): ) assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" + + +def test_variable_substitution_double_curly_bracklets_line_magic(ip, sql_magic): + ip.user_global_ns["test_limit"] = 3 + ip.user_global_ns["test_column_name_str"] = "first_name" + print("Hey") + + cmd = SQLCommand( + sql_magic, + ip.user_ns, + line="SELECT {{test_column_name_str}} FROM author LIMIT {{test_limit}}", + cell="", + ) + + assert cmd.parsed["sql"] == "SELECT first_name FROM author LIMIT 3" + + +def test_variable_substitution_double_curly_bracklets_cell_magic(ip, sql_magic): + ip.user_global_ns["username"] = "some-user" + + cmd = SQLCommand( + sql_magic, + ip.user_ns, + line="", + cell="GRANT CONNECT ON DATABASE postgres TO {{username}};", + ) + + assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" From d40d5ada340d999685e06bc86a4f89554d5c1663 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 17:38:47 -0500 Subject: [PATCH 08/31] Revert "Move: var_expand func" This reverts commit 3e15aeea5127f1be0a242da60c5463a57a76682a. --- src/sql/command.py | 23 ++++++++++++----------- src/tests/test_command.py | 28 ---------------------------- 2 files changed, 12 insertions(+), 39 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 995b3c864..167c6cea6 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -21,7 +21,7 @@ class SQLCommand: def __init__(self, magic, user_ns, line, cell) -> None: # Support for the variable substition in the SQL clause - # line, cell = self._var_expand(magic, user_ns, line, cell) + line, cell = self._var_expand(magic, user_ns, line, cell) self.args = parse.magic_args(magic.execute, line) # self.args.line (everything that appears after %sql/%%sql in the first line) # is splited in tokens (delimited by spaces), this checks if we have one arg @@ -50,8 +50,6 @@ def __init__(self, magic, user_ns, line, cell) -> None: self.command_text = infile.read() + "\n" + self.command_text self.parsed = parse.parse(self.command_text, magic) - # Variable substition - self.parsed["sql"] = self._var_expand(magic, user_ns, self.parsed["sql"]) self.parsed["sql_original"] = self.parsed["sql"] @@ -111,7 +109,7 @@ def is_float(element): params_dict[key] = value return params_dict - def _var_expand(self, magic, user_ns, sql): + def _var_expand(self, magic, user_ns, line, cell): """ Support for the variable substition in the SQL clause For now, we have enabled two ways: @@ -123,16 +121,19 @@ def _var_expand(self, magic, user_ns, sql): self.is_legacy_var_expand_parsed = False # Latest format parsing # TODO: support --param and --use-global logic here - sql = Template(sql).render(user_ns) + line = Template(line).render(user_ns) + cell = Template(cell).render(user_ns) # Legacy format parsing - parsed_sql = magic.shell.var_expand(sql) - has_SQLAlchemy_var_expand = ":" in sql + parsed_cell = magic.shell.var_expand(cell) + parsed_line = magic.shell.var_expand(line) + has_SQLAlchemy_var_expand = ":" in line or ":" in cell - if parsed_sql != sql or has_SQLAlchemy_var_expand: + if parsed_line != line or parsed_cell != cell or has_SQLAlchemy_var_expand: self.is_legacy_var_expand_parsed = True print( - "Warning: The variable substition" + "Please aware the variable substition" " as {a}, $a, and :a format has been deprecated." ) - print("Instead, use {{a}} format.") - return parsed_sql + print("Use {{a}} instead.") + + return parsed_line, parsed_cell diff --git a/src/tests/test_command.py b/src/tests/test_command.py index f7ba2606e..a0aaabeb0 100644 --- a/src/tests/test_command.py +++ b/src/tests/test_command.py @@ -181,31 +181,3 @@ def test_variable_substitution_cell_magic(ip, sql_magic): ) assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" - - -def test_variable_substitution_double_curly_bracklets_line_magic(ip, sql_magic): - ip.user_global_ns["test_limit"] = 3 - ip.user_global_ns["test_column_name_str"] = "first_name" - print("Hey") - - cmd = SQLCommand( - sql_magic, - ip.user_ns, - line="SELECT {{test_column_name_str}} FROM author LIMIT {{test_limit}}", - cell="", - ) - - assert cmd.parsed["sql"] == "SELECT first_name FROM author LIMIT 3" - - -def test_variable_substitution_double_curly_bracklets_cell_magic(ip, sql_magic): - ip.user_global_ns["username"] = "some-user" - - cmd = SQLCommand( - sql_magic, - ip.user_ns, - line="", - cell="GRANT CONNECT ON DATABASE postgres TO {{username}};", - ) - - assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" From b922ff8cffc8ab12953d8c36dccf76d85dc92a47 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 17:39:34 -0500 Subject: [PATCH 09/31] Add: more test cases --- src/tests/test_command.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/tests/test_command.py b/src/tests/test_command.py index a0aaabeb0..d12ad84a3 100644 --- a/src/tests/test_command.py +++ b/src/tests/test_command.py @@ -181,3 +181,31 @@ def test_variable_substitution_cell_magic(ip, sql_magic): ) assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" + + +def test_variable_substitution_double_curly_cell_magic(ip, sql_magic): + ip.user_global_ns["username"] = "some-user" + + cmd = SQLCommand( + sql_magic, + ip.user_ns, + line="", + cell="GRANT CONNECT ON DATABASE postgres TO {{username}};", + ) + + print("cmd.parsed['sql']", cmd.parsed["sql"]) + assert cmd.parsed["sql"] == "\nGRANT CONNECT ON DATABASE postgres TO some-user;" + + +def test_variable_substitution_double_curly_lin_magic(ip, sql_magic): + ip.user_global_ns["limit_number"] = 5 + ip.user_global_ns["column_name"] = "first_name" + cmd = SQLCommand( + sql_magic, + ip.user_ns, + line="SELECT {{column_name}} FROM author LIMIT {{limit_number}};", + cell="", + ) + + # print ("cmd.parsed['sql']", cmd.parsed["sql"]) + assert cmd.parsed["sql"] == "SELECT first_name FROM author LIMIT 5;\n" From 01f056c22dfd9b91244652948384d94767b85ead Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 17:49:28 -0500 Subject: [PATCH 10/31] Update: regex --- src/sql/command.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/sql/command.py b/src/sql/command.py index 167c6cea6..022171742 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -1,3 +1,4 @@ +import re from IPython.core.magic_arguments import parse_argstring from jinja2 import Template @@ -126,7 +127,8 @@ def _var_expand(self, magic, user_ns, line, cell): # Legacy format parsing parsed_cell = magic.shell.var_expand(cell) parsed_line = magic.shell.var_expand(line) - has_SQLAlchemy_var_expand = ":" in line or ":" in cell + # Exclusive the string with "://", but has :variable + has_SQLAlchemy_var_expand = re.search("(? Date: Wed, 22 Feb 2023 17:58:14 -0500 Subject: [PATCH 11/31] Add: more test cases --- src/sql/command.py | 6 +++--- src/tests/test_command.py | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 5 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 022171742..695b4802f 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -125,10 +125,10 @@ def _var_expand(self, magic, user_ns, line, cell): line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) # Legacy format parsing - parsed_cell = magic.shell.var_expand(cell) - parsed_line = magic.shell.var_expand(line) + parsed_cell = magic.shell.var_expand(cell, depth=2) + parsed_line = magic.shell.var_expand(line, depth=2) # Exclusive the string with "://", but has :variable - has_SQLAlchemy_var_expand = re.search("(? Date: Wed, 22 Feb 2023 18:06:20 -0500 Subject: [PATCH 12/31] Add: more test cases --- src/tests/test_command.py | 55 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/src/tests/test_command.py b/src/tests/test_command.py index fea1a0257..01255d69e 100644 --- a/src/tests/test_command.py +++ b/src/tests/test_command.py @@ -170,6 +170,61 @@ def test_parse_sql_when_passing_engine(ip, sql_magic, tmp_empty, line): assert cmd.sql_original == sql_expected +def test_variable_substitution_legacy_warning_message_dollar_prefix( + ip, sql_magic, capsys +): + ip.user_global_ns["limit_number"] = 1 + out = ip.run_cell_magic( + "sql", + "", + """ + SELECT * FROM author LIMIT $limit_number + """, + ) + out, _ = capsys.readouterr() + assert ( + "Please aware the variable substition" + " as {a}, $a, and :a format has been deprecated." + in out + ) + + +def test_variable_substitution_legacy_warning_message_single_curly( + ip, sql_magic, capsys +): + ip.user_global_ns["limit_number"] = 1 + out = ip.run_cell_magic( + "sql", + "", + """ + SELECT * FROM author LIMIT {limit_number} + """, + ) + out, _ = capsys.readouterr() + assert ( + "Please aware the variable substition" + " as {a}, $a, and :a format has been deprecated." + in out + ) + + +def test_variable_substitution_legacy_warning_message_colon(ip, sql_magic, capsys): + ip.user_global_ns["limit_number"] = 1 + out = ip.run_cell_magic( + "sql", + "", + """ + SELECT * FROM author LIMIT :limit_number + """, + ) + out, _ = capsys.readouterr() + assert ( + "Please aware the variable substition" + " as {a}, $a, and :a format has been deprecated." + in out + ) + + def test_variable_substitution_legacy_dollar_prefix_cell_magic(ip, sql_magic): ip.user_global_ns["username"] = "some-user" From 808f0d0f25d0cee32ecce55d230d9471129e4d15 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Wed, 22 Feb 2023 23:32:03 -0500 Subject: [PATCH 13/31] Add: CHANGELOG --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index b50b9a050..2af8dc3c3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,8 @@ ## 0.5.7dev +* [Feature] Support new variable substitution as {{a}} format ([#137](https://github.com/ploomber/jupysql/pull/137)) + ## 0.5.6 (2023-02-16) * [Feature] Shows missing driver package suggestion message ([#124](https://github.com/ploomber/jupysql/issues/124)) From 143b1af0d9a91c88fd6596628e9eb7f97198e80b Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 00:11:45 -0500 Subject: [PATCH 14/31] Remove: global & parameter support code --- src/sql/command.py | 22 ---------------------- src/sql/magic.py | 10 ---------- 2 files changed, 32 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 695b4802f..aec1f679e 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -88,28 +88,6 @@ def result_var(self): """Returns the result_var""" return self.parsed["result_var"] - def _params_helper(self, params): - def is_float(element): - if element is None: - return False - try: - float(element) - return True - except ValueError: - return False - - params_dict = {} - if not params: - return params_dict - # Throw some exception - - for key, value in params: - if is_float(value): - params_dict[key] = int(value) - else: - params_dict[key] = value - return params_dict - def _var_expand(self, magic, user_ns, line, cell): """ Support for the variable substition in the SQL clause diff --git a/src/sql/magic.py b/src/sql/magic.py index 0291a236c..7ec70b210 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -193,16 +193,6 @@ def __init__(self, shell): type=str, help="Assign an alias to the connection", ) - # @argument("-G", "--use-globals", action="store_true", help="use global namespace") - # @argument( - # "-P", - # "--param", - # type=str, - # nargs=2, - # action="append", - # metavar=("NAME", "VALUE"), - # help="stroe a param", - # ) @telemetry.log_call("execute") def execute(self, line="", cell="", local_ns={}): """ From 269447d07a10fa5579906fd345f70d45b655f653 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 00:12:57 -0500 Subject: [PATCH 15/31] Add: Ref to original issue in comment --- src/sql/command.py | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sql/command.py b/src/sql/command.py index aec1f679e..66578b6bf 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -100,6 +100,7 @@ def _var_expand(self, magic, user_ns, line, cell): self.is_legacy_var_expand_parsed = False # Latest format parsing # TODO: support --param and --use-global logic here + # Ref: https://github.com/ploomber/jupysql/issues/93 line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) # Legacy format parsing From ff8c1d44bf03072dd547c49bec060c059c9c1377 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 01:01:33 -0500 Subject: [PATCH 16/31] Add: PendingDeprecationWarning & Test cases --- src/sql/command.py | 11 +++---- src/tests/test_command.py | 69 +++++++++++++++------------------------ 2 files changed, 31 insertions(+), 49 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 66578b6bf..520653ed2 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -1,4 +1,5 @@ import re +import warnings from IPython.core.magic_arguments import parse_argstring from jinja2 import Template @@ -108,13 +109,9 @@ def _var_expand(self, magic, user_ns, line, cell): parsed_line = magic.shell.var_expand(line, depth=2) # Exclusive the string with "://", but has :variable has_SQLAlchemy_var_expand = re.search("(? Date: Tue, 28 Feb 2023 12:05:00 -0500 Subject: [PATCH 17/31] Add: doc --- doc/_toc.yml | 1 + doc/intro.md | 8 +++++- doc/user-guide/template.md | 52 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 doc/user-guide/template.md diff --git a/doc/_toc.yml b/doc/_toc.yml index eaceeacc2..b8448315c 100644 --- a/doc/_toc.yml +++ b/doc/_toc.yml @@ -13,6 +13,7 @@ parts: - file: compose - file: user-guide/tables-columns - file: plot-legacy + - file: template - caption: Integrations chapters: diff --git a/doc/intro.md b/doc/intro.md index 350e492de..878c1808b 100644 --- a/doc/intro.md +++ b/doc/intro.md @@ -6,7 +6,7 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.14.4 + jupytext_version: 1.14.5 kernelspec: display_name: Python 3 (ipykernel) language: python @@ -166,6 +166,12 @@ can be used in multi-line ``%%sql``: FROM languages ``` +```{versionchanged} 0.5.7 +This has been deprecated use '{{a}}' [Variable Expansion in Template](https://jupysql.ploomber.io/en/latest/template.html) +``` + ++++ + ## Considerations Because jupysql accepts `--`-delimited options like `--persist`, but `--` diff --git a/doc/user-guide/template.md b/doc/user-guide/template.md new file mode 100644 index 000000000..03bef4d9a --- /dev/null +++ b/doc/user-guide/template.md @@ -0,0 +1,52 @@ +--- +jupytext: + text_representation: + extension: .md + format_name: myst + format_version: 0.13 + jupytext_version: 1.14.5 +kernelspec: + display_name: Python 3 (ipykernel) + language: python + name: python3 +--- + +# Template + +## Variable Expansion as `{{variable}}` + +We support the variable expansion in the form of `{{variable}}`, this also allows the user to write the query as template with some dynamic variables + +```{code-cell} ipython3 +:tags: [remove-cell] + +%load_ext sql +from pathlib import Path +from urllib.request import urlretrieve + +if not Path("penguins.csv").is_file(): + urlretrieve( + "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/penguins.csv", + "penguins.csv", + ) +%sql duckdb:// +``` + +Now, let's give a simple query template and define some variables where we will apply in the template: + +```{code-cell} ipython3 +dynamic_limit = 5 +dynamic_column = "island, sex" +``` + +```{code-cell} ipython3 +%sql SELECT {{dynamic_column}} FROM penguins.csv LIMIT {{dynamic_limit}} +``` + +Note that variables will be fetched from the local namespace into the SQL statement. + +Please aware that we also support the `$variable` or `{variable_name}` way, but those will be deprecated in future version, [see more](https://jupysql.ploomber.io/en/latest/intro.html?highlight=variable#variable-substitution). + +```{code-cell} ipython3 + +``` From dbf7dc406831c028805826b5017b11b1c24e16c4 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 12:12:28 -0500 Subject: [PATCH 18/31] Update: intro --- doc/intro.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/intro.md b/doc/intro.md index 878c1808b..333476078 100644 --- a/doc/intro.md +++ b/doc/intro.md @@ -6,7 +6,7 @@ jupytext: extension: .md format_name: myst format_version: 0.13 - jupytext_version: 1.14.5 + jupytext_version: 1.14.4 kernelspec: display_name: Python 3 (ipykernel) language: python @@ -150,6 +150,10 @@ be used to replace strings passed to SQL. ``$`` and ``{}`` are substituted before passing to SQL and can be used to form SQL statements dynamically. +```{versionchanged} 0.5.7 +This has been deprecated use '{{a}}' [Variable Expansion in Template](https://jupysql.ploomber.io/en/latest/template.html) +``` + ## Assignment Ordinary IPython assignment works for single-line `%sql` queries: @@ -166,10 +170,6 @@ can be used in multi-line ``%%sql``: FROM languages ``` -```{versionchanged} 0.5.7 -This has been deprecated use '{{a}}' [Variable Expansion in Template](https://jupysql.ploomber.io/en/latest/template.html) -``` - +++ ## Considerations From a010cc38098bae166bb014e61429fa49b65e99fb Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 13:51:41 -0500 Subject: [PATCH 19/31] Add: doc --- doc/_toc.yml | 2 +- doc/intro.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/_toc.yml b/doc/_toc.yml index b8448315c..77c7cd894 100644 --- a/doc/_toc.yml +++ b/doc/_toc.yml @@ -13,7 +13,7 @@ parts: - file: compose - file: user-guide/tables-columns - file: plot-legacy - - file: template + - file: user-guide/template - caption: Integrations chapters: diff --git a/doc/intro.md b/doc/intro.md index 333476078..e39597cf8 100644 --- a/doc/intro.md +++ b/doc/intro.md @@ -124,6 +124,10 @@ or a single dictionary with a tuple of scalar values per key (``result.dict()``) ## Variable substitution +```{versionchanged} 0.5.7 +This is a legacy API that's kept for backwards compatibility. +``` + Bind variables (bind parameters) can be used in the "named" (:x) style. The variable names used should be defined in the local namespace. @@ -150,10 +154,6 @@ be used to replace strings passed to SQL. ``$`` and ``{}`` are substituted before passing to SQL and can be used to form SQL statements dynamically. -```{versionchanged} 0.5.7 -This has been deprecated use '{{a}}' [Variable Expansion in Template](https://jupysql.ploomber.io/en/latest/template.html) -``` - ## Assignment Ordinary IPython assignment works for single-line `%sql` queries: From 7cb4c2860f0106efc8cdb33f078401ff143f8011 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:18:07 -0500 Subject: [PATCH 20/31] Add: vs.html --- doc/community/vs.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index 06aac9ff6..e7cfd2a46 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -6,4 +6,5 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): -- Since `0.6` JupySQL no longer supports old versions of IPython \ No newline at end of file +- Since `0.6` JupySQL no longer supports old versions of IPython +- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}}, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file From ca52b8da21aada384bbdae5d433da837d25baa1b Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:20:26 -0500 Subject: [PATCH 21/31] Fix: merge issue --- src/sql/magic.py | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/sql/magic.py b/src/sql/magic.py index 9df9406e8..2c57db83d 100644 --- a/src/sql/magic.py +++ b/src/sql/magic.py @@ -21,12 +21,6 @@ from sql.magic_cmd import SqlCmdMagic -try: - from traitlets.config.configurable import Configurable - from traitlets import Bool, Int, Unicode -except ImportError: - from IPython.config.configurable import Configurable - from IPython.utils.traitlets import Bool, Int, Unicode from traitlets.config.configurable import Configurable from traitlets import Bool, Int, Unicode, observe From 0902aef334af37289e3559eb01163facde721618 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:30:32 -0500 Subject: [PATCH 22/31] Make vs.html build success --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index e7cfd2a46..5814f08a7 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}}, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}} \ No newline at end of file From 24505dacc6fa0aebf616cc0b7e9d0cd1fbe2fb7f Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:31:03 -0500 Subject: [PATCH 23/31] Add: template link in vs.html, this will expected failed --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index 5814f08a7..e7cfd2a46 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}} \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}}, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file From 23812635aec1fbcaf27a46f1dfdf362e8bb1d742 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:41:49 -0500 Subject: [PATCH 24/31] Rebuild --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index e7cfd2a46..5814f08a7 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}}, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}} \ No newline at end of file From 6c4d9cb501d1ae2855373790debfa2b9167d30da Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 14:49:59 -0500 Subject: [PATCH 25/31] Fix: variable typo? --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index 5814f08a7..808774a4d 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to {{variable}} \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to `{{variable}}` \ No newline at end of file From dff8b2348a1b5911fa87938bd37591150a118121 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 15:02:22 -0500 Subject: [PATCH 26/31] Add: see more template link --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index 808774a4d..29c6d31d2 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to `{{variable}}` \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to `{{variable}}`, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file From 365dd1487b6403419545032b9e27e8bf271b942a Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Tue, 28 Feb 2023 21:25:44 -0500 Subject: [PATCH 27/31] Revert "Add: see more template link" This reverts commit dff8b2348a1b5911fa87938bd37591150a118121. --- doc/community/vs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/community/vs.md b/doc/community/vs.md index 29c6d31d2..808774a4d 100644 --- a/doc/community/vs.md +++ b/doc/community/vs.md @@ -7,4 +7,4 @@ JupySQL is an actively maintained fork of [ipython-sql](https://github.com/cathe If you're migrating from `ipython-sql` to JupySQL, these are the differences (it most cases, no code changes are needed): - Since `0.6` JupySQL no longer supports old versions of IPython -- Variable expansion is being replaced from `{variable}`, `${variable}` to `{{variable}}`, [see more](https://jupysql.ploomber.io/en/latest/user-guide/template.html) \ No newline at end of file +- Variable expansion is being replaced from `{variable}`, `${variable}` to `{{variable}}` \ No newline at end of file From 00a45ebe1cf202bd039c024621ceaf2e1ad47a4e Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Thu, 2 Mar 2023 11:51:34 -0500 Subject: [PATCH 28/31] fix: comments --- src/sql/command.py | 7 +++---- src/sql/magic.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 520653ed2..8566ab193 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -105,13 +105,12 @@ def _var_expand(self, magic, user_ns, line, cell): line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) # Legacy format parsing - parsed_cell = magic.shell.var_expand(cell, depth=2) - parsed_line = magic.shell.var_expand(line, depth=2) + parsed_cell = magic.shell.var_expand(cell) + parsed_line = magic.shell.var_expand(line) # Exclusive the string with "://", but has :variable has_SQLAlchemy_var_expand = re.search("(? Date: Thu, 2 Mar 2023 11:57:21 -0500 Subject: [PATCH 29/31] Fix: test cases --- src/tests/test_command.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tests/test_command.py b/src/tests/test_command.py index a747760ea..63ee871f8 100644 --- a/src/tests/test_command.py +++ b/src/tests/test_command.py @@ -173,7 +173,7 @@ def test_parse_sql_when_passing_engine(ip, sql_magic, tmp_empty, line): def test_variable_substitution_legacy_warning_message_dollar_prefix( ip, sql_magic, capsys ): - with pytest.warns(PendingDeprecationWarning): + with pytest.warns(FutureWarning): ip.user_global_ns["limit_number"] = 1 ip.run_cell_magic( "sql", @@ -187,7 +187,7 @@ def test_variable_substitution_legacy_warning_message_dollar_prefix( def test_variable_substitution_legacy_warning_message_single_curly( ip, sql_magic, capsys ): - with pytest.warns(PendingDeprecationWarning): + with pytest.warns(FutureWarning): ip.user_global_ns["limit_number"] = 1 ip.run_cell_magic( "sql", @@ -199,7 +199,7 @@ def test_variable_substitution_legacy_warning_message_single_curly( def test_variable_substitution_legacy_warning_message_colon(ip, sql_magic, capsys): - with pytest.warns(PendingDeprecationWarning): + with pytest.warns(FutureWarning): ip.user_global_ns["limit_number"] = 1 ip.run_cell_magic( "sql", From e74be16d56e7d63a2989a8519b23b73f67bf2ac1 Mon Sep 17 00:00:00 2001 From: Tony Kuo Date: Thu, 2 Mar 2023 12:08:31 -0500 Subject: [PATCH 30/31] Depth --- src/sql/command.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 8566ab193..5726205af 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -105,8 +105,8 @@ def _var_expand(self, magic, user_ns, line, cell): line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) # Legacy format parsing - parsed_cell = magic.shell.var_expand(cell) - parsed_line = magic.shell.var_expand(line) + parsed_cell = magic.shell.var_expand(cell, depth=1) + parsed_line = magic.shell.var_expand(line, depth=1) # Exclusive the string with "://", but has :variable has_SQLAlchemy_var_expand = re.search("(? Date: Thu, 2 Mar 2023 12:12:27 -0500 Subject: [PATCH 31/31] Depth --- src/sql/command.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/sql/command.py b/src/sql/command.py index 5726205af..920a1675a 100644 --- a/src/sql/command.py +++ b/src/sql/command.py @@ -105,8 +105,8 @@ def _var_expand(self, magic, user_ns, line, cell): line = Template(line).render(user_ns) cell = Template(cell).render(user_ns) # Legacy format parsing - parsed_cell = magic.shell.var_expand(cell, depth=1) - parsed_line = magic.shell.var_expand(line, depth=1) + parsed_cell = magic.shell.var_expand(cell, depth=2) + parsed_line = magic.shell.var_expand(line, depth=2) # Exclusive the string with "://", but has :variable has_SQLAlchemy_var_expand = re.search("(?