mdbq 4.0.22__py3-none-any.whl → 4.0.24__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.
@@ -22,7 +22,14 @@ T = TypeVar('T') # 类型变量
22
22
 
23
23
 
24
24
  class ConfigError(Exception):
25
- """配置相关的基础异常类"""
25
+ """配置相关的基础异常类
26
+
27
+ Attributes:
28
+ message: 错误消息
29
+ file_path: 配置文件路径
30
+ section: 配置节名称
31
+ key: 配置键名称
32
+ """
26
33
  def __init__(self, message: str, file_path: Optional[Union[str, Path]] = None,
27
34
  section: Optional[str] = None, key: Optional[str] = None):
28
35
  self.message = message
@@ -44,13 +51,17 @@ class ConfigError(Exception):
44
51
 
45
52
 
46
53
  class ConfigFileNotFoundError(ConfigError):
47
- """配置文件不存在异常"""
54
+ """当指定的配置文件不存在时抛出的异常"""
48
55
  def __init__(self, file_path: Union[str, Path]):
49
56
  super().__init__("配置文件不存在", file_path=file_path)
50
57
 
51
58
 
52
59
  class ConfigReadError(ConfigError):
53
- """读取配置文件失败异常"""
60
+ """当读取配置文件失败时抛出的异常
61
+
62
+ Attributes:
63
+ original_error: 原始错误对象
64
+ """
54
65
  def __init__(self, file_path: Union[str, Path], original_error: Exception):
