q2rad 0.1.202__py3-none-any.whl → 0.1.203__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.

Potentially problematic release.


This version of q2rad might be problematic. Click here for more details.

q2rad/q2appmanager.py CHANGED
@@ -20,7 +20,7 @@ from q2gui.q2dialogs import q2AskYN, q2Mess, Q2WaitShow, q2ask, q2working
20
20
 
21
21
  from q2rad import Q2Form
22
22
  from q2terminal.q2terminal import Q2Terminal
23
- from q2rad.q2raddb import today, insert, update, get
23
+ from q2rad.q2raddb import insert, update, get
24
24
  from datetime import datetime
25
25
 
26
26
  import json
@@ -108,7 +108,7 @@ class AppManager(Q2Form):
108
108
  self.add_control(
109
109
  "drl",
110
110
  "Database type",
111
- data=app_data["driver_logic"],
111
+ data=app_data["driver_logic"].lower(),
112
112
  disabled=1,
113
113
  datalen=len(app_data["driver_logic"].strip()) + 5,
114
114
  )
@@ -186,7 +186,7 @@ class AppManager(Q2Form):
186
186
  self.add_control(
187
187
  "drd",
188
188
  "Database type",
189
- data=app_data["driver_data"],
189
+ data=app_data["driver_data"].lower(),
190
190
  disabled=1,
191
191
  datalen=len(app_data["driver_data"].strip()) + 5,
192
192
  )
q2rad/q2appselector.py CHANGED
@@ -15,8 +15,8 @@
15
15
 
16
16
  from q2gui import q2app
17
17
  from q2gui.q2form import NEW, COPY
18
- from q2gui.q2model import Q2CursorModel
19
- from q2gui.q2dialogs import q2Mess, q2Wait, q2mess, q2working
18
+ from q2gui.q2dialogs import q2Mess
19
+ from q2gui.q2utils import Q2Crypto
20
20
 
21
21
  from q2db.schema import Q2DbSchema
22
22
  from q2db.db import Q2Db
@@ -33,7 +33,7 @@ from q2rad.q2appmanager import AppManager
33
33
  from q2rad.q2raddb import open_url
34
34
 
35
35
 
36
- SQL_ENGINES = ["MySQl", "Sqlite", "Postgresql"]
36
+ SQL_ENGINES = ["MySQL", "SQLite", "PostgreSQL"]
37
37
 
38
38
  _ = gettext.gettext
39
39
 
@@ -81,11 +81,6 @@ class Q2AppSelect(Q2Form):
81
81
  self.add_control("/")
82
82
  if self.add_control("/f", _("Data storage")):
83
83
 
84
- def driverDataValid(self=self):
85
- self.w.host_data.set_enabled(self.s.driver_data != "Sqlite")
86
- self.w.port_data.set_enabled(self.s.driver_data != "Sqlite")
87
- self.w.select_data_storage_file.set_enabled(self.s.driver_data == "Sqlite")
88
-
89
84
  self.add_control(
90
85
  "driver_data",
91
86
  label=_("Storage type"),
@@ -94,7 +89,7 @@ class Q2AppSelect(Q2Form):
94
89
  datatype="char",
95
90
  datalen=30,
96
91
  pic=";".join(SQL_ENGINES),
97
- valid=driverDataValid,
92
+ valid=self.driver_data_valid,
98
93
  )
99
94
  if self.add_control("/h"):
100
95
  self.add_control(
@@ -109,7 +104,6 @@ class Q2AppSelect(Q2Form):
109
104
  _("?"),
110
105
  mess=_("Open Data Storage sqlite database file"),
111
106
  control="button",
112
- datalen=3,
113
107
  valid=self.openSqliteDataFile,
114
108
  )
115
109
  self.add_control("/")
@@ -130,11 +124,6 @@ class Q2AppSelect(Q2Form):
130
124
 
131
125
  if self.add_control("/f", _("Logic storage")):
132
126
 
133
- def driverLogicValid(form=self):
134
- form.w.host_logic.set_enabled(form.s.driver_logic != "Sqlite")
135
- form.w.port_logic.set_enabled(form.s.driver_logic != "Sqlite")
136
- form.w.select_app_storage_file.set_enabled(form.s.driver_logic == "Sqlite")
137
-
138
127
  self.add_control(
139
128
  "driver_logic",
140
129
  label=_("Storage type"),
@@ -143,7 +132,7 @@ class Q2AppSelect(Q2Form):
143
132
  datatype="char",
144
133
  datalen=30,
145
134
  pic=";".join(SQL_ENGINES),
146
- valid=driverLogicValid,
135
+ valid=self.driver_logic_valid,
147
136
  )
