Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-py-partiql-parser for 
openSUSE:Factory checked in at 2024-02-04 19:09:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-py-partiql-parser (Old)
 and      /work/SRC/openSUSE:Factory/.python-py-partiql-parser.new.1815 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-py-partiql-parser"

Sun Feb  4 19:09:54 2024 rev:6 rq:1143990 version:0.5.1

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-py-partiql-parser/python-py-partiql-parser.changes
        2023-12-28 23:03:39.443253542 +0100
+++ 
/work/SRC/openSUSE:Factory/.python-py-partiql-parser.new.1815/python-py-partiql-parser.changes
      2024-02-04 19:12:22.943485976 +0100
@@ -1,0 +2,9 @@
+Sun Feb  4 11:43:50 UTC 2024 - Dirk Müller <dmuel...@suse.com>
+
+- update to 0.5.1:
+  * Support INSERT/DELETE/UPDATE queries:
+    * that contain a table name without quotes
+    * that contain parameters
+    * when calling get_query_metadata()
+
+-------------------------------------------------------------------

Old:
----
  py-partiql-parser-0.5.0.tar.gz

New:
----
  py-partiql-parser-0.5.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-py-partiql-parser.spec ++++++
--- /var/tmp/diff_new_pack.SqXZhf/_old  2024-02-04 19:12:23.339500247 +0100
+++ /var/tmp/diff_new_pack.SqXZhf/_new  2024-02-04 19:12:23.339500247 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-py-partiql-parser
 #
-# Copyright (c) 2023 SUSE LLC
+# Copyright (c) 2024 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -18,7 +18,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-py-partiql-parser
-Version:        0.5.0
+Version:        0.5.1
 Release:        0
 Summary:        Pure Python PartiQL Parser
 License:        MIT

++++++ py-partiql-parser-0.5.0.tar.gz -> py-partiql-parser-0.5.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/CHANGELOG.md 
new/py-partiql-parser-0.5.1/CHANGELOG.md
--- old/py-partiql-parser-0.5.0/CHANGELOG.md    2023-12-17 01:06:55.000000000 
+0100
+++ new/py-partiql-parser-0.5.1/CHANGELOG.md    2024-02-01 22:30:48.000000000 
+0100
@@ -1,6 +1,16 @@
 CHANGELOG
 =========
 
+0.5.1
+-----
+
+ - Support INSERT/DELETE/UPDATE queries:
+
+   - that contain a table name without quotes
+   - that contain parameters
+   - when calling get_query_metadata()
+
+
 0.5.0
 -----
  - Improved typing support
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/__init__.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/__init__.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/__init__.py   2023-12-17 
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/__init__.py   2024-02-01 
22:30:48.000000000 +0100
@@ -1,4 +1,4 @@
-__version__ = "0.5.0"
+__version__ = "0.5.1"
 
 
 from ._internal.parser import DynamoDBStatementParser, S3SelectParser  # noqa
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/delete_parser.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/delete_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/delete_parser.py    
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/delete_parser.py    
2024-02-01 22:30:48.000000000 +0100
@@ -48,6 +48,11 @@
                     assert current_phrase.upper() == "AND"
                     section = "WHERE"
                     current_phrase = ""
+                if section == "TABLE_NAME":
+                    table_name = current_phrase
+                    current_phrase = ""
+                    tokenizer.skip_white_space()
+                    section = "SECTION_WHERE"
                 continue
             elif c in ["'", '"']:
                 if section == "TABLE_NAME":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/insert_parser.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/insert_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/insert_parser.py    
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/insert_parser.py    
2024-02-01 22:30:48.000000000 +0100
@@ -41,6 +41,11 @@
                     attr = JsonParser().parse(tokenizer.give_remaining())
                     for key, value in attr.items():
                         attr[key] = serializer.serialize(value)
+                if section == "TABLE_NAME":
+                    table_name = current_phrase
+                    current_phrase = ""
+                    tokenizer.skip_white_space()
+                    section = "SECTION_VALUE"
                 continue
             elif c in ["'", '"']:
                 if section == "TABLE_NAME":
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/parser.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/parser.py   
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/parser.py   
2024-02-01 22:30:48.000000000 +0100
@@ -2,6 +2,7 @@
 
 from typing import Dict, Any, List, Optional, Tuple
 
+from ..exceptions import ParserException
 from .delete_parser import DeleteParser
 from .from_parser import DynamoDBFromParser, S3FromParser, FromParser
 from .insert_parser import InsertParser
@@ -86,7 +87,7 @@
             return return_data, updates
 
         if query.lower().startswith("update"):
