not1mm 25.4.12__py3-none-any.whl → 25.4.14__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.
not1mm/__main__.py CHANGED
@@ -3705,6 +3705,11 @@ class MainWindow(QtWidgets.QMainWindow):
3705
3705
  result = self.database.check_dupe_on_band_mode(call, band, mode)
3706
3706
  if self.contest.dupe_type == 4:
3707
3707
  result = {"isdupe": False}
3708
+ if self.contest.dupe_type == 5:
3709
+ result = {"isdupe": False} # in case contest has no function.
3710
+ if hasattr(self.contest, "check_dupe"):
3711
+ result = self.contest.specific_contest_check_dupe(self, call)
3712
+
3708
3713
  debugline = f"{result}"
3709
3714
  logger.debug("%s", debugline)
3710
3715
  self.contact_is_dupe = result.get("isdupe", False)
@@ -4095,7 +4100,8 @@ class MainWindow(QtWidgets.QMainWindow):
4095
4100
  """
4096
4101
 
4097
4102
  logger.debug("******EDI*****")
4098
- self.contest.edi(self)
4103
+ if hasattr(self.contest, "edi"):
4104
+ self.contest.edi(self)
4099
4105
 
4100
4106
  def generate_cabrillo(self, file_encoding: str) -> None:
4101
4107
  """
not1mm/data/donors.html CHANGED
@@ -11,4 +11,5 @@
11
11
  <center>Brian KB3ORR</center>
12
12
  <center>Connor KD9LSV</center>
13
13
  <center>Jeff KE9BPZ</center>
14
+ <center>Tarmo ES1TAR</center>
14
15
  </p>
@@ -347,6 +347,11 @@
347
347
  <string>EA RTTY</string>
348
348
  </property>
349
349
  </item>
350
+ <item>
351
+ <property name="text">
352
+ <string>ES OPEN</string>
353
+ </property>
354
+ </item>
350
355
  <item>
351
356
  <property name="text">
352
357
  <string>HELVETIA</string>
not1mm/lib/database.py CHANGED
@@ -1217,3 +1217,63 @@ class DataBase:
1217
1217
  except sqlite3.OperationalError as exception:
1218
1218
  logger.debug("%s", exception)
1219
1219
  return ()
1220
+
1221
+ def check_dupe_on_period_1_mode(
1222
+ self, call, band, mode, contest_start_time, contest_time_period_1
1223
+ ) -> dict:
1224
+ """Checks if a call is dupe on band/mode"""
1225
+ try:
1226
+ with sqlite3.connect(self.database) as conn:
1227
+ conn.row_factory = self.row_factory
1228
+ cursor = conn.cursor()
1229
+ cursor.execute(
1230
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_start_time}' AND TS <= '{contest_time_period_1}';"
1231
+ )
1232
+ return cursor.fetchone()
1233
+ except sqlite3.OperationalError as exception:
1234
+ logger.debug("%s", exception)
1235
+ return {}
1236
+
1237
+ def check_dupe_on_period_2_mode(
1238
+ self,
1239
+ call,
1240
+ band,
1241
+ mode,
1242
+ contest_start_time,
1243
+ contest_time_period_1,
1244
+ contest_time_period_2,
1245
+ ) -> dict:
1246
+ """Checks if a call is dupe on band/mode"""
1247
+ try:
1248
+ with sqlite3.connect(self.database) as conn:
1249
+ conn.row_factory = self.row_factory
1250
+ cursor = conn.cursor()
1251
+ cursor.execute(
1252
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_time_period_1}' AND TS <= '{contest_time_period_2}';"
1253
+ )
1254
+ return cursor.fetchone()
1255
+ except sqlite3.OperationalError as exception:
1256
+ logger.debug("%s", exception)
1257
+ return {}
1258
+
1259
+ def check_dupe_on_period_3_mode(
1260
+ self,
1261
+ call,
1262
+ band,
1263
+ mode,
1264
+ contest_start_time,
1265
+ contest_time_period_2,
1266
+ contest_time_period_3,
1267
+ ) -> dict:
1268
+ """Checks if a call is dupe on band/mode"""
1269
+ try:
1270
+ with sqlite3.connect(self.database) as conn:
1271
+ conn.row_factory = self.row_factory
1272
+ cursor = conn.cursor()
1273
+ cursor.execute(
1274
+ f"select count(*) as isdupe from dxlog where Call = '{call}' and Mode = '{mode}' and Band = '{band}' and ContestNR = {self.current_contest} AND TS >= '{contest_time_period_2}' AND TS <= '{contest_time_period_3}';"
1275
+ )
1276
+ return cursor.fetchone()
1277
+ except sqlite3.OperationalError as exception:
1278
+ logger.debug("%s", exception)
1279
+ return {}
not1mm/lib/version.py CHANGED
@@ -1,3 +1,3 @@
1
1
  """It's the version"""
2
2
 