55
66
  super().__init__(
56
67
  f"读取配置文件失败: {str(original_error)}",
@@ -60,7 +71,11 @@ class ConfigReadError(ConfigError):
60
71
 
61
72
 
62
73
  class ConfigWriteError(ConfigError):
63
- """写入配置文件失败异常"""
74
+ """当写入配置文件失败时抛出的异常
75
+
76
+ Attributes:
77
+ original_error: 原始错误对象
78
+ """
64
79
  def __init__(self, file_path: Union[str, Path], original_error: Exception):
65
80
  super().__init__(
66
81
  f"写入配置文件失败: {str(original_error)}",
@@ -70,14 +85,14 @@ class ConfigWriteError(ConfigError):
70
85
 
71
86
 
72
87
  class ConfigValueError(ConfigError):
73
- """配置值无效异常"""
88
+ """当配置值无效时抛出的异常"""
74
89
  def __init__(self, message: str, file_path: Union[str, Path],
75
90
  section: Optional[str] = None, key: Optional[str] = None):
76
91
  super().__init__(message, file_path=file_path, section=section, key=key)
77
92
 
78
93
 
79
94
  class ConfigSectionNotFoundError(ConfigError):
80
- """配置节不存在异常"""
95
+ """当指定的配置节不存在时抛出的异常"""
81
96
  def __init__(self, file_path: Union[str, Path], section: str):
82
97
  super().__init__(
83
98
  f"配置节不存在",
@@ -87,7 +102,7 @@ class ConfigSectionNotFoundError(ConfigError):
87
102
 
88
103
 
89
104
  class ConfigKeyNotFoundError(ConfigError):
90
- """配置键不存在异常"""
105
+ """当指定的配置键不存在时抛出的异常"""
91
106
  def __init__(self, file_path: Union[str, Path], section: str, key: str):
92
107
  super().__init__(
93
108
  f"配置键不存在",
@@ -106,7 +121,21 @@ class CommentStyle(Enum):
106
121
 
107
122
  @dataclass
108
123
  class ConfigOptions:
109
- """配置解析器选项"""
124
+ """配置解析器的选项类
125
+
126
+ Attributes:
127
+ comment_styles: 支持的注释风格列表
128
+ encoding: 文件编码
129
+ auto_create: 是否自动创建不存在的配置文件
130
+ strip_values: 是否去除配置值的首尾空白
131
+ preserve_comments: 是否保留注释
132
+ default_section: 默认配置节名称
133
+ separators: 支持的分隔符列表
134
+ cache_ttl: 缓存过期时间(秒)
135
+ validate_keys: 是否验证键名
136
+ key_pattern: 键名正则表达式模式
137
+ case_sensitive: 是否区分大小写
138
+ """
110
139
  comment_styles: List[CommentStyle] = field(default_factory=lambda: [CommentStyle.HASH, CommentStyle.DOUBLE_SLASH])
111
140
  encoding: str = 'utf-8'
112
141
  auto_create: bool = False
@@ -121,26 +150,57 @@ class ConfigOptions:
121
150
 
122
151
 
123
152
  class ConfigParser:
124
- """配置文件解析器"""
153
+ """配置文件解析器,用于读取和写入配置文件
154
+
155
+ Attributes:
156
+ options: 解析器配置选项
157
+ _config_cache: 配置缓存,用于存储已读取的配置
158
+ _cache_timestamps: 缓存时间戳,用于管理缓存过期
159
+ _comments_cache: 注释缓存,用于存储每个配置节的注释
160
+ _section_map: 用于存储大小写映射
161
+ _current_file: 当前正在处理的文件路径
162
+ """
125
163
 
126
164
  def __init__(self, options: Optional[ConfigOptions] = None):
127
165
  self.options = options or ConfigOptions()
128
166
  self._config_cache: Dict[str, Dict[str, Any]] = {}
129
167
  self._cache_timestamps: Dict[str, float] = {}
130
168
  self._comments_cache: Dict[str, Dict[str, List[str]]] = {}
131
- self._section_map: Dict[str, Dict[str, str]] = {}
132
- self._current_file: Optional[Path] = None
169
+ self._section_map: Dict[str, Dict[str, str]] = {} # 用于存储大小写映射
170
+ self._current_file: Optional[Path] = None # 当前正在处理的文件路径
133
171
 
134
172
  def __enter__(self) -> 'ConfigParser':
173
+ """进入上下文管理器
174
+
175
+ Returns:
176
+ ConfigParser: 返回当前实例
177
+ """
135
178
  return self
136
179
 
137
180
  def __exit__(self, exc_type: Optional[Type[BaseException]],
138
181
  exc_val: Optional[BaseException],
139
182
  exc_tb: Optional[Any]) -> None:
183
+ """退出上下文管理器
184
+
185
+ Args:
186
+ exc_type: 异常类型
187
+ exc_val: 异常值
188
+ exc_tb: 异常追踪信息
189
+ """
140
190
  self._current_file = None
141
191
 
142
192
  def open(self, file_path: Union[str, Path]) -> 'ConfigParser':
143
- """打开配置文件"""
193
+ """打开配置文件
194
+
195
+ Args:
196
+ file_path: 配置文件路径
197
+
198
+ Returns:
199
+ ConfigParser: 返回当前实例,支持链式调用
200
+
201
+ Raises:
202
+ ConfigFileNotFoundError: 当配置文件不存在且未启用自动创建时
203
+ """
144
204
  file_path = Path(file_path)
145
205
  if not file_path.exists() and not self.options.auto_create:
146
206
  raise ConfigFileNotFoundError(file_path)
@@ -148,17 +208,25 @@ class ConfigParser:
148
208
  return self
149
209
 
150
210
  def _ensure_file_open(self) -> None:
151
- """确保文件已打开"""
211
+ """确保文件已打开
212
+
213
+ Raises:
214
+ ConfigError: 当文件未打开时
215
+ """
152
216
  if self._current_file is None:
153
217
  raise ConfigError("未打开任何配置文件,请先调用 open() 方法")
154
218
 
155
219
  def _is_comment_line(self, line: str) -> bool:
156
- """判断是否为注释行"""
220
+ """判断一行是否为注释行"""
157
221
  stripped = line.strip()
158
222
  return any(stripped.startswith(style.value) for style in self.options.comment_styles)
159
223
 
160
224
  def _extract_comment(self, line: str) -> Tuple[str, str]:
161
- """从行中提取注释"""
225
+ """从行中提取注释
226
+
227
+ Returns:
228
+ Tuple[str, str]: (去除注释后的行内容, 注释内容)
229
+ """
162
230
  for style in self.options.comment_styles:
163
231
  comment_match = re.search(fr'\s+{re.escape(style.value)}.*$', line)
164
232
  if comment_match:
@@ -166,7 +234,14 @@ class ConfigParser:
166
234
  return line.strip(), ''
167
235
 
168
236
  def _split_key_value(self, line: str) -> Optional[Tuple[str, str]]:
169
- """分割配置行为键值对"""
237
+ """分割配置行为键值对
238
+
239
+ Args:
240
+ line: 要分割的配置行
241
+
242
+ Returns:
243
+ Optional[Tuple[str, str]]: 键值对元组,如果无法分割则返回None
244
+ """
170
245
  for sep in self.options.separators:
171
246
  if sep in line:
172
247
  key_part, value_part = line.split(sep, 1)
@@ -188,8 +263,11 @@ class ConfigParser:
188
263
  return bool(re.match(self.options.key_pattern, key))
189
264
 
190
265
  def _get_cached_config(self, file_path: str) -> Optional[Dict[str, Any]]:
191
- """获取缓存的配置"""
192
- if file_path not in self._config_cache or file_path not in self._cache_timestamps:
266
+ """获取缓存的配置,如果过期则返回None"""
267
+ if file_path not in self._config_cache:
268
+ return None
269
+
270
+ if file_path not in self._cache_timestamps:
193
271
  return None
194
272
 
195
273
  if time.time() - self._cache_timestamps[file_path] > self.options.cache_ttl:
@@ -203,8 +281,10 @@ class ConfigParser:
203
281
  self._cache_timestamps[file_path] = time.time()
204
282
 
205
283
  def _normalize_section(self, section: str) -> str:
206
- """标准化节名称"""
207
- return section if self.options.case_sensitive else section.lower()
284
+ """标准化节名称(处理大小写)"""
285
+ if self.options.case_sensitive:
286
+ return section
287
+ return section.lower()
208
288
 
209
289
  def _get_original_section(self, file_path: str, normalized_section: str) -> Optional[str]:
210
290
  """获取原始节名称"""
@@ -234,35 +314,57 @@ class ConfigParser:
234
314
  self._section_map.clear()
235
315
 
236
316
  def _convert_value(self, value: str, target_type: Type[T]) -> T:
237
- """转换配置值到指定类型"""
317
+ """转换配置值到指定类型
318
+
319
+ Args:
320
+ value: 要转换的值
321
+ target_type: 目标类型
322
+
323
+ Returns:
324
+ T: 转换后的值
325
+
326
+ Raises:
327
+ ConfigValueError: 当值无法转换为指定类型时
328
+ """
238
329
  try:
239
330
  if target_type == bool:
240
331
  return bool(value.lower() in ('true', 'yes', '1', 'on'))
241
332
  elif target_type == list:
333
+ # 支持多种分隔符的列表
242
334
  if not value.strip():
243
335
  return []
336
+ # 尝试不同的分隔符
244
337
  for sep in [',', ';', '|', ' ']:
245
338
  if sep in value:
246
339
  return [item.strip() for item in value.split(sep) if item.strip()]
340
+ # 如果没有分隔符,则作为单个元素返回
247
341
  return [value.strip()]
248
342
  elif target_type == tuple:
343
+ # 支持元组类型
249
344
  if not value.strip():
250
345
  return ()
346
+ # 尝试不同的分隔符
251
347
  for sep in [',', ';', '|', ' ']:
252
348
  if sep in value:
253
349
  return tuple(item.strip() for item in value.split(sep) if item.strip())
350
+ # 如果没有分隔符,则作为单个元素返回
254
351
  return (value.strip(),)
255
352
  elif target_type == set:
353
+ # 支持集合类型
256
354
  if not value.strip():
257
355
  return set()
356
+ # 尝试不同的分隔符
258
357
  for sep in [',', ';', '|', ' ']:
259
358
  if sep in value:
260
359
  return {item.strip() for item in value.split(sep) if item.strip()}
360
+ # 如果没有分隔符,则作为单个元素返回
261
361
  return {value.strip()}
262
362
  elif target_type == dict:
363
+ # 支持字典类型,格式:key1=value1,key2=value2
263
364
  if not value.strip():
264
365
  return {}
265
366
  result = {}
367
+ # 尝试不同的分隔符
266
368
  for sep in [',', ';', '|']:
267
369
  if sep in value:
268
370
  pairs = [pair.strip() for pair in value.split(sep) if pair.strip()]
@@ -271,11 +373,13 @@ class ConfigParser:
271
373
  key, val = pair.split('=', 1)
272
374
  result[key.strip()] = val.strip()
273
375
  return result
376
+ # 如果没有分隔符,尝试单个键值对
274
377
  if '=' in value:
275
378
  key, val = value.split('=', 1)
276
379
  return {key.strip(): val.strip()}
277
380
  return {}
278
381
  elif target_type == int:
382
+ # 支持十六进制、八进制、二进制
279
383
  value = value.strip().lower()
280
384
  if value.startswith('0x'):
281
385
  return int(value, 16)
@@ -297,6 +401,7 @@ class ConfigParser:
297
401
  elif target_type == frozenset:
298
402
  return frozenset(value.split(','))
299
403
  elif target_type == range:
404
+ # 支持 range 类型,格式:start:stop:step 或 start:stop
300
405
  parts = value.split(':')
301
406
  if len(parts) == 2:
302
407
  return range(int(parts[0]), int(parts[1]))
@@ -314,7 +419,23 @@ class ConfigParser:
314
419
  def get_value(self, file_path: Optional[Union[str, Path]] = None, key: str = None,
315
420
  section: Optional[str] = None, default: Any = None,
316
421
  value_type: Optional[Type[T]] = None) -> T:
317
- """获取指定配置项的值"""
422
+ """获取指定配置项的值
423
+
424
+ Args:
425
+ file_path: 配置文件路径,如果为None则使用当前打开的文件
426
+ key: 配置键
427
+ section: 配置节名称,如果为None则使用默认节
428
+ default: 当配置项不存在时返回的默认值
429
+ value_type: 期望的值的类型
430
+
431
+ Returns:
432
+ T: 配置值
433
+
434
+ Raises:
435
+ ConfigSectionNotFoundError: 当指定的节不存在且未提供默认值时
436
+ ConfigKeyNotFoundError: 当指定的键不存在且未提供默认值时
437
+ ConfigValueError: 当值无法转换为指定类型时
438
+ """
318
439
  if file_path is None:
319
440
  self._ensure_file_open()
320
441
  file_path = self._current_file
@@ -325,6 +446,7 @@ class ConfigParser:
325
446
  section = section or self.options.default_section
326
447
  normalized_section = self._normalize_section(section)
327
448
 
449
+ # 获取原始节名称
328
450
  original_section = self._get_original_section(str(file_path), normalized_section)
329
451
  if original_section is None:
330
452
  if default is not None:
@@ -347,7 +469,22 @@ class ConfigParser:
347
469
  file_path: Optional[Union[str, Path]] = None,
348
470
  defaults: Optional[Dict[str, Any]] = None,
349
471
  value_types: Optional[Dict[str, Type]] = None) -> Dict[str, Any]:
350
- """批量获取多个配置项的值"""
472
+ """批量获取多个配置项的值
473
+
474
+ Args:
475
+ keys: 配置项列表,每个元素为 (section, key) 元组
476
+ file_path: 配置文件路径,如果为None则使用当前打开的文件
477
+ defaults: 默认值字典,格式为 {key: default_value}
478
+ value_types: 值类型字典,格式为 {key: type}
479
+
480
+ Returns:
481
+ Dict[str, Any]: 配置值字典,格式为 {key: value}
482
+
483
+ Raises:
484
+ ConfigSectionNotFoundError: 当指定的节不存在且未提供默认值时
485
+ ConfigKeyNotFoundError: 当指定的键不存在且未提供默认值时
486
+ ConfigValueError: 当值无法转换为指定类型时
487
+ """
351
488
  if file_path is None:
352
489
  self._ensure_file_open()
353
490
  file_path = self._current_file
@@ -378,7 +515,23 @@ class ConfigParser:
378
515
  file_path: Optional[Union[str, Path]] = None,
379
516
  defaults: Optional[Dict[str, Any]] = None,
380
517
  value_types: Optional[Dict[str, Type]] = None) -> Tuple[Any, ...]:
381
- """获取指定节点下多个键的值元组"""
518
+ """获取指定节点下多个键的值元组
519
+
520
+ Args:
521
+ keys: 要获取的键列表
522
+ section: 配置节名称,默认为 DEFAULT
523
+ file_path: 配置文件路径,如果为None则使用当前打开的文件
524
+ defaults: 默认值字典,格式为 {key: default_value}
525
+ value_types: 值类型字典,格式为 {key: type}
526
+
527
+ Returns:
528
+ Tuple[Any, ...]: 按键列表顺序返回的值元组
529
+
530
+ Raises:
531
+ ConfigSectionNotFoundError: 当指定的节不存在且未提供默认值时
532
+ ConfigKeyNotFoundError: 当指定的键不存在且未提供默认值时
533
+ ConfigValueError: 当值无法转换为指定类型时
534
+ """
382
535
  if file_path is None:
383
536
  self._ensure_file_open()
384
537
  file_path = self._current_file
@@ -408,18 +561,32 @@ class ConfigParser:
408
561
  section: Optional[str] = None,
409
562
  file_path: Optional[Union[str, Path]] = None,
410
563
  value_type: Optional[Type] = None) -> None:
411
- """设置指定配置项的值"""
564
+ """设置指定配置项的值,保持原始文件的格式和注释
565
+
566
+ Args:
567
+ key: 配置键
568
+ value: 要设置的值
569
+ section: 配置节名称,如果为None则使用默认节
570
+ file_path: 配置文件路径,如果为None则使用当前打开的文件
571
+ value_type: 值的类型,用于验证和转换
572
+
573
+ Raises:
574
+ ConfigValueError: 当值无法转换为指定类型时
575
+ ConfigError: 当其他配置错误发生时
576
+ """
412
577
  if file_path is None:
413
578
  self._ensure_file_open()
414
579
  file_path = self._current_file
415
580
  if not self._validate_key(key):
416
581
  raise ConfigValueError(f"无效的键名: {key}", file_path=file_path, key=key)
417
582
 
583
+ # 读取原始文件內容
418
584
  original_lines = []
419
585
  if file_path.exists():
420
586
  with open(file_path, 'r', encoding=self.options.encoding) as file:
421
587
  original_lines = file.readlines()
422
588
 
589
+ # 读取当前配置
423
590
  config = self.read(file_path)
424
591
 
425
592
  if section not in config:
@@ -447,53 +614,61 @@ class ConfigParser:
447
614
  else:
448
615
  value = str(value)
449
616
 
617
+ # 更新配置
450
618
  config[section][key] = value
451
619
 
620
+ # 写入文件,保持原始格式
452
621
  try:
453
622
  file_path.parent.mkdir(parents=True, exist_ok=True)
454
623
 
455
624
  with open(file_path, 'w', encoding=self.options.encoding) as file:
456
625
  current_section = self.options.default_section
457
- section_separators = {}
626
+ section_separators = {} # 用于存储每个section使用的分隔符
458
627
 
628
+ # 解析原始文件,提取格式信息
459
629
  for line in original_lines:
460
630
  stripped_line = line.strip()
461
631
 
462
632
  if not stripped_line:
463
- file.write(line)
633
+ file.write(line) # 保持空行
464
634
  continue
465
635
 
466
636
  if stripped_line.startswith('[') and stripped_line.endswith(']'):
467
637
  current_section = stripped_line[1:-1]
468
- file.write(line)
638
+ file.write(line) # 保持节标记的原始格式
469
639
  continue
470
640
 
471
641
  if self._is_comment_line(stripped_line):
472
- file.write(line)
642
+ file.write(line) # 保持注释的原始格式
473
643
  continue
474
644
 
475
645
  key_value = self._split_key_value(stripped_line)
476
646
  if key_value:
477
647
  orig_key, orig_value = key_value
648
+ # 检测使用的分隔符
478
649
  for sep in self.options.separators:
479
650
  if sep in line:
480
651
  section_separators.setdefault(current_section, {})[orig_key] = sep
481
652
  break
482
653
 
654
+ # 如果是当前要修改的键,则写入新值
483
655
  if current_section == section and orig_key == key:
484
656
  separator = section_separators.get(current_section, {}).get(orig_key, self.options.separators[0])
657
+ # 提取行尾注释
485
658
  comment = ''
486
659
  for style in self.options.comment_styles:
487
660
  comment_match = re.search(fr'\s+{re.escape(style.value)}.*$', line)
488
661
  if comment_match:
489
662
  comment = comment_match.group(0)
490
663
  break
664
+ # 写入新值并保留注释
491
665
  file.write(f'{key}{separator}{value}{comment}\n')
492
666
  else:
493
- file.write(line)
667
+ file.write(line) # 保持其他行的原始格式
494
668
  else:
495
- file.write(line)
669
+ file.write(line) # 保持无法解析的行的原始格式
496
670
 
671
+ # 如果section不存在,则添加新的section
497
672
  if section not in [line.strip()[1:-1] for line in original_lines if line.strip().startswith('[') and line.strip().endswith(']')]:
498
673
  file.write(f'\n[{section}]\n')
499
674
  file.write(f'{key}={value}\n')
@@ -504,13 +679,25 @@ class ConfigParser:
504
679
  raise ConfigWriteError(file_path, e)
505
680
 
506
681
  def read(self, file_path: Optional[Union[str, Path]] = None) -> Dict[str, Any]:
507
- """读取配置文件内容"""
682
+ """读取配置文件内容
683
+
684
+ Args:
685
+ file_path: 配置文件路径,如果为None则使用当前打开的文件
686
+
687
+ Returns:
688
+ Dict[str, Any]: 配置字典,格式为 {section: {key: value}}
689
+
690
+ Raises:
691
+ ConfigFileNotFoundError: 当配置文件不存在且未启用自动创建时
692
+ ConfigReadError: 当读取配置文件失败时
693
+ """
508
694
  if file_path is None:
509
695
  self._ensure_file_open()
510
696
  file_path = self._current_file
511
697
  else:
512
- file_path = Path(file_path)
698
+ file_path = Path(file_path) # 确保 file_path 是 Path 对象
513
699
 
700
+ # 检查缓存
514
701
  cached_config = self._get_cached_config(str(file_path))
515
702
  if cached_config is not None:
516
703
  return cached_config
@@ -580,10 +767,10 @@ class ConfigParser:
580
767
 
581
768
  except Exception as e:
582
769
  raise ConfigReadError(file_path, e)
583
-
770
+
584
771
 
585
772
  def main() -> None:
586
- """示例用法"""
773
+ # 使用示例
587
774
  config_file = Path('/Users/xigua/spd.txt')
588
775
 
589
776
  # 方式1:使用上下文管理器
@@ -595,8 +782,17 @@ def main() -> None:
595
782
  )
