encommon 0.11.1__tar.gz → 0.12.0__tar.gz

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.
Files changed (81) hide show
  1. {encommon-0.11.1/encommon.egg-info → encommon-0.12.0}/PKG-INFO +2 -1
  2. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_timers.py +38 -32
  3. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_windows.py +47 -45
  4. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/timers.py +102 -84
  5. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/windows.py +122 -101
  6. encommon-0.12.0/encommon/version.txt +1 -0
  7. {encommon-0.11.1 → encommon-0.12.0/encommon.egg-info}/PKG-INFO +2 -1
  8. {encommon-0.11.1 → encommon-0.12.0}/encommon.egg-info/requires.txt +1 -0
  9. {encommon-0.11.1 → encommon-0.12.0}/reqs-install.txt +1 -0
  10. encommon-0.11.1/encommon/version.txt +0 -1
  11. {encommon-0.11.1 → encommon-0.12.0}/LICENSE +0 -0
  12. {encommon-0.11.1 → encommon-0.12.0}/MANIFEST.in +0 -0
  13. {encommon-0.11.1 → encommon-0.12.0}/README.md +0 -0
  14. {encommon-0.11.1 → encommon-0.12.0}/encommon/__init__.py +0 -0
  15. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/__init__.py +0 -0
  16. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/config.py +0 -0
  17. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/files.py +0 -0
  18. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/logger.py +0 -0
  19. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/params.py +0 -0
  20. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/paths.py +0 -0
  21. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/__init__.py +0 -0
  22. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/test_config.py +0 -0
  23. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/test_files.py +0 -0
  24. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/test_logger.py +0 -0
  25. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/test_paths.py +0 -0
  26. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/test/test_utils.py +0 -0
  27. {encommon-0.11.1 → encommon-0.12.0}/encommon/config/utils.py +0 -0
  28. {encommon-0.11.1 → encommon-0.12.0}/encommon/conftest.py +0 -0
  29. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/__init__.py +0 -0
  30. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/crypts.py +0 -0
  31. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/hashes.py +0 -0
  32. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/params.py +0 -0
  33. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/test/__init__.py +0 -0
  34. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/test/test_crypts.py +0 -0
  35. {encommon-0.11.1 → encommon-0.12.0}/encommon/crypts/test/test_hashes.py +0 -0
  36. {encommon-0.11.1 → encommon-0.12.0}/encommon/py.typed +0 -0
  37. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/__init__.py +0 -0
  38. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/common.py +0 -0
  39. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/duration.py +0 -0
  40. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/params.py +0 -0
  41. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/parse.py +0 -0
  42. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/__init__.py +0 -0
  43. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_duration.py +0 -0
  44. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_params.py +0 -0
  45. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_parse.py +0 -0
  46. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_timer.py +0 -0
  47. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_times.py +0 -0
  48. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_utils.py +0 -0
  49. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/test/test_window.py +0 -0
  50. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/timer.py +0 -0
  51. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/times.py +0 -0
  52. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/utils.py +0 -0
  53. {encommon-0.11.1 → encommon-0.12.0}/encommon/times/window.py +0 -0
  54. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/__init__.py +0 -0
  55. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/dicts.py +0 -0
  56. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/empty.py +0 -0
  57. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/notate.py +0 -0
  58. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/strings.py +0 -0
  59. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/test/__init__.py +0 -0
  60. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/test/test_dicts.py +0 -0
  61. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/test/test_empty.py +0 -0
  62. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/test/test_notate.py +0 -0
  63. {encommon-0.11.1 → encommon-0.12.0}/encommon/types/test/test_strings.py +0 -0
  64. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/__init__.py +0 -0
  65. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/common.py +0 -0
  66. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/files.py +0 -0
  67. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/match.py +0 -0
  68. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/paths.py +0 -0
  69. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/sample.py +0 -0
  70. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/stdout.py +0 -0
  71. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/__init__.py +0 -0
  72. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/test_files.py +0 -0
  73. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/test_match.py +0 -0
  74. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/test_paths.py +0 -0
  75. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/test_sample.py +0 -0
  76. {encommon-0.11.1 → encommon-0.12.0}/encommon/utils/test/test_stdout.py +0 -0
  77. {encommon-0.11.1 → encommon-0.12.0}/encommon.egg-info/SOURCES.txt +0 -0
  78. {encommon-0.11.1 → encommon-0.12.0}/encommon.egg-info/dependency_links.txt +0 -0
  79. {encommon-0.11.1 → encommon-0.12.0}/encommon.egg-info/top_level.txt +0 -0
  80. {encommon-0.11.1 → encommon-0.12.0}/pyproject.toml +0 -0
  81. {encommon-0.11.1 → encommon-0.12.0}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: encommon