3
- __version__ = "25.4.12"
3
+ __version__ = "25.4.14"
@@ -0,0 +1,568 @@
1
+ """ """
2
+
3
+ import datetime
4
+ import logging
5
+ import platform
6
+
7
+ from pathlib import Path
8
+
9
+ from PyQt6 import QtWidgets
10
+
11
+ from not1mm.lib.plugin_common import gen_adif, get_points
12
+
13
+ from not1mm.lib.ham_utility import calculate_wpx_prefix
14
+ from not1mm.lib.version import __version__
15
+
16
+ logger = logging.getLogger(__name__)
17
+
18
+ EXCHANGE_HINT = "#"
19
+
20
+ name = "ES OPEN"
21
+ cabrillo_name = "ES-OPEN"
22
+ mode = "BOTH" # CW SSB BOTH RTTY
23
+
24
+ columns = [
25
+ "YYYY-MM-DD HH:MM:SS",
26
+ "Call",
27
+ "Freq",
28
+ "Mode",
29
+ "Snt",
30
+ "Rcv",
31
+ "SentNr",
32
+ "RcvNr",
33
+ "PTS",
34
+ ]
35
+
36
+ advance_on_space = [True, True, True, True, True]
37
+
38
+ # 5 Contest specific dupe check.
39
+ dupe_type = 5
40
+
41
+
42
+ def specific_contest_check_dupe(self, call):
43
+ """"""
44
+
45
+ # constant to split the contest
46
+ contest_length_in_minutes = 60
47
+ split_contest_by_minutes = 20
48
+
49
+ period_count = int(contest_length_in_minutes / split_contest_by_minutes)
50
+
51
+ # think about generic solution by splitting the contest to n different periods
52
+ start_date_init = self.contest_settings.get("StartDate", "")
53
+ self.contest_start_date = start_date_init.split(" ")[0]
54
+ self.contest_start_time = start_date_init.split(" ")[1]
55
+
56
+ start_date_init_date = datetime.strptime(start_date_init, "%Y-%m-%d %H:%M:%S")
57
+
58
+ # Create time periods dynamically based on period count
59
+ time_periods = []
60
+ for i in range(period_count):
61
+ minutes_to_add = split_contest_by_minutes * (i + 1)
62
+ time_period = start_date_init_date + datetime.timedelta(minutes=minutes_to_add)
63
+ time_periods.append(time_period)
64
+
65
+ # Assign to variables for backwards compatibility
66
+ time_period_1 = time_periods[0] if len(time_periods) > 0 else None
67
+ time_period_2 = time_periods[1] if len(time_periods) > 1 else None
68
+ time_period_3 = time_periods[2] if len(time_periods) > 2 else None
69
+
70
+ # get current time in UTC
71
+ iso_current_time = datetime.now(datetime.timezone.utc)
72
+ current_time = iso_current_time.replace(tzinfo=None)
73
+
74
+ if current_time < time_period_1:
75
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
76
+
77
+ result = self.database.check_dupe_on_period_1_mode(
78
+ call,
79
+ self.contact.get("Band", ""),
80
+ mode,
81
+ start_date_init,
82
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
83
+ )
84
+
85
+ if current_time < time_period_2 and current_time >= time_period_1:
86
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
87
+
88
+ result = self.database.check_dupe_on_period_2_mode(
89
+ call,
90
+ self.contact.get("Band", ""),
91
+ mode,
92
+ start_date_init,
93
+ time_period_1.strftime("%Y-%m-%d %H:%M:%S"),
94
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
95
+ )
96
+
97
+ if current_time < time_period_3 and current_time >= time_period_2:
98
+ start_date_init = self.contest_start_date + " " + self.contest_start_time
99
+
100
+ result = self.database.check_dupe_on_period_3_mode(
101
+ call,
102
+ self.contact.get("Band", ""),
103
+ mode,
104
+ start_date_init,
105
+ time_period_2.strftime("%Y-%m-%d %H:%M:%S"),
106
+ time_period_3.strftime("%Y-%m-%d %H:%M:%S"),
107
+ )
108
+ else:
109
+ result = self.database.check_dupe_on_period_mode(
110
+ call, self.contact.get("Band", ""), mode, start_date_init
111
+ )
112
+ return result
113
+
114
+
115
+ def init_contest(self):
116
+ """setup plugin"""
117
+ set_tab_next(self)
118
+ set_tab_prev(self)
119
+ interface(self)
120
+ self.next_field = self.other_2
121
+
122
+
123
+ def interface(self):
124
+ """Setup user interface"""
125
+ self.field1.show()
126
+ self.field2.show()
127
+ self.field3.show()
128
+ self.field4.show()
129
+ self.other_label.setText("Sent")
130
+ self.field3.setAccessibleName("Sent")
131
+ self.exch_label.setText("SN")
132
+ self.field4.setAccessibleName("SN")
133
+
134
+
135
+ def reset_label(self):
136
+ """reset label after field cleared"""
137
+
138
+
139
+ def set_tab_next(self):
140
+ """Set TAB Advances"""
141
+ self.tab_next = {
142
+ self.callsign: self.other_1,
143
+ self.sent: self.other_1,
144
+ self.receive: self.other_1,
145
+ self.other_1: self.other_2,
146
+ self.other_2: self.callsign,
147
+ }
148
+
149
+
150
+ def set_tab_prev(self):
151
+ """Set TAB Advances"""
152
+ self.tab_prev = {
153
+ self.callsign: self.other_2,
154
+ self.sent: self.callsign,
155
+ self.receive: self.callsign,
156
+ self.other_1: self.callsign,
157
+ self.other_2: self.other_1,
158
+ }
159
+
160
+
161
+ def set_contact_vars(self):
162
+ """Contest Specific"""
163
+ self.contact["SNT"] = self.sent.text()
164
+ self.contact["RCV"] = self.receive.text()
165
+ self.contact["SentNr"] = self.other_1.text().upper()
166
+ self.contact["NR"] = self.other_2.text().upper()
167
+
168
+ self.contact["IsMultiplier1"] = 0
169
+ self.contact["IsMultiplier2"] = 0
170
+
171
+
172
+ def predupe(self):
173
+ """called after callsign entered"""
174
+
175
+
176
+ def prefill(self):
177
+ """Fill SentNR"""
178
+ sent_sxchange_setting = self.contest_settings.get("SentExchange", "")
179
+ if sent_sxchange_setting.strip() == "#":
180
+ result = self.database.get_serial()
181
+ serial_nr = str(result.get("serial_nr", "1")).zfill(3)
182
+ if serial_nr == "None":
183
+ serial_nr = "001"
184
+ if len(self.other_1.text()) == 0:
185
+ self.other_1.setText(serial_nr)
186
+ else:
187
+ self.other_1.setText(sent_sxchange_setting)
188
+
189
+
190
+ def points(self):
191
+ """ """
192
+ if self.contact_is_dupe > 0:
193
+ return 0
194
+
195
+ _mode = self.contact.get("Mode", "")
196
+ if _mode in "SSB, USB, LSB, FM, AM":
197
+ return 1
198
+ if _mode in "CW":
199
+ return 2
200
+
201
+ return 0
202
+
203
+
204
+ def show_mults(self, rtc=None):
205
+ """Return display string for mults"""
206
+ our_prefix = calculate_wpx_prefix(self.station.get("Call", ""))
207
+ query = f"SELECT count(DISTINCT(substr(WPXPrefix,3,1) || ':' || Band || ':' || Mode)) as mults from DXLOG where ContestNR = {self.pref.get('contest', '1')} AND CountryPrefix = 'ES' AND WPXPrefix != '{our_prefix}';"
208
+ result = self.database.exec_sql(query)
209
+ if result:
210
+ mult_count = result.get("mults", 0)
211
+ return mult_count
212
+ return 0
213
+
214
+
215
+ def show_qso(self):
216
+ """Return qso count"""
217
+ result = self.database.fetch_qso_count()
218
+ if result:
219
+ return int(result.get("qsos", 0))
220
+ return 0
221
+
222
+
223
+ def calc_score(self):
224
+ """Return calculated score"""
225
+ result = self.database.fetch_points()
226
+ if result is not None:
227
+ score = result.get("Points", "0")
228
+ if score is None:
229
+ score = "0"
230
+ contest_points = int(score)
231
+ mults = show_mults(self)
232
+ return contest_points * (mults + 1)
233
+ return 0
234
+
235
+
236
+ def recalculate_mults(self):
237
+ """Recalculates multipliers after change in logged qso."""
238
+
239
+
240
+ def adif(self):
241
+ """Call the generate ADIF function"""
242
+ gen_adif(self, cabrillo_name, "ES OPEN")
243
+
244
+
245
+ def output_cabrillo_line(line_to_output, ending, file_descriptor, file_encoding):
246
+ """"""
247
+ print(
248
+ line_to_output.encode(file_encoding, errors="ignore").decode(),
249
+ end=ending,
250
+ file=file_descriptor,
251
+ )
252
+
253
+
254
+ def cabrillo(self, file_encoding):
255
+ """Generates Cabrillo file. Maybe."""
256
+ # https://www.cqwpx.com/cabrillo.htm
257
+ logger.debug("******Cabrillo*****")
258
+ logger.debug("Station: %s", f"{self.station}")
259
+ logger.debug("Contest: %s", f"{self.contest_settings}")
260
+ now = datetime.datetime.now()
261
+ date_time = now.strftime("%Y-%m-%d_%H-%M-%S")
262
+ filename = (
263
+ str(Path.home())
264
+ + "/"
265
+ + f"{self.station.get('Call', '').upper()}_{cabrillo_name}_{date_time}.log"
266
+ )
267
+ logger.debug("%s", filename)
268
+ log = self.database.fetch_all_contacts_asc()
269
+ try:
270
+ with open(filename, "w", encoding=file_encoding, newline="") as file_descriptor:
271
+ output_cabrillo_line(
272
+ "START-OF-LOG: 3.0",
273
+ "\r\n",
274
+ file_descriptor,
275
+ file_encoding,
276
+ )
277
+ output_cabrillo_line(
278
+ f"CREATED-BY: Not1MM v{__version__}",
279
+ "\r\n",
280
+ file_descriptor,
281
+ file_encoding,
282
+ )
283
+ output_cabrillo_line(
284
+ f"CONTEST: {cabrillo_name}",
285
+ "\r\n",
286
+ file_descriptor,
287
+ file_encoding,
288
+ )
289
+ if self.station.get("Club", ""):
290
+ output_cabrillo_line(
291
+ f"CLUB: {self.station.get('Club', '').upper()}",
292
+ "\r\n",
293
+ file_descriptor,
294
+ file_encoding,
295
+ )
296
+ output_cabrillo_line(
297
+ f"CALLSIGN: {self.station.get('Call','')}",
298
+ "\r\n",
299
+ file_descriptor,
300
+ file_encoding,
301
+ )
302
+ output_cabrillo_line(
303
+ f"LOCATION: {self.station.get('ARRLSection', '')}",
304
+ "\r\n",
305
+ file_descriptor,
306
+ file_encoding,
307
+ )
308
+ output_cabrillo_line(
309
+ f"CATEGORY-OPERATOR: {self.contest_settings.get('OperatorCategory','')}",
310
+ "\r\n",
311
+ file_descriptor,
312
+ file_encoding,
313
+ )
314
+ output_cabrillo_line(
315
+ f"CATEGORY-ASSISTED: {self.contest_settings.get('AssistedCategory','')}",
316
+ "\r\n",
317
+ file_descriptor,
318
+ file_encoding,
319
+ )
320
+ output_cabrillo_line(
321
+ f"CATEGORY-BAND: {self.contest_settings.get('BandCategory','')}",
322
+ "\r\n",
323
+ file_descriptor,
324
+ file_encoding,
325
+ )
326
+ mode = self.contest_settings.get("ModeCategory", "")
327
+ if mode in ["SSB+CW", "SSB+CW+DIGITAL"]:
328
+ mode = "MIXED"
329
+ output_cabrillo_line(
330
+ f"CATEGORY-MODE: {mode}",
331
+ "\r\n",
332
+ file_descriptor,
333
+ file_encoding,
334
+ )
335
+ output_cabrillo_line(
336
+ f"CATEGORY-TRANSMITTER: {self.contest_settings.get('TransmitterCategory','')}",
337
+ "\r\n",
338
+ file_descriptor,
339
+ file_encoding,
340
+ )
341
+ if self.contest_settings.get("OverlayCategory", "") != "N/A":
342
+ output_cabrillo_line(
343
+ f"CATEGORY-OVERLAY: {self.contest_settings.get('OverlayCategory','')}",
344
+ "\r\n",
345
+ file_descriptor,
346
+ file_encoding,
347
+ )
348
+ output_cabrillo_line(
349
+ f"GRID-LOCATOR: {self.station.get('GridSquare','')}",
350
+ "\r\n",
351
+ file_descriptor,
352
+ file_encoding,
353
+ )
354
+ output_cabrillo_line(
355
+ f"CATEGORY-POWER: {self.contest_settings.get('PowerCategory','')}",
356
+ "\r\n",
357
+ file_descriptor,
358
+ file_encoding,
359
+ )
360
+
361
+ output_cabrillo_line(
362
+ f"CLAIMED-SCORE: {calc_score(self)}",
363
+ "\r\n",
364
+ file_descriptor,
365
+ file_encoding,
366
+ )
367
+ ops = f"@{self.station.get('Call','')}"
368
+ list_of_ops = self.database.get_ops()
369
+ for op in list_of_ops:
370
+ ops += f", {op.get('Operator', '')}"
371
+ output_cabrillo_line(
372
+ f"OPERATORS: {ops}",
373
+ "\r\n",
374
+ file_descriptor,
375
+ file_encoding,
376
+ )
377
+ output_cabrillo_line(
378
+ f"NAME: {self.station.get('Name', '')}",
379
+ "\r\n",
380
+ file_descriptor,
381
+ file_encoding,
382
+ )
383
+ output_cabrillo_line(
384
+ f"ADDRESS: {self.station.get('Street1', '')}",
385
+ "\r\n",
386
+ file_descriptor,
387
+ file_encoding,
388
+ )
389
+ output_cabrillo_line(
390
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
391
+ "\r\n",
392
+ file_descriptor,
393
+ file_encoding,
394
+ )
395
+ output_cabrillo_line(
396
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
397
+ "\r\n",
398
+ file_descriptor,
399
+ file_encoding,
400
+ )
401
+ output_cabrillo_line(
402
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
403
+ "\r\n",
404
+ file_descriptor,
405
+ file_encoding,
406
+ )
407
+ output_cabrillo_line(
408
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
409
+ "\r\n",
410
+ file_descriptor,
411
+ file_encoding,
412
+ )
413
+ output_cabrillo_line(
414
+ f"EMAIL: {self.station.get('Email', '')}",
415
+ "\r\n",
416
+ file_descriptor,
417
+ file_encoding,
418
+ )
419
+ for contact in log:
420
+ the_date_and_time = contact.get("TS", "")
421
+ themode = contact.get("Mode", "")
422
+ if themode == "LSB" or themode == "USB":
423
+ themode = "PH"
424
+ frequency = str(int(contact.get("Freq", "0"))).rjust(5)
425
+
426
+ loggeddate = the_date_and_time[:10]
427
+ loggedtime = the_date_and_time[11:13] + the_date_and_time[14:16]
428
+ output_cabrillo_line(
429
+ f"QSO: {frequency} {themode} {loggeddate} {loggedtime} "
430
+ f"{contact.get('StationPrefix', '').ljust(13)} "
431
+ f"{str(contact.get('SNT', '')).ljust(3)} "
432
+ f"{str(contact.get('SentNr', '')).ljust(6)} "
433
+ f"{contact.get('Call', '').ljust(13)} "
434
+ f"{str(contact.get('RCV', '')).ljust(3)} "
435
+ f"{str(contact.get('NR', '')).ljust(6)}",
436
+ "\r\n",
437
+ file_descriptor,
438
+ file_encoding,
439
+ )
440
+ output_cabrillo_line("END-OF-LOG:", "\r\n", file_descriptor, file_encoding)
441
+ self.show_message_box(f"Cabrillo saved to: {filename}")
442
+ except IOError as exception:
443
+ logger.critical("cabrillo: IO error: %s, writing to %s", exception, filename)
444
+ self.show_message_box(f"Error saving Cabrillo: {exception} {filename}")
445
+ return
446
+
447
+
448
+ # def populate_history_info_line(self):
449
+ # result = self.database.fetch_call_history(self.callsign.text())
450
+ # if result:
451
+ # self.history_info.setText(
452
+ # f"{result.get('Call', '')}, {result.get('Exch1', '')}, {result.get('UserText','...')}"
453
+ # )
454
+ # else:
455
+ # self.history_info.setText("")
456
+
457
+
458
+ # def check_call_history(self):
459
+ # """"""
460
+ # result = self.database.fetch_call_history(self.callsign.text())
461
+ # print(f"{result=}")
462
+ # if result:
463
+ # self.history_info.setText(f"{result.get('UserText','')}")
464
+ # if self.other_2.text() == "":
465
+ # self.other_2.setText(f"{result.get('Exch1', '')}")
466
+
467
+
468
+ def process_esm(self, new_focused_widget=None, with_enter=False):
469
+ """ESM State Machine"""
470
+
471
+ # self.pref["run_state"]
472
+
473
+ # -----===== Assigned F-Keys =====-----
474
+ # self.esm_dict["CQ"]
475
+ # self.esm_dict["EXCH"]
476
+ # self.esm_dict["QRZ"]
477
+ # self.esm_dict["AGN"]
478
+ # self.esm_dict["HISCALL"]
479
+ # self.esm_dict["MYCALL"]
480
+ # self.esm_dict["QSOB4"]
481
+
482
+ # ----==== text fields ====----
483
+ # self.callsign
484
+ # self.sent
485
+ # self.receive
486
+ # self.other_1
487
+ # self.other_2
488
+
489
+ if new_focused_widget is not None:
490
+ self.current_widget = self.inputs_dict.get(new_focused_widget)
491
+
492
+ # print(f"checking esm {self.current_widget=} {with_enter=} {self.pref.get("run_state")=}")
493
+
494
+ for a_button in [
495
+ self.esm_dict["CQ"],
496
+ self.esm_dict["EXCH"],
497
+ self.esm_dict["QRZ"],
498
+ self.esm_dict["AGN"],
499
+ self.esm_dict["HISCALL"],
500
+ self.esm_dict["MYCALL"],
501
+ self.esm_dict["QSOB4"],
502
+ ]:
503
+ if a_button is not None:
504
+ self.restore_button_color(a_button)
505
+
506
+ buttons_to_send = []
507
+
508
+ if self.pref.get("run_state"):
509
+ if self.current_widget == "callsign":
510
+ if len(self.callsign.text()) < 3:
511
+ self.make_button_green(self.esm_dict["CQ"])
512
+ buttons_to_send.append(self.esm_dict["CQ"])
513
+ elif len(self.callsign.text()) > 2:
514
+ self.make_button_green(self.esm_dict["HISCALL"])
515
+ self.make_button_green(self.esm_dict["EXCH"])
516
+ buttons_to_send.append(self.esm_dict["HISCALL"])
517
+ buttons_to_send.append(self.esm_dict["EXCH"])
518
+
519
+ elif self.current_widget == "other_2":
520
+ if self.other_2.text() == "":
521
+ self.make_button_green(self.esm_dict["AGN"])
522
+ buttons_to_send.append(self.esm_dict["AGN"])
523
+ else:
524
+ self.make_button_green(self.esm_dict["QRZ"])
525
+ buttons_to_send.append(self.esm_dict["QRZ"])
526
+ buttons_to_send.append("LOGIT")
527
+
528
+ if with_enter is True and bool(len(buttons_to_send)):
529
+ for button in buttons_to_send:
530
+ if button:
531
+ if button == "LOGIT":
532
+ self.save_contact()
533
+ continue
534
+ self.process_function_key(button)
535
+ else:
536
+ if self.current_widget == "callsign":
537
+ if len(self.callsign.text()) > 2:
538
+ self.make_button_green(self.esm_dict["MYCALL"])
539
+ buttons_to_send.append(self.esm_dict["MYCALL"])
540
+
541
+ elif self.current_widget == "other_2":
542
+ if self.other_2.text() == "":
543
+ self.make_button_green(self.esm_dict["AGN"])
544
+ buttons_to_send.append(self.esm_dict["AGN"])
545
+ else:
546
+ self.make_button_green(self.esm_dict["EXCH"])
547
+ buttons_to_send.append(self.esm_dict["EXCH"])
548
+ buttons_to_send.append("LOGIT")
549
+
550
+ if with_enter is True and bool(len(buttons_to_send)):
551
+ for button in buttons_to_send:
552
+ if button:
553
+ if button == "LOGIT":
554
+ self.save_contact()
555
+ continue
556
+ self.process_function_key(button)
557
+
558
+
559
+ def get_mults(self):
560
+ """Get mults for RTC XML"""
561
+ mults = {}
562
+ mults["country"], mults["state"] = show_mults(self, rtc=True)
563
+ return mults
564
+
565
+
566
+ def just_points(self):
567
+ """Get points for RTC XML"""
568
+ return get_points(self)
not1mm/plugins/jidx_cw.py CHANGED
@@ -335,14 +335,25 @@ def cabrillo(self, file_encoding):
335
335
  file_encoding,