596
783
  print("方式1结果:", host, port, username, password)
597
784
 
598
- parser.set_value('username', 'root', section='mysql')
785
+ # 修改配置
786
+ parser.set_value('host', 'localhost', section='mysql')
599
787
  parser.set_value('port', 3306, section='mysql')
788
+
789
+ # # 读取整个配置
790
+ # config = parser.read()
791
+ # print("\n当前配置:")
792
+ # for section, items in config.items():
793
+ # print(f"\n[{section}]")
794
+ # for key, value in items.items():
795
+ # print(f"{key} = {value}")
600
796
 
601
797
  # 方式2:链式调用
602
798
  parser = ConfigParser()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: mdbq
3
- Version: 4.0.22
3
+ Version: 4.0.24
4
4
  Home-page: https://pypi.org/project/mdbq
5
5
  Author: xigua,
6
6
  Author-email: 2587125111@qq.com
@@ -1,12 +1,12 @@
1
1
  mdbq/__init__.py,sha256=Il5Q9ATdX8yXqVxtP_nYqUhExzxPC_qk_WXQ_4h0exg,16
2
- mdbq/__version__.py,sha256=gSoWvHL6N2Idp7W1joFJ-FzlUGBvhO24bsaGJ6I1x-Y,18
2
+ mdbq/__version__.py,sha256=wqkHwHHyiDvYn4A3ae0ZValbllKttXTiaXdM1wQ4Oio,18
3
3
  mdbq/aggregation/__init__.py,sha256=EeDqX2Aml6SPx8363J-v1lz0EcZtgwIBYyCJV6CcEDU,40