-            return self._parse_update(query)
+            return self._parse_update(query, parameters)
 
         if query.lower().startswith("delete"):
             return self._parse_delete(query)
@@ -123,11 +124,31 @@
         ] = {}
         return queried_data, updates
 
-    def _parse_update(self, query: str) -> TYPE_RESPONSE:
+    def _parse_update(
+        self, query: str, parameters: Optional[List[Dict[str, Any]]] = None
+    ) -> TYPE_RESPONSE:
         query = query.replace("\n", " ")
 
         table_name, attrs_to_update, attrs_to_filter = 
UpdateParser().parse(query)
 
+        parameters_requested = len(
+            [_ for _, val in attrs_to_update + attrs_to_filter if val == "?"]
+        )
+        if parameters_requested and len(parameters) != parameters_requested:  
# type: ignore
+            raise ParserException(
+                name="ValidationError",
+                message="Number of parameters in request and statement don't 
match.",
+            )
+
+        attrs_to_update = [
+            (key, parameters.pop(0) if val == "?" else val)  # type: ignore
+            for key, val in attrs_to_update
+        ]
+        attrs_to_filter = [
+            (key, parameters.pop(0) if val == "?" else val)  # type: ignore
+            for key, val in attrs_to_filter
+        ]
+
         source_data = self.documents[table_name]
         updates_per_table: Dict[
             str, List[Tuple[Optional[Dict[str, Any]], Optional[Dict[str, 
Any]]]]
@@ -172,15 +193,31 @@
     @classmethod
     def get_query_metadata(cls, query: str) -> QueryMetadata:
         query = query.replace("\n", " ")
-        clauses = re.split("SELECT | FROM | WHERE ", query, 
flags=re.IGNORECASE)
-
-        from_parser = FromParser(clauses[2])
+        if query.lower().startswith("select"):
+            clauses = re.split("SELECT | FROM | WHERE ", query, 
flags=re.IGNORECASE)
 
-        # WHERE
-        if len(clauses) > 3:
-            where_clause = clauses[3]
-            where = WhereParser.parse_where_clause(where_clause)
-        else:
-            where = None
+            from_parser = FromParser(clauses[2])
+            # WHERE
+            if len(clauses) > 3:
+                where_clause = clauses[3]
+                where = WhereParser.parse_where_clause(where_clause)
+            else:
+                where = None
 
-        return QueryMetadata(tables=from_parser.clauses, where_clause=where)
+            return QueryMetadata(
+                tables=from_parser.clauses, where_clause=where, 
is_select_query=True
+            )
+        elif query.lower().startswith("update"):
+            table_name, attrs_to_update, attrs_to_filter = 
UpdateParser().parse(query)
+            return QueryMetadata(tables={table_name: table_name}, 
where_clause=None)
+        elif query.lower().startswith("delete"):
+            query = query.replace("\n", " ")
+
+            table_name, attrs_to_filter = DeleteParser().parse(query)
+            return QueryMetadata(tables={table_name: table_name})
+        elif query.lower().startswith("insert"):
+            query = query.replace("\n", " ")
+
+            table_name, new_item = InsertParser().parse(query)
+            return QueryMetadata(tables={table_name: table_name})
+        raise Exception
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/update_parser.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/update_parser.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/update_parser.py    
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/update_parser.py    
2024-02-01 22:30:48.000000000 +0100
@@ -1,4 +1,4 @@
-from typing import Any, Dict, List, Tuple, Optional
+from typing import Any, List, Tuple
 
 from .clause_tokenizer import ClauseTokenizer
 from .utils import serializer
@@ -7,19 +7,15 @@
 class UpdateParser:
     def parse(
         self, query: str
-    ) -> Tuple[
-        str,
-        List[Tuple[str, Optional[Dict[str, Any]]]],
-        List[Tuple[str, Dict[str, Any]]],
-    ]:
+    ) -> Tuple[str, List[Tuple[str, Any]], List[Tuple[str, Any]]]:
         tokenizer = ClauseTokenizer(query)
 
         section = "START"
         current_phrase = ""
 
         table_name = ""
-        attrs_to_update: List[Tuple[str, Optional[Dict[str, Any]]]] = []
-        attr_filters = []
+        attrs_to_update: List[Tuple[str, Any]] = []
+        attr_filters: List[Tuple[str, Any]] = []
 
         while True:
             c = tokenizer.next()
@@ -33,6 +29,7 @@
                     ), f"{current_phrase} should be UPDATE"
                     current_phrase = ""
                     section = "TABLE_NAME"
