pwact 0.3.1__py3-none-any.whl → 0.3.3__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.
@@ -8,7 +8,7 @@ def comm_info():
8
8
  print("\n" + "=" * 50)
9
9
  print(" PWACT Basic Information")
10
10
  print("=" * 50)
11
- print("Version: 0.3.0")
11
+ print("Version: 0.3.1")
12
12
  print("Compatible pwdata: >= 0.5.0")
13
13
  print("Compatible MatPL: >= 2025.3")
14
14
  print("Contact: support@pwmat.com")
@@ -80,7 +80,8 @@ class Explore(object):
80
80
  def back_explore(self):
81
81
  slurm_remain, slurm_success = get_slurm_job_run_info(self.real_md_dir, \
82
82
  job_patten="*-{}".format(EXPLORE_FILE_STRUCTURE.md_job), \
83
- tag_patten="*-{}".format(EXPLORE_FILE_STRUCTURE.md_tag))
83
+ tag_patten="*-{}".format(EXPLORE_FILE_STRUCTURE.md_tag),
84
+ for_back = True)
84
85
  slurm_done = True if len(slurm_remain) == 0 and len(slurm_success) > 0 else False
85
86
  if slurm_done:
86
87
  # bk and do new job
@@ -180,9 +181,6 @@ class Explore(object):
180
181
  job_patten="*-{}".format(EXPLORE_FILE_STRUCTURE.md_job), \
181
182
  tag_patten="*-{}".format(EXPLORE_FILE_STRUCTURE.md_tag))
182
183
  # for slurm remain, check if tags done
183
- slurm_done = True if len(slurm_remain) == 0 and len(slurm_success) > 0 else False
184
- if slurm_done is False:
185
- slurm_remain = recheck_slurm_by_jobtag(slurm_remain, EXPLORE_FILE_STRUCTURE.md_tag)
186
184
  if len(slurm_remain) > 0:
187
185
  #recover slurm jobs
188
186
  if len(slurm_remain) > 0:
@@ -149,7 +149,8 @@ class Labeling(object):
149
149
  if self.input_param.scf.dft_style == DFT_STYLE.bigmodel:
150
150
  slurm_remain, slurm_success = get_slurm_job_run_info(self.real_bigmodel_dir, \
151
151
  job_patten="*-{}".format(LABEL_FILE_STRUCTURE.bigmodel_job), \
152
- tag_patten="*-{}".format(LABEL_FILE_STRUCTURE.bigmodel_tag))
152
+ tag_patten="*-{}".format(LABEL_FILE_STRUCTURE.bigmodel_tag),
153
+ for_back = True)
153
154
  slurm_done = True if len(slurm_remain) == 0 and len(slurm_success) > 0 else False
154
155
  else:
155
156
  slurm_remain, slurm_success = get_slurm_job_run_info(self.real_scf_dir, \
@@ -50,7 +50,8 @@ class ModelTrian(object):
50
50
  def back_train(self):
51
51
  slurm_remain, slurm_success = get_slurm_job_run_info(self.real_train_dir, \
52
52
  job_patten="*-{}".format(TRAIN_FILE_STRUCTUR.train_job), \
53
- tag_patten="*-{}".format(TRAIN_FILE_STRUCTUR.train_tag))
53
+ tag_patten="*-{}".format(TRAIN_FILE_STRUCTUR.train_tag),
54
+ for_back = True)
54
55
  slurm_done = True if len(slurm_remain) == 0 and len(slurm_success) > 0 else False # len(slurm_remain) > 0 exist slurm jobs need to do
55
56
  if slurm_done:
56
57
  # bk and do new job
@@ -6,7 +6,7 @@ class Resource(object):
6
6
  # scf_style for init_bulk relabel
7
7
  def __init__(self, json_dict:dict, job_type:str=AL_WORK.run_iter, dft_style:str=None, scf_style:str=None) -> None:
8
8
  if job_type == AL_WORK.run_iter:
9
- self.train_resource = self.get_resource(get_required_parameter("train", json_dict))
9
+ self.train_resource = self.get_resource(get_required_parameter("train", json_dict), default_groupsize=1)
10
10
  if self.train_resource.number_node > 1:
11
11
  self.train_resource.number_node = 1
12
12
  if self.train_resource.gpu_per_node > 1:
@@ -16,28 +16,28 @@ class Resource(object):
16
16
  print("Warining: the resouce of node, gpu per node and cpu per node in training automatically adjust to [1, 1, 1]")
17
17
  self.train_resource.command = self.train_resource.command.upper()
18
18
 
19
- self.explore_resource = self.get_resource(get_required_parameter("explore", json_dict))
19
+ self.explore_resource = self.get_resource(get_required_parameter("explore", json_dict), default_groupsize=1)
20
20
  if "-in" in self.explore_resource.command:
21
21
  self.explore_resource.command = self.explore_resource.command.split('-in')[0].strip()
22
22
  self.explore_resource.command = "{} -in {} > {}".format(self.explore_resource.command, LAMMPS.input_lammps, SLURM_OUT.md_out)
23
23
  else:
24
24
  if "explore" in json_dict.keys():
25
- self.explore_resource = self.get_resource(get_required_parameter("explore", json_dict))
25
+ self.explore_resource = self.get_resource(get_required_parameter("explore", json_dict), default_groupsize=1)
26
26
  else:
27
27
  self.explore_resource = None
28
28
  # check dft resource
29
29
  if "dft" in json_dict.keys():
30
- self.dft_resource = self.get_resource(get_required_parameter("dft", json_dict))
30
+ self.dft_resource = self.get_resource(get_required_parameter("dft", json_dict), default_groupsize=-1)
31
31
  else:
32
32
  self.dft_resource = ResourceDetail("mpirun -np 1 PWmat", 1, 1, 1, 1, 1, None, None, None)
33
33
 
34
34
  if "direct" in json_dict.keys():
35
- self.direct_resource = self.get_resource(get_required_parameter("direct", json_dict))
35
+ self.direct_resource = self.get_resource(get_required_parameter("direct", json_dict), default_groupsize=1)
36
36
  else:
37
37
  self.direct_resource = None
38
38
 
39
39
  if "scf" in json_dict.keys():
40
- self.scf_resource = self.get_resource(get_parameter("scf", json_dict, None))
40
+ self.scf_resource = self.get_resource(get_parameter("scf", json_dict, None), default_groupsize=-1)
41
41
  else:
42
42
  self.scf_resource = None
43
43
  # dftb_command = get_parameter("dftb_command", json_dict["dft"], None)
@@ -66,9 +66,9 @@ class Resource(object):
66
66
  # cls._instance = cls(json_dict)
67
67
  # return cls._instance
68
68
 
69
- def get_resource(self, json_dict:dict):
69
+ def get_resource(self, json_dict:dict, default_groupsize=1):
70
70
  command = get_required_parameter("command", json_dict)
71
- group_size = get_parameter("group_size", json_dict, 1)
71
+ group_size = get_parameter("group_size", json_dict, default_groupsize)
72
72
  parallel_num = get_parameter("parallel_num", json_dict, 1)
73
73
  number_node = get_parameter("number_node", json_dict, 1)
74
74
  gpu_per_node = get_parameter("gpu_per_node", json_dict, 0)
pwact/main.py CHANGED
@@ -183,14 +183,20 @@ def gather_pwmata(input_cmds):
183
183
  pwdata_lists = sorted(pwdata_lists)
184
184
  save_dir = "./final_pwdata"
185
185
  res_data_list = []
186
- for pwdata in pwdata_lists: # /path/iter.0001/label/result/md.000.sys.001.t.001
187
- data_name = os.path.basename(pwdata) # md.000.sys.001.t.001
186
+
187
+ for pwdata in pwdata_lists: # /path/iter.0001/label/result/*
188
+ data_name = os.path.basename(pwdata)
188
189
  iter_name = os.path.basename(os.path.dirname(os.path.dirname(os.path.dirname(pwdata)))) #iter.0001