336
336
  )
337
337
  output_cabrillo_line(
338
- f"ADDRESS: {self.station.get('City', '')}, {self.station.get('State', '')} ",
339
- f"{self.station.get('Zip', '')}",
338
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
340
339
  "\r\n",
341
340
  file_descriptor,
342
341
  file_encoding,
343
342
  )
344
343
  output_cabrillo_line(
345
- f"ADDRESS: {self.station.get('Country', '')}",
344
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
345
+ "\r\n",
346
+ file_descriptor,
347
+ file_encoding,
348
+ )
349
+ output_cabrillo_line(
350
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
351
+ "\r\n",
352
+ file_descriptor,
353
+ file_encoding,
354
+ )
355
+ output_cabrillo_line(
356
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
346
357
  "\r\n",
347
358
  file_descriptor,
348
359
  file_encoding,
not1mm/plugins/jidx_ph.py CHANGED
@@ -304,14 +304,25 @@ def cabrillo(self, file_encoding):
304
304
  file_encoding,
305
305
  )
306
306
  output_cabrillo_line(
307
- f"ADDRESS: {self.station.get('City', '')}, {self.station.get('State', '')} ",
308
- f"{self.station.get('Zip', '')}",
307
+ f"ADDRESS-CITY: {self.station.get('City', '')}",
309
308
  "\r\n",
310
309
  file_descriptor,
311
310
  file_encoding,
312
311
  )