+                    continue
                 if section == "ACTION":
                     assert current_phrase.upper() in ["SET", "REMOVE"]
                     section = f"ACTION_{current_phrase.upper()}"
@@ -42,6 +39,7 @@
                     assert current_phrase.upper() == "WHERE"
                     section = "WHERE"
                     current_phrase = ""
+                    continue
                 if section == "WHERE_AND":
                     assert current_phrase.upper() == "AND"
                     section = "WHERE"
@@ -54,38 +52,64 @@
 
                     tokenizer.skip_white_space()
                     section = "SECTION_WHERE"
+                if section == "TABLE_NAME":
+                    table_name = current_phrase
+                    current_phrase = ""
+                    tokenizer.skip_white_space()
+                    section = "ACTION"
                 continue
             elif c in ["'", '"']:
                 if section == "TABLE_NAME":
                     table_name = tokenizer.next_until([c])
                     tokenizer.skip_white_space()
                     section = "ACTION"
+                if section == "ACTION_SET":
+                    current_phrase = tokenizer.next_until([c])
+                    tokenizer.skip_white_space()
+                if section == "WHERE":
+                    current_phrase = tokenizer.next_until([c])
+                    tokenizer.skip_white_space()
                 continue
             elif c == "=":
                 if section == "ACTION_SET":
                     attr_name = current_phrase
                     tokenizer.skip_white_space()
-                    quote_type = tokenizer.current()
-                    assert quote_type in ["'", '"']
-
-                    tokenizer.next()
-                    attr_value = tokenizer.next_until([quote_type])
-                    attrs_to_update.append(
-                        (attr_name, serializer.serialize(attr_value))
-                    )
+                    if tokenizer.current() == "?":
+                        attrs_to_update.append((attr_name, "?"))
+                        tokenizer.next_until(["?"])
+                    else:
+                        quote_type = tokenizer.current()
+                        assert quote_type in ["'", '"', "?"]
+
+                        tokenizer.next()
+                        attr_value = tokenizer.next_until([quote_type])
+                        attrs_to_update.append(
+                            (attr_name, serializer.serialize(attr_value))
+                        )
                     current_phrase = ""
 
                     tokenizer.skip_white_space()
-                    section = "SECTION_WHERE"
+                    if tokenizer.current() == ",":
+                        tokenizer.next_until([","])
+                        # Another attr to update
+                        pass
+                    else:
+                        section = "SECTION_WHERE"
                 elif section == "WHERE":
                     attr_name = current_phrase
                     tokenizer.skip_white_space()
-                    quote_type = tokenizer.current()
-                    assert quote_type in ["'", '"']
-
-                    tokenizer.next()
-                    attr_value = tokenizer.next_until([quote_type])
-                    attr_filters.append((attr_name, 
serializer.serialize(attr_value)))
+                    if tokenizer.current() == "?":
+                        attr_filters.append((current_phrase, "?"))
+                        tokenizer.next_until(["?"])
+                    else:
+                        quote_type = tokenizer.current()
+                        assert quote_type in ["'", '"']
+
+                        tokenizer.next()
+                        attr_value = tokenizer.next_until([quote_type])
+                        attr_filters.append(
+                            (attr_name, serializer.serialize(attr_value))
+                        )
 
                     tokenizer.skip_white_space()
                     current_phrase = ""
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/utils.py 
new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/utils.py
--- old/py-partiql-parser-0.5.0/py_partiql_parser/_internal/utils.py    
2023-12-17 01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/py_partiql_parser/_internal/utils.py    
2024-02-01 22:30:48.000000000 +0100
@@ -133,9 +133,11 @@
         self,
         tables: Dict[str, str],
         where_clause: Optional["AbstractWhereClause"] = None,
+        is_select_query: bool = False,
     ):
         self._tables = tables
         self._where_clause = where_clause
+        self._is_select_query = is_select_query
 
     def get_table_names(self) -> List[str]:
         return list(self._tables.values())
@@ -145,6 +147,9 @@
             return self._where_clause.get_filter_names()
         return []
 
+    def is_select_query(self) -> bool:
+        return self._is_select_query
+
 
 class Variable:
     def __init__(self, value: Any) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/pyproject.toml 
new/py-partiql-parser-0.5.1/pyproject.toml
--- old/py-partiql-parser-0.5.0/pyproject.toml  2023-12-17 01:06:55.000000000 
+0100
+++ new/py-partiql-parser-0.5.1/pyproject.toml  2024-02-01 22:30:48.000000000 
+0100
@@ -1,6 +1,6 @@
 [project]
 name = "py-partiql-parser"
-version = "0.5.0"
+version = "0.5.1"
 description = "Pure Python PartiQL Parser"
 readme = "README.md"
 keywords = ["pypartiql", "parser"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/py-partiql-parser-0.5.0/tests/test_dynamodb_examples.py 
new/py-partiql-parser-0.5.1/tests/test_dynamodb_examples.py
--- old/py-partiql-parser-0.5.0/tests/test_dynamodb_examples.py 2023-12-17 
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/tests/test_dynamodb_examples.py 2024-02-01 
22:30:48.000000000 +0100
@@ -259,6 +259,32 @@
     assert updates == {"table": [(items[1], updated_item)]}
 
 
+def test_update_with_quoted_attributes_and_parameters() -> None:
+    # Note that the table is without parameters
+    query = 'UPDATE users SET "first_name" = ?, "last_name" = ? WHERE "id"= ?'
+    items = [
+        {"id": {"S": "yes"}, "first_name": {"S": "old"}, "last_name": {"S": 
"old"}},
+        {"id": {"S": "no"}, "first_name": {"S": "old"}, "last_name": {"S": 
"old"}},
+    ]
+    return_value, updates = DynamoDBStatementParser(source_data={"users": 
items}).parse(
+        query, parameters=[{"S": "fn"}, {"S": "ln"}, {"S": "yes"}]
+    )
+
+    assert return_value == []
+    assert len(updates["users"]) == 1
+    old, new = updates["users"][0]
+    assert old == {
+        "id": {"S": "yes"},
+        "first_name": {"S": "old"},
+        "last_name": {"S": "old"},
+    }
+    assert new == {
+        "id": {"S": "yes"},
+        "first_name": {"S": "fn"},
+        "last_name": {"S": "ln"},
+    }
+
+
 def test_update_remove() -> None:
     query = "UPDATE 'table' REMOVE attr WHERE Id='id1'"
     items = [
@@ -276,8 +302,11 @@
     assert updates == {"table": [(items[0], updated_item)]}
 
 
-def test_delete() -> None:
-    query = "DELETE FROM 'tablename' WHERE Id='id1'"
+@pytest.mark.parametrize(
+    "query",
+    ["DELETE FROM 'tablename' WHERE Id='id1'", "DELETE FROM tablename WHERE 
Id='id1'"],
+)
+def test_delete(query: str) -> None:
     items = [
         {"id": {"S": "id1"}, "attr": {"S": "sth"}},
         {"id": {"S": "id2"}, "attr": {"S": "oth"}},
@@ -317,8 +346,14 @@
     assert updates == {"tablename": []}
 
 
-def test_insert() -> None:
-    query = "INSERT INTO 'mytable' value {'id': 'id1'}"
+@pytest.mark.parametrize(
+    "query",
+    [
+        "INSERT INTO 'mytable' value {'id': 'id1'}",
+        "INSERT INTO mytable value {'id': 'id1'}",
+    ],
+)
+def test_insert(query: str) -> None:
     items = [{"id": {"S": "asdf"}}]
     return_value, updates = DynamoDBStatementParser(
         source_data={"mytable": items}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/py-partiql-parser-0.5.0/tests/test_query_metadata.py 
new/py-partiql-parser-0.5.1/tests/test_query_metadata.py
--- old/py-partiql-parser-0.5.0/tests/test_query_metadata.py    2023-12-17 
01:06:55.000000000 +0100
+++ new/py-partiql-parser-0.5.1/tests/test_query_metadata.py    2024-02-01 
22:30:48.000000000 +0100
@@ -41,3 +41,27 @@
     metadata = DynamoDBStatementParser.get_query_metadata(query)
 
     assert metadata.get_filter_names() == ["k1", "k2.sth"]
+
+
+def test_update_statement() -> None:
+    query = 'UPDATE users SET "first_name" = ?, "last_name" = ? WHERE 
"username"= ?'
+    metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+    assert metadata.get_table_names() == ["users"]
+    assert metadata.get_filter_names() == []
+
+
+def test_insert_statement() -> None:
+    query = "INSERT INTO 'mytable' value {'id': 'id1'}"
+    metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+    assert metadata.get_table_names() == ["mytable"]
+    assert metadata.get_filter_names() == []
+
+
+def test_delete_statement() -> None:
+    query = "DELETE FROM 'tablename' WHERE Id='id1'"
+    metadata = DynamoDBStatementParser.get_query_metadata(query)
+
+    assert metadata.get_table_names() == ["tablename"]
+    assert metadata.get_filter_names() == []

Reply via email to