pymud 0.21.2a2__py3-none-any.whl → 0.21.2.post1__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.
- pymud/extras.py +116 -74
- pymud/pymud.py +6 -6
- pymud/session.py +0 -11
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/METADATA +8 -6
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/RECORD +9 -9
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/WHEEL +0 -0
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/entry_points.txt +0 -0
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/licenses/LICENSE.txt +0 -0
- {pymud-0.21.2a2.dist-info → pymud-0.21.2.post1.dist-info}/top_level.txt +0 -0
pymud/extras.py
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# External Libraries
|
2
|
+
from functools import lru_cache
|
2
3
|
from unicodedata import east_asian_width
|
3
4
|
from wcwidth import wcwidth
|
4
5
|
from dataclasses import dataclass
|
5
|
-
import time, re, logging
|
6
|
-
|
6
|
+
import time, re, logging, linecache, os
|
7
|
+
from typing import Optional, List, Dict
|
7
8
|
from typing import Iterable, NamedTuple, Optional, Union, Tuple
|
8
9
|
from prompt_toolkit import ANSI
|
9
10
|
from prompt_toolkit.application import get_app
|
@@ -236,7 +237,7 @@ class VSplitWindow(Window):
|
|
236
237
|
below = total - upper - 1
|
237
238
|
|
238
239
|
#if isNotMargin:
|
239
|
-
if isinstance(self.content,
|
240
|
+
if isinstance(self.content, PyMudBufferControl):
|
240
241
|
b = self.content.buffer
|
241
242
|
if not b:
|
242
243
|
return y
|
@@ -379,7 +380,7 @@ class VSplitWindow(Window):
|
|
379
380
|
if info is None:
|
380
381
|
return
|
381
382
|
|
382
|
-
if isinstance(self.content,
|
383
|
+
if isinstance(self.content, PyMudBufferControl):
|
383
384
|
b = self.content.buffer
|
384
385
|
if not b:
|
385
386
|
return
|
@@ -396,7 +397,7 @@ class VSplitWindow(Window):
|
|
396
397
|
if info is None:
|
397
398
|
return
|
398
399
|
|
399
|
-
if isinstance(self.content,
|
400
|
+
if isinstance(self.content, PyMudBufferControl):
|
400
401
|
b = self.content.buffer
|
401
402
|
if not b:
|
402
403
|
return
|
@@ -520,6 +521,7 @@ class EasternMenuContainer(MenuContainer):
|
|
520
521
|
|
521
522
|
return Window(FormattedTextControl(get_text_fragments), style="class:menu")
|
522
523
|
|
524
|
+
|
523
525
|
@dataclass
|
524
526
|
class SessionSelectionState:
|
525
527
|
start_row: int = -1
|
@@ -549,9 +551,53 @@ class SessionSelectionState:
|
|
549
551
|
return self.end_row - self.start_row + 1
|
550
552
|
else:
|
551
553
|
return 0
|
552
|
-
|
553
554
|
|
554
|
-
|
555
|
+
|
556
|
+
class BufferBase:
|
557
|
+
def __init__(self, name, newline = "\n", max_buffered_lines = 10000) -> None:
|
558
|
+
self.name = name
|
559
|
+
self.newline = newline
|
560
|
+
self.max_buffered_lines = max_buffered_lines
|
561
|
+
self.start_lineno = -1
|
562
|
+
self.selection = SessionSelectionState(-1, -1, -1, -1)
|
563
|
+
|
564
|
+
def clear(self):
|
565
|
+
pass
|
566
|
+
|
567
|
+
@property
|
568
|
+
def lineCount(self) -> int:
|
569
|
+
return 0
|
570
|
+
|
571
|
+
def getLine(self, lineno: int) -> str:
|
572
|
+
return ""
|
573
|
+
|
574
|
+
# 获取指定某行到某行的内容。当start未设置时,从首行开始。当end未设置时,到最后一行结束。
|
575
|
+
# 注意判断首位顺序逻辑,以及给定参数是否越界
|
576
|
+
def selection_range_at_line(self, lineno: int) -> Optional[Tuple[int, int]]:
|
577
|
+
if self.selection.is_valid():
|
578
|
+
if self.selection.rows > 1:
|
579
|
+
if lineno == self.selection.start_row:
|
580
|
+
return (self.selection.start_col, len(self.getLine(lineno)) - 1)
|
581
|
+
elif lineno == self.selection.end_row:
|
582
|
+
return (0, self.selection.end_col)
|
583
|
+
elif lineno > self.selection.start_row and lineno < self.selection.end_row:
|
584
|
+
return (0, len(self.getLine(lineno)) - 1)
|
585
|
+
|
586
|
+
elif self.selection.rows == 1:
|
587
|
+
if lineno == self.selection.start_row:
|
588
|
+
return (self.selection.start_col, self.selection.end_col)
|
589
|
+
|
590
|
+
return None
|
591
|
+
|
592
|
+
def exit_selection(self):
|
593
|
+
self.selection = SessionSelectionState(-1, -1, -1, -1)
|
594
|
+
|
595
|
+
def nosplit(self):
|
596
|
+
self.start_lineno = -1
|
597
|
+
get_app().invalidate()
|
598
|
+
|
599
|
+
|
600
|
+
class SessionBuffer(BufferBase):
|
555
601
|
def __init__(
|
556
602
|
self,
|
557
603
|
name,
|
@@ -559,13 +605,10 @@ class SessionBuffer:
|
|
559
605
|
max_buffered_lines = 10000,
|
560
606
|
) -> None:
|
561
607
|
|
562
|
-
|
563
|
-
|
564
|
-
self.
|
565
|
-
self.
|
566
|
-
self.max_buffered_lines = max_buffered_lines
|
567
|
-
self.selection = SessionSelectionState(-1, -1, -1, -1)
|
568
|
-
self.start_lineno = -1
|
608
|
+
super().__init__(name, newline, max_buffered_lines)
|
609
|
+
|
610
|
+
self._lines : List[str] = []
|
611
|
+
self._isnewline = True
|
569
612
|
|
570
613
|
def append(self, line: str):
|
571
614
|
"""
|
@@ -578,25 +621,25 @@ class SessionBuffer:
|
|
578
621
|
line = line.rstrip(self.newline)
|
579
622
|
newline_after_append = True
|
580
623
|
if not self.newline in line:
|
581
|
-
if self.
|
582
|
-
self.
|
624
|
+
if self._isnewline:
|
625
|
+
self._lines.append(line)
|
583
626
|
else:
|
584
|
-
self.
|
627
|
+
self._lines[-1] += line
|
585
628
|
|
586
629
|
else:
|
587
630
|
lines = line.split(self.newline)
|
588
|
-
if self.
|
589
|
-
self.
|
631
|
+
if self._isnewline:
|
632
|
+
self._lines.extend(lines)
|
590
633
|
else:
|
591
|
-
self.
|
592
|
-
self.
|
634
|
+
self._lines[-1] += lines[0]
|
635
|
+
self._lines.extend(lines[1:])
|
593
636
|
|
594
|
-
self.
|
637
|
+
self._isnewline = newline_after_append
|
595
638
|
|
596
639
|
## limit buffered lines
|
597
|
-
if len(self.
|
598
|
-
diff = self.
|
599
|
-
del self.
|
640
|
+
if len(self._lines) > self.max_buffered_lines:
|
641
|
+
diff = len(self._lines) - self.max_buffered_lines
|
642
|
+
del self._lines[:diff]
|
600
643
|
## adjust selection
|
601
644
|
if self.selection.start_row >= 0:
|
602
645
|
self.selection.start_row -= diff
|
@@ -605,68 +648,60 @@ class SessionBuffer:
|
|
605
648
|
get_app().invalidate()
|
606
649
|
|
607
650
|
def clear(self):
|
608
|
-
self.
|
651
|
+
self._lines.clear()
|
609
652
|
self.selection = SessionSelectionState(-1, -1, -1, -1)
|
610
653
|
|
611
654
|
get_app().invalidate()
|
612
655
|
|
613
|
-
def loadfile(self, filename, encoding = 'utf-8', errors = 'ignore'):
|
614
|
-
with open(filename, 'r', encoding = encoding, errors = errors) as fp:
|
615
|
-
lines = fp.readlines()
|
616
|
-
self.clear()
|
617
|
-
self.lines.extend(lines)
|
618
|
-
|
619
|
-
get_app().invalidate()
|
620
|
-
|
621
656
|
@property
|
622
657
|
def lineCount(self):
|
623
|
-
return len(self.
|
658
|
+
return len(self._lines)
|
624
659
|
|
625
|
-
def getLine(self, lineno):
|
626
|
-
if lineno < 0 or lineno >= len(self.
|
660
|
+
def getLine(self, lineno: int):
|
661
|
+
if lineno < 0 or lineno >= len(self._lines):
|
627
662
|
return ""
|
628
|
-
return self.
|
663
|
+
return self._lines[lineno]
|
629
664
|
|
630
|
-
# 获取指定某行到某行的内容。当start未设置时,从首行开始。当end未设置时,到最后一行结束。
|
631
|
-
# 注意判断首位顺序逻辑,以及给定参数是否越界
|
632
|
-
def getLines(self, start = None, end = None):
|
633
|
-
if start is None:
|
634
|
-
start = 0
|
635
|
-
if end is None:
|
636
|
-
end = len(self.lines) - 1
|
637
|
-
if start < 0:
|
638
|
-
start = 0
|
639
|
-
if end >= len(self.lines):
|
640
|
-
end = len(self.lines) - 1
|
641
|
-
if start > end:
|
642
|
-
return []
|
643
|
-
return self.lines[start:end+1]
|
644
|
-
|
645
|
-
def selection_range_at_line(self, lineno):
|
646
|
-
if self.selection.is_valid():
|
647
|
-
if self.selection.rows > 1:
|
648
|
-
if lineno == self.selection.start_row:
|
649
|
-
return (self.selection.start_col, len(self.lines[lineno]) - 1)
|
650
|
-
elif lineno == self.selection.end_row:
|
651
|
-
return (0, self.selection.end_col)
|
652
|
-
elif lineno > self.selection.start_row and lineno < self.selection.end_row:
|
653
|
-
return (0, len(self.lines[lineno]) - 1)
|
654
665
|
|
655
|
-
|
656
|
-
|
657
|
-
|
666
|
+
class LogFileBuffer(BufferBase):
|
667
|
+
def __init__(
|
668
|
+
self,
|
669
|
+
name,
|
670
|
+
filepath: Optional[str] = None,
|
671
|
+
) -> None:
|
658
672
|
|
659
|
-
|
673
|
+
super().__init__(name)
|
674
|
+
self._lines : Dict[int, str] = {}
|
675
|
+
self.loadfile(filepath)
|
676
|
+
|
677
|
+
def loadfile(self, filepath: Optional[str] = None):
|
678
|
+
if filepath and os.path.exists(filepath):
|
679
|
+
self.filepath = filepath
|
680
|
+
else:
|
681
|
+
self.filepath = None
|
660
682
|
|
661
|
-
def
|
662
|
-
self.
|
683
|
+
def clear(self):
|
684
|
+
self.filepath = None
|
663
685
|
|
664
|
-
|
665
|
-
|
666
|
-
|
686
|
+
@property
|
687
|
+
def lineCount(self):
|
688
|
+
if not self.filepath or not os.path.exists(self.filepath):
|
689
|
+
return 0
|
690
|
+
|
691
|
+
with open(self.filepath, 'r', encoding = 'utf-8', errors = 'ignore') as fp:
|
692
|
+
return sum(1 for _ in fp)
|
693
|
+
|
694
|
+
def getLine(self, lineno: int):
|
695
|
+
if not self.filepath or not os.path.exists(self.filepath):
|
696
|
+
return ""
|
667
697
|
|
668
|
-
|
669
|
-
|
698
|
+
return linecache.getline(self.filepath, lineno).rstrip(self.newline)
|
699
|
+
|
700
|
+
def __del__(self):
|
701
|
+
self._lines.clear()
|
702
|
+
|
703
|
+
class PyMudBufferControl(UIControl):
|
704
|
+
def __init__(self, buffer: Optional[BufferBase]) -> None:
|
670
705
|
self.buffer = buffer
|
671
706
|
|
672
707
|
# 为MUD显示进行校正的处理,包括对齐校正,换行颜色校正等
|
@@ -746,10 +781,14 @@ class SessionBufferControl(UIControl):
|
|
746
781
|
def get_line(i: int) -> StyleAndTextTuples:
|
747
782
|
line = buffer.getLine(i)
|
748
783
|
# 颜色校正
|
784
|
+
SEARCH_LINES = 10
|
749
785
|
thislinecolors = len(self.AVAI_COLOR_REGX.findall(line))
|
750
786
|
if thislinecolors == 0:
|
751
787
|
lineno = i - 1
|
752
|
-
|
788
|
+
search = 0
|
789
|
+
while lineno >= 0 and search < SEARCH_LINES:
|
790
|
+
search += 1
|
791
|
+
|
753
792
|
lastline = buffer.getLine(lineno)
|
754
793
|
allcolors = self.ALL_COLOR_REGX.findall(lastline)
|
755
794
|
|
@@ -885,6 +924,9 @@ class SessionBufferControl(UIControl):
|
|
885
924
|
else:
|
886
925
|
# Don't handle scroll events here.
|
887
926
|
return NotImplemented
|
927
|
+
else:
|
928
|
+
# Don't handle scroll events here.
|
929
|
+
return NotImplemented
|
888
930
|
|
889
931
|
# Not focused, but focusing on click events.
|
890
932
|
else:
|
pymud/pymud.py
CHANGED
@@ -37,7 +37,7 @@ from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
|
37
37
|
from wcwidth import wcwidth, wcswidth
|
38
38
|
|
39
39
|
from .objects import CodeBlock
|
40
|
-
from .extras import SessionBuffer,
|
40
|
+
from .extras import BufferBase, LogFileBuffer, SessionBuffer, PyMudBufferControl, EasternMenuContainer, VSplitWindow, DotDict, MenuItem
|
41
41
|
from .modules import Plugin
|
42
42
|
from .session import Session
|
43
43
|
from .settings import Settings
|
@@ -164,7 +164,7 @@ class PyMudApp:
|
|
164
164
|
self.logFileShown = '' # 记录页显示的记录文件名
|
165
165
|
#self.logSessionBuffer = SessionBuffer()
|
166
166
|
#self.logSessionBuffer.name = "LOGBUFFER"
|
167
|
-
self.logSessionBuffer =
|
167
|
+
self.logSessionBuffer = LogFileBuffer("LOGBUFFER")
|
168
168
|
|
169
169
|
self.load_plugins()
|
170
170
|
|
@@ -218,7 +218,7 @@ class PyMudApp:
|
|
218
218
|
show_cursor=False
|
219
219
|
)
|
220
220
|
|
221
|
-
self.consoleView =
|
221
|
+
self.consoleView = PyMudBufferControl(
|
222
222
|
buffer = None,
|
223
223
|
)
|
224
224
|
|
@@ -398,7 +398,7 @@ class PyMudApp:
|
|
398
398
|
else:
|
399
399
|
b = None
|
400
400
|
|
401
|
-
if isinstance(b,
|
401
|
+
if isinstance(b, BufferBase):
|
402
402
|
if lines < 0:
|
403
403
|
if b.start_lineno < 0:
|
404
404
|
self.console._scroll_up()
|
@@ -659,7 +659,7 @@ class PyMudApp:
|
|
659
659
|
if os.path.exists(filename):
|
660
660
|
lock = threading.RLock()
|
661
661
|
lock.acquire()
|
662
|
-
self.logSessionBuffer.loadfile(filename
|
662
|
+
self.logSessionBuffer.loadfile(filename)
|
663
663
|
lock.release()
|
664
664
|
|
665
665
|
#self.logSessionBuffer.cursor_position = len(self.logSessionBuffer.text)
|
@@ -751,7 +751,7 @@ class PyMudApp:
|
|
751
751
|
|
752
752
|
elif self.showLog:
|
753
753
|
b = self.logSessionBuffer
|
754
|
-
b.exit_selection()
|
754
|
+
#b.exit_selection()
|
755
755
|
#b.cursor_position = len(b.text)
|
756
756
|
#b.start_lineno = -1
|
757
757
|
b.nosplit()
|
pymud/session.py
CHANGED
@@ -571,16 +571,6 @@ class Session:
|
|
571
571
|
self._line_count += 1
|
572
572
|
self.log.log(self.newline_cli)
|
573
573
|
|
574
|
-
def clear_half(self):
|
575
|
-
"""
|
576
|
-
清除半数缓冲。 **脚本中无需调用。**
|
577
|
-
|
578
|
-
半数的数量由 Settings.client['buffer_lines'] 确定,默认为5000行。
|
579
|
-
"""
|
580
|
-
# if (Settings.client["buffer_lines"] > 0) and (self._line_count >= 2 * Settings.client["buffer_lines"]) and self.buffer.document.is_cursor_at_the_end:
|
581
|
-
# self._line_count = self.buffer.clear_half()
|
582
|
-
pass
|
583
|
-
|
584
574
|
def feed_data(self, data) -> None:
|
585
575
|
"""
|
586
576
|
由协议对象调用,将收到的远程数据加入会话缓冲。永远只会传递1个字节的数据,以bytes形式。 **脚本中无需调用。**
|
@@ -695,7 +685,6 @@ class Session:
|
|
695
685
|
|
696
686
|
# 将数据写入缓存添加到此处
|
697
687
|
if len(self.display_line) > 0:
|
698
|
-
self.clear_half()
|
699
688
|
self.writetobuffer(self.display_line)
|
700
689
|
|
701
690
|
def set_exception(self, exc: Exception):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pymud
|
3
|
-
Version: 0.21.
|
3
|
+
Version: 0.21.2.post1
|
4
4
|
Summary: a MUD Client written in Python
|
5
5
|
Author-email: "newstart@pkuxkx" <crapex@hotmail.com>
|
6
6
|
Maintainer-email: "newstart@pkuxkx" <crapex@hotmail.com>
|
@@ -44,11 +44,11 @@ Dynamic: license-file
|
|
44
44
|
|
45
45
|
### 北大侠客行Mud (www.pkuxkx.net),最好的中文Mud游戏!
|
46
46
|
### PyMUD是我为了更好的玩北大侠客行,特意自行开发的MUD客户端。PyMUD具有以下特点:
|
47
|
-
+ 原生Python开发,除prompt-toolkit
|
47
|
+
+ 原生Python开发,除prompt-toolkit及其依赖库 wcwidth, pygment, pyperclip 外,不需要其他第三方库支持
|
48
48
|
+ 原生Python的asyncio实现的通信协议处理,支持async/await语法在脚本中直接应用,脚本实现的同步异步两种模式由你自己选择
|
49
|
-
+ 基于控制台的全屏UI界面设计,支持鼠标操作(Android
|
49
|
+
+ 基于控制台的全屏UI界面设计,支持鼠标操作(Android上支持触摸屏操作),极低资源需求,在单核1GB内存的Linux VPS上也可流畅运行
|
50
50
|
+ 支持分屏显示,在数据快速滚动的时候,上半屏保持不动,以确保不错过信息
|
51
|
-
+ 解决了99
|
51
|
+
+ 解决了99%情况下,北大侠客行中文对不齐,也就是看不清字符画的问题
|
52
52
|
+ 真正的支持多session会话,支持命令或鼠标切换会话
|
53
53
|
+ 原生支持多种服务器端编码方式,不论是GBK、BIG5、还是UTF-8
|
54
54
|
+ 支持NWAS、MTTS协商,支持GMCP、MSDP、MSSP协议
|
@@ -66,10 +66,12 @@ Dynamic: license-file
|
|
66
66
|
|
67
67
|
## 版本更新信息
|
68
68
|
|
69
|
-
### 0.
|
69
|
+
### 0.21.2 (2025-06-01)
|
70
70
|
|
71
71
|
+ 问题修复: 修复了当自动重连启动时,即使会话关闭了,也会自动重连的问题。
|
72
|
-
+ 实现调整:
|
72
|
+
+ 实现调整: 重写了专用的会话缓冲、记录缓冲与PyMud缓冲显示控制器,在prompt_toolkit的原Buffer和BufferControl的基础仅提供了PYMUD所需的基础功能,以降低内存占用。
|
73
|
+
经测试,当前内存基本稳定,视会话数量和脚本情况差异,维持在几百兆左右(500M以下),且不会有大幅波动。重写后,低配置的VPS也可以稳定运行PyMUD。
|
74
|
+
+ post1: 问题修复: 修复了当缓存行数超过规定值时,由于代码错误导致清屏的问题。
|
73
75
|
|
74
76
|
### 0.21.0 (2025-05-20)
|
75
77
|
|
@@ -2,7 +2,7 @@ pymud/__init__.py,sha256=oeHz0NM7_DwChCY8f_vQ_fBq0e_HoTd0cahCFwaavWE,806
|
|
2
2
|
pymud/__main__.py,sha256=lIOBiJmi8X-EWXVIx_OoxSgUZ0FYKlZI8hXVnLUYTJQ,61
|
3
3
|
pymud/decorators.py,sha256=XaxcZqHw4s44lC2EAgB5kZmbNvJnHGmpZnoW75tUeNY,9844
|
4
4
|
pymud/dialogs.py,sha256=4kHycr47UgKQUHGX-KMZvERuWViPjT4hNrGhbe4j-NU,7056
|
5
|
-
pymud/extras.py,sha256=
|
5
|
+
pymud/extras.py,sha256=FQKZWn7ZR9J4H-FjXzbF5sxOTUNZ3b7tWxWhHhywplg,36657
|
6
6
|
pymud/i18n.py,sha256=qLgvrmYhVfkTHKpbBR-LfYMOrGgi0skHrelbsj7ItbE,3034
|
7
7
|
pymud/logger.py,sha256=WCsfXVkgl63qdq1RQEDJBnM7U0S6u8TeORFSMhcoydI,5840
|
8
8
|
pymud/main.py,sha256=zaSjNhpbX3FMulKg-UNFrdiIJO8sOmmrUQrkPOalB-4,10224
|
@@ -10,14 +10,14 @@ pymud/modules.py,sha256=DoCregng5iAj_Hq_yUvRPreRTv2Ehb6sV6_4jfdbsik,11912
|
|
10
10
|
pymud/objects.py,sha256=ZOxNjlPD_d4jk5DMBcXgYcvkt9d8xZih0IQtQlA3f1Y,38668
|
11
11
|
pymud/pkuxkx.py,sha256=qDVry-Vd6MNui0NKWZFT52IpmP1sKS5Dz74EDY4tVGQ,14740
|
12
12
|
pymud/protocol.py,sha256=KNKJYj9HFRoUy-jigNfhiQdDOM_kRSJE17QFpBarQTg,48335
|
13
|
-
pymud/pymud.py,sha256=
|
14
|
-
pymud/session.py,sha256=
|
13
|
+
pymud/pymud.py,sha256=40hn5XyMH9mtjimx_zG7N2M6fAGciee1izO08jsfFzQ,53486
|
14
|
+
pymud/session.py,sha256=8sl8hdmq2jwNxj3bAAp5zTv8eNGBW-GOxNpGCuHKbAg,154603
|
15
15
|
pymud/settings.py,sha256=S2sBEM7YtaDOVu3UpGfHBaU7zSB3Zhs7w-Z7PtdS0WQ,7697
|
16
16
|
pymud/lang/i18n_chs.py,sha256=2cyaHHLwpYEBBwuQXyRTxa1opX53fTv1f8_QDQeGlC0,16836
|
17
17
|
pymud/lang/i18n_eng.py,sha256=jcPz6Y5UuxJBQLY_e8UnEF3GYTlnAD44C14Oj7sK-QI,45935
|
18
|
-
pymud-0.21.
|
19
|
-
pymud-0.21.
|
20
|
-
pymud-0.21.
|
21
|
-
pymud-0.21.
|
22
|
-
pymud-0.21.
|
23
|
-
pymud-0.21.
|
18
|
+
pymud-0.21.2.post1.dist-info/licenses/LICENSE.txt,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
19
|
+
pymud-0.21.2.post1.dist-info/METADATA,sha256=dBJD-AP44lsOfy-glrThVBKIcAA_mTbWvJUkNX2PEmE,45258
|
20
|
+
pymud-0.21.2.post1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
21
|
+
pymud-0.21.2.post1.dist-info/entry_points.txt,sha256=diPUOtTkhgC1hVny7Cdg4aRhaHSynMQoraE7ZhJxUcw,37
|
22
|
+
pymud-0.21.2.post1.dist-info/top_level.txt,sha256=8Gp1eXjxixXjqhhti6tLCspV_8s9sNV3z5Em2_KRhD4,6
|
23
|
+
pymud-0.21.2.post1.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|