fastapi-sqlalchemy-ease 0.1.3__py3-none-any.whl → 0.1.5__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,7 +1,7 @@
1
1
  from .core import SQLAlchemy
2
2
  from .exceptions import DatabaseError, DatabaseNotInitializedError
3
3
 
4
- __version__='0.1.3'
4
+ __version__='0.1.5'
5
5
 
6
6
  # when someone call: from fastapi_sqlalchemy import SQLAlchemy
7
7
  # only these things are available
@@ -6,7 +6,8 @@ from sqlalchemy import (
6
6
  Numeric,
7
7
  ForeignKey,
8
8
  UniqueConstraint, CheckConstraint,
9
- Index, Table
9
+ Index, Table,
10
+ func, and_, any_, not_, or_, select, update, delete, desc, asc
10
11
  )
11
12
  from sqlalchemy.orm import declarative_base, sessionmaker, Session, relationship
12
13
  from typing import Generator, Optional
@@ -32,6 +33,24 @@ class SQLAlchemy:
32
33
  LargeBinary = LargeBinary
33
34
  Numeric = Numeric
34
35
 
36
+ '''Logic and Boolean operators'''
37
+ and_ = and_
38
+ or_ = or_
39
+ not_ = not_
40
+
41
+ '''SQL Functions (count, now, max, min, etc.)'''
42
+ func = func
43
+
44
+ '''Query Execution Utilities'''
45
+ select = select
46
+ update = update
47
+ delete = delete
48
+
49
+ '''ordering'''
50
+ desc = desc
51
+ asc = asc
52
+
53
+
35
54
  '''Relationships and Constraints'''
36
55
  ForeignKey = ForeignKey
37
56
  UniqueConstraint = UniqueConstraint
@@ -43,18 +62,21 @@ class SQLAlchemy:
43
62
  def __new__(cls):
44
63
  if cls._instance is None:
45
64
  cls._instance = super().__new__(cls)
65
+ cls._instance._Model = declarative_base()
46
66
  return cls._instance
47
67
 
48
68
 
49
69
  def __init__(self):
50
- # Everything starts as None Until db.init_app() is called
51
- self.engine = None
52
- self._SessionLocal = None
53
- self._Model = None
54
- self._initialized = False
70
+ if not hasattr(self, '_initialized_vars'):
71
+ # Everything starts as None Until db.init_app() is called
72
+ self.engine = None
73
+ self._SessionLocal = None
74
+ self.session = None
75
+ self._initialized = False
76
+ self._initialized_vars = True
55
77
 
56
78
 
57
- def init_app(self, DATABASE_URI: str, connect_args: Optional[dict]=None):
79
+ def init_app(self, DATABASE_URI: str, **kwargs):
58
80
  '''
59
81
  Docstring for init_app
60
82
 
@@ -64,12 +86,16 @@ class SQLAlchemy:
64
86
  connect_args: used only when initializing sqlite db
65
87
  '''
66
88
 
67
- engine_kwargs={}
89
+ engine_kwargs={
90
+ "pool_pre_ping": True,
91
+ }
68
92
 
69
- if connect_args:
70
- engine_kwargs['connect_args'] = connect_args # sqlite need this
71
- else:
72
- engine_kwargs['pool_pre_ping'] = True # Keeps connection alive for PostgreSQL/MySQL
93
+ # Only add pooling if NOT using SQLite
94
+ if not DATABASE_URI.startswith("sqlite"):
95
+ engine_kwargs["pool_size"] = kwargs.get("pool_size", 10)
96
+ engine_kwargs["max_overflow"] = kwargs.get("max_overflow", 20)
97
+
98
+ engine_kwargs.update(kwargs)
73
99
 
74
100
  # Engine connection to database
75
101
  self.engine = create_engine(DATABASE_URI, **engine_kwargs)
@@ -77,8 +103,9 @@ class SQLAlchemy:
77
103
  # SessionLocal - Factory data creates new sessions
78
104
  self._SessionLocal = sessionmaker(autoflush=False ,bind=self.engine)
79
105
 
80
- # Model - base class, all our database models will inherit from
81
- self._Model = declarative_base()
106
+ from sqlalchemy.orm import scoped_session
107
+ self.session = scoped_session(self._SessionLocal)
108
+ self._Model.query = self.session.query_property()
82
109
 
