Coverage for .tox/coverage/lib/python3.13/site-packages/wuttjamaican/db/sess.py: 100%

24 statements  

« prev     ^ index     » next       coverage.py v7.16.1, created at 2026-09-22 12:31 -0500

1# -*- coding: utf-8; -*- 

2################################################################################ 

3# 

4# WuttJamaican -- Base package for Wutta Framework 

5# Copyright © 2023-2025 Lance Edgar 

6# 

7# This file is part of Wutta Framework. 

8# 

9# Wutta Framework is free software: you can redistribute it and/or modify it 

10# under the terms of the GNU General Public License as published by the Free 

11# Software Foundation, either version 3 of the License, or (at your option) any 

12# later version. 

13# 

14# Wutta Framework is distributed in the hope that it will be useful, but 

15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 

17# more details. 

18# 

19# You should have received a copy of the GNU General Public License along with 

20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>. 

21# 

22################################################################################ 

23""" 

24WuttJamaican - database sessions 

25 

26.. class:: Session 

27 

28 SQLAlchemy session class used for all (normal) :term:`app database` 

29 connections. 

30 

31 See the upstream :class:`sqlalchemy:sqlalchemy.orm.Session` docs 

32 for more info. 

33""" 

34 

35from sqlalchemy import orm 

36 

37Session = orm.sessionmaker() # pylint: disable=invalid-name 

38 

39 

40class short_session: # pylint: disable=invalid-name 

41 """ 

42 Context manager for a short-lived database session. 

43 

44 A canonical use case for this is when the config object needs to 

45 grab a single setting value from the DB, but it does not have an 

46 active DB session to do it. This context manager is used to 

47 produce the session, and close it when finished. For example:: 

48 

49 with short_session(config) as s: 

50 result = s.query("select something from somewhere").scalar() 

51 

52 How it goes about producing the session instance will depend on 

53 which of the following 3 params are given (explained below): 

54 

55 * ``config`` 

56 * ``factory`` 

57 * ``session`` 

58 

59 Note that it is also okay if you provide *none* of the above 

60 params, in which case the main :class:`Session` class will be used 

61 as the factory. 

62 

63 :param config: Optional app config object. If a new session must 

64 be created, the config will be consulted to determine the 

65 factory which is used to create the new session. 

66 

67 :param factory: Optional factory to use when making a new session. 

68 If specified, this will override the ``config`` mechanism. 

69 

70 :param session: Optional SQLAlchemy session instance. If a valid 

71 session is provided here, it will be used instead of creating a 

72 new/temporary session. 

73 

74 :param commit: Whether the temporary session should be committed 

75 before it is closed. This flag has no effect if a valid 

76 ``session`` instance is provided, since no temporary session 

77 will be created. 

78 """ 

79 

80 def __init__(self, config=None, factory=None, session=None, commit=False): 

81 self.config = config 

82 self.factory = factory 

83 self.session = session 

84 self.private = not bool(session) 

85 self.commit = commit 

86 

87 def __enter__(self): 

88 if not self.session: 

89 if not self.factory: 

90 if self.config: 

91 app = self.config.get_app() 

92 self.factory = app.make_session 

93 else: 

94 self.factory = Session 

95 self.session = self.factory() 

96 return self.session 

97 

98 def __exit__(self, exc_type, exc_value, traceback): 

99 if self.private: 

100 if self.commit: 

101 self.session.commit() 

102 self.session.close() 

103 self.session = None