148
137
  if self.add_control("/h"):
149
138
  self.add_control(
@@ -158,7 +147,6 @@ class Q2AppSelect(Q2Form):
158
147
  _("?"),
159
148
  mess=_("Open App Storage sqlite database file"),
160
149
  control="button",
161
- datalen=3,
162
150
  valid=self.openSqliteDataFile,
163
151
  )
164
152
  self.add_control("/")
@@ -174,6 +162,19 @@ class Q2AppSelect(Q2Form):
174
162
  mess=_("Allow to change App"),
175
163
  )
176
164
  self.add_control("/")
165
+ self.add_control("/")
166
+
167
+ if self.add_control("/h", "Database Credentials"):
168
+ self.add_control("epwd", "Credentials settings", control="button", valid=self.show_password_form)
169
+ self.add_control(
170
+ "credhash",
171
+ "Credhash",
172
+ datatype="char",
173
+ datalen=256,
174
+ noform=1,
175
+ nogrid=1,
176
+ )
177
+ self.add_control("/")
177
178
 
178
179
  self.add_action(
179
180
  _("Select"),
@@ -202,6 +203,147 @@ class Q2AppSelect(Q2Form):
202
203
 
203
204
  self.actions.add_action("/crud")
204
205
 
206
+ @staticmethod
207
+ def decrypt_creds(pin, credhash):
208
+ creds = Q2Crypto(pin).decrypt(credhash)
209
+ if creds is not None:
210
+ username = creds.split(":")[0]
211
+ password = creds.split(":")[1]
212
+ return username, password
213
+ else:
214
+ return None
215
+
216
+ def show_password_form(self):
217
+ username = ""
218
+ password = ""
219
+ if self.crud_mode == "EDIT" and self.s.credhash:
220
+ pin = self.get_pin(self.r.name)
221
+ if pin is None:
222
+ return
223
+ if Q2Crypto(pin).check_pin(self.s.credhash) is None:
224
+ q2Mess("Wrong PIN")
225
+ return
226
+ creds = self.decrypt_creds(pin, self.s.credhash)
227
+ if creds is not None:
228
+ username, password = creds
229
+ else:
230
+ pin = ""
231
+
232
+ pform = Q2Form("Database credentials")
233
+ pform.add_control("/f", "Username")
234
+ pform.add_control(
235
+ "user1",
236
+ "Enter username",
237
+ datatype="char",
238
+ datalen=100,
239
+ pic="*",
240
+ data=username,
241
+ )
242
+ pform.add_control(
243
+ "user2",
244
+ "Repeat username",
245
+ datatype="char",
246
+ datalen=100,
247
+ pic="*",
248
+ data=username,
249
+ )
250
+ pform.add_control("/")
251
+
252
+ pform.add_control("/")
253
+ pform.add_control("/f", "Password")
254
+ pform.add_control(
255
+ "pass1",
256
+ "Enter password",
257
+ datatype="char",
258
+ datalen=100,
259
+ pic="*",
260
+ data=password,
261
+ )
262
+ pform.add_control(
263
+ "pass2",
264
+ "Repeat password",
265
+ datatype="char",
266
+ datalen=100,
267
+ pic="*",
268
+ data=password,
269
+ )
270
+ pform.add_control("/")
271
+ pform.add_control("/f", "Protect credentials with PIN")
272
+ pform.add_control("pin1", "Enter PIN", datatype="char", datalen=10, pic="*", data=pin)
273
+ pform.add_control("pin2", "Repeat PIN", datatype="char", datalen=10, pic="*", data=pin)
274
+ pform.add_control("/")
275
+
276
+ def after_form_show():
277
+ pass
278
+
279
+ pform.after_form_show = after_form_show
280
+
281
+ def valid():
282
+ if (pform.s.user1 or pform.s.user2) and pform.s.user1 != pform.s.user2:
283
+ q2Mess("Username mismatch")
284
+ return False
285
+ if (pform.s.pass1 or pform.s.pass2) and pform.s.pass1 != pform.s.pass2:
286
+ q2Mess("Password mismatch")
287
+ return False
288
+ if (pform.s.pin1 or pform.s.pin2) and pform.s.pin1 != pform.s.pin2:
289
+ q2Mess("PIN mismatch")
290
+ return False
291
+ return True
292
+
293
+ pform.valid = valid
294
+ pform.ok_button = 1
295
+ pform.cancel_button = 1
296
+ pform.run()
297
+
298
+ if pform.ok_pressed:
299
+ if pform.s.user1 == "" and pform.s.pass1 == "":
300
+ self.s.credhash = ""
301
+ else:
302
+ self.s.credhash = Q2Crypto(pform.s.pin1).encrypt(pform.s.user1 + ":" + pform.s.pass1)
303
+
304
+ def get_pin(self, app_name=""):
305
+ pinform = Q2Form("Enter PIN")
306
+ pinform.add_control("/")
307
+ pinform.add_control("/h")
308
+ pinform.add_control("/s")
309
+ pinform.add_control("", "Application:", control="label")
310
+ pinform.add_control("appname", app_name, control="label", style="color:green;font-weight:bold;background:white")
311
+ pinform.add_control("/s")
312
+ pinform.add_control("/")
313
+ pinform.add_control("/f")
314
+ pinform.add_control("pin", "PIN", pic="*")
315
+ pinform.ok_button = 1
316
+ pinform.cancel_button = 1
317
+
318
+ # def before_form_show():
319
+ # pinform.w.appname.set_style_sheet("color:green;font-weight:bold")
320
+
321
+ # pinform.before_form_show = before_form_show
322
+ pinform.run()
323
+ if pinform.ok_pressed:
324
+ return pinform.s.pin
325
+ else:
326
+ return None
327
+
328
+ def driver_logic_valid(self):
329
+ is_sqlite = self.s.driver_logic.lower() == "sqlite"
330
+ self.w.host_logic.set_enabled(not is_sqlite)
331
+ self.w.port_logic.set_enabled(not is_sqlite)
332
+ self.w.select_app_storage_file.set_enabled(is_sqlite)
333
+ self.credentials_fields_enable()
334
+
335
+ def driver_data_valid(self):
336
+ is_sqlite = self.s.driver_data.lower() == "sqlite"
337
+ self.w.host_data.set_enabled(not is_sqlite)
338
+ self.w.port_data.set_enabled(not is_sqlite)
339
+ self.w.select_data_storage_file.set_enabled(is_sqlite)
340
+ self.credentials_fields_enable()
341
+
342
+ def credentials_fields_enable(self):
343
+ creds_required = self.s.driver_data.lower() != "sqlite" or self.s.driver_logic.lower() != "sqlite"
344
+ # self.w.credhash.set_enabled(creds_required)
345
+ self.w.epwd.set_enabled(creds_required)
346
+
205
347
  def set_autoload(self):
206
348
  clean_this = self.r.autoselect
207
349
  self.db.cursor("update applications set autoselect='' ")
@@ -223,9 +365,6 @@ class Q2AppSelect(Q2Form):
223
365
  self.s.database_data = fname
224
366
 
225
367
  def before_grid_show(self):
226
- self.q2_app.sleep(0.2)
227
- if self.q2_app.keyboard_modifiers() != "":
228
- return
229
368
  if self.db.table("applications").row_count() <= 0:
230
369
  if not os.path.isdir("databases"):
231
370
  os.mkdir("databases")
@@ -234,15 +373,22 @@ class Q2AppSelect(Q2Form):
234
373
  {
235
374
  "ordnum": 1,
236
375
  "name": "My first app",
237
- "driver_data": "Sqlite",
376
+ "driver_data": "SQLite",
238
377
  "database_data": "databases/my_first_app_data_storage.sqlite",
239
- "driver_logic": "Sqlite",
378
+ "driver_logic": "SQLite",
240
379
  "database_logic": "databases/my_first_app_logic_storage.sqlite",
241
380
  "dev_mode": "",
242
381
  },
243
382
  self.db,
244
383
  )
245
384
  self.refresh()
385
+ elif (
386
+ q2cursor("select * from applications where autoselect<>''", self.db).row_count() == 1
387
+ ): # seek autoload
388
+ for row in range(self.model.row_count()):
389
+ if self.model.get_record(row).get("autoselect"):
390
+ self.set_grid_index(row)
391
+ break
246
392
 
247
393
  def before_crud_save(self):
248
394
  if self.s.name == "":
@@ -258,13 +404,13 @@ class Q2AppSelect(Q2Form):
258
404
  self.w.database_logic.set_focus()
259
405
  return False
260
406
 
261
- if self.s.driver_logic == "Sqlite":
407
+ if self.s.driver_logic.lower() == "sqlite":
262
408
  self.s.host_logic = ""
263
409
  self.s.port_logic = ""
264
410
  if not os.path.isdir(os.path.dirname(self.s.database_logic)):
265
411
  os.makedirs(os.path.dirname(self.s.database_logic))
266
412
 
267
- if self.s.driver_data == "Sqlite":
413
+ if self.s.driver_data.lower() == "sqlite":
268
414
  self.s.host_data = ""
269
415
  self.s.port_data = ""
270
416
  if not os.path.isdir(os.path.dirname(self.s.database_data)):
@@ -276,11 +422,19 @@ class Q2AppSelect(Q2Form):
276
422
 