83
110
  self._initialized = True
84
111
 
@@ -91,9 +118,6 @@ class SQLAlchemy:
91
118
  Base class for creating database models
92
119
  User writes: class User(db.Model):
93
120
  '''
94
-
95
- if not self._initialized:
96
- raise DatabaseNotInitializedError('Database not Intialized, call db.init_app() first.')
97
121
 
98
122
  return self._Model
99
123
 
@@ -136,8 +160,8 @@ class SQLAlchemy:
136
160
  if not self._initialized:
137
161
  raise DatabaseNotInitializedError('Database not Intialized, call db.init_app() first.')
138
162
 
139
- session = self._SessionLocal()
163
+ session = self.session()
140
164
  try:
141
165
  yield session # Give session to the route
142
166
  finally:
143
- session.close() #always close after one requst
167
+ self.session.remove() #proper cleanup for scoped sessions
@@ -0,0 +1,109 @@
1
+ Metadata-Version: 2.4
2
+ Name: fastapi-sqlalchemy-ease
3
+ Version: 0.1.5
4
+ Summary: A reusable SQLAlchemy extension for FastAPI
5
+ Requires-Python: >=3.8
6
+ Description-Content-Type: text/markdown
7
+ License-File: LICENSE
8
+ Requires-Dist: sqlalchemy>=2.0.0
9
+ Dynamic: description
10
+ Dynamic: description-content-type
11
+ Dynamic: license-file
12
+ Dynamic: requires-dist
13
+ Dynamic: requires-python
14
+ Dynamic: summary
15
+
16
+ # fastapi-sqlalchemy-ease
17
+
18
+ fastapi-sqlalchemy-ease is a singleton-based SQLAlchemy extension for FastAPI. It provides a centralized interface for database initialization, model declaration, and session management, inspired by the simplicity of Flask-SQLAlchemy.
19
+
20
+ ## ◽ Key Features
21
+
22
+ - Singleton Design: Ensures a single database instance across your entire FastAPI application.
23
+
24
+ - Consolidated API: Access all SQLAlchemy types (Integer, String, ForeignKey, etc.) directly from the db object.
25
+
26
+ - Auto-Cleanup: Includes a generator-based session handler designed for FastAPI's Depends to ensure sessions are always closed.
27
+
28
+ - Built-in Lifecycle Management: Simple methods for create_all() and drop_all().
29
+
30
+
31
+ ## ◽ Installation
32
+
33
+ pip install fastapi-sqlalchemy-ease
34
+
35
+
36
+
37
+ ## ◽ Usage Guide
38
+
39
+ ### 1. Basic setup
40
+ Initialize your database instance in a centralized file (e.g. database.py).
41
+
42
+
43
+ from fastapi_sqlalchemy_ease import SQLAlchemy
44
+
45
+ '''Create the singleton instance'''
46
+ db = SQLAlchemy()
47
+
48
+ '''Initialize with your URI'''
49
+ DATABASE_URI = "sqlite:///./test.db"
50
+
51
+ '''Use connect_args={"check_same_thread": False} for SQLite'''
52
+ db.init_app(DATABASE_URI, connect_args={"check_same_thread": False})
53
+
54
+
55
+
56
+ ### 2. Defining Models
57
+ No need to import types from SQLAlchemy; use the db instance directly.
58
+
59
+ class User(db.Model):
60
+ __tablename__ = "users"
61
+
62
+ id = db.Column(db.Integer, primary_key=True)
63
+ username = db.Column(db.String, unique=True, nullable=False)
64
+ created_at = db.Column(db.DateTime)
65
+
66
+
67
+
68
+ ### 3. Creating Tables
69
+ You can trigger table creation easily.
70
+
71
+ db.create_all()
72
+
73
+
74
+
75
+ ### 3. Database Operations in Routes
76
+ Use db.Session with FastAPI's Depends to get a clean session for every request.
77
+
78
+ from fastapi import FastAPI, Depends
79
+ from .. import db
80
+
81
+ app = FastAPI()
82
+
83
+ @app.get("/users")
84
+ def read_users(session: Session = Depends(db.Session)):
85
+ users = session.query(User).all()
86
+ return users
87
+
88
+
89
+
90
+ ## ◽ Available Attributes
91
+ Your db instance provides easy access to standard SQLAlchemy types and constraints:
92
+
93
+ Category - Available Attributes
94
+
95
+ Data Types - String, Integer, Float, Boolean, Text, Date, DateTime, JSON, Numeric
96
+ Constraints - ForeignKey, UniqueConstraint, CheckConstraint, Index
97
+ ORM - relationship, Table, Column
98
+
99
+
100
+
101
+ ## ◽ Error Handling
102
+ The library includes a DatabaseNotInitializedError. If you attempt to access db.Model, db.Session, or lifecycle methods before calling db.init_app(), a clear exception will be raised to help you debug quickly.
103
+
104
+
105
+
106
+ ## 📄 License
107
+ Distributed under the MIT License.
108
+
109
+ --
@@ -0,0 +1,8 @@
1
+ fastapi_sqlalchemy_ease/__init__.py,sha256=bJALhusgwO6bgq3Y1y9FwT1TfSiRYO4zh10SlFK-D8s,303
2
+ fastapi_sqlalchemy_ease/core.py,sha256=Uc6rbLLZ6gTCetkzX0a9VqVvafJQm5eyTOw_02dIM1g,4470
3
+ fastapi_sqlalchemy_ease/exceptions.py,sha256=6YU6mJvOGXC9D0mPH99GjMWpj21NA5jD8II7DWEcHaA,222
4
+ fastapi_sqlalchemy_ease-0.1.5.dist-info/licenses/LICENSE,sha256=jVnW2ZK4LFNHmDZE-xj0EyVpbHVMpwO7FcTk_We8qrA,1068
5
+ fastapi_sqlalchemy_ease-0.1.5.dist-info/METADATA,sha256=2XnxNnRUxd7Ge_TKeDGCM7c_Yhs7l1N6SvJU4kFNceU,3144
6
+ fastapi_sqlalchemy_ease-0.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
7
+ fastapi_sqlalchemy_ease-0.1.5.dist-info/top_level.txt,sha256=Y9kRilavMJot8bwOZymZ0cRjiBNIzsVqx9EwvXGiq-8,24
8
+ fastapi_sqlalchemy_ease-0.1.5.dist-info/RECORD,,
@@ -1,11 +0,0 @@
1
- Metadata-Version: 2.4
2
- Name: fastapi-sqlalchemy-ease
3
- Version: 0.1.3
4
- Summary: A reusable SQLAlchemy extension for FastAPI
5
- Requires-Python: >=3.8
6
- License-File: LICENSE
7
- Requires-Dist: sqlalchemy>=2.0.0
8
- Dynamic: license-file
9
- Dynamic: requires-dist
10
- Dynamic: requires-python
11
- Dynamic: summary
@@ -1,8 +0,0 @@
1
- fastapi_sqlalchemy_ease/__init__.py,sha256=rUUx_WPD1D830v7DpNSh_3_CsbJNMeJHHSBMF7GJLvs,303
2
- fastapi_sqlalchemy_ease/core.py,sha256=nQSzioMp6TiD7yuKD7niImA2BSL2PQLCKnCzk0eFWrA,3920
3
- fastapi_sqlalchemy_ease/exceptions.py,sha256=6YU6mJvOGXC9D0mPH99GjMWpj21NA5jD8II7DWEcHaA,222
4
- fastapi_sqlalchemy_ease-0.1.3.dist-info/licenses/LICENSE,sha256=jVnW2ZK4LFNHmDZE-xj0EyVpbHVMpwO7FcTk_We8qrA,1068
5
- fastapi_sqlalchemy_ease-0.1.3.dist-info/METADATA,sha256=LE0IDLlbyKIsWgRhyw5Jpo8p4HoKOwlif_AVJ8_zPkw,285
6
- fastapi_sqlalchemy_ease-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
7
- fastapi_sqlalchemy_ease-0.1.3.dist-info/top_level.txt,sha256=Y9kRilavMJot8bwOZymZ0cRjiBNIzsVqx9EwvXGiq-8,24
8
- fastapi_sqlalchemy_ease-0.1.3.dist-info/RECORD,,