313
312
  output_cabrillo_line(
314
- f"ADDRESS: {self.station.get('Country', '')}",
313
+ f"ADDRESS-STATE-PROVINCE: {self.station.get('State', '')}",
314
+ "\r\n",
315
+ file_descriptor,
316
+ file_encoding,
317
+ )
318
+ output_cabrillo_line(
319
+ f"ADDRESS-POSTALCODE: {self.station.get('Zip', '')}",
320
+ "\r\n",
321
+ file_descriptor,
322
+ file_encoding,
323
+ )
324
+ output_cabrillo_line(
325
+ f"ADDRESS-COUNTRY: {self.station.get('Country', '')}",
315
326
  "\r\n",
316
327
  file_descriptor,
317
328
  file_encoding,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: not1mm
3
- Version: 25.4.12
3
+ Version: 25.4.14
4
4
  Summary: NOT1MM Logger
5
5
  Author-email: Michael Bridak <michael.bridak@gmail.com>
6
6
  License: GPL-3.0-or-later
@@ -105,6 +105,8 @@ Dynamic: license-file
105
105
  - [Sending CW](#sending-cw)
106
106
  - [Sending CW Macros](#sending-cw-macros)
107
107
  - [Auto CQ](#auto-cq)
108
+ - [Setting the delay](#setting-the-delay)
109
+ - [Cancelling the Auto CQ](#cancelling-the-auto-cq)
108
110
  - [Sending CW Free Form](#sending-cw-free-form)
109
111
  - [Editing macro keys](#editing-macro-keys)
110
112
  - [Macro substitutions](#macro-substitutions)
@@ -117,7 +119,7 @@ Dynamic: license-file
117
119
  - [The Log Window](#the-log-window)
118
120
  - [Editing a contact](#editing-a-contact)
119
121
  - [The Bandmap Window](#the-bandmap-window)
120
- - [The Check Window](#the-check-window)
122
+ - [The Check Partial Window](#the-check-partial-window)
121
123
  - [The Rate Window](#the-rate-window)
122
124
  - [The Remote VFO Window](#the-remote-vfo-window)
123
125
  - [Cabrillo](#cabrillo)
@@ -228,6 +230,7 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
228
230
  - EA Majistad CW
229
231
  - EA Majistad SSB
230
232
  - EA RTTY
233
+ - ES OPEN HF
231
234
  - Helvetia
232
235
  - IARU Fieldday R1 CW, SSB
233
236
  - IARU HF
@@ -251,14 +254,16 @@ generated, 'cause I'm lazy, list of those who've submitted PR's.
251
254
 
252
255
  ## Recent Changes
253
256
 
257
+ - [25-4-14] Add ES Open HF Chanmpionship.
258
+ - [25-4-13] Fix crash in JIDX Cabrillo output.
254
259
  - [25-4-12] Added an Auto CQ time to fire progress bar.
255
260
  - [25-4-11-3] Fixed issue with winkeyer not sending multiple macros in ESM mode.
256
261
  - [25-4-11-2] Fixed a crash.
257
262
  - [25-4-11-1] Add clear buffer to winkeyer interface to stop sending.
258
263
  - [25-4-11] Add Scandinavian Activity Contest
259
- - [25-4-10-1] Add ARI 40/80 contest. Add Auto CQ visual indicator. Add CTRL-R to toggle Run state.
264
+ - [25-4-10-1] Add ARI 40/80 contest. Add CTRL-R to toggle Run state.
260
265
  - [25-4-10] Add Auto CQ visual indicator.
261
- - [25-4-9] Added UKEI DX
266
+ - [25-4-9] Added UKEI DX Contest.
262
267
  - [25-4-8] Remove focus from statistics table widget.
263
268
  - [25-4-7] Merge in changes from dj1yfk correcting SPDX Cabrillo name.
264
269
  - [25-4-5] Add SPDX.
@@ -671,14 +676,22 @@ pressing F1 - F12. See next section on Editing macro keys.
671
676
 
672
677
  ### Auto CQ
673
678
 
674
- If you press `SHIFT-F1` The Auto CQ mode will be activated and the F1 macro will be resent
675
- after each Auto CQ Delay interval has passed. An indicator will appear to the upper left of
676
- the F1 macro key as a visual reminder that your Auto CQ is active.
679
+ If you press `SHIFT-F1` The Auto CQ mode will be activated, you will be placed in a Run state
680
+ and the F1 macro will be resent after each Auto CQ Delay interval has passed.
681
+ An indicator will appear to the upper left of the F1 macro key as a visual reminder that your
682
+ Auto CQ is active. With it to the right, you will see a small progress bar giving you a visual
683
+ indication as to when F1 will fire next.
677
684
 
678
685
  ![Auto CQ Visual Indicator](https://github.com/mbridak/not1mm/raw/master/pic/auto_cq_indicator.png)
679
686
 
687
+ #### Setting the delay
688
+
680
689
  The delay can be changed by going to the `Options` TAB in the Configuration dialog. If you are in
681
- S&P mode when you enable Auto CQ, you will be automatically switched into RUN mode.
690
+ S&P mode when you enable Auto CQ, you will be automatically switched into RUN mode. To properly set
691
+ the delay you should time how long your F1 macro takes to key, then add how many seconds of pause
692
+ you would like. This is your delay value.
693
+
694
+ #### Cancelling the Auto CQ
682
695
 
683
696
  The auto CQ can be cancelled by either typing in the call sign field, or by pressing ESC.
684
697
 
@@ -759,6 +772,8 @@ is this has happened, since the gridsquare will replace the word "Regional".
759
772
 
760
773
  ## Other uses for the call field
761
774
 
775
+ **You must press the SPACE bar after entering any of the below.**
776
+
762
777
  - [A Frequency] You can enter a frequency in kilohertz. This will change the band you're logging on. If you have CAT control, this will change the frequency of the radio as well.
763
778
  - [CW, SSB, RTTY] You can set the mode logged. If you have CAT control this will also change the mode on the radio.
764
779
  - [OPON] Change the operator currently logging.
@@ -775,9 +790,9 @@ is this has happened, since the gridsquare will replace the word "Regional".
775
790
 
776
791
  | Key | Result |
777
792
  | -------------- | --- |
778
- | [Esc] | Stops cwdaemon from sending Morse. |
779
- | [PgUp] | Increases the cw sending speed. |
780
- | [PgDown] | Decreases the cw sending speed. |
793
+ | [Esc] | Stops sending CW. |
794
+ | [PgUp] | Increases the CW sending speed. |
795
+ | [PgDown] | Decreases the CW sending speed. |
781
796
  | [Arrow-Up] | Jump to the next spot above the current VFO cursor in the bandmap window (CAT Required). |
782
797
  | [Arrow-Down] | Jump to the next spot below the current VFO cursor in the bandmap window (CAT Required). |
783
798
  | [TAB] | Move cursor to the right one field. |
@@ -792,6 +807,12 @@ is this has happened, since the gridsquare will replace the word "Regional".
792
807
  | [CTRL-SHIFT-K] | Open CW text input field. |
793
808
  | [CTRL-=] | Log the contact without sending the ESM macros.|
794
809
  | [CTRL-W] | Clears the input fields of any text. |
810
+ | [ALT-B] | Toggles the BandMap window. |
811
+ | [ALT-C] | Toggles the Check Partial window. |
812
+ | [ALT-L] | Toggles the QSO Log window. |
813
+ | [ALT-R] | Toggles the Rate window. |
814
+ | [ALT-S] | Toggles the Statistics window. |
815
+ | [ALT-V] | Toggles the VFO window. |
795
816
 
796
817
  ### The Log Window
797
818
 
@@ -839,9 +860,9 @@ blue rectangle shows the receivers bandwidth if one is reported.
839
860
  Clicked on spots now tune the radio and set the callsign field. Previously
840
861
  worked calls are displayed in red.
841
862
 
842
- ### The Check Window
863
+ ### The Check Partial Window
843
864
 
844
- `Window`>`Check Window`
865
+ `Window`>`Check Partial Window`
845
866
 
846
867
  As you enter a callsign, the Check Window will show probable matches to calls
847
868
  either in the MASTER.SCP file, your local log or the recent telnet spots. The
@@ -905,8 +926,12 @@ change.
905
926
 
906
927
  ## ESM
907
928
 
908
- I caved and started working on ESM or Enter Sends Message. To test it out you can
909
- go to `FILE -> Configuration Settings`
929
+ ESM or Enter Sends Message. ESM is a feature in which the logging program will automatically
930
+ send the right function key macros based on the information present in the input fields and
931
+ which input field is active when you press the Enter key. You can see a common flow in the
932
+ examples below.
933
+
934
+ To test it out you can go to `FILE -> Configuration Settings`
910
935
 
911
936
  ![Config Screen](https://github.com/mbridak/not1mm/raw/master/pic/configuration_options.png)
912
937
 
@@ -1,5 +1,5 @@
1
1
  not1mm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- not1mm/__main__.py,sha256=_sobv7fOxQw5gIM1Q2-fLSMn2EXSdOgki0PnZ2xTFGo,153631
2
+ not1mm/__main__.py,sha256=T03w3kUEWO4gy1oiDYG7GnqxhN4P5MH4ZB1u6SWB7pQ,153922
3
3
  not1mm/bandmap.py,sha256=-zu5slsuAm2GmeW8g3yvURzsuQxemwIQfw1HEq8xKHM,29920
4
4
  not1mm/checkwindow.py,sha256=zEHlw40j6Wr3rvKbCQf2lcezCoiZqaBqEvBjQU5aKW0,7630
5
5
  not1mm/fsutils.py,sha256=ukHKxKTeNKxKwqRaJjtzRShL4X5Xl0jRBbADyy3Ifp8,1701
@@ -23,7 +23,7 @@ not1mm/data/configuration.ui,sha256=mqhEvxD9lQGeoEkUrvbO9uNrOG62z6EIUUMa_b_SG-o,
23
23
  not1mm/data/contests.sql,sha256=4hmJCDvrbxnA_Y5S4T5o52TZieeFk6QUwFerwlFePNA,89307
24
24
  not1mm/data/cty.json,sha256=bwPhOrOAgvV9JiXUDT9kzCqfNWAhGuJQt489h0SKsCk,4925375
25
25
  not1mm/data/cwmacros.txt,sha256=NztufsX6R52gAO7VyJ2AHr7wOh41pJTwHKh5Lcs32ds,468
26
- not1mm/data/donors.html,sha256=0NEh7eu9Dsfv1Gy0_f6UMp4ZjVjm7OgoQJEQd-4whoU,267
26
+ not1mm/data/donors.html,sha256=qLg2n3NoJ5ZMNZye-nD_lgNjtSqL7952k_Z_bbJM5hA,297
27
27
  not1mm/data/editcontact.ui,sha256=TNOsXETYfDaON4wj6AkzCJ-n2SmbNRO2-g2SLl5m8s0,27437
28
28
  not1mm/data/editmacro.ui,sha256=Vg-S62ogKYcWlDDlza_JYyZkCQfa8mCfF-cFqpBej-w,2700
29
29
  not1mm/data/greendot.png,sha256=El9TomJcGtViRcHOR7kMxGzjzvYs0TSAqOb3tZv0JDA,368
@@ -34,7 +34,7 @@ not1mm/data/k6gte.not1mm-64.png,sha256=6ku45Gq1g5ezh04F07osoKRtanb3e4kbx5XdIEh3N
34
34
  not1mm/data/logwindow.ui,sha256=f7vULj96tHIQuR1nJMyvPHHcmVgzkhv9D1isyojsnFU,1458
35
35
  not1mm/data/logwindowx.ui,sha256=CwpI-h7cI1yqyldH9quKftsdHL5lTyL9ABOcf80nfqc,1632
36
36
  not1mm/data/main.ui,sha256=-JDQXOaxj8_7Wda9KT2rEM4YUjBs31CiT1Rjc_DBobM,64907
37
- not1mm/data/new_contest.ui,sha256=Q8ZORq_9iRls5AJTroh1HAhEkTCOu02nBv9e9xXMOCU,25119
37
+ not1mm/data/new_contest.ui,sha256=glqsmFGF5gh-JB-zuEVxAWrOR7-Hok5ibvZYCMcDCWE,25223
38
38
  not1mm/data/not1mm.html,sha256=c9-mfjMwDt4f5pySUruz2gREW33CQ2_rCddM2z5CZQo,23273
39
39
  not1mm/data/opon.ui,sha256=QDicqAk2lORG2UWsHa6jHlsGn6uzrrI2R4HSAocpPes,2258
40
40
  not1mm/data/pickcontest.ui,sha256=4hPBszCglObThx_eIWtmK9CEcbr7WBjbB1rKZdI-o3I,1707
@@ -102,7 +102,7 @@ not1mm/lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
102
102
  not1mm/lib/about.py,sha256=sWycfGcruN3SaEe4JmaJ61K6D8Itq0WxpUYT-lEcmYM,416
103
103
  not1mm/lib/cat_interface.py,sha256=BJvy-34ZyiN73kKNQcCzE4w6ll2O6Ue0uz01T_3sf1E,25204
104
104
  not1mm/lib/cwinterface.py,sha256=rKUnqljHQC_Iljq4TCmAgSPe49lWbKcfxg58cE8YX5Y,5177
105
- not1mm/lib/database.py,sha256=-9iAPTXDGVUc3OfnZNZCaWRxg3u-qdJyO5jvSvrJQSk,49203
105
+ not1mm/lib/database.py,sha256=fykyaQaTa_Pwde51f09Odbexy1mlUqObv0fjZ7hf3E0,51693
106
106
  not1mm/lib/edit_contact.py,sha256=Ki9bGPpqyQQBB1cU8VIBDCal3lbXeQ6qxhzklmhE2_w,353
107
107
  not1mm/lib/edit_macro.py,sha256=raKWBwsHInj5EUKmvyLQ6gqc3ZFDlstsD3xqoM4PC8E,517
108
108
  not1mm/lib/edit_opon.py,sha256=j3qJ1aBsQoIOnQ9yiBl3lyeISvKTP0I_rtBYBPAfgeI,359
@@ -118,7 +118,7 @@ not1mm/lib/plugin_common.py,sha256=D1OBjyLmX7zuSPqgTCmHwXzAKA12J_zTQItvyIem-4Y,1
118
118
  not1mm/lib/select_contest.py,sha256=WsptLuwkouIHeocJL3oZ6-eUfEnhpwdc-x7eMZ_TIVM,359
119
119
  not1mm/lib/settings.py,sha256=mXffn8Xaj5KATPQinNBR0V5DbHWQPsRfh24_axWGYuk,15254
120
120
  not1mm/lib/super_check_partial.py,sha256=hwT2NRwobu0PLDyw6ltmbmcAtGBD02CKGFbgGWjXMqA,2334
121
- not1mm/lib/version.py,sha256=atqnAZN-9H5r7AsrRXx2wU6Jo8y4lw4ILqxIBpKnWYk,48
121
+ not1mm/lib/version.py,sha256=VF2ECEwHJr0MWw2BVQtIHH1HDZfZCrSeIks7YLhW7iU,48
122
122
  not1mm/lib/versiontest.py,sha256=8vDNptuBBunn-1IGkjNaquehqBYUJyjrPSF8Igmd4_Y,1286
123
123
  not1mm/plugins/10_10_fall_cw.py,sha256=oJh3JKqjOpnWElSlZpiQ631UnaOd8qra5s9bl_QoInk,14783
124
124
  not1mm/plugins/10_10_spring_cw.py,sha256=p7dSDtbFK0e6Xouw2V6swYn3VFVgHKyx4IfRWyBjMZY,14786
@@ -152,14 +152,15 @@ not1mm/plugins/darc_xmas.py,sha256=p5UNYLdtylsC_sSlxT8NvXXL1oSW0KyUhIN-rJonHgI,1
152
152
  not1mm/plugins/ea_majistad_cw.py,sha256=tl9y92Oz4NTch4H-SrBnZND2tHGqWQvtgl3emXfU8og,23352
153
153
  not1mm/plugins/ea_majistad_ssb.py,sha256=TwZLHwgybpIgA4ECXzV3bIeP89MLr3vXa4_O99-mgxQ,22946
154
154
  not1mm/plugins/ea_rtty.py,sha256=JvszWdtUqC_Sn2sJAlMhMp2AdlLyAIj-6nWT-yFkihw,23229
155
+ not1mm/plugins/es_ll_kv.py,sha256=A0zW59A6DYzPTM6Q_zBGKM3zeDr9DXlS9oaAPdxKt5k,18384
155
156
  not1mm/plugins/general_logging.py,sha256=eQuna-LnrWpf93LmHTTo6956GWoGocVfeYnzY5cyTmw,9600
156
157
  not1mm/plugins/helvetia.py,sha256=fDKhvjDh5PxxLxmxvqTHzt-u0cMjHOjlF6JWBu3qB20,20079
157
158
  not1mm/plugins/iaru_fieldday_r1_cw.py,sha256=1AVyZFi3ri2zqaNJY181Wtyz74fai8QLoi7PoyXpfaY,17218
158
159
  not1mm/plugins/iaru_fieldday_r1_ssb.py,sha256=w0j4MY1LeGxOaQfRjxRS-Q4waTOOt-hbxA1spil7z_I,17222
159
160
  not1mm/plugins/iaru_hf.py,sha256=VtNCijj_p03EIRfUJE-5FSarGb8P-Ek7gxIdPF_zHQQ,16721
160
161
  not1mm/plugins/icwc_mst.py,sha256=IUpAETCjXxeTmOFu2ItivXiZGRaQgcuaPSu6Q1kOJAk,16539
161
- not1mm/plugins/jidx_cw.py,sha256=dsirWVEmogPSxSpo2uNGYa12qXiokAGad1IoclG5rpA,15945
162
- not1mm/plugins/jidx_ph.py,sha256=Ln47W-lPDieG3e67vVHwtPN3jKHVtb87fviyYBL8pi0,14894
162
+ not1mm/plugins/jidx_cw.py,sha256=fbdo-KDzNAHq-lH1V0X99wsZJkBVUkJN4yyegTRZFrs,16292
163
+ not1mm/plugins/jidx_ph.py,sha256=oFHZOPIa0pzVge0F73WPZ3z4cLiZCSBlO3499_Pe9NI,15241
163
164
  not1mm/plugins/k1usn_sst.py,sha256=yeaejs9rgXot1ISayTHFCWtYcNxOT2NG4E9oeXfQrq8,17198
164
165
  not1mm/plugins/labre_rs_digi.py,sha256=93awbxHK2Wi_XZWvUvtaZlQaxpoyX-ev_uj5lm0IZ60,20125
165
166
  not1mm/plugins/lz-dx.py,sha256=hP6APYus4AFpz1rMxU82mq7ZB15_hwgsfuR4qInEG6k,19886
@@ -178,9 +179,9 @@ not1mm/plugins/stew_perry_topband.py,sha256=3U-Dr28haBTqTaZWLiC1qHQBmLsLENDL-ihy
178
179
  not1mm/plugins/ukeidx.py,sha256=0ABGW7_9Ui0Rgr8mkPBxOJokAIerM1a4-HWnl6VsnV8,19105
179
180
  not1mm/plugins/weekly_rtty.py,sha256=C8Xs3Q5UgSYx-mFFar8BVARWtmqlyrbeC98Ubzb4UN8,20128
180
181
  not1mm/plugins/winter_field_day.py,sha256=hmAMgkdqIXtnCNyUp8J9Bb8liN8wj10wps6ROuG-Bok,15284
181
- not1mm-25.4.12.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
182
- not1mm-25.4.12.dist-info/METADATA,sha256=2CaR_uTiFmy3n94pB5vwG4eRTjCO0iTgLAkVBU9C3rA,38276
183
- not1mm-25.4.12.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
184
- not1mm-25.4.12.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
185
- not1mm-25.4.12.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
186
- not1mm-25.4.12.dist-info/RECORD,,
182
+ not1mm-25.4.14.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
183
+ not1mm-25.4.14.dist-info/METADATA,sha256=zEUjyqIWcZk19fufgQqtY-OwoWxDYPuoZ9y0gdbxYEc,39394
184
+ not1mm-25.4.14.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
185
+ not1mm-25.4.14.dist-info/entry_points.txt,sha256=pMcZk_0dxFgLkcUkF0Q874ojpwOmF3OL6EKw9LgvocM,47
186
+ not1mm-25.4.14.dist-info/top_level.txt,sha256=0YmTxEcDzQlzXub-lXASvoLpg_mt1c2thb5cVkDf5J4,7
187
+ not1mm-25.4.14.dist-info/RECORD,,