3
- Version: 0.11.1
3
+ Version: 0.12.0
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Classifier: Programming Language :: Python :: 3
@@ -15,6 +15,7 @@ Requires-Dist: pydantic
15
15
  Requires-Dist: python-dateutil
16
16
  Requires-Dist: pyyaml
17
17
  Requires-Dist: snaptime
18
+ Requires-Dist: sqlalchemy
18
19
 
19
20
  # Enasis Network Common Library
20
21
 
@@ -17,6 +17,7 @@ from pytest import raises
17
17
  from ..params import TimerParams
18
18
  from ..params import TimersParams
19
19
  from ..timers import Timers
20
+ from ..timers import TimersTable
20
21
  from ..times import Times
21
22
  from ...types import inrepr
22
23
  from ...types import instr
@@ -34,40 +35,45 @@ def timers(
34
35
  :returns: Newly constructed instance of related class.
35
36
  """
36
37
 
38
+
37
39
  source: dict[str, Any] = {
38
40
  'one': {'timer': 1},
39
41
  'two': {'timer': 1}}
40
42
 
43
+
41
44
  params = TimersParams(
42
45
  timers=source)
43
46
 
47
+ store = (
48
+ f'sqlite:///{tmp_path}'
49
+ '/cache.db')
50
+
44
51
  timers = Timers(
45
52
  params,
46
- file=f'{tmp_path}/cache.db')
47
-
48
- sqlite = timers.sqlite
49
-
50
- sqlite.execute(
51
- """
52
- insert into timers
53
- ("group", "unique",
54
- "update")
55
- values (
56
- "default", "two",
57
- "1970-01-01T00:00:00Z")
58
- """) # noqa: LIT003
59
-
60
- sqlite.execute(
61
- """
62
- insert into timers
63
- ("group", "unique",
64
- "update")
65
- values (
66
- "default", "tre",
67
- "1970-01-01T00:00:00Z")
68
- """) # noqa: LIT003
69
-
70
- sqlite.commit()
53
+ store=store)
54
+
55
+ session = timers.store_session
56
+
57
+
58
+ timer = TimersTable(
59
+ group='default',
60
+ unique='two',
61
+ update='1970-01-01T00:00:00Z')
62
+
63
+ session.add(timer)
64
+
65
+ session.commit()
66
+
67
+
68
+ timer = TimersTable(
69
+ group='default',
70
+ unique='tre',
71
+ update='1970-01-01T00:00:00Z')
72
+
73
+ session.add(timer)
74
+
75
+ session.commit()
76
+
71
77
 
72
78
  timers.load_children()
73
79
 
@@ -89,10 +95,10 @@ def test_Timers(
89
95
 
90
96
  assert attrs == [
91
97
  '_Timers__params',
92
- '_Timers__sqlite',
93
- '_Timers__file',
94
- '_Timers__table',
98
+ '_Timers__store',
95
99
  '_Timers__group',
100
+ '_Timers__store_engine',
101
+ '_Timers__store_session',
96
102
  '_Timers__timers']
97
103
 
98
104
 
@@ -109,13 +115,13 @@ def test_Timers(
109
115
 
110
116
  assert timers.params is not None
111
117
 
112
- assert timers.sqlite is not None
118
+ assert timers.store[:6] == 'sqlite'
113
119
 
114
- assert timers.file[-8:] == 'cache.db'
120
+ assert timers.group == 'default'
115
121
 
116
- assert timers.table == 'timers'
122
+ assert timers.store_engine is not None
117
123
 
118
- assert timers.group == 'default'
124
+ assert timers.store_session is not None
119
125
 
120
126
  assert len(timers.children) == 2
121
127
 
@@ -17,6 +17,7 @@ from pytest import raises
17
17
  from ..params import WindowParams
18
18
  from ..params import WindowsParams
19
19
  from ..windows import Windows
20
+ from ..windows import WindowsTable
20
21
  from ...types import inrepr
21
22
  from ...types import instr
22
23
 
@@ -33,6 +34,7 @@ def windows(
33
34
  :returns: Newly constructed instance of related class.
34
35
  """
35
36
 
37
+
36
38
  source: dict[str, Any] = {
37
39
  'one': WindowParams(
38
40
  window='* * * * *',
@@ -45,46 +47,46 @@ def windows(
45
47
  stop=620,
46
48
  delay=10)}
47
49
 
50
+
48
51
  params = WindowsParams(
49
52
  windows=source)
50
53
 
54
+ store = (
55
+ f'sqlite:///{tmp_path}'
56
+ '/cache.db')
57
+
51
58
  windows = Windows(
52
59
  params,
53
60
  start=310,
54
61
  stop=610,
55
- file=f'{tmp_path}/cache.db')
56
-
57
- sqlite = windows.sqlite
58
-
59
- sqlite.execute(
60
- """
61
- insert into windows
62
- ("group", "unique",
63
- "last", "next",
64
- "update")
65
- values (
66
- "default", "two",
67
- "1970-01-01T00:06:00Z",
68
- "1970-01-01T00:07:00Z",
69
- "1970-01-01T01:00:00Z")
70
- """) # noqa: LIT003
71
-
72
- sqlite.commit()
73
-
74
- sqlite.execute(
75
- """
76
- insert into windows
77
- ("group", "unique",
78
- "last", "next",
79
- "update")
80
- values (
81
- "default", "tre",
82
- "1970-01-01T00:06:00Z",
83
- "1970-01-01T00:07:00Z",
84
- "1970-01-01T01:00:00Z")
85
- """) # noqa: LIT003
86
-
87
- sqlite.commit()
62
+ store=store)
63
+
64
+ session = windows.store_session
65
+
66
+
67
+ window = WindowsTable(
68
+ group='default',
69
+ unique='two',
70
+ last='1970-01-01T00:06:00Z',
71
+ next='1970-01-01T00:07:00Z',
72
+ update='1970-01-01T01:00:00Z')
73
+
74
+ session.add(window)
75
+
76
+ session.commit()
77
+
78
+
79
+ window = WindowsTable(
80
+ group='default',
81
+ unique='tre',
82
+ last='1970-01-01T00:06:00Z',
83
+ next='1970-01-01T00:07:00Z',
84
+ update='1970-01-01T01:00:00Z')
85
+
86
+ session.add(window)
87
+
88
+ session.commit()
89
+
88
90
 
89
91
  windows.load_children()
90
92
 
@@ -106,12 +108,12 @@ def test_Windows(
106
108
 
107
109
  assert attrs == [
108
110
  '_Windows__params',
111
+ '_Windows__store',
112
+ '_Windows__group',
113
+ '_Windows__store_engine',
114
+ '_Windows__store_session',
109
115
  '_Windows__start',
110
116
  '_Windows__stop',
111
- '_Windows__sqlite',
112
- '_Windows__file',
113
- '_Windows__table',
114
- '_Windows__group',
115
117
  '_Windows__windows']
116
118
 
117
119
 
@@ -128,19 +130,19 @@ def test_Windows(
128
130
 
129
131
  assert windows.params is not None
130
132
 
131
- assert windows.start == (
132
- '1970-01-01T00:05:10Z')
133
+ assert windows.store[:6] == 'sqlite'
133
134
 
134
- assert windows.stop == (
135
- '1970-01-01T00:10:10Z')
135
+ assert windows.group == 'default'
136
136
 
137
- assert windows.sqlite is not None
137
+ assert windows.store_engine is not None
138
138
 
139
- assert windows.file[-8:] == 'cache.db'
139
+ assert windows.store_session is not None
140
140
 
141
- assert windows.table == 'windows'
141
+ assert windows.start == (
142
+ '1970-01-01T00:05:10Z')
142
143
 
143
- assert windows.group == 'default'
144
+ assert windows.stop == (
145
+ '1970-01-01T00:10:10Z')
144
146
 
145
147
  assert len(windows.children) == 2
146
148
 
@@ -8,35 +8,61 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from copy import deepcopy
11
- from sqlite3 import Connection
12
- from sqlite3 import connect as SQLite
13
11
  from typing import Optional
14
12
  from typing import TYPE_CHECKING
15
13
 
14
+ from sqlalchemy import Column
15
+ from sqlalchemy import String
16
+ from sqlalchemy import create_engine
17
+ from sqlalchemy.engine import Engine
18
+ from sqlalchemy.orm import DeclarativeBase
19
+ from sqlalchemy.orm import Session
20
+ from sqlalchemy.orm import sessionmaker
21
+
16
22
  from .common import PARSABLE
23
+ from .params import TimersParams
17
24
  from .timer import Timer
18
25
  from .times import Times
19
26
 
20
27
  if TYPE_CHECKING:
21
28
  from .params import TimerParams
22
- from .params import TimersParams
23
29
 
24
30
 
25
31
 
26
- CACHE_TABLE = (
32
+ TIMERS = dict[str, Timer]
33
+
34
+
35
+
36
+ class SQLBase(DeclarativeBase):
37
+ """
38
+ Some additional class that SQLAlchemy requires to work.
27
39
  """
28
- create table if not exists
29
- {0} (
30
- "group" text not null,
31
- "unique" text not null,
32
- "update" text not null,
33
- primary key (
34
- "group", "unique"));
35
- """) # noqa: LIT003
36
40
 
37
41
 
38
42
 
39
- TIMERS = dict[str, Timer]
43
+ class TimersTable(SQLBase):
44
+ """
45
+ Schematic for the database operations using SQLAlchemy.
46
+
47
+ .. note::
48
+ Fields are not completely documented for this model.
49
+ """
50
+
51
+ __tablename__ = 'timers'
52
+
53
+ group = Column(
54
+ String,
55
+ primary_key=True,
56
+ nullable=False)
57
+
58
+ unique = Column(
59
+ String,
60
+ primary_key=True,
61
+ nullable=False)
62
+
63
+ update = Column(
64
+ String,
65
+ nullable=False)
40
66
 
41
67
 
42
68
 
@@ -65,19 +91,20 @@ class Timers:
65
91
  True
66
92
 
67
93
  :param params: Parameters for instantiating the instance.
68
- :param file: Optional path to file for SQLite database,
69
- allowing for state retention between the executions.
70
- :param table: Optional override for default table name.
94
+ :param store: Optional database path for keeping state.
71
95
  :param group: Optional override for default group name.
72
96
  """
73
97
 
74
98
  __params: 'TimersParams'
75
99
 
76
- __sqlite: Connection
77
- __file: str
78
- __table: str
100
+ __store: str
79
101
  __group: str
80
102
 
103
+ __store_engine: Engine
104
+ __store_session: (
105
+ # pylint: disable=unsubscriptable-object
106
+ sessionmaker[Session])
107
+
81
108
  __timers: TIMERS
82
109
 
83
110
 
@@ -85,41 +112,52 @@ class Timers:
85
112
  self,
86
113
  params: Optional['TimersParams'] = None,
87
114
  *,
88
- file: str = ':memory:',
89
- table: str = 'timers',
115
+ store: str = 'sqlite:///:memory:',
90
116
  group: str = 'default',
91
117
  ) -> None:
92
118
  """
93
119
  Initialize instance for class using provided parameters.
94
120
  """
95
121
 
96
- from .params import TimersParams
122
+ params = deepcopy(params)
97
123
 
98
124
  if params is None:
99
125
  params = TimersParams()
100
126
 
101
- self.__params = deepcopy(params)
102
-
127
+ self.__params = params
103
128
 
104
- sqlite = SQLite(file)
105
129
 
106
- sqlite.execute(
107
- CACHE_TABLE
108
- .format(table))
109
-
110
- sqlite.commit()
111
-
112
- self.__sqlite = sqlite
113
- self.__file = file
114
- self.__table = table
130
+ self.__store = store
115
131
  self.__group = group
116
132
 
133
+ self.__make_engine()
134
+
117
135
 
118
136
  self.__timers = {}
119
137
 
120
138
  self.load_children()
121
139
 
122
140
 
141
+ def __make_engine(
142
+ self,
143
+ ) -> None:
144
+ """
145
+ Construct instances using the configuration parameters.
146
+ """
147
+
148
+ store = self.__store
149
+
150
+ engine = create_engine(store)
151
+
152
+ (SQLBase.metadata
153
+ .create_all(engine))
154
+
155
+ session = sessionmaker(engine)
156
+
157
+ self.__store_engine = engine
158
+ self.__store_session = session
159
+
160
+
123
161
  @property
124
162
  def params(
125
163
  self,
@@ -134,20 +172,20 @@ class Timers:
134
172
 
135
173
 
136
174
  @property
137
- def sqlite(
175
+ def store(
138
176
  self,
139
- ) -> Connection:
177
+ ) -> str:
140
178
  """
141
179
  Return the value for the attribute from class instance.
142
180
 
143
181
  :returns: Value for the attribute from class instance.
144
182
  """
145
183
 
146
- return self.__sqlite
184
+ return self.__store
147
185
 
148
186
 
149
187
  @property
150
- def file(
188
+ def group(
151
189
  self,
152
190
  ) -> str:
153
191
  """
@@ -156,33 +194,33 @@ class Timers:
156
194
  :returns: Value for the attribute from class instance.
157
195
  """
158
196
 
159
- return self.__file
197
+ return self.__group
160
198
 
161
199
 
162
200
  @property
163
- def table(
201
+ def store_engine(
164
202
  self,
165
- ) -> str:
203
+ ) -> Engine:
166
204
  """
167
205
  Return the value for the attribute from class instance.
168
206
 
169
207
  :returns: Value for the attribute from class instance.
170
208
  """
171
209
 
172
- return self.__table
210
+ return self.__store_engine
173
211
 
174
212
 
175
213
  @property
176
- def group(
214
+ def store_session(
177
215
  self,
178
- ) -> str:
216
+ ) -> Session:
179
217
  """
180
218
  Return the value for the attribute from class instance.
181
219
 
182
220
  :returns: Value for the attribute from class instance.
183
221
  """
184
222
 
185
- return self.__group
223
+ return self.__store_session()
186
224
 
187
225
 
188
226
  @property
@@ -208,27 +246,24 @@ class Timers:
208
246
  params = self.__params
209
247
  timers = self.__timers
210
248
 
211
- sqlite = self.__sqlite
212
- table = self.__table
213
249
  group = self.__group
214
250
 
251
+ session = self.store_session
252
+ table = TimersTable
215
253
 
216
- config = params.timers
217
254
 
255
+ config = params.timers
218
256
 
219
- cursor = sqlite.execute(
220
- f"""
221
- select * from {table}
222
- where "group"="{group}"
223
- order by "unique" asc
224
- """) # noqa: LIT003
225
257
 
226
- records = cursor.fetchall()
258
+ records = (
259
+ session.query(table)
260
+ .filter(table.group == group)
261
+ .order_by(table.unique))
227
262
 
228
- for record in records:
263
+ for record in records.all():
229
264
 
230
- unique = record[1]
231
- update = record[2]
265
+ unique = str(record.unique)
266
+ update = str(record.update)
232
267
 
233
268
  if unique not in config:
234
269
  continue
@@ -246,8 +281,7 @@ class Timers:
246
281
 
247
282
  timer = timers[key]
248
283
 
249
- timer.update(
250
- value.start)
284
+ timer.update(value.start)
251
285
 
252
286
  continue
253
287
 
@@ -270,42 +304,26 @@ class Timers:
270
304
 
271
305
  timers = self.__timers
272
306
 
273
- sqlite = self.__sqlite
274
- table = self.__table
275
307
  group = self.__group
276
308
 
309
+ session = self.store_session
277
310
 
278
- insert = tuple[
279
- str, # group
280
- str, # unique
281
- str] # update
282
-
283
- inserts: list[insert] = []
284
311
 
285
312
  items = timers.items()
286
313
 
287
314
  for unique, timer in items:
288
315
 
289
- append = (
290
- group, unique,
291
- Times('now').subsec)
292
-
293
- inserts.append(append)
316
+ update = Times('now')
294
317
 
318
+ append = TimersTable(
319
+ group=group,
320
+ unique=unique,
321
+ update=update.subsec)
295
322
 
296
- statement = (
297
- f"""
298
- replace into {table}
299
- ("group", "unique",
300
- "update")
301
- values (?, ?, ?)
302
- """) # noqa: LIT003
323
+ session.merge(append)
303
324
 
304
- sqlite.executemany(
305
- statement,
306
- tuple(sorted(inserts)))
307
325
 
308
- sqlite.commit()
326
+ session.commit()
309
327
 
310
328
 
311
329
  def ready(
@@ -8,37 +8,69 @@ is permitted, for more information consult the project license file.
8
8
 
9
9
 
10
10
  from copy import deepcopy
11
- from sqlite3 import Connection
12
- from sqlite3 import connect as SQLite
13
11
  from typing import Optional
14
12
  from typing import TYPE_CHECKING
15
13
 
14
+ from sqlalchemy import Column
15
+ from sqlalchemy import String
16
+ from sqlalchemy import create_engine
17
+ from sqlalchemy.engine import Engine
18
+ from sqlalchemy.orm import DeclarativeBase
19
+ from sqlalchemy.orm import Session
20
+ from sqlalchemy.orm import sessionmaker
21
+
16
22
  from .common import PARSABLE
23
+ from .params import WindowsParams
17
24
  from .times import Times
18
25
  from .window import Window
19
26
 
20
27
  if TYPE_CHECKING:
21
28
  from .params import WindowParams
22
- from .params import WindowsParams
23
29
 
24
30
 
25
31
 
26
- CACHE_TABLE = (
32
+ WINDOWS = dict[str, Window]
33
+
34
+
35
+
36
+ class SQLBase(DeclarativeBase):
37
+ """
38
+ Some additional class that SQLAlchemy requires to work.
27
39
  """
28
- create table if not exists
29
- {0} (
30
- "group" text not null,
31
- "unique" text not null,
32
- "last" text not null,
33
- "next" text not null,
34
- "update" text not null,
35
- primary key (
36
- "group", "unique"));
37
- """) # noqa: LIT003
38
40
 
39
41
 
40
42
 
41
- WINDOWS = dict[str, Window]
43
+ class WindowsTable(SQLBase):
44
+ """
45
+ Schematic for the database operations using SQLAlchemy.
46
+
47
+ .. note::
48
+ Fields are not completely documented for this model.
49
+ """
50
+
51
+ __tablename__ = 'windows'
52
+
53
+ group = Column(
54
+ String,
55
+ primary_key=True,
56
+ nullable=False)
57
+
58
+ unique = Column(
59
+ String,
60
+ primary_key=True,
61
+ nullable=False)
62
+
63
+ last = Column(
64
+ String,
65
+ nullable=False)
66
+
67
+ next = Column(
68
+ String,
69
+ nullable=False)
70
+
71
+ update = Column(
72
+ String,
73
+ nullable=False)
42
74
 
43
75
 
44
76
 
@@ -65,45 +97,51 @@ class Windows:
65
97
  :param params: Parameters for instantiating the instance.
66
98
  :param start: Determine the start for scheduling window.
67
99
  :param stop: Determine the ending for scheduling window.
68
- :param file: Optional path to file for SQLite database,
69
- allowing for state retention between the executions.
70
- :param table: Optional override for default table name.
100
+ :param store: Optional database path for keeping state.
71
101
  :param group: Optional override for default group name.
72
102
  """
73
103
 
74
104
  __params: 'WindowsParams'
75
105
 
106
+ __store: str
107
+ __group: str
108
+
109
+ __store_engine: Engine
110
+ __store_session: (
111
+ # pylint: disable=unsubscriptable-object
112
+ sessionmaker[Session])
113
+
76
114
  __start: Times
77
115
  __stop: Times
78
116
 
79
- __sqlite: Connection
80
- __file: str
81
- __table: str
82
- __group: str
83
-
84
117
  __windows: WINDOWS
85
118
 
86
119
 
87
- def __init__( # noqa: CFQ002
120
+ def __init__(
88
121
  self,
89
122
  params: Optional['WindowsParams'] = None,
90
123
  start: PARSABLE = 'now',
91
124
  stop: PARSABLE = '3000-01-01',
92
125
  *,
93
- file: str = ':memory:',
94
- table: str = 'windows',
126
+ store: str = 'sqlite:///:memory:',
95
127
  group: str = 'default',
96
128
  ) -> None:
97
129
  """
98
130
  Initialize instance for class using provided parameters.
99
131
  """
100
132
 
101
- from .params import WindowsParams
133
+ params = deepcopy(params)
102
134
 
103
135
  if params is None:
104
136
  params = WindowsParams()
105
137
 
106
- self.__params = deepcopy(params)
138
+ self.__params = params
139
+
140
+
141
+ self.__store = store
142
+ self.__group = group
143
+
144
+ self.__make_engine()
107
145
 
108
146
 
109
147
  start = Times(start)
@@ -115,23 +153,29 @@ class Windows:
115
153
  self.__stop = stop
116
154
 
117
155
 
118
- sqlite = SQLite(file)
156
+ self.__windows = {}
119
157
 
120
- sqlite.execute(
121
- CACHE_TABLE
122
- .format(table))
158
+ self.load_children()
123
159
 
124
- sqlite.commit()
125
160
 
126
- self.__sqlite = sqlite
127
- self.__file = file
128
- self.__table = table
129
- self.__group = group
161
+ def __make_engine(
162
+ self,
163
+ ) -> None:
164
+ """
165
+ Construct instances using the configuration parameters.
166
+ """
130
167
 
168
+ store = self.__store
131
169
 
132
- self.__windows = {}
170
+ engine = create_engine(store)
133
171
 
134
- self.load_children()
172
+ (SQLBase.metadata
173
+ .create_all(engine))
174
+
175
+ session = sessionmaker(engine)
176
+
177
+ self.__store_engine = engine
178
+ self.__store_session = session
135
179
 
136
180
 
137
181
  @property
@@ -148,81 +192,81 @@ class Windows:
148
192
 
149
193
 
150
194
  @property
151
- def start(
195
+ def store(
152
196
  self,
153
- ) -> Times:
197
+ ) -> str:
154
198
  """
155
199
  Return the value for the attribute from class instance.
156
200
 
157
201
  :returns: Value for the attribute from class instance.
158
202
  """
159
203
 
160
- return Times(self.__start)
204
+ return self.__store
161
205
 
162
206
 
163
207
  @property
164
- def stop(
208
+ def group(
165
209
  self,
166
- ) -> Times:
210
+ ) -> str:
167
211
  """
168
212
  Return the value for the attribute from class instance.
169
213
 
170
214
  :returns: Value for the attribute from class instance.
171
215
  """
172
216
 
173
- return Times(self.__stop)
217
+ return self.__group
174
218
 
175
219
 
176
220
  @property
177
- def sqlite(
221
+ def store_engine(
178
222
  self,
179
- ) -> Connection:
223
+ ) -> Engine:
180
224
  """
181
225
  Return the value for the attribute from class instance.
182
226
 
183
227
  :returns: Value for the attribute from class instance.
184
228
  """
185
229
 
186
- return self.__sqlite
230
+ return self.__store_engine
187
231
 
188
232
 
189
233
  @property
190
- def file(
234
+ def store_session(
191
235
  self,
192
- ) -> str:
236
+ ) -> Session:
193
237
  """
194
238
  Return the value for the attribute from class instance.
195
239
 
196
240
  :returns: Value for the attribute from class instance.
197
241
  """
198
242
 
199
- return self.__file
243
+ return self.__store_session()
200
244
 
201
245
 
202
246
  @property
203
- def table(
247
+ def start(
204
248
  self,
205
- ) -> str:
249
+ ) -> Times:
206
250
  """
207
251
  Return the value for the attribute from class instance.
208
252
 
209
253
  :returns: Value for the attribute from class instance.
210
254
  """
211
255
 
212
- return self.__table
256
+ return Times(self.__start)
213
257
 
214
258
 
215
259
  @property
216
- def group(
260
+ def stop(
217
261
  self,
218
- ) -> str:
262
+ ) -> Times:
219
263
  """
220
264
  Return the value for the attribute from class instance.
221
265
 
222
266
  :returns: Value for the attribute from class instance.
223
267
  """
224
268
 
225
- return self.__group
269
+ return Times(self.__stop)
226
270
 
227
271
 
228
272
  @property
@@ -251,27 +295,24 @@ class Windows:
251
295
  start = self.__start
252
296
  stop = self.__stop
253
297
 
254
- sqlite = self.__sqlite
255
- table = self.__table
256
298
  group = self.__group
257
299
 
300
+ session = self.store_session
301
+ table = WindowsTable
258
302
 
259
- config = params.windows
260
303
 
304
+ config = params.windows
261
305
 
262
- cursor = sqlite.execute(
263
- f"""
264
- select * from {table}
265
- where "group"="{group}"
266
- order by "unique" asc
267
- """) # noqa: LIT003
268
306
 
269
- records = cursor.fetchall()
307
+ records = (
308
+ session.query(table)
309
+ .filter(table.group == group)
310
+ .order_by(table.unique))
270
311
 
271
- for record in records:
312
+ for record in records.all():
272
313
 
273
- unique = record[1]
274
- next = record[3]
314
+ unique = str(record.unique)
315
+ next = str(record.next)
275
316
 
276
317
  if unique not in config:
277
318
  continue
@@ -290,8 +331,7 @@ class Windows:
290
331
 
291
332
  window = windows[key]
292
333
 
293
- window.update(
294
- value.start)
334
+ window.update(value.start)
295
335
 
296
336
  continue
297
337
 
@@ -332,47 +372,28 @@ class Windows:
332
372
 
333
373
  windows = self.__windows
334
374
 
335
- sqlite = self.__sqlite
336
- table = self.__table
337
375
  group = self.__group
338
376
 
377
+ session = self.store_session
339
378
 
340
- insert = tuple[
341
- str, # group
342
- str, # unique
343
- str, # last
344
- str, # next
345
- str] # update
346
-
347
- inserts: list[insert] = []
348
379
 
349
380
  items = windows.items()
350
381
 
351
382
  for unique, window in items:
352
383
 
353
- append = (
354
- group, unique,
355
- window.last.subsec,
356
- window.next.subsec,
357
- Times('now').subsec)
358
-
359
- inserts.append(append)
384
+ update = Times('now')
360
385
 
386
+ append = WindowsTable(
387
+ group=group,
388
+ unique=unique,
389
+ last=window.last.subsec,
390
+ next=window.next.subsec,
391
+ update=update.subsec)
361
392
 
362
- statement = (
363
- f"""
364
- replace into {table}
365
- ("group", "unique",
366
- "next", "last",
367
- "update")
368
- values (?, ?, ?, ?, ?)
369
- """) # noqa: LIT003
393
+ session.merge(append)
370
394
 
371
- sqlite.executemany(
372
- statement,
373
- tuple(sorted(inserts)))
374
395
 
375
- sqlite.commit()
396
+ session.commit()
376
397
 
377
398
 
378
399
  def ready(
@@ -0,0 +1 @@
1
+ 0.12.0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: encommon
3
- Version: 0.11.1
3
+ Version: 0.12.0
4
4
  Summary: Enasis Network Common Library
5
5
  License: MIT
6
6
  Classifier: Programming Language :: Python :: 3
@@ -15,6 +15,7 @@ Requires-Dist: pydantic
15
15
  Requires-Dist: python-dateutil
16
16
  Requires-Dist: pyyaml
17
17
  Requires-Dist: snaptime
18
+ Requires-Dist: sqlalchemy
18
19
 
19
20
  # Enasis Network Common Library
20
21
 
@@ -4,3 +4,4 @@ pydantic
4
4
  python-dateutil
5
5
  pyyaml
6
6
  snaptime
7
+ sqlalchemy
@@ -4,3 +4,4 @@ pydantic
4
4
  python-dateutil
5
5
  pyyaml
6
6
  snaptime
7
+ sqlalchemy
@@ -1 +0,0 @@
1
- 0.11.1
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes