oafuncs 0.0.97.5__py3-none-any.whl → 0.0.97.7__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.
oafuncs/__init__.py CHANGED
@@ -1,18 +1,5 @@
1
1
  #!/usr/bin/env python
2
2
  # coding=utf-8
3
- """
4
- Author: Liu Kun && 16031215@qq.com
5
- Date: 2024-09-17 16:09:20
6
- LastEditors: Liu Kun && 16031215@qq.com
7
- LastEditTime: 2025-03-09 16:28:01
8
- FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\__init__.py
9
- Description:
10
- EditPlatform: vscode
11
- ComputerInfo: XPS 15 9510
12
- SystemInfo: Windows 11
13
- Python Version: 3.12
14
- """
15
-
16
3
 
17
4
  # 会导致OAFuncs直接导入所有函数,不符合模块化设计
18
5
  # from oafuncs.oa_s.oa_cmap import *
@@ -52,3 +39,5 @@ from .oa_tool import *
52
39
  # path: My_Funcs/OAFuncs/oafuncs/_script/
53
40
  # from ._script import *
54
41
  # ------------------- 2025-03-16 15:56:01 -------------------
42
+ from .oa_date import *
43
+ # ------------------- 2025-03-27 16:56:57 -------------------
oafuncs/oa_date.py ADDED
@@ -0,0 +1,90 @@
1
+ #!/usr/bin/env python
2
+ # coding=utf-8
3
+ """
4
+ Author: Liu Kun && 16031215@qq.com
5
+ Date: 2025-03-27 16:56:57
6
+ LastEditors: Liu Kun && 16031215@qq.com
7
+ LastEditTime: 2025-03-27 16:56:57
8
+ FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_date.py
9
+ Description:
10
+ EditPlatform: vscode
11
+ ComputerInfo: XPS 15 9510
12
+ SystemInfo: Windows 11
13
+ Python Version: 3.12
14
+ """
15
+
16
+ import calendar
17
+ import datetime
18
+
19
+ __all__ = ["get_days_in_month", "generate_hour_list", "adjust_time"]
20
+
21
+
22
+ def get_days_in_month(year, month):
23
+ return calendar.monthrange(year, month)[1]
24
+
25
+
26
+ def generate_hour_list(start_date, end_date, interval_hours=6):
27
+ """
28
+ Generate a list of datetime strings with a specified interval in hours.
29
+
30
+ Args:
31
+ start_date (str): Start date in the format "%Y%m%d%H".
32
+ end_date (str): End date in the format "%Y%m%d%H".
33
+ interval_hours (int): Interval in hours between each datetime.
34
+
35
+ Returns:
36
+ list: List of datetime strings in the format "%Y%m%d%H".
37
+ """
38
+ date_s = datetime.datetime.strptime(start_date, "%Y%m%d%H")
39
+ date_e = datetime.datetime.strptime(end_date, "%Y%m%d%H")
40
+ date_list = []
41
+ while date_s <= date_e:
42
+ date_list.append(date_s.strftime("%Y%m%d%H"))
43
+ date_s += datetime.timedelta(hours=interval_hours)
44
+ return date_list
45
+
46
+
47
+ def adjust_time(initial_time, amount, time_unit="hours", output_format=None):
48
+ """
49
+ Adjust a given initial time by adding a specified amount of time.
50
+
51
+ Args:
52
+ initial_time (str): Initial time in the format "yyyymmdd" to "yyyymmddHHMMSS".
53
+ Missing parts are assumed to be "0".
54
+ amount (int): The amount of time to add.
55
+ time_unit (str): The unit of time to add ("seconds", "minutes", "hours", "days").
56
+ output_format (str, optional): Custom output format for the adjusted time. Defaults to None.
57
+
58
+ Returns:
59
+ str: The adjusted time as a string, formatted according to the output_format or time unit.
60
+ """
61
+ # Normalize the input time to "yyyymmddHHMMSS" format
62
+ time_format = "%Y%m%d%H%M%S"
63
+ initial_time = initial_time.ljust(14, "0")
64
+ time_obj = datetime.datetime.strptime(initial_time, time_format)
65
+
66
+ # Add the specified amount of time
67
+ if time_unit == "seconds":
68
+ time_obj += datetime.timedelta(seconds=amount)
69
+ elif time_unit == "minutes":
70
+ time_obj += datetime.timedelta(minutes=amount)
71
+ elif time_unit == "hours":
72
+ time_obj += datetime.timedelta(hours=amount)
73
+ elif time_unit == "days":
74
+ time_obj += datetime.timedelta(days=amount)
75
+ else:
76
+ raise ValueError("Invalid time unit. Use 'seconds', 'minutes', 'hours', or 'days'.")
77
+
78
+ # Determine the output format
79
+ if output_format:
80
+ return time_obj.strftime(output_format)
81
+ else:
82
+ if time_unit == "seconds":
83
+ default_format = "%Y%m%d%H%M%S"
84
+ elif time_unit == "minutes":
85
+ default_format = "%Y%m%d%H%M"
86
+ elif time_unit == "hours":
87
+ default_format = "%Y%m%d%H"
88
+ elif time_unit == "days":
89
+ default_format = "%Y%m%d"
90
+ return time_obj.strftime(default_format)
oafuncs/oa_draw.py CHANGED
@@ -76,26 +76,51 @@ def fig_minus(ax_x=None, ax_y=None, cbar=None, decimal=None, add_space=False):
76
76
 
77
77
 
78
78
  # ** 将生成图片/已有图片制作成动图
79
- def gif(image_list: list, gif_name: str, duration=0.2): # 制作动图,默认间隔0.2
79
+ def gif(image_list: list, gif_name: str, duration=200, resize=None): # 制作动图,默认间隔0.2
80
80
  """
81
81
  Description
82
82
  Make gif from images
83
83
  Parameters
84
84
  image_list : list, list of images
85
85
  gif_name : str, name of gif
86
- duration : float, duration of each frame
86
+ duration : float, duration of each frame, units: ms
87
+ resize : tuple, (width, height) to resize images, if None, use first image size
87
88
  Returns
88
89
  None
89
90
  Example
90
91
  gif(["1.png", "2.png"], "test.gif", duration=0.2)
91
92
  """
92
93
  import imageio.v2 as imageio
94
+ import numpy as np
95
+ from PIL import Image
93
96
 
94
97
  frames = []
98
+
99
+ # 获取目标尺寸
100
+ if resize is None and image_list:
101
+ # 使用第一张图片的尺寸作为标准
102
+ with Image.open(image_list[0]) as img:
103
+ resize = img.size
104
+
105
+ # 读取并调整所有图片的尺寸
95
106
  for image_name in image_list:
96
- frames.append(imageio.imread(image_name))
97
- imageio.mimsave(gif_name, frames, format="GIF", duration=duration)
98
- print("Gif制作完成!")
107
+ with Image.open(image_name) as img:
108
+ if resize:
109
+ img = img.resize(resize, Image.LANCZOS)
110
+ frames.append(np.array(img))
111
+
112
+ # 修改此处:明确使用 duration 值,并将其作为每帧的持续时间(以秒为单位)
113
+ # 某些版本的 imageio 可能需要以毫秒为单位,或者使用 fps 参数
114
+ try:
115
+ # 先尝试直接使用 duration 参数(以秒为单位)
116
+ imageio.mimsave(gif_name, frames, format="GIF", duration=duration)
117
+ except Exception as e:
118
+ print(f"尝试使用fps参数替代duration: {e}")
119
+ # 如果失败,尝试使用 fps 参数(fps = 1/duration)
120
+ fps = 1.0 / duration if duration > 0 else 5.0
121
+ imageio.mimsave(gif_name, frames, format="GIF", fps=fps)
122
+
123
+ print(f"Gif制作完成!尺寸: {resize}, 帧间隔: {duration}毫秒")
99
124
  return
100
125
 
101
126
 