189
- target_dir = os.path.join(save_dir, iter_name, data_name) #./final_pwdata/iter.0001/md.000.sys.001.t.001
190
+ target_dir = os.path.join(save_dir, iter_name, data_name) #./final_pwdata/iter.0001
190
191
  copy_dir(pwdata, target_dir)
191
- # print("target: {}\n source: {}\n".format(target_dir, pwdata))
192
- res_data_list.append(target_dir)
193
-
192
+ for path, dirList, fileList in os.walk(pwdata):
193
+ for _ in fileList:
194
+ if "train.xyz" in _:
195
+ res_data_list.append(os.path.join(path, _))
196
+ for root, dirs, files in os.walk(pwdata):
197
+ if 'energies.npy' in files:
198
+ res_data_list.append(root)
199
+
194
200
  result_lines = ["\"{}\",".format(_) for _ in res_data_list]
195
201
  result_lines = "\n".join(result_lines)
196
202
  # result_lines = result_lines[:-1] # Filter the last ','
@@ -8,7 +8,7 @@ def kill_process(pid:str, job_id:str):
8
8
  if job_id is None:
9
9
  try:
10
10
  # 发送终止信号 (SIGTERM) 给指定的进程
11
- os.kill(pid, signal.SIGTERM)
11
+ os.kill(int(pid), signal.SIGTERM)
12
12
  print(f"process {pid} has been terminated.")
13
13
  except ProcessLookupError:
14
14
  print(f"process {pid} non-existent.")
@@ -35,11 +35,13 @@ Obtain the execution status of the slurm jobs under the 'dir'
35
35
 
36
36
  0-scf.job 1-scf.job 2-scf.job 3-scf.job 4-scf.job
37
37
  0-tag.scf.success 1-tag.scf.success 2-tag.scf.success 3-tag.scf.success 4-tag.scf.success
38
+ new change:
39
+ only jugt the slurm file is done by the tag under each subwork tag. so the tag of job file is nouse maybe
38
40
  param {*} dir
39
41
  Returns:
40
42
  Author: WU Xingxing
41
43
  '''
42
- def get_slurm_job_run_info(dir:str, job_patten:str="*.job", tag_patten:str="tag.*.success"):
44
+ def get_slurm_job_run_info(dir:str, job_patten:str="*.job", tag_patten:str="tag.*.success", for_back:bool=False):
43
45
  slurm_job_files = sorted(glob.glob(os.path.join(dir, job_patten)))
44
46
  slrum_job_dirs = [int(os.path.basename(_).split('-')[0]) for _ in slurm_job_files]
45
47
 
@@ -49,14 +51,39 @@ def get_slurm_job_run_info(dir:str, job_patten:str="*.job", tag_patten:str="tag.
49
51
  slurm_failed = []
50
52
  slurm_success = []
51
53
 
52
- for i, d in enumerate(slrum_job_dirs):
53
- if d in slrum_tag_sucess_dirs:
54
- slurm_success.append(slurm_job_files[i])
55
- else:
56
- slurm_failed.append(slurm_job_files[i])
54
+ if for_back is False:
55
+ for slurm_file in slurm_job_files:
56
+ if slurm_job_done_by_jobtag(slurm_file):
57
+ slurm_success.append(slurm_file)
58
+ else:
59
+ slurm_failed.append(slurm_file)
60
+ else:
61
+ for i, d in enumerate(slrum_job_dirs):
62
+ if d in slrum_tag_sucess_dirs:
63
+ slurm_success.append(slurm_job_files[i])
64
+ else:
65
+ slurm_failed.append(slurm_job_files[i])
57
66
 
58
67
  return slurm_failed, slurm_success
59
68
 
69
+
70
+ def slurm_job_done_by_jobtag(slurm_file):
71
+ with open(slurm_file, 'r') as f:
72
+ content = f.read()
73
+ cd_pattern = r'cd\s+([^\n]+)'
74
+ directories = re.findall(cd_pattern, content)
75
+ if not directories:
76
+ raise Exception("Error! There is no task in the slurm.job file {}".format(slurm_file))
77
+ for directory in directories:
78
+ directory = directory.strip()
79
+ success_file = glob.glob(os.path.join(directory, "*.success"))
80
+ if len(success_file) > 0:
81
+ continue
82
+ else:
83
+ return False
84
+ return True
85
+
86
+
60
87
  def recheck_slurm_by_jobtag(slurm_files:list[str], tag):
61
88
  remain_job = []
62
89
  for slurm_file in slurm_files:
@@ -76,6 +103,27 @@ def recheck_slurm_by_jobtag(slurm_files:list[str], tag):
76
103
  break
77
104
  return remain_job
78
105
 
106
+ # def slurm_job_is_done_by_jobtag(dir:str, job_patten:str="*.job", tag_patten:str="tag.*.success"):
107
+ # slurm_job_files = sorted(glob.glob(os.path.join(dir, job_patten)))
108
+ # slurm_failed = []
109
+ # for slurm_file in slurm_job_files:
110
+ # with open(slurm_file, 'r') as f:
111
+ # content = f.read()
112
+ # cd_pattern = r'cd\s+([^\n]+)'
113
+ # directories = re.findall(cd_pattern, content)
114
+ # if not directories:
115
+ # raise Exception("Error! There is no task in the slurm.job file {}".format(slurm_file))
116
+ # for directory in directories:
117
+ # directory = directory.strip()
118
+ # success_file = os.path.join(directory, tag_patten)
119
+ # if os.path.exists(success_file):
120
+ # continue
121
+ # else:
122
+ # slurm_failed.append(slurm_file)
123
+ # break
124
+ # return slurm_failed
125
+
126
+
79
127
  '''
