dcicutils 8.8.4.1b16__py3-none-any.whl → 8.8.4.1b18__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.
dcicutils/file_utils.py CHANGED
@@ -23,46 +23,59 @@ def search_for_file(file: str,
23
23
  first file which is found is returns (as a string), or None if none; if the single flag
24
24
  is False, then all matched files are returned in a list, or and empty list if none.
25
25
  """
26
- if file and isinstance(file, (str, pathlib.PosixPath)):
27
- if os.path.isabs(file):
28
- if os.path.exists(file):
29
- return file if single else [file]
30
- return None if single else []
31
- files_found = []
32
- if not location:
33
- location = ["."]
34
- elif isinstance(location, (str, pathlib.PosixPath)):
35
- location = [location]
36
- elif not isinstance(location, list):
37
- location = []
26
+ if not (file and isinstance(file, (str, pathlib.PosixPath))):
27
+ return None if single is True else []
28
+ if os.path.isabs(file):
29
+ if os.path.exists(file):
30
+ return file if single is True else [file]
31
+ return None if single is True else []
32
+ files_found = []
33
+ if not location:
34
+ location = ["."]
35
+ elif isinstance(location, (str, pathlib.PosixPath)):
36
+ location = [location]
37
+ elif not isinstance(location, list):
38
+ location = []
39
+ location_pruned = []
40
+ for directory in location:
41
+ if not isinstance(directory, str):
42
+ if not isinstance(directory, pathlib.PosixPath):
43
+ continue
44
+ directory = str(directory)
45
+ if not (directory := directory.strip()):
46
+ continue
47
+ if os.path.isfile(directory):
48
+ # Allow a file; assume its parent directory was intended.
49
+ if not (directory := os.path.dirname(directory)):
50
+ continue
51
+ location_pruned.append(directory)
52
+ location = location_pruned
53
+ for directory in location:
54
+ if os.path.exists(os.path.join(directory, file)):
55
+ file_found = os.path.abspath(os.path.normpath(os.path.join(directory, file)))
56
+ if single is True:
57
+ return file_found
58
+ if file_found not in files_found:
59
+ files_found.append(file_found)
60
+ if recursive is True:
38
61
  for directory in location:
39
62
  if not directory:
40
63
  continue
41
- if isinstance(directory, (str, pathlib.PosixPath)) and os.path.exists(os.path.join(directory, file)):
42
- file_found = os.path.abspath(os.path.normpath(os.path.join(directory, file)))
43
- if single:
44
- return file_found
45
- if file_found not in files_found:
46
- files_found.append(file_found)
47
- if recursive:
48
- for directory in location:
49
- if not directory:
50
- continue
51
- if not directory.endswith("/**") and not file.startswith("**/"):
52
- path = f"{directory}/**/{file}"
53
- else:
54
- path = f"{directory}/{file}"
55
- files = glob.glob(path, recursive=recursive)
56
- if files:
57
- for file_found in files:
58
- file_found = os.path.abspath(file_found)
59
- if single:
60
- return file_found
61
- if file_found not in files_found:
62
- files_found.append(file_found)
63
- if files_found:
64
- return files_found[0] if single else files_found
65
- return None if single else []
64
+ if not directory.endswith("/**") and not file.startswith("**/"):
65
+ path = f"{directory}/**/{file}"
66
+ else:
67
+ path = f"{directory}/{file}"
68
+ files = glob.glob(path, recursive=True if recursive is True else False)
69
+ if files:
70
+ for file_found in files:
71
+ file_found = os.path.abspath(file_found)
72
+ if single is True:
73
+ return file_found
74
+ if file_found not in files_found:
75
+ files_found.append(file_found)
76
+ if files_found:
77
+ return files_found[0] if single is True else files_found
78
+ return None if single is True else []
66
79
 
67
80
 
68
81
  def normalize_file_path(path: str, home_directory: bool = True) -> str:
dcicutils/http_utils.py CHANGED
@@ -1,20 +1,31 @@
1
1
  from contextlib import contextmanager
2
2
  import requests
3
- from typing import Optional
3
+ from typing import Callable, Optional
4
4
  from dcicutils.tmpfile_utils import temporary_file
5
5
 
6
6
 
7
7
  @contextmanager
8
- def download(url: str, suffix: Optional[str] = None, binary: bool = True) -> Optional[str]:
8
+ def download(url: str, suffix: Optional[str] = None, binary: bool = True,
9
+ progress: Optional[Callable] = None) -> Optional[str]:
9
10
  """
10
11
  Context manager to ownload the given URL into a temporary file and yields the file
11
12
  path to it. An optional file suffix may be specified. Defaults to binary file mode;
12
13
  if this is not desired then pass False as the binary argument.
13
14
  """
15
+ if not callable(progress):
16
+ progress = None
14
17
  with temporary_file(suffix=suffix) as file:
15
18
  response = requests.get(url, stream=True)
19
+ if progress:
20
+ nbytes = 0
21
+ nbytes_total = None
22
+ if isinstance(content_length := response.headers.get("Content-Length"), str) and content_length.isdigit():
23
+ nbytes_total = int(content_length)
16
24
  with open(file, "wb" if binary is True else "w") as f:
17
25
  for chunk in response.iter_content(chunk_size=8192):
18
26
  if chunk:
19
27
  f.write(chunk)
28
+ if progress:
29
+ nbytes += len(chunk)
30
+ progress(nbytes, nbytes_total)
20
31
  yield file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: dcicutils
3
- Version: 8.8.4.1b16
3
+ Version: 8.8.4.1b18
4
4
  Summary: Utility package for interacting with the 4DN Data Portal and other 4DN resources
5
5
  Home-page: https://github.com/4dn-dcic/utils
6
6
  License: MIT
@@ -28,10 +28,10 @@ dcicutils/es_utils.py,sha256=ZksLh5ei7kRUfiFltk8sd2ZSfh15twbstrMzBr8HNw4,7541
28
28
  dcicutils/exceptions.py,sha256=4giQGtpak-omQv7BP6Ckeu91XK5fnDosC8gfdmN_ccA,9931
29
29
  dcicutils/ff_mocks.py,sha256=6RKS4eUiu_Wl8yP_8V0CaV75w4ZdWxdCuL1CVlnMrek,36918
30
30
  dcicutils/ff_utils.py,sha256=oIhuZPnGtfwj6bWyCc1u23JbMB_6InPp01ZqUOljd8M,73123
31
- dcicutils/file_utils.py,sha256=msxA3fFTtK09Qc_I3-r9Y5Pp5WVJRPPpLlFYv3Rju-E,8697
31
+ dcicutils/file_utils.py,sha256=GI3DfD11iM4Z76QbZftIJ1e6tWATxFtZ8as-vrlHTps,9139
32
32
  dcicutils/function_cache_decorator.py,sha256=XMyiEGODVr2WoAQ68vcoX_9_Xb9p8pZXdXl7keU8i2g,10026
33
33
  dcicutils/glacier_utils.py,sha256=Q4CVXsZCbP-SoZIsZ5NMcawDfelOLzbQnIlQn-GdlTo,34149
34
- dcicutils/http_utils.py,sha256=RB0x9hRMZM9Xd1x00c5J0iUzUdYzIQR0XKFiQ94HWO0,807
34
+ dcicutils/http_utils.py,sha256=Je5ErNjR5e6lfSXGRncK_lcR_-zP38PIpmHjApy9Wi4,1289
35
35
  dcicutils/jh_utils.py,sha256=Gpsxb9XEzggF_-Eq3ukjKvTnuyb9V1SCSUXkXsES4Kg,11502
36
36
  dcicutils/kibana/dashboards.json,sha256=wHMB_mpJ8OaYhRRgvpZuihaB2lmSF64ADt_8hkBWgQg,16225
37
37
  dcicutils/kibana/readme.md,sha256=3KmHF9FH6A6xwYsNxRFLw27q0XzHYnjZOlYUnn3VkQQ,2164
@@ -73,8 +73,8 @@ dcicutils/trace_utils.py,sha256=g8kwV4ebEy5kXW6oOrEAUsurBcCROvwtZqz9fczsGRE,1769
73
73
  dcicutils/validation_utils.py,sha256=cMZIU2cY98FYtzK52z5WUYck7urH6JcqOuz9jkXpqzg,14797
74
74
  dcicutils/variant_utils.py,sha256=2H9azNx3xAj-MySg-uZ2SFqbWs4kZvf61JnK6b-h4Qw,4343
75
75
  dcicutils/zip_utils.py,sha256=_Y9EmL3D2dUZhxucxHvrtmmlbZmK4FpSsHEb7rGSJLU,3265
76
- dcicutils-8.8.4.1b16.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
77
- dcicutils-8.8.4.1b16.dist-info/METADATA,sha256=7R_Eatzjy4Ez8_JufgAKLIQ_O6z0fVvjqHzLEwfE9O0,3440
78
- dcicutils-8.8.4.1b16.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
79
- dcicutils-8.8.4.1b16.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
80
- dcicutils-8.8.4.1b16.dist-info/RECORD,,
76
+ dcicutils-8.8.4.1b18.dist-info/LICENSE.txt,sha256=qnwSmfnEWMl5l78VPDEzAmEbLVrRqQvfUQiHT0ehrOo,1102
77
+ dcicutils-8.8.4.1b18.dist-info/METADATA,sha256=YbKpFyKttkQQ6Exbw6SfcOkW76dDpxqlJ2DhyBHzTxM,3440
78
+ dcicutils-8.8.4.1b18.dist-info/WHEEL,sha256=7Z8_27uaHI_UZAc4Uox4PpBhQ9Y5_modZXWMxtUi4NU,88
79
+ dcicutils-8.8.4.1b18.dist-info/entry_points.txt,sha256=51Q4F_2V10L0282W7HFjP4jdzW4K8lnWDARJQVFy_hw,270
80
+ dcicutils-8.8.4.1b18.dist-info/RECORD,,