4
4
  mdbq/aggregation/query_data.py,sha256=hdaB0vPh5BcTu9kLViRvM7OAE0b07D4jzAIipqxGI-I,166757
5
5
  mdbq/log/__init__.py,sha256=Mpbrav0s0ifLL7lVDAuePEi1hJKiSHhxcv1byBKDl5E,15
6
6
  mdbq/log/mylogger.py,sha256=9w_o5mYB3FooIxobq_lSa6oCYTKIhPxDFox-jeLtUHI,21714
7
7
  mdbq/myconf/__init__.py,sha256=jso1oHcy6cJEfa7udS_9uO5X6kZLoPBF8l3wCYmr5dM,18
8
- mdbq/myconf/myconf.py,sha256=39tLUBVlWQZzQfrwk7YoLEfipo11fpwWjaLBHcUt2qM,33341
9
- mdbq/myconf/myconf2.py,sha256=kaHhOvKMVOilu9JYKfsefF08tUyC99B8aWUZJvc_oh8,25481
8
+ mdbq/myconf/myconf.py,sha256=8b3qHPKII9eh0zPHu97UiykminLjT7ePL_Bj4511wno,30737
9
+ mdbq/myconf/myconf_bak.py,sha256=39tLUBVlWQZzQfrwk7YoLEfipo11fpwWjaLBHcUt2qM,33341
10
10
  mdbq/mysql/__init__.py,sha256=A_DPJyAoEvTSFojiI2e94zP0FKtCkkwKP1kYUCSyQzo,11
11
11
  mdbq/mysql/deduplicator.py,sha256=kAnkI_vnN8CchgDQAFzeh0M0vLXE2oWq9SfDPNZZ3v0,73215
12
12
  mdbq/mysql/mysql.py,sha256=pDg771xBugCMSTWeskIFTi3pFLgaqgyG3smzf-86Wn8,56772
@@ -25,7 +25,7 @@ mdbq/redis/__init__.py,sha256=YtgBlVSMDphtpwYX248wGge1x-Ex_mMufz4-8W0XRmA,12
25
25
  mdbq/redis/getredis.py,sha256=vpBuNc22uj9Vr-_Dh25_wpwWM1e-072EAAIBdB_IpL0,23494
26
26
  mdbq/spider/__init__.py,sha256=RBMFXGy_jd1HXZhngB2T2XTvJqki8P_Fr-pBcwijnew,18
27
27
  mdbq/spider/aikucun.py,sha256=juOqpr_dHeE1RyjCu67VcpzoJAWMO7FKv0i8KiH8WUo,21552
28
- mdbq-4.0.22.dist-info/METADATA,sha256=EVHw5Bw16kqgOfKjnTmRY9SpDDpj882dD0UjB_ogT6w,364
29
- mdbq-4.0.22.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
30
- mdbq-4.0.22.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
31
- mdbq-4.0.22.dist-info/RECORD,,
28
+ mdbq-4.0.24.dist-info/METADATA,sha256=JcQ-QkG1iGN2YJu6zumBvrliRSpKSZIJ_ARoJDc28so,364
29
+ mdbq-4.0.24.dist-info/WHEEL,sha256=jB7zZ3N9hIM9adW7qlTAyycLYW9npaWKLRzaoVcLKcM,91
30
+ mdbq-4.0.24.dist-info/top_level.txt,sha256=2FQ-uLnCSB-OwFiWntzmwosW3X2Xqsg0ewh1axsaylA,5
31
+ mdbq-4.0.24.dist-info/RECORD,,
File without changes