From 43f82c2b223ecafa078fa71194137fd4c6b33a25 Mon Sep 17 00:00:00 2001
From: Firepup Sixfifty <firepyp650@gmail.com>
Date: Thu, 27 Mar 2025 20:30:47 -0500
Subject: [PATCH] 1.0.6

---
 .gitignore                    |   2 +
 LICENSE                       |  21 ++++
 package/README.md             |   4 +-
 package/pyproject.toml        |   4 +-
 package/src/fpsql/__init__.py | 214 +++++++++++++++++++++++++++++++++-
 5 files changed, 238 insertions(+), 7 deletions(-)
 create mode 100644 LICENSE

diff --git a/.gitignore b/.gitignore
index f21c9ec..0c79684 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ venv/**
 replit*txt
 .config/**
 .replit
+**/dist/**
+**/.env
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1e26c53
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2025 Firepup Sixfifty
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/package/README.md b/package/README.md
index aaf0e6f..32a56fb 100644
--- a/package/README.md
+++ b/package/README.md
@@ -1,6 +1,8 @@
 # FPSQL
 An easy to use SQLite package
 #### Change log:
+###### v.1.0.6:
+Add AsyncSql, start working on dict actions
 ###### v.1.0.5:
 Double check mypy problems and resolve them
 ###### v.1.0.4:
@@ -14,4 +16,4 @@ Actual release
 ###### v.1.0.0:
 Initial Release!
 ###### v.1.0.26:
-Mistake release :facepalm:
\ No newline at end of file
+Mistake release :facepalm:
diff --git a/package/pyproject.toml b/package/pyproject.toml
index 47840c1..21f91c6 100644
--- a/package/pyproject.toml
+++ b/package/pyproject.toml
@@ -1,6 +1,6 @@
 [tool.poetry]
 name = "fpsql"
-version = "1.0.5"
+version = "1.0.6"
 authors = ["Firepup650 <firepyp650@gmail.com>"]
 description = "An easy to use SQLite package"
 readme = "README.md"
@@ -27,4 +27,4 @@ python = "^3.8"
 
 [build-system]
 requires = ["poetry-core>=1.0.0"]
-build-backend = "poetry.core.masonry.api"
\ No newline at end of file
+build-backend = "poetry.core.masonry.api"
diff --git a/package/src/fpsql/__init__.py b/package/src/fpsql/__init__.py
index a7e8938..6d95370 100644
--- a/package/src/fpsql/__init__.py
+++ b/package/src/fpsql/__init__.py
@@ -1,7 +1,8 @@
 """Firepup650's SQL Package"""
 
 from typing import Any
-import sqlite3, ast, pydoc
+import sqlite3, aiosqlite, ast, pydoc
+from asyncio import run as aRun
 
 
 def alias(Function):
@@ -15,8 +16,8 @@ def alias(Function):
     return decorator
 
 
-__VERSION__ = "1.0.5"
-__NEW__ = "Double check mypy problems and resolve them"
+__VERSION__ = "1.0.6"
+__NEW__ = "Add AsyncSql, start working on dict actions"
 __LICENSE__ = "MIT"
 
 
@@ -111,6 +112,20 @@ class sql:
                 return data[0]
         return None
 
+    def __setitem__(self, name: str, value: object) -> int:
+        """# Function: sql.__getitem__
+          Sets the value of a key
+        # Inputs:
+          name: str - The name of the key to set
+          value: object - The value of the key
+
+        # Returns:
+          int - `1` if the key was created, `2` if it was updated
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        return set(name)
+
     def set(self, name: str, value: object) -> int:
         """# Function: sql.set
           Sets the value of a key
