atomicshop 2.18.28__py3-none-any.whl → 2.18.30__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.
Potentially problematic release.
This version of atomicshop might be problematic. Click here for more details.
- atomicshop/__init__.py +1 -1
- atomicshop/basics/multiprocesses.py +2 -2
- atomicshop/filesystem.py +118 -2
- atomicshop/permissions/ubuntu_permissions.py +42 -0
- {atomicshop-2.18.28.dist-info → atomicshop-2.18.30.dist-info}/METADATA +1 -1
- {atomicshop-2.18.28.dist-info → atomicshop-2.18.30.dist-info}/RECORD +9 -9
- {atomicshop-2.18.28.dist-info → atomicshop-2.18.30.dist-info}/LICENSE.txt +0 -0
- {atomicshop-2.18.28.dist-info → atomicshop-2.18.30.dist-info}/WHEEL +0 -0
- {atomicshop-2.18.28.dist-info → atomicshop-2.18.30.dist-info}/top_level.txt +0 -0
atomicshop/__init__.py
CHANGED
|
@@ -125,8 +125,8 @@ class MultiProcessorRecursive:
|
|
|
125
125
|
result = async_result.get()
|
|
126
126
|
# Assuming process_function returns a list, extend new_input_list
|
|
127
127
|
new_input_list.extend(result)
|
|
128
|
-
except Exception
|
|
129
|
-
|
|
128
|
+
except Exception:
|
|
129
|
+
raise
|
|
130
130
|
|
|
131
131
|
# Update the input_list for the next iteration
|
|
132
132
|
self.input_list = new_input_list
|
atomicshop/filesystem.py
CHANGED
|
@@ -329,6 +329,30 @@ def remove_directory(directory_path: str, force_readonly: bool = False, print_kw
|
|
|
329
329
|
return False
|
|
330
330
|
|
|
331
331
|
|
|
332
|
+
def clear_directory(directory: str) -> tuple[list[str], list[str]]:
|
|
333
|
+
"""
|
|
334
|
+
The function will clear the directory of all files and subdirectories.
|
|
335
|
+
:param directory:
|
|
336
|
+
:return: tuple of lists of removed file paths and removed directory paths.
|
|
337
|
+
"""
|
|
338
|
+
|
|
339
|
+
file_paths: list = []
|
|
340
|
+
directory_paths: list = []
|
|
341
|
+
# Iterate through all files and subdirectories in the directory
|
|
342
|
+
for item in os.listdir(directory):
|
|
343
|
+
item_path = os.path.join(directory, item)
|
|
344
|
+
# If it's a file, remove it
|
|
345
|
+
if os.path.isfile(item_path) or os.path.islink(item_path): # Handle symbolic links too
|
|
346
|
+
os.remove(item_path)
|
|
347
|
+
file_paths.append(item_path)
|
|
348
|
+
# If it's a directory, remove it and its contents
|
|
349
|
+
elif os.path.isdir(item_path):
|
|
350
|
+
shutil.rmtree(item_path)
|
|
351
|
+
directory_paths.append(item_path)
|
|
352
|
+
|
|
353
|
+
return file_paths, directory_paths
|
|
354
|
+
|
|
355
|
+
|
|
332
356
|
def remove_empty_directories(directory_path: str) -> list[str]:
|
|
333
357
|
"""
|
|
334
358
|
Recursively removes empty directories in the given path, including the given path if it is empty.
|
|
@@ -675,12 +699,12 @@ def move_folder_contents_to_folder(
|
|
|
675
699
|
|
|
676
700
|
if os.path.isdir(s):
|
|
677
701
|
if os.path.exists(d) and not overwrite:
|
|
678
|
-
|
|
702
|
+
raise FileExistsError(f"Directory already exists: {d}. Skipping due to overwrite=False.")
|
|
679
703
|
else:
|
|
680
704
|
shutil.move(s, d)
|
|
681
705
|
else:
|
|
682
706
|
if os.path.exists(d) and not overwrite:
|
|
683
|
-
|
|
707
|
+
raise FileExistsError(f"File {d} already exists. Skipping due to overwrite=False.")
|
|
684
708
|
else:
|
|
685
709
|
shutil.move(s, d)
|
|
686
710
|
|
|
@@ -1675,3 +1699,95 @@ def find_file(file_name: str, directory_path: str):
|
|
|
1675
1699
|
if filename == file_name:
|
|
1676
1700
|
return os.path.join(dir_path, filename)
|
|
1677
1701
|
return None
|
|
1702
|
+
|
|
1703
|
+
|
|
1704
|
+
def create_ubuntu_desktop_shortcut(
|
|
1705
|
+
file_path: str = None,
|
|
1706
|
+
shortcut_name: str = None,
|
|
1707
|
+
command: str = None,
|
|
1708
|
+
working_directory: str = None,
|
|
1709
|
+
icon_path: str = None,
|
|
1710
|
+
terminal: bool = False,
|
|
1711
|
+
comment: str = "Shortcut to execute the Python script",
|
|
1712
|
+
categories: str = "Utility",
|
|
1713
|
+
set_executable: bool = False,
|
|
1714
|
+
set_trusted: bool = False,
|
|
1715
|
+
set_xfce_exe_checksum: bool = False
|
|
1716
|
+
):
|
|
1717
|
+
"""
|
|
1718
|
+
Create a desktop shortcut on Ubuntu.
|
|
1719
|
+
|
|
1720
|
+
Either file_path or command must be specified.
|
|
1721
|
+
If command is specified, working_directory must be specified.
|
|
1722
|
+
|
|
1723
|
+
:param file_path: string, The file_path to execute when the shortcut is clicked.
|
|
1724
|
+
Example2: '/path/to/script.sh'
|
|
1725
|
+
:param shortcut_name: string, The name of the shortcut.
|
|
1726
|
+
Example: 'My Python Script'
|
|
1727
|
+
Result: 'My Python Script.desktop'
|
|
1728
|
+
:param command: string, The command to execute when the shortcut is clicked.
|
|
1729
|
+
Example: 'python3 /path/to/script.py'
|
|
1730
|
+
:param working_directory: string, The working directory for the command.
|
|
1731
|
+
If None, the command will be executed in the same script's directory.
|
|
1732
|
+
:param icon_path: string, The path to the icon file.
|
|
1733
|
+
:param terminal: boolean, If True, the command will be executed in a terminal.
|
|
1734
|
+
:param comment: string, A comment to describe the shortcut.
|
|
1735
|
+
:param categories: string, The categories of the shortcut.
|
|
1736
|
+
:param set_executable: boolean, If True, the shortcut will be made executable.
|
|
1737
|
+
:param set_trusted: boolean, If True, the shortcut will be marked as trusted.
|
|
1738
|
+
This is needed for GNOME.
|
|
1739
|
+
:param set_xfce_exe_checksum: boolean, If True, the shortcut will be made safe executable for XFCE.
|
|
1740
|
+
|
|
1741
|
+
:return: None
|
|
1742
|
+
"""
|
|
1743
|
+
|
|
1744
|
+
if not file_path and not command:
|
|
1745
|
+
raise ValueError("Either 'file_path' or 'command' must be specified.")
|
|
1746
|
+
if command and file_path:
|
|
1747
|
+
raise ValueError("Only one of 'file_path' or 'command' can be specified.")
|
|
1748
|
+
if command and not working_directory:
|
|
1749
|
+
raise ValueError("Working directory must be specified if 'command' is specified.")
|
|
1750
|
+
|
|
1751
|
+
from .permissions import ubuntu_permissions
|
|
1752
|
+
|
|
1753
|
+
# Get the user's directory.
|
|
1754
|
+
desktop_dir = os.path.expanduser("~/Desktop")
|
|
1755
|
+
|
|
1756
|
+
if not working_directory:
|
|
1757
|
+
working_directory = os.path.dirname(file_path)
|
|
1758
|
+
|
|
1759
|
+
if not shortcut_name:
|
|
1760
|
+
shortcut_name: str = Path(file_path).stem
|
|
1761
|
+
|
|
1762
|
+
# Full path to the .desktop file
|
|
1763
|
+
shortcut_path = os.path.join(desktop_dir, f"{shortcut_name}.desktop")
|
|
1764
|
+
|
|
1765
|
+
# Generate the content for the .desktop file
|
|
1766
|
+
desktop_entry = [
|
|
1767
|
+
"[Desktop Entry]",
|
|
1768
|
+
"Version=1.0",
|
|
1769
|
+
"Type=Application",
|
|
1770
|
+
f"Name={shortcut_name}",
|
|
1771
|
+
f"Exec={file_path}",
|
|
1772
|
+
f"Path={working_directory}",
|
|
1773
|
+
f"Icon={icon_path}" if icon_path else "",
|
|
1774
|
+
f"Terminal={'true' if terminal else 'false'}",
|
|
1775
|
+
f"Comment={comment}",
|
|
1776
|
+
f"Categories={categories};",
|
|
1777
|
+
]
|
|
1778
|
+
|
|
1779
|
+
# Write the .desktop file
|
|
1780
|
+
with open(shortcut_path, "w") as shortcut_file:
|
|
1781
|
+
shortcut_file.write("\n".join(line for line in desktop_entry if line)) # Skip empty lines
|
|
1782
|
+
|
|
1783
|
+
# Make the .desktop file executable
|
|
1784
|
+
if set_executable:
|
|
1785
|
+
ubuntu_permissions.set_executable(shortcut_path)
|
|
1786
|
+
|
|
1787
|
+
# Mark the .desktop file as trusted
|
|
1788
|
+
if set_trusted:
|
|
1789
|
+
ubuntu_permissions.set_trusted_executable(shortcut_path)
|
|
1790
|
+
|
|
1791
|
+
# Make the .desktop file safe executable for XFCE
|
|
1792
|
+
if set_xfce_exe_checksum:
|
|
1793
|
+
ubuntu_permissions.set_xfce_exe_checksum(shortcut_path)
|
|
@@ -33,6 +33,48 @@ def set_executable(file_path: str):
|
|
|
33
33
|
os.chmod(file_path, os.stat(file_path).st_mode | stat.S_IXUSR)
|
|
34
34
|
|
|
35
35
|
|
|
36
|
+
def set_trusted_executable(file_path: str):
|
|
37
|
+
"""
|
|
38
|
+
Function sets the executable permission on a file and marks it as trusted.
|
|
39
|
+
:param file_path: str, path to the file.
|
|
40
|
+
:return:
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
# Check if the file exists
|
|
44
|
+
if not os.path.exists(file_path):
|
|
45
|
+
raise FileNotFoundError(f"The file does not exist: {file_path} ")
|
|
46
|
+
|
|
47
|
+
# Execute the `gio set` command
|
|
48
|
+
subprocess.run(
|
|
49
|
+
["gio", "set", file_path, "metadata::trusted", "true"],
|
|
50
|
+
check=True
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def set_xfce_exe_checksum(desktop_file_path):
|
|
55
|
+
# Expand `~` to the full home directory path
|
|
56
|
+
desktop_file_path = os.path.expanduser(desktop_file_path)
|
|
57
|
+
|
|
58
|
+
# Ensure the file exists
|
|
59
|
+
if not os.path.exists(desktop_file_path):
|
|
60
|
+
raise FileNotFoundError(f"The file does not exist: {desktop_file_path} ")
|
|
61
|
+
|
|
62
|
+
# Calculate the SHA256 checksum of the file
|
|
63
|
+
result = subprocess.run(
|
|
64
|
+
["sha256sum", desktop_file_path],
|
|
65
|
+
stdout=subprocess.PIPE,
|
|
66
|
+
check=True,
|
|
67
|
+
text=True
|
|
68
|
+
)
|
|
69
|
+
checksum = result.stdout.split()[0]
|
|
70
|
+
|
|
71
|
+
# Set the metadata::xfce-exe-checksum attribute using `gio`
|
|
72
|
+
subprocess.run(
|
|
73
|
+
["gio", "set", "-t", "string", desktop_file_path, "metadata::xfce-exe-checksum", checksum],
|
|
74
|
+
check=True
|
|
75
|
+
)
|
|
76
|
+
|
|
77
|
+
|
|
36
78
|
def change_file_owner(file_path: str, username: str):
|
|
37
79
|
"""
|
|
38
80
|
Function changes the owner of the file to the specified user.
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
atomicshop/__init__.py,sha256=
|
|
1
|
+
atomicshop/__init__.py,sha256=6a8s52oEErBoMqHlOVc95TxLFuoK8ZGvWHPZKkVUgAA,124
|
|
2
2
|
atomicshop/_basics_temp.py,sha256=6cu2dd6r2dLrd1BRNcVDKTHlsHs_26Gpw8QS6v32lQ0,3699
|
|
3
3
|
atomicshop/_create_pdf_demo.py,sha256=Yi-PGZuMg0RKvQmLqVeLIZYadqEZwUm-4A9JxBl_vYA,3713
|
|
4
4
|
atomicshop/_patch_import.py,sha256=ENp55sKVJ0e6-4lBvZnpz9PQCt3Otbur7F6aXDlyje4,6334
|
|
@@ -14,7 +14,7 @@ atomicshop/dns.py,sha256=5Gimq_WY2arqg7BeGmR7P--fGfnH0Dsh8lrOt_H0jRY,6817
|
|
|
14
14
|
atomicshop/domains.py,sha256=Rxu6JhhMqFZRcoFs69IoEd1PtYca0lMCG6F1AomP7z4,3197
|
|
15
15
|
atomicshop/emails.py,sha256=I0KyODQpIMEsNRi9YWSOL8EUPBiWyon3HRdIuSj3AEU,1410
|
|
16
16
|
atomicshop/file_types.py,sha256=-0jzQMRlmU1AP9DARjk-HJm1tVE22E6ngP2mRblyEjY,763
|
|
17
|
-
atomicshop/filesystem.py,sha256=
|
|
17
|
+
atomicshop/filesystem.py,sha256=vXyc73_8ltcsuvPrmFor8QtehZs0Dg3_FvflAoZKT00,67857
|
|
18
18
|
atomicshop/functions.py,sha256=pK8hoCE9z61PtWCxQJsda7YAphrLH1wxU5x-1QJP-sY,499
|
|
19
19
|
atomicshop/get_process_list.py,sha256=8cxb7gKe9sl4R6H2yMi8J6oe-RkonTvCdKjRFqi-Fs4,6075
|
|
20
20
|
atomicshop/get_process_name_cmd_dll.py,sha256=CtaSp3mgxxJKCCVW8BLx6BJNx4giCklU_T7USiCEwfc,5162
|
|
@@ -100,7 +100,7 @@ atomicshop/basics/isinstancing.py,sha256=fQ35xfqbguQz2BUn-3a4KVGskhTcIn8JjRtxV2r
|
|
|
100
100
|
atomicshop/basics/list_of_classes.py,sha256=PJoE1VJdhhQ4gSFr88zW7IApXd4Ez7xLz-7vAM-7gug,978
|
|
101
101
|
atomicshop/basics/list_of_dicts.py,sha256=tj0LNPf1ljNI_qpoO-PiOT4Ulmk1M-UpTGyn9twVcw8,8039
|
|
102
102
|
atomicshop/basics/lists.py,sha256=I0C62vrDrNwCTNl0EjUZNa1Jsd8l0rTkp28GEx9QoEI,4258
|
|
103
|
-
atomicshop/basics/multiprocesses.py,sha256=
|
|
103
|
+
atomicshop/basics/multiprocesses.py,sha256=oU6LjcLLGBtPIGJzZBpDWoLU3HRmMoanITEOE2luAYw,18799
|
|
104
104
|
atomicshop/basics/numbers.py,sha256=ESX0z_7o_ok3sOmCKAUBoZinATklgMy2v-4RndqXlVM,1837
|
|
105
105
|
atomicshop/basics/package_module.py,sha256=fBd0uVgFce25ZCVtLq83iyowRlbwdWYFj_t4Ml7LU14,391
|
|
106
106
|
atomicshop/basics/randoms.py,sha256=DmYLtnIhDK29tAQrGP1Nt-A-v8WC7WIEB8Edi-nk3N4,282
|
|
@@ -159,7 +159,7 @@ atomicshop/monitor/checks/process_running.py,sha256=x66wd6-l466r8sbRQaIli0yswyGt
|
|
|
159
159
|
atomicshop/monitor/checks/url.py,sha256=1PvKt_d7wFg7rDMFpUejAQhj0mqWsmlmrNfjNAV2G4g,4123
|
|
160
160
|
atomicshop/permissions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
161
161
|
atomicshop/permissions/permissions.py,sha256=CYTDVOI0jh9ks0ZLnnOuPzppgCszFEc9-92DTkVTYi4,522
|
|
162
|
-
atomicshop/permissions/ubuntu_permissions.py,sha256=
|
|
162
|
+
atomicshop/permissions/ubuntu_permissions.py,sha256=n8z1vcIXDts4zLVue33dtJiTopjgEAYPg4dqFn0qwwc,5943
|
|
163
163
|
atomicshop/permissions/win_permissions.py,sha256=eDQm1jfK9x_hkbLqIJjFTwfqinAWQ0iSr0kW3XrF1BE,1272
|
|
164
164
|
atomicshop/process_poller/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
165
165
|
atomicshop/process_poller/process_pool.py,sha256=4Qs427qd7OcBxu5PMFU5PTmyuxRy0vgj2GLsRt0IoEw,9565
|
|
@@ -321,8 +321,8 @@ atomicshop/wrappers/socketw/statistics_csv.py,sha256=fgMzDXI0cybwUEqAxprRmY3lqbh
|
|
|
321
321
|
atomicshop/wrappers/winregw/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
322
322
|
atomicshop/wrappers/winregw/winreg_installed_software.py,sha256=Qzmyktvob1qp6Tjk2DjLfAqr_yXV0sgWzdMW_9kwNjY,2345
|
|
323
323
|
atomicshop/wrappers/winregw/winreg_network.py,sha256=AENV88H1qDidrcpyM9OwEZxX5svfi-Jb4N6FkS1xtqA,8851
|
|
324
|
-
atomicshop-2.18.
|
|
325
|
-
atomicshop-2.18.
|
|
326
|
-
atomicshop-2.18.
|
|
327
|
-
atomicshop-2.18.
|
|
328
|
-
atomicshop-2.18.
|
|
324
|
+
atomicshop-2.18.30.dist-info/LICENSE.txt,sha256=lLU7EYycfYcK2NR_1gfnhnRC8b8ccOTElACYplgZN88,1094
|
|
325
|
+
atomicshop-2.18.30.dist-info/METADATA,sha256=c7ZY3AG2mw1LVujTZo1Svw7dQLemtJdNBBLUE_7obZc,10631
|
|
326
|
+
atomicshop-2.18.30.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
327
|
+
atomicshop-2.18.30.dist-info/top_level.txt,sha256=EgKJB-7xcrAPeqTRF2laD_Np2gNGYkJkd4OyXqpJphA,11
|
|
328
|
+
atomicshop-2.18.30.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|