277
423
  def before_form_show(self):
278
424
  if self.crud_mode == "NEW":
279
- self.s.driver_logic = "Sqlite"
280
- self.s.driver_data = "Sqlite"
425
+ self.s.driver_logic = "SQLite"
426
+ self.s.driver_data = "SQLite"
281
427
  self.s.dev_mode = ""
282
428
  self.s.database_logic = "databases/_logic"
283
429
  self.s.database_data = "databases/_data"
430
+ else:
431
+ self.s.driver_logic = SQL_ENGINES[
432
+ ["mysql", "sqlite", "postgresql"].index(self.r.driver_logic.lower())
433
+ ]
434
+ self.s.driver_data = SQL_ENGINES[
435
+ ["mysql", "sqlite", "postgresql"].index(self.r.driver_data.lower())
436
+ ]
437
+
284
438
  self.w.driver_data.valid()
285
439
  self.w.driver_logic.valid()
286
440
  if self.crud_mode in [NEW, COPY]:
@@ -289,9 +443,9 @@ class Q2AppSelect(Q2Form):
289
443
 
290
444
  def run_demo(self):
291
445
  row = {
292
- "driver_data": "Sqlite",
446
+ "driver_data": "SQLite",
293
447
  "database_data": ":memory:",
294
- "driver_logic": "Sqlite",
448
+ "driver_logic": "SQLite",
295
449
  "database_logic": ":memory:",
296
450
  "dev_mode": "",
297
451
  }
@@ -313,6 +467,19 @@ class Q2AppSelect(Q2Form):
313
467
  q2Mess(_("Can't to load Demo App"))
314
468
 
315
469
  def _select_application(self, app_data={}):
470
+ if app_data.get("credhash"):
471
+ pin = self.get_pin(app_data.get("name", ""))
472
+ if pin is None:
473
+ return False
474
+ creds = self.decrypt_creds(pin, app_data.get("credhash"))
475
+ if creds is None:
476
+ q2Mess("Wrong PIN")
477
+ return False
478
+ app_data["username"] = creds[0]
479
+ app_data["password"] = creds[1]
480
+ else:
481
+ app_data["username"] = "q2user"
482
+ app_data["password"] = "q2password"
316
483
  q2_app: Q2App = q2app.q2_app
317
484
  q2_app.dev_mode = app_data.get("dev_mode")
318
485
  q2_app.selected_application = app_data
@@ -322,11 +489,13 @@ class Q2AppSelect(Q2Form):
322
489
  q2_app.show_statusbar()
323
490
  q2_app.show_tabbar()
324
491
  self.q2_app.process_events()
492
+ return True
325
493
 
326
494
  def select_application(self):
327
- self.close()
495
+ # self.close()
328
496
  self.q2_app.process_events()
329
- self._select_application(self.model.get_record(self.current_row))
497
+ if self._select_application(self.model.get_record(self.current_row)):
498
+ self.close()
330
499
 
331
500
  def run(self, autoload_enabled=True):
332
501
  q2_app: Q2App = q2app.q2_app
@@ -338,9 +507,12 @@ class Q2AppSelect(Q2Form):
338
507
  q2_app.hide_tabbar()
339
508
 
340
509
  self.autoload_enabled = autoload_enabled
341
- if autoload_enabled:
510
+ self.q2_app.process_events()
511
+ self.q2_app.sleep(0.1)
512
+ km = self.q2_app.keyboard_modifiers()
513
+ if autoload_enabled and km != "shift":
342
514
  cu = q2cursor("select * from applications where autoselect<>''", self.db)
343
515
  if cu.row_count() > 0:
344
- self._select_application(cu.record(0))
345
- return False
516
+ if self._select_application(cu.record(0)):
517
+ return False
346
518
  super().run()
q2rad/q2lines.py CHANGED
@@ -271,6 +271,13 @@ class Q2Lines(Q2Form, Q2_save_and_run):
271
271
  nogrid="*",
272
272
  datatype="longtext",
273
273
  )
274
+ self.add_control("/t", _("Stylesheet"))
275
+ self.add_control(
276
+ "style",
277
+ control="code",
278
+ nogrid="*",
279
+ datatype="longtext",
280
+ )
274
281
  self.add_control("/")
275
282
  self._add_save_and_run()
276
283
  self._add_save_and_run_visible()
q2rad/q2rad.py CHANGED
@@ -297,9 +297,9 @@ class Q2RadApp(Q2App):
297
297
  self.open_selected_app(True)
298
298
  self.check_app_update()
299
299
  self.on_new_tab()
300
- # self.update_app_packages()
301
300
  else:
302
301
  self.close()
302
+ self.subwindow_count_changed()
303
303
 
304
304
  def open_selected_app(self, go_to_q2market=False):
305
305
  wait = Q2WaitShow(5, "Loading app> ")
@@ -475,8 +475,8 @@ class Q2RadApp(Q2App):
475
475
  host=self.selected_application.get("host_data", ""),
476
476
  port=self.selected_application.get("port_data", ""),
477
477
  guest_mode=self.selected_application.get("guest_mode", ""),
478
- user="q2user",
479
- password="q2password",
478
+ user=self.selected_application.get("username", ""),
479
+ password=self.selected_application.get("password", ""),
480
480
  )
481
481
  self.db = self.db_data
482
482
  if self.db_data:
@@ -485,8 +485,8 @@ class Q2RadApp(Q2App):
485
485
  db_engine_name=self.selected_application.get("driver_logic", "").lower(),
486
486
  host=self.selected_application.get("host_logic", ""),
487
487
  port=self.selected_application.get("port_logic", ""),
488
- user="q2user",
489
- password="q2password",
488
+ user=self.selected_application.get("username", ""),
489
+ password=self.selected_application.get("password", ""),
490
490
  )
491
491
  self.last_root_password = ""
492
492
  if self.db_data is None or self.db_logic is None:
@@ -1040,6 +1040,7 @@ class Q2RadApp(Q2App):
1040
1040
  , code_valid as valid
1041
1041
  , code_when as _when
1042
1042
  , code_show as _show
1043
+ , style
1043
1044
  from `lines`
1044
1045
  where name = '{name}'
1045
1046
  order by seq
q2rad/q2utils.py CHANGED
@@ -81,6 +81,7 @@ class Q2Form(_Q2Form):
81
81
  tag="",
82
82
  eat_enter=None,
83
83
  hotkey="",
84
+ style="",
84
85
  **args,
85
86
  ):
86
87
  if isinstance(to_form, str) and to_form != "":
@@ -123,6 +124,7 @@ class Q2Form(_Q2Form):
123
124
  tag,
124
125
  eat_enter,
125
126
  hotkey,
127
+ style,
126
128
  **args,
127
129
  )
128
130
 
q2rad/version.py CHANGED
@@ -1 +1 @@
1
- __version__ = "0.1.202"
1
+ __version__ = "0.1.203"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: q2rad
3
- Version: 0.1.202
3
+ Version: 0.1.203
4
4
  Summary: RAD - database, GUI, reports
5
5
  Author: Andrei Puchko
6
6
  Author-email: andrei.puchko@gmx.de
@@ -1,24 +1,24 @@
1
1
  q2rad/__init__.py,sha256=Y0Up-UTXOmCYC9llNmTF10CpDDgF2kv10pyHT3-YwmQ,183
2
2
  q2rad/__main__.py,sha256=zP4JARM-FzFHM-vWLehx7c5N4v4m_F-TuMobCdFzr4Q,824
3
3
  q2rad/q2actions.py,sha256=eExRvOSyLhT_v1XCR-DmLEhQ9g_LRkrlyXnwDCjT0LM,8258
4
- q2rad/q2appmanager.py,sha256=f_xM1XsYTRHdr3ZLBRVFKR3-jk_JbHMTZWjj8OxF_I4,15966
5
- q2rad/q2appselector.py,sha256=3VlYG2kn0cOVOuRfA3dWIStvtnyKZWmfbP9Jpb8w9VI,12595
4
+ q2rad/q2appmanager.py,sha256=pdEdyTXWr9zjdZgVmfNXJrjDmQ_Ntq21udhD1b4vA2I,15975
5
+ q2rad/q2appselector.py,sha256=PZWSXaiUswinB_Zj1Q8fyRhzqK9ViB8lUHlNVUr85rI,18597
6
6
  q2rad/q2constants.py,sha256=dQtN4OMvZw0FATDAFYjolI7eGMVUnNnbTl6qM-ggZ4I,3416