@@ -125,7 +140,7 @@ class sql:
           AttributeError - If the table is unset"""
         if not self.__table:
             raise AttributeError("Attempted to write to unset table")
-        if self.get(name):
+        if self.get(name) != None:
             self.__con.execute(
                 f"""UPDATE "{self.__table}" SET value = ? WHERE name = ?""",
                 (str(value), name),
@@ -190,3 +205,194 @@ class sql:
         self.__con = None  # type: ignore[assignment]
         self.__db = ""
         self.__table = ""
+
+
+class asyncSql:
+    async def addTable(self, tableName: str, mode: int = 0, address: str = "") -> None:
+        """# Function: sql.addTable
+          Adds a table to the database
+        # Inputs:
+          tableName: str - The name of the table to create
+          mode: int - Not yet implemented
+          address: str - Not yet implemented
+
+        # Returns:
+          None
+
+        # Raises:
+          None"""
+        async with aiosqlite.connect(self.__db) as con:
+            await con.execute(
+                f"""CREATE TABLE IF NOT EXISTS "{tableName}"
+                    (id INTEGER PRIMARY KEY AUTOINCREMENT,
+                    name TEXT NOT NULL,
+                    value TEXT NOT NULL)"""
+            )
+            await con.commit()
+            self.__table = tableName
+
+    def __init__(self, filename: str):
+        """# Function: sql.__init__
+          Constructs an SQL instance
+        # Inputs:
+          filename: str - The name of the database file to connect to
+
+        # Returns:
+          None
+
+        # Raises:
+          ValueError - If the filename is `:memory:`, because the memory table doesn't work with how I've setup my async logic
+        """
+        if filename == ":memory:":
+            raise ValueError("Cannot use `:memory:` table with async code")
+        if filename.endswith(".db"):
+            self.__db = filename
+        else:
+            self.__db = filename + ".db"
+        aRun(self.addTable("default"))
+
+    async def setTable(self, tableName: str) -> None:
+        """# Function: sql.setTable
+          Sets the currently active table
+        # Inputs:
+          tableName: str - The name of the table to use
+
+        # Returns:
+          None
+
+        # Raises:
+          None"""
+        self.__table = tableName
+
+    async def __getitem__(self, name: str) -> Any:
+        """# Function: sql.__getitem__
+          Gets the value of a key
+        # Inputs:
+          name: str - The name of the key to retrieve
+
+        # Returns:
+          Any - If the key exists, return it's value (casted), otherwise, return `None`
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        return await get(name)
+
+    async def get(self, name: str) -> Any:
+        """# Function: sql.get
+          Gets the value of a key
+        # Inputs:
+          name: str - The name of the key to retrieve
+
+        # Returns:
+          Any - If the key exists, return it's value (casted), otherwise, return `None`
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        if not self.__table:
+            raise AttributeError("Attempted to read from unset table")
+        async with aiosqlite.connect(self.__db) as con:
+            cur = await con.execute(
+                f"""SELECT value FROM "{self.__table}" WHERE name = ?""", (name,)
+            )
+            data = await cur.fetchone()
+            if data:
+                try:
+                    return ast.literal_eval(data[0])
+                except:
+                    return data[0]
+            return None
+
+    async def __setitem__(self, name: str, value: object) -> int:
+        """# Function: sql.__setitem__
+          Sets the value of a key
+          name: str - The name of the key to set
+          value: object - The value of the key
+
+        # Returns:
+          int - `1` if the key was created, `2` if it was updated
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        return await set()
+
+    async def set(self, name: str, value: object) -> int:
+        """# Function: sql.set
+          Sets the value of a key
+        # Inputs:
+          name: str - The name of the key to set
+          value: object - The value of the key
+
+        # Returns:
+          int - `1` if the key was created, `2` if it was updated
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        async with aiosqlite.connect(self.__db) as con:
+            if not self.__table:
+                raise AttributeError("Attempted to write to unset table")
+            if await self.get(name) != None:
+                await con.execute(
+                    f"""UPDATE "{self.__table}" SET value = ? WHERE name = ?""",
+                    (str(value), name),
+                )
+                await con.commit()
+                return 2
+            else:
+                await con.execute(
+                    f"""INSERT INTO "{self.__table}" (name, value) VALUES (?, ?)""",
+                    (name, str(value)),
+                )
+                await con.commit()
+                return 1
+
+    async def delete(self, name: str) -> None:
+        """# Function: sql.delete
+          Deletes a key from the table
+        # Inputs:
+          name: str - The name of the key to delete
+
+        # Returns:
+          None
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        async with aiosqlite.connect(self.__db) as con:
+            if not self.__table:
+                raise AttributeError("Attempted to delete from unset table")
+            if await self.get(name):
+                await con.execute(
+                    f"""DELETE FROM "{self.__table}" WHERE name = ?""", (name,)
+                )
+                await con.commit()
+
+    async def deleteAll(self) -> None:
+        """# Function: sql.delete_all
+          Deletes all keys from the table
+        # Inputs:
+          None
+
+        # Returns:
+          None
+
+        # Raises:
+          AttributeError - If the table is unset"""
+        async with aiosqlite.connect(self.__db) as con:
+            if not self.__table:
+                raise AttributeError("Attempted to delete from unset table")
+            await con.execute(f"""DELETE FROM "{self.__table}" """)
+            await con.commit()
+
+    async def close(self) -> None:
+        """# Function: sql.close
+          Closes the database connection
+        # Inputs:
+          None
+
+        # Returns:
+          None
+
+        # Raises:
+          None"""
+        self.__con = None  # type: ignore[assignment]
+        self.__db = ""
+        self.__table = ""