@@ -171,8 +196,8 @@ def add_cartopy(ax, lon=None, lat=None, projection=ccrs.PlateCarree(), gridlines
171
196
 
172
197
  # set extent
173
198
  if lon is not None and lat is not None:
174
- lon_min, lon_max = lon.min(), lon.max()
175
- lat_min, lat_max = lat.min(), lat.max()
199
+ lon_min, lon_max = np.nanmin(lon), np.nanmax(lon)
200
+ lat_min, lat_max = np.nanmin(lat), np.nanmax(lat)
176
201
  ax.set_extent([lon_min, lon_max, lat_min, lat_max], crs=projection)
177
202
 
178
203
 
oafuncs/oa_file.py CHANGED
@@ -18,10 +18,10 @@ import os
18
18
  import re
19
19
  import shutil
20
20
 
21
- from ._script.replace_file_concent import replace_direct_content
21
+
22
22
  from rich import print
23
23
 
24
- __all__ = ["find_file", "link_file", "copy_file", "rename_file", "make_folder", "clear_folder", "remove_empty_folder", "remove", "file_size", "mean_size", "make_dir", "replace_content"]
24
+ __all__ = ["find_file", "link_file", "copy_file", "rename_file", "make_folder", "clear_folder", "remove_empty_folder", "remove", "file_size", "mean_size", "make_dir", "replace_content", "move_file"]
25
25
 
26
26
 
27
27
  # ** 查找文件,支持通配符
@@ -157,6 +157,55 @@ def copy_file(src_pattern, dst):
157
157
  print(f"Copy and rename file or directory: {src_file} -> {dst_file}")
158
158
 
159
159
 
160
+
161
+ # ** 移动文件或目录,支持通配符
162
+ def move_file(src_pattern, dst):
163
+ """
164
+ # 描述:移动文件或目录,支持通配符
165
+ # 使用示例
166
+ # move_file(r'/data/hejx/liukun/era5/*', r'/data/hejx/liukun/Test/')
167
+ # move_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test/py.o')
168
+ # move_file(r'/data/hejx/liukun/era5/py.o*', r'/data/hejx/liukun/Test')
169
+ param {*} src_pattern # 源文件或目录
170
+ param {*} dst # 目标文件或目录
171
+ """
172
+ src_pattern = str(src_pattern)
173
+ # 使用glob.glob来处理可能包含通配符的src
174
+ src_files = glob.glob(src_pattern)
175
+ if not src_files:
176
+ raise FileNotFoundError("File does not exist: {}".format(src_pattern))
177
+
178
+ # 判断dst是路径还是包含文件名的路径
179
+ if os.path.isdir(dst):
180
+ # 如果dst是路径,则保持源文件的文件名
181
+ dst_dir = dst
182
+ for src_file in src_files:
183
+ src_file_basename = os.path.basename(src_file)
184
+ dst_file = os.path.join(dst_dir, src_file_basename)
185
+ if os.path.exists(dst_file):
186
+ if os.path.isdir(dst_file):
187
+ shutil.rmtree(dst_file)
188
+ else:
189
+ os.remove(dst_file)
190
+ shutil.move(src_file, dst_file)
191
+ print(f"Move file or directory: {src_file} -> {dst_file}")
192
+ else:
193
+ # 如果dst包含文件名,则移动后重命名
194
+ dst_dir = os.path.dirname(dst)
195
+ os.makedirs(dst_dir, exist_ok=True)
196
+ # 只处理第一个匹配的文件
197
+ src_file = src_files[0]
198
+ dst_file = dst
199
+ if os.path.exists(dst_file):
200
+ if os.path.isdir(dst_file):
201
+ shutil.rmtree(dst_file)
202
+ else:
203
+ os.remove(dst_file)
204
+ shutil.move(src_file, dst_file)
205
+ print(f"Move and rename file or directory: {src_file} -> {dst_file}")
206
+
207
+
208
+
160
209
  # ** 重命名文件,支持通配符
161
210
  def rename_file(directory, old_str, new_str):
162
211
  """
@@ -420,6 +469,7 @@ def replace_content(source_file, content_dict, key_value=False, target_dir=None,
420
469
  返回:
421
470
  bool: 替换是否成功
422
471
  """
472
+ from ._script.replace_file_concent import replace_direct_content
423
473
  if target_dir is None:
424
474
  target_dir = os.path.dirname(source_file)
425
475
  replace_direct_content(source_file, target_dir, content_dict, key_value=key_value, new_name=new_name)
oafuncs/oa_nc.py CHANGED
@@ -20,8 +20,6 @@ import numpy as np
20
20
  import xarray as xr
21
21
  from rich import print
22
22
 
23
- from ._script.plot_dataset import func_plot_dataset
24
-
25
23
  __all__ = ["get_var", "extract", "save", "merge", "modify", "rename", "check", "convert_longitude", "isel", "draw"]
26
24
 
27
25
 
@@ -280,15 +278,21 @@ def _modify_var(nc_file_path, variable_name, new_value):
280
278
  """
281
279
  try:
282
280
  # Open the NetCDF file
283
- dataset = nc.Dataset(nc_file_path, "r+")
284
- # Get the variable to be modified
285
- variable = dataset.variables[variable_name]
286
- # Modify the value of the variable
287
- variable[:] = new_value
288
- dataset.close()
289
- print(f"Successfully modified variable {variable_name} in {nc_file_path}.")
281
+ with nc.Dataset(nc_file_path, "r+") as dataset:
282
+ # Check if the variable exists
283
+ if variable_name not in dataset.variables:
284
+ raise ValueError(f"Variable '{variable_name}' not found in the NetCDF file.")
285
+ # Get the variable to be modified
286
+ variable = dataset.variables[variable_name]
287
+ # Check if the shape of the new value matches the variable's shape
288
+ if variable.shape != new_value.shape:
289
+ raise ValueError(f"Shape mismatch: Variable '{variable_name}' has shape {variable.shape}, "
290
+ f"but new value has shape {new_value.shape}.")
291
+ # Modify the value of the variable
292
+ variable[:] = new_value
293
+ print(f"Successfully modified variable '{variable_name}' in '{nc_file_path}'.")
290
294
  except Exception as e:
291
- print(f"An error occurred while modifying variable {variable_name} in {nc_file_path}: {e}")
295
+ print(f"An error occurred while modifying variable '{variable_name}' in '{nc_file_path}': {e}")
292
296
 
293
297
 
294
298
  def _modify_attr(nc_file_path, variable_name, attribute_name, attribute_value):
@@ -306,21 +310,18 @@ def _modify_attr(nc_file_path, variable_name, attribute_name, attribute_value):
306
310
  modify_attr('test.nc', 'temperature', 'long_name', 'Temperature in Celsius')
307
311
  """
308
312
  try:
309
- ds = nc.Dataset(nc_file_path, "r+")
310
- if variable_name not in ds.variables:
311
- raise ValueError(f"Variable '{variable_name}' not found in the NetCDF file.")
312
-
313
- variable = ds.variables[variable_name]
314
- if attribute_name in variable.ncattrs():
315
- print(f"Warning: Attribute '{attribute_name}' already exists. Replacing it.")
313
+ with nc.Dataset(nc_file_path, "r+") as ds:
314
+ # Check if the variable exists
315
+ if variable_name not in ds.variables:
316
+ raise ValueError(f"Variable '{variable_name}' not found in the NetCDF file.")
317
+ # Get the variable
318
+ variable = ds.variables[variable_name]
319
+ # Add or modify the attribute
316
320
  variable.setncattr(attribute_name, attribute_value)
317
- else:
318
- print(f"Adding attribute '{attribute_name}'...")
319
- variable.setncattr(attribute_name, attribute_value)
320
-
321
- ds.close()
321
+ print(f"Successfully modified attribute '{attribute_name}' of variable '{variable_name}' in '{nc_file_path}'.")
322
322
  except Exception as e:
323
- raise RuntimeError(f"An error occurred: {e}")
323
+ print(f"[red]Error:[/red] Failed to modify attribute '{attribute_name}' of variable '{variable_name}' "
324
+ f"in file '{nc_file_path}'. [bold]Details:[/bold] {e}")
324
325
 
325
326
 
326
327
  def modify(nc_file, var_name, attr_name=None, new_value=None):
@@ -338,10 +339,13 @@ def modify(nc_file, var_name, attr_name=None, new_value=None):
338
339
  modify('test.nc', 'temperature', 'long_name', 'Temperature in Celsius')
339
340
  modify('test.nc', 'temperature', None, np.random.rand(100, 50))
340
341
  """
341
- if attr_name is None:
342
- _modify_var(nc_file, var_name, new_value)
343
- else:
344
- _modify_attr(nc_file, var_name, attr_name, new_value)
342
+ try:
343
+ if attr_name is None:
344
+ _modify_var(nc_file, var_name, new_value)
345
+ else:
346
+ _modify_attr(nc_file, var_name, attr_name, new_value)
347
+ except Exception as e:
348
+ print(f"An error occurred while modifying '{var_name}' in '{nc_file}': {e}")
345
349
 
346
350
 
347
351
  def rename(ncfile_path, old_name, new_name):
@@ -499,6 +503,7 @@ def draw(output_dir=None, dataset=None, ncfile=None, xyzt_dims=("longitude", "la
499
503
  Example:
500
504
  draw(ncfile, output_dir, x_dim="longitude", y_dim="latitude", z_dim="level", t_dim="time", fixed_colorscale=False)
501
505
  """
506
+ from ._script.plot_dataset import func_plot_dataset
502
507
  if output_dir is None:
503
508
  output_dir = str(os.getcwd())
504
509
  if isinstance(xyzt_dims, (list, tuple)):
@@ -1,19 +1,7 @@
1
1
  #!/usr/bin/env python
2
2
  # coding=utf-8
3
- """
4
- Author: Liu Kun && 16031215@qq.com
5
- Date: 2024-11-21 09:48:00
6
- LastEditors: Liu Kun && 16031215@qq.com
7
- LastEditTime: 2025-01-11 20:09:09
8
- FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_tool\\__init__.py
9
- Description:
10
- EditPlatform: vscode
11
- ComputerInfo: XPS 15 9510
12
- SystemInfo: Windows 11
13
- Python Version: 3.12
14
- """
3
+
15
4
 
16
5
  # 会导致OAFuncs直接导入所有函数,不符合模块化设计
17
6
  from .email import *
18
7
  from .parallel import *
19
- from .time import *
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: oafuncs
3
- Version: 0.0.97.5
3
+ Version: 0.0.97.7
4
4
  Summary: Oceanic and Atmospheric Functions
5
5
  Home-page: https://github.com/Industry-Pays/OAFuncs
6
6
  Author: Kun Liu
@@ -32,6 +32,7 @@ Requires-Dist: geopandas
32
32
  Requires-Dist: Cartopy
33
33
  Requires-Dist: rasterio
34
34
  Requires-Dist: salem
35
+ Requires-Dist: psutil
35
36
  Dynamic: author
36
37
  Dynamic: author-email
37
38
  Dynamic: classifier
@@ -1,10 +1,11 @@
1
- oafuncs/__init__.py,sha256=GrygzGa_GDaWm3ERmxjNP1Pr7lrVx0MPOO_FcqkrvB8,1692
1
+ oafuncs/__init__.py,sha256=T_-VtnWWllV3Q91twT5Yt2sUapeA051QbPNnBxmg9nw,1456
2
2
  oafuncs/oa_cmap.py,sha256=OfJ2DOBOGX5X1GihE6CPcTV8bAFdDqJSXV7vbqUgV9s,7552
3
3
  oafuncs/oa_data.py,sha256=32elvoBHibTunDXAK9ptQ-e-xrXxKM4GrPiMqWNv_lE,12169
4
- oafuncs/oa_draw.py,sha256=QypQp4vJIrbAyFddEVxd9K9Q4d85PRYqYQi9xDUmSZw,11150
5
- oafuncs/oa_file.py,sha256=pGtlIXCvzrmhZRkbL0juFOivge2GscfQWVIaz0AS6sQ,15262
4
+ oafuncs/oa_date.py,sha256=--3uXYq3_n9HBJbY1io1H1PE-FyiVxbQCyFUcudxQks,3210
5
+ oafuncs/oa_draw.py,sha256=d23R6OEco7EbvcrL5YsnrSupnKKUn55hLw1B_d-kxOg,12308
6
+ oafuncs/oa_file.py,sha256=nYTsMataaC790lSqxjuMB4uVqUJz_tMm_kRve4CHql4,17235
6
7
  oafuncs/oa_help.py,sha256=loyzTbjU_0VpSIBvAEUA_tqxG8MVsO0xFE_2hgQ3zMw,4188
7
- oafuncs/oa_nc.py,sha256=7qxmx36ADkd8EGpTzAuFueMiZ2ewp5Sf-eAuRu5n7Xo,20115
8
+ oafuncs/oa_nc.py,sha256=eTioHFT8eeg3T7S5wFUiFm1zU1w8Fo11Un8fjBaPhuY,20860
8
9
  oafuncs/oa_python.py,sha256=Q-6UGGw_dJff7Ef8i87fsLPoGeHV5jBzfb-7HP4THR0,4018
9
10
  oafuncs/_data/OAFuncs.png,sha256=y1_x-mUP3gFjcy6m8FqfvQO_HgjzPhQKfXjnSHjslZE,3436152
10
11
  oafuncs/_data/hycom_3hourly.png,sha256=azt_uPcXtl_8CSKRLLPCIf5pPrcxMiOzvoFQnwb0zUo,12411415
@@ -15,7 +16,6 @@ oafuncs/_script/replace_file_concent.py,sha256=eCFZjnZcwyRvy6b4mmIfBna-kylSZTyJR
15
16
  oafuncs/oa_down/User_Agent-list.txt,sha256=pazxSip8_lphEBOPHG902zmIBUg8sBKXgmqp_g6j_E4,661062
16
17
  oafuncs/oa_down/__init__.py,sha256=kRX5eTUCbAiz3zTaQM1501paOYS_3fizDN4Pa0mtNUA,585
17
18
  oafuncs/oa_down/hycom_3hourly.py,sha256=lCdbYQd7o_2jMgwmbrClNo5omrj5b5cnWnp6lnXMloQ,65307
18
- oafuncs/oa_down/hycom_3hourly_20250129.py,sha256=zbUp5NNBMzDXEqSC0-Z9H_EoM6Fg-6tXymK0AXH9qRk,65553
19
19
  oafuncs/oa_down/idm.py,sha256=XfYCNnQWADxOhhJd-T8sNYN0nGiRrAs7zbQcsB5-UmI,1668
20
20
  oafuncs/oa_down/literature.py,sha256=2bF9gSKQbzcci9LcKE81j8JEjIJwON7jbwQB3gDDA3E,11331
21
21
  oafuncs/oa_down/test_ua.py,sha256=0IQq3NjqfNr7KkyjS_U-a4mYu-r-E7gzawwo4IfEa6Y,10851
@@ -29,12 +29,11 @@ oafuncs/oa_sign/__init__.py,sha256=QKqTFrJDFK40C5uvk48GlRRbGFzO40rgkYwu6dYxatM,5
29
29
  oafuncs/oa_sign/meteorological.py,sha256=mLbupsZSq427HTfVbZMvIlFzDHwSzQAbK3X19o8anFY,6525
30
30
  oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
31
31
  oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
32
- oafuncs/oa_tool/__init__.py,sha256=WPrWq_vWWcUVQ32tsjA4jPQiV0LCxhxS0l4vmX43xDg,508
32
+ oafuncs/oa_tool/__init__.py,sha256=AvrCNR2-xad9ZRjthIdAoSk8UX4vOpEWLg6CV1NQNKc,161
33
33
  oafuncs/oa_tool/email.py,sha256=4lJxV_KUzhxgLYfVwYTqp0qxRugD7fvsZkXDe5WkUKo,3052
34
34
  oafuncs/oa_tool/parallel.py,sha256=LBFWEKPcILVCbfSulETJE4wGPiOw1P_Fl9DzjYoCqgk,21844
35
- oafuncs/oa_tool/time.py,sha256=n8Ir5QFxJGZlEsOI3frxyQcN92wIvmS7-2SPQHYCg_c,486
36
- oafuncs-0.0.97.5.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
37
- oafuncs-0.0.97.5.dist-info/METADATA,sha256=defSpljPoBK_2UVFLEvAtoNmOl6ghws_g9vTw1lQH-o,4181
38
- oafuncs-0.0.97.5.dist-info/WHEEL,sha256=1tXe9gY0PYatrMPMDd6jXqjfpz_B-Wqm32CPfRC58XU,91
39
- oafuncs-0.0.97.5.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
40
- oafuncs-0.0.97.5.dist-info/RECORD,,
35
+ oafuncs-0.0.97.7.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
36
+ oafuncs-0.0.97.7.dist-info/METADATA,sha256=L8CwqaBvrrajJfxqWnwWI0r472K1AnLoS6AVtb36Z7Q,4204
37
+ oafuncs-0.0.97.7.dist-info/WHEEL,sha256=CmyFI0kx5cdEMTLiONQRbGQwjIoR1aIYB7eCAQ4KPJ0,91
38
+ oafuncs-0.0.97.7.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
39
+ oafuncs-0.0.97.7.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (77.0.3)
2
+ Generator: setuptools (78.1.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5