7
7
  q2rad/q2forms.py,sha256=A5VeBK8OdE3zn0L1TgvCk4OjpB1nLibJqBFfpVZr_Uc,10181
8
- q2rad/q2lines.py,sha256=ttiINynYBnRbUg7WOs6xUNRT6h4iQrCiRecMN4Yaz8A,16970
8
+ q2rad/q2lines.py,sha256=yHQAEULVt9FTSgZa3atnoTSBSXMHCEMCjAK08ARhNMc,17167
9
9
  q2rad/q2make.py,sha256=wXoyBUwf2zaAl9JjWDCbjAteUElRq0O7ippyaMY9eug,6476
10
10
  q2rad/q2market.py,sha256=nyIBhZYqxNSlBXpcxdBRQ1vGSzWV8jI4cQoVa9JdRhE,2589
11
11
  q2rad/q2modules.py,sha256=N3OkUKfiwVZtmDyAtnJcs2Rprd7uIHd0HhjHTyFoN_s,4294
12
12
  q2rad/q2packages.py,sha256=ifRu8LuVrrTphiJe1JUVED_KB2sHJCPVnZq9VEh3K8w,3473
13
13
  q2rad/q2queries.py,sha256=EXcau1UCdPrvTvsYr0857NoXldmrkhdrkmbUTk5LrMQ,12536
14
- q2rad/q2rad.py,sha256=6tdOqShosy379Q_5MtTKl4_9vISvYrukT2XVMoM-QdQ,45868
14
+ q2rad/q2rad.py,sha256=IYQQaTGRagUTWTuhS8Jy8ua2ERCuTlBaCKC4DRP9pDY,46031
15
15
  q2rad/q2raddb.py,sha256=ISqT5EBFO7eaXcQRNpA0hMiRU84kbd-FcfckwKMlGfs,4506
16
16
  q2rad/q2reports.py,sha256=Q-bZONOSDDQPrLziHTpW_L6FS82CkWzxITkv5EX5x98,84439
17
17
  q2rad/q2stylesettings.py,sha256=rEJLyLzsffJEXnMbg9bPB3KHLjYfw-49QgrtcYOfGV0,4769
18
- q2rad/q2utils.py,sha256=n8BBzh-2G05zSRJLv2cCx2919laN9FmxzLVHOOoyoyg,19180
19
- q2rad/version.py,sha256=ENd5zaP0caBdahFV3gqq_Ugt-hgm_mU8gicYRh0aKO0,23
20
- q2rad-0.1.202.dist-info/entry_points.txt,sha256=DmsJQE6f3wYuhdN2h6ARYxSe8_d03paeepfGpdVj5rs,42
21
- q2rad-0.1.202.dist-info/LICENSE,sha256=JRR3LlR18ghhYXT4G2cWgXmnxRvcuVcKlqncWWK4MRY,10347
22
- q2rad-0.1.202.dist-info/METADATA,sha256=ShW-j3uKVIZThOzdnmLcruBbWHFj-htcN1dKr_cXZag,3369
23
- q2rad-0.1.202.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
24
- q2rad-0.1.202.dist-info/RECORD,,
18
+ q2rad/q2utils.py,sha256=tLiDYgGGUCUwDRpyxirIc3xe0hPquzXhYvJw6bL-8jI,19219
19
+ q2rad/version.py,sha256=ibT5FfNRP69rFPNhBV9hZ1u7zlfZmf4fSwvzMRzfu_o,23
20
+ q2rad-0.1.203.dist-info/entry_points.txt,sha256=DmsJQE6f3wYuhdN2h6ARYxSe8_d03paeepfGpdVj5rs,42
21
+ q2rad-0.1.203.dist-info/LICENSE,sha256=JRR3LlR18ghhYXT4G2cWgXmnxRvcuVcKlqncWWK4MRY,10347
22
+ q2rad-0.1.203.dist-info/METADATA,sha256=1JfnGyY7aSvHk4kupptJBiIJtGIZwoco4ps6rV1AMxo,3369
23
+ q2rad-0.1.203.dist-info/WHEEL,sha256=WGfLGfLX43Ei_YORXSnT54hxFygu34kMpcQdmgmEwCQ,88
24
+ q2rad-0.1.203.dist-info/RECORD,,