80
128
  description:
81
129
  split the job_list with groupsize
@@ -85,7 +133,7 @@ return {*} [["job1","job2",...,"job_groupseze"], ..., [..., "job_N", "NONE",...,
85
133
  author: wuxingxing
86
134
  '''
87
135
  def split_job_for_group(groupsize:int , job_list:list[str], parallel_num=1):
88
- groupsize = 1 if groupsize is None else groupsize
136
+ groupsize = len(job_list) if groupsize == -1 else groupsize
89
137
  if groupsize > 1:
90
138
  groupsize_adj = ceil(groupsize/parallel_num)
91
139
  if groupsize_adj*parallel_num > groupsize:
@@ -1,7 +1,7 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: pwact
3
- Version: 0.3.1
4
- Summary: PWACT is an open-source automated active learning platform based on PWMLFF for efficient data sampling.
3
+ Version: 0.3.3
4
+ Summary: PWACT is an open-source automated active learning platform based on MatPL for efficient data sampling.
5
5
  Home-page: https://github.com/LonxunQuantum/PWact
6
6
  Author: LonxunQuantum
7
7
  Author-email: lonxun@pwmat.com
@@ -1,9 +1,9 @@
1
1
  pwact/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- pwact/main.py,sha256=jCqNp0tn8P7R8EdPt81bqZlC-Ixjp_rnnFxMT7JAfXI,15375
2
+ pwact/main.py,sha256=ZmfzShuphHUuVH9OsPV_obf0g0jK3ka9UwStim_YJ7s,15538
3
3
  pwact/active_learning/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- pwact/active_learning/environment.py,sha256=oDeSMCnBnwRe3bA0l9miDyQGaIE-gcf2ML2eOE7rPJk,512
4
+ pwact/active_learning/environment.py,sha256=aySFa--fTWAgIR9_PKwfJ9pLKVexmL22lJ1NTtnQuNo,512
5
5
  pwact/active_learning/explore/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- pwact/active_learning/explore/run_model_md.py,sha256=n3f6aSMr1Cpw_cSUrlH28JwoWW7VLwUMcF1XB0ao2sw,27448
6
+ pwact/active_learning/explore/run_model_md.py,sha256=1mjQB63mMCSngjMA2cd0U3f8AcB9oM_wa6xBAfNOwi0,27255
7
7
  pwact/active_learning/explore/select_image.py,sha256=1zpTCs_15FRlffBYfy1HQ1r79p2dNM8u8ZHvPysQTvc,14597
8
8
  pwact/active_learning/init_bulk/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
9
  pwact/active_learning/init_bulk/aimd.py,sha256=XzDlX2vylaljQKoUnv6nrI2NfiOdHZpq8qr3DenA1F4,10465
@@ -14,7 +14,7 @@ pwact/active_learning/init_bulk/init_bulk_run.py,sha256=1wXf4iFhMjrjhyI4JVRoIibE
14
14
  pwact/active_learning/init_bulk/relabel.py,sha256=gP_qqMWT_hMIcwFBdNmyVBHBpkQS52BzbQK80rGTvPQ,11974
15
15
  pwact/active_learning/init_bulk/relax.py,sha256=edyCZLEylUckIwOLBa55agUMo-aedj0dvoyG165YpuE,10450
16
16
  pwact/active_learning/label/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
- pwact/active_learning/label/labeling.py,sha256=Vq2hH9i3DH4X0XidrzxwE-MzgYiWQ0VkFWZKj1Lhc_I,21800
17
+ pwact/active_learning/label/labeling.py,sha256=9bTjw6wOJ63J-x9IAiDY2DddSBp3Pj0mxjVyY47lsok,21833
18
18
  pwact/active_learning/slurm/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
19
19
  pwact/active_learning/slurm/slurm.py,sha256=-Dmc2B9y4_27THCR2tZFXnwJvMmifivJeZ2FX8iy2Tw,16881
20
20
  pwact/active_learning/slurm/slurm_tool.py,sha256=-4tc5dkpAUP0vmEdmqM8oYLcsUwixa4Z8h5_E9Gevdg,1249
@@ -22,12 +22,12 @@ pwact/active_learning/test/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJ
22
22
  pwact/active_learning/test/test.py,sha256=TXsk-gDDOHDLywVljpqA-zHK3-PrZbGAHnK1T7T6T-o,3587
23
23
  pwact/active_learning/train/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  pwact/active_learning/train/dp_kpu.py,sha256=GkGKEGhLmOvPERqgTkf_0_vD9zOEPlBX2N7vuSQG_-c,9317
25
- pwact/active_learning/train/train_model.py,sha256=Hh6_yq_86Y4pqP60sbEaeCJexD9a-BTqop07l2FAQSI,12021
25
+ pwact/active_learning/train/train_model.py,sha256=yaBcGLBnM7NpuZu0o7lzZp2NjWPWzHXyJ39oS6pmHB4,12050
26
26
  pwact/active_learning/user_input/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
27
  pwact/active_learning/user_input/cmd_infos.py,sha256=g1QW5Wi3JvmC5xEY4F-7AO1xBuJSjHG8IhZjom8haxQ,3728
28
28
  pwact/active_learning/user_input/init_bulk_input.py,sha256=M8IlT4ABJUEwomb6eQGq8d3h1darMHtDlws1fcq077k,9422
29
29
  pwact/active_learning/user_input/iter_input.py,sha256=TctIZ3WAWQ_waGuPaK6F_uZjRKFM8oidF5iVE4SAI1o,12752
30
- pwact/active_learning/user_input/resource.py,sha256=OtsJEAWmMknLyrPB309C6ipyL1fCXHriF8sjXs5pjmg,7351
30
+ pwact/active_learning/user_input/resource.py,sha256=V1FkcoLrjzKTkbd_3dYok69KyiKmwRCwGBatWAb-WoU,7517
31
31
  pwact/active_learning/user_input/scf_param.py,sha256=QX_Dd6c9Q2sjV4lIKjfV7t-DgIwDKZp7fh2KY5HyKOU,11262
32
32
  pwact/active_learning/user_input/workdir.py,sha256=64J3wBbYzy6ztYHs513YHfEIF5d8zwv_WpF-U9HOEkA,8245
33
33
  pwact/active_learning/user_input/train_param/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -46,8 +46,8 @@ pwact/utils/file_operation.py,sha256=bfLezgJHD3BRtZFm0HwSGTNBPukVNICZFpXYWMs68A4
46
46
  pwact/utils/format_input_output.py,sha256=oYFydQy3-btXzieO2O2LbHFoeRyhPnLVE4c5TNgS-IQ,1798
47
47
  pwact/utils/json_operation.py,sha256=BqBsnIjk1URoMW_s2yu7Gk8IBxlir-oo6ivt8P3RIqg,1794
48
48
  pwact/utils/pre_al_data_util.py,sha256=QE-axnVYUIyORFiVs-WK9-UaJlMUFY816_rSyYOOJc8,2542
49
- pwact/utils/process_tool.py,sha256=j4yp9DoPshTxTX3g7SS-yuEbBVhuoYNNZdAv2mq3efE,876
50
- pwact/utils/slurm_script.py,sha256=tbclNkYBVM-t8GeiLGNK2s5kxypjy8luf4ZrlHEGjjM,8278
49
+ pwact/utils/process_tool.py,sha256=bsSsS42toOWz6ZzWCq5_7TrLEBTAif5tz2FbSo4YT3E,881
50
+ pwact/utils/slurm_script.py,sha256=t0gshBMgnf5nzLPphwIIV4KxmwI3RmTuknLLf9tTZCg,10173
51
51
  pwact/utils/tmp.py,sha256=en_GltoNwfA40vSHttMRi9cEg-8xnPZlvnnBq1_vHfw,2285
52
52
  pwact/utils/app_lib/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
53
53
  pwact/utils/app_lib/common.py,sha256=lQmI-9Qumq62MNjr-eVlLL88ISDHBOb6vAfYYFcDIgM,6040
@@ -59,9 +59,9 @@ pwact/utils/app_lib/lammps.py,sha256=t3nkBqwkViO6UbnInGKAHiwVngHKayeat2pPEtaZZIU
59
59
  pwact/utils/app_lib/pwmat.py,sha256=PTRPkG_d00ibGhpCe2-4M7MW3dx2ZuAyb9hT2jl_LAs,18047
60
60
  pwact/utils/draw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
61
61
  pwact/utils/draw/hist_model_devi.py,sha256=o1Try-ekith2A7S6u1mt3zuTqaQwyw5tdURReh8BeLY,4945
62
- pwact-0.3.1.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
63
- pwact-0.3.1.dist-info/METADATA,sha256=lDIsIiByaSvWIEV_cLqEAqWTuHVkHn9bvs825xYZwnk,612
64
- pwact-0.3.1.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
65
- pwact-0.3.1.dist-info/entry_points.txt,sha256=p61auAnpbn8E2WjvHNBA7rb9_NRAOCew4zdcCj33cGc,42
66
- pwact-0.3.1.dist-info/top_level.txt,sha256=fY1_7sH5Lke4dC9L8MbYM4fT5aat5eCkAmpkIzY1SlM,6
67
- pwact-0.3.1.dist-info/RECORD,,
62
+ pwact-0.3.3.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
63
+ pwact-0.3.3.dist-info/METADATA,sha256=RKEDTPP72Lhu1USAu-WcBUzqfT48mBAkeVtVF9rdO8w,611
64
+ pwact-0.3.3.dist-info/WHEEL,sha256=2wepM1nk4DS4eFpYrW1TTqPcoGNfHhhO_i5m4cOimbo,92
65
+ pwact-0.3.3.dist-info/entry_points.txt,sha256=p61auAnpbn8E2WjvHNBA7rb9_NRAOCew4zdcCj33cGc,42
66
+ pwact-0.3.3.dist-info/top_level.txt,sha256=fY1_7sH5Lke4dC9L8MbYM4fT5aat5eCkAmpkIzY1SlM,6
67
+ pwact-0.3.3.dist-info/RECORD,,
File without changes
File without changes