cht_utils 2.0.0__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.
- cht_utils/__init__.py +28 -0
- cht_utils/cog/__init__.py +6 -0
- cht_utils/cog/geotiff_to_cog.py +79 -0
- cht_utils/cog/netcdf_to_cog.py +85 -0
- cht_utils/cog/xyz_to_cog.py +86 -0
- cht_utils/colors/__init__.py +6 -0
- cht_utils/colors/colors.py +117 -0
- cht_utils/fileio/__init__.py +21 -0
- cht_utils/fileio/deltares_ini.py +326 -0
- cht_utils/fileio/json_js.py +72 -0
- cht_utils/fileio/pli_file.py +233 -0
- cht_utils/fileio/tekal.py +234 -0
- cht_utils/fileio/xml.py +184 -0
- cht_utils/fileio/yaml.py +39 -0
- cht_utils/fileops/__init__.py +25 -0
- cht_utils/fileops/fileops.py +344 -0
- cht_utils/interpolation/__init__.py +5 -0
- cht_utils/interpolation/interpolation.py +152 -0
- cht_utils/maps/__init__.py +2 -0
- cht_utils/maps/fileops.py +191 -0
- cht_utils/maps/flood_map.py +1231 -0
- cht_utils/maps/topobathy_map.py +463 -0
- cht_utils/maps/utils.py +700 -0
- cht_utils/physics/__init__.py +8 -0
- cht_utils/physics/deshoal.py +63 -0
- cht_utils/physics/disper.py +91 -0
- cht_utils/physics/runup_vo21.py +229 -0
- cht_utils/physics/waves.py +59 -0
- cht_utils/probabilistic/__init__.py +5 -0
- cht_utils/probabilistic/prob_maps.py +263 -0
- cht_utils/remote/__init__.py +4 -0
- cht_utils/remote/s3.py +380 -0
- cht_utils/remote/sftp.py +192 -0
- cht_utils-2.0.0.dist-info/METADATA +30 -0
- cht_utils-2.0.0.dist-info/RECORD +39 -0
- cht_utils-2.0.0.dist-info/WHEEL +5 -0
- cht_utils-2.0.0.dist-info/licenses/LICENSE +21 -0
- cht_utils-2.0.0.dist-info/top_level.txt +1 -0
- cht_utils-2.0.0.dist-info/zip-safe +1 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
"""Read and write Delft3D Tekal ASCII files.
|
|
2
|
+
|
|
3
|
+
A Tekal file consists of consecutive blocks, each containing:
|
|
4
|
+
|
|
5
|
+
- Optional ``*``-prefixed comment lines
|
|
6
|
+
- A block name line
|
|
7
|
+
- A size line (nrows, ncols, and optionally nx, ny)
|
|
8
|
+
- Data lines
|
|
9
|
+
|
|
10
|
+
Example usage::
|
|
11
|
+
|
|
12
|
+
import cht_utils.fileio.tekal as tek
|
|
13
|
+
|
|
14
|
+
D = tek.tekal("myfile.tek")
|
|
15
|
+
D.info()
|
|
16
|
+
print(D)
|
|
17
|
+
M = D.read(0) # load first block
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
from typing import IO, List, Optional
|
|
21
|
+
|
|
22
|
+
import numpy as np
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
class tekalblock:
|
|
26
|
+
"""A single data block within a Tekal file."""
|
|
27
|
+
|
|
28
|
+
def __init__(self) -> None:
|
|
29
|
+
self.header: List[str] = []
|
|
30
|
+
self.nhdr: Optional[int] = None
|
|
31
|
+
self.index: Optional[int] = None
|
|
32
|
+
self.name: Optional[str] = None
|
|
33
|
+
self.npts: Optional[int] = None
|
|
34
|
+
self.nvar: Optional[int] = None
|
|
35
|
+
self.nx: Optional[int] = None
|
|
36
|
+
self.ny: Optional[int] = None
|
|
37
|
+
self.data: Optional[np.ndarray] = None
|
|
38
|
+
self.tell: float = 0.0
|
|
39
|
+
|
|
40
|
+
def __str__(self) -> str:
|
|
41
|
+
return (
|
|
42
|
+
f"{self.index:5g}: nvar={self.nvar:4g} npts={self.npts:5g} "
|
|
43
|
+
f"({self.nx:5g} x{self.ny:4g}) {self.nhdr:4} '{self.name}'\n"
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
def strheader(self) -> str:
|
|
47
|
+
"""Return a header line describing the column layout."""
|
|
48
|
+
return (
|
|
49
|
+
f"{'block':>5s}: {'nvar':>4s} {'npts':>5s} "
|
|
50
|
+
f"({'nx':>5s} x{'ny':>4s}) {'nhdr':>4s} '{'blockname'}'\n"
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
def info(self, fid: IO, index: int) -> Optional["tekalblock"]:
|
|
54
|
+
"""Read block metadata (header, name, dimensions) from an open file.
|
|
55
|
+
|
|
56
|
+
Parameters
|
|
57
|
+
----------
|
|
58
|
+
fid : IO
|
|
59
|
+
Open file handle.
|
|
60
|
+
index : int
|
|
61
|
+
Block index.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
tekalblock or None
|
|
66
|
+
Self if successful, ``None`` at end-of-file.
|
|
67
|
+
"""
|
|
68
|
+
self.tell = fid.tell()
|
|
69
|
+
|
|
70
|
+
rec = fid.readline()
|
|
71
|
+
if len(rec) == 0:
|
|
72
|
+
return None
|
|
73
|
+
|
|
74
|
+
while rec[0] == "*":
|
|
75
|
+
self.header.append(rec)
|
|
76
|
+
rec = fid.readline()
|
|
77
|
+
|
|
78
|
+
self.index = index
|
|
79
|
+
self.name = rec.split()[0]
|
|
80
|
+
self.header.append(rec)
|
|
81
|
+
self.nhdr = len(self.header)
|
|
82
|
+
|
|
83
|
+
rec = fid.readline()
|
|
84
|
+
parts = rec.split()
|
|
85
|
+
self.npts = int(parts[0])
|
|
86
|
+
self.nvar = int(parts[1])
|
|
87
|
+
if len(parts) == 2:
|
|
88
|
+
self.nx = self.npts
|
|
89
|
+
self.ny = 1
|
|
90
|
+
else:
|
|
91
|
+
self.nx = int(parts[2])
|
|
92
|
+
self.ny = int(parts[3])
|
|
93
|
+
|
|
94
|
+
# Skip data lines
|
|
95
|
+
for _ in range(self.npts):
|
|
96
|
+
fid.readline()
|
|
97
|
+
|
|
98
|
+
return self
|
|
99
|
+
|
|
100
|
+
def load(self, fid: IO) -> np.ndarray:
|
|
101
|
+
"""Load the data from this block into a 3-D numpy array.
|
|
102
|
+
|
|
103
|
+
The returned array has shape ``(nvar, nx, ny)``.
|
|
104
|
+
|
|
105
|
+
Parameters
|
|
106
|
+
----------
|
|
107
|
+
fid : IO
|
|
108
|
+
Open file handle, sought to ``self.tell``.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
np.ndarray
|
|
113
|
+
Data array of shape ``(nvar, nx, ny)``.
|
|
114
|
+
"""
|
|
115
|
+
# Skip header
|
|
116
|
+
rec = fid.readline()
|
|
117
|
+
while rec[0] == "*":
|
|
118
|
+
rec = fid.readline()
|
|
119
|
+
|
|
120
|
+
rec = fid.readline()
|
|
121
|
+
parts = rec.split()
|
|
122
|
+
npts = int(parts[0])
|
|
123
|
+
nvar = int(parts[1])
|
|
124
|
+
if len(parts) == 2:
|
|
125
|
+
nx, ny = npts, 1
|
|
126
|
+
else:
|
|
127
|
+
nx, ny = int(parts[2]), int(parts[3])
|
|
128
|
+
|
|
129
|
+
M = np.zeros([nvar, nx, ny])
|
|
130
|
+
for ix in range(nx):
|
|
131
|
+
for it in range(ny):
|
|
132
|
+
rec = fid.readline()
|
|
133
|
+
values = rec.split()
|
|
134
|
+
M[:, ix, it] = [float(v) for v in values[:nvar]]
|
|
135
|
+
|
|
136
|
+
self.data = M
|
|
137
|
+
return M
|
|
138
|
+
|
|
139
|
+
def check(self) -> None:
|
|
140
|
+
"""Assert that all required fields are populated."""
|
|
141
|
+
assert self.header != []
|
|
142
|
+
assert self.nhdr is not None
|
|
143
|
+
assert self.name is not None
|
|
144
|
+
assert self.npts is not None
|
|
145
|
+
assert self.nvar is not None
|
|
146
|
+
assert self.nx is not None
|
|
147
|
+
assert self.ny is not None
|
|
148
|
+
assert self.data is not None
|
|
149
|
+
|
|
150
|
+
def copy(self) -> "tekalblock":
|
|
151
|
+
"""Create a deep copy of this block."""
|
|
152
|
+
cp = tekalblock()
|
|
153
|
+
cp.header = self.header[:]
|
|
154
|
+
cp.nhdr = self.nhdr
|
|
155
|
+
cp.name = self.name
|
|
156
|
+
cp.npts = self.npts
|
|
157
|
+
cp.nvar = self.nvar
|
|
158
|
+
cp.nx = self.nx
|
|
159
|
+
cp.ny = self.ny
|
|
160
|
+
cp.data = self.data.copy()
|
|
161
|
+
return cp
|
|
162
|
+
|
|
163
|
+
|
|
164
|
+
class tekal:
|
|
165
|
+
"""Container for a Tekal file with multiple blocks.
|
|
166
|
+
|
|
167
|
+
Parameters
|
|
168
|
+
----------
|
|
169
|
+
filename : str
|
|
170
|
+
Path to the Tekal file.
|
|
171
|
+
"""
|
|
172
|
+
|
|
173
|
+
def __init__(self, filename: str) -> None:
|
|
174
|
+
self.filename = filename
|
|
175
|
+
self.blocks: List[tekalblock] = []
|
|
176
|
+
|
|
177
|
+
def append(self, block: tekalblock) -> None:
|
|
178
|
+
"""Append a validated block to the file structure."""
|
|
179
|
+
block.check()
|
|
180
|
+
self.blocks.append(block)
|
|
181
|
+
self.blocks[-1].index = len(self.blocks) - 1
|
|
182
|
+
|
|
183
|
+
def __str__(self) -> str:
|
|
184
|
+
txt = self.blocks[0].strheader()
|
|
185
|
+
for block in self.blocks:
|
|
186
|
+
txt += str(block)
|
|
187
|
+
return txt
|
|
188
|
+
|
|
189
|
+
def info(self) -> None:
|
|
190
|
+
"""Read metadata for all blocks (without loading data)."""
|
|
191
|
+
fid = open(self.filename, "rb")
|
|
192
|
+
index = 0
|
|
193
|
+
while True:
|
|
194
|
+
B = tekalblock()
|
|
195
|
+
result = B.info(fid, index)
|
|
196
|
+
if result is None or B.npts is None:
|
|
197
|
+
break
|
|
198
|
+
self.blocks.append(B)
|
|
199
|
+
index += 1
|
|
200
|
+
fid.close()
|
|
201
|
+
|
|
202
|
+
def read(self, index: int) -> np.ndarray:
|
|
203
|
+
"""Load data from a specific block.
|
|
204
|
+
|
|
205
|
+
Parameters
|
|
206
|
+
----------
|
|
207
|
+
index : int
|
|
208
|
+
Block index.
|
|
209
|
+
|
|
210
|
+
Returns
|
|
211
|
+
-------
|
|
212
|
+
np.ndarray
|
|
213
|
+
Data array of shape ``(nvar, nx, ny)``.
|
|
214
|
+
"""
|
|
215
|
+
fid = open(self.filename, "rb")
|
|
216
|
+
fid.seek(self.blocks[index].tell)
|
|
217
|
+
M = self.blocks[index].load(fid)
|
|
218
|
+
fid.close()
|
|
219
|
+
return M
|
|
220
|
+
|
|
221
|
+
def write(self) -> None:
|
|
222
|
+
"""Write all blocks to the file."""
|
|
223
|
+
with open(self.filename, "a") as fid:
|
|
224
|
+
for block in self.blocks:
|
|
225
|
+
block.check()
|
|
226
|
+
fid.write("".join(block.header))
|
|
227
|
+
if block.ny == 1:
|
|
228
|
+
fid.write(f"{block.npts:g} {block.nvar:g}\n")
|
|
229
|
+
else:
|
|
230
|
+
fid.write(f"{block.npts:g} {block.nvar:g} {block.ny:g}\n")
|
|
231
|
+
for it in range(block.ny):
|
|
232
|
+
for ix in range(block.nx):
|
|
233
|
+
row = " ".join(f"{v:f}" for v in block.data[:, ix, it])
|
|
234
|
+
fid.write(row + "\n")
|
cht_utils/fileio/xml.py
ADDED
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
"""XML serialization and deserialization with type conversion.
|
|
2
|
+
|
|
3
|
+
Supports reading/writing Python objects and dictionaries as XML, with
|
|
4
|
+
optional type attributes (``float``, ``int``, ``datetime``) for automatic
|
|
5
|
+
value conversion.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import urllib.request
|
|
9
|
+
import xml.etree.ElementTree as ET
|
|
10
|
+
from datetime import datetime
|
|
11
|
+
from typing import IO, Any
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class XMLObject:
|
|
15
|
+
"""Marker base class for XML-deserialized objects."""
|
|
16
|
+
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
def write_node(file: IO, node: Any, nspaces: int) -> None:
|
|
21
|
+
"""Recursively write a node (dict or object) to an XML file.
|
|
22
|
+
|
|
23
|
+
Parameters
|
|
24
|
+
----------
|
|
25
|
+
file : IO
|
|
26
|
+
Open file handle.
|
|
27
|
+
node : dict or object
|
|
28
|
+
Node to serialize.
|
|
29
|
+
nspaces : int
|
|
30
|
+
Current indentation level.
|
|
31
|
+
"""
|
|
32
|
+
node_dict = node if isinstance(node, dict) else node.__dict__
|
|
33
|
+
spaces = " " * nspaces
|
|
34
|
+
|
|
35
|
+
for key, children in node_dict.items():
|
|
36
|
+
for child in children:
|
|
37
|
+
if isinstance(child, dict) or (
|
|
38
|
+
not isinstance(child, dict) and not hasattr(child, "value")
|
|
39
|
+
):
|
|
40
|
+
if hasattr(child, "value"):
|
|
41
|
+
_write_leaf(file, spaces, key, child)
|
|
42
|
+
else:
|
|
43
|
+
file.write(f"{spaces}<{key}>\n")
|
|
44
|
+
write_node(file, child, nspaces + 2)
|
|
45
|
+
file.write(f"{spaces}</{key}>\n")
|
|
46
|
+
else:
|
|
47
|
+
_write_leaf(file, spaces, key, child)
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _write_leaf(file: IO, spaces: str, key: str, node: Any) -> None:
|
|
51
|
+
"""Write a leaf node with optional type attribute."""
|
|
52
|
+
if isinstance(node.value, int):
|
|
53
|
+
attr = ' type="int"'
|
|
54
|
+
val = str(node.value)
|
|
55
|
+
elif isinstance(node.value, float):
|
|
56
|
+
attr = ' type="float"'
|
|
57
|
+
val = str(node.value)
|
|
58
|
+
else:
|
|
59
|
+
attr = ""
|
|
60
|
+
val = node.value
|
|
61
|
+
file.write(f"{spaces}<{key}{attr}>{val}</{key}>\n")
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def obj2xml(obj: Any, file_name: str) -> None:
|
|
65
|
+
"""Serialize a Python object to an XML file.
|
|
66
|
+
|
|
67
|
+
Parameters
|
|
68
|
+
----------
|
|
69
|
+
obj : Any
|
|
70
|
+
Object whose ``__dict__`` will be serialized.
|
|
71
|
+
file_name : str
|
|
72
|
+
Output file path.
|
|
73
|
+
"""
|
|
74
|
+
with open(file_name, "w") as f:
|
|
75
|
+
f.write('<?xml version="1.0"?>\n<root>\n')
|
|
76
|
+
write_node(f, obj, 2)
|
|
77
|
+
f.write("</root>\n")
|
|
78
|
+
|
|
79
|
+
|
|
80
|
+
def dict2xml(xml_dict: dict, file_name: str) -> None:
|
|
81
|
+
"""Serialize a dictionary to an XML file.
|
|
82
|
+
|
|
83
|
+
Parameters
|
|
84
|
+
----------
|
|
85
|
+
xml_dict : dict
|
|
86
|
+
Dictionary to serialize.
|
|
87
|
+
file_name : str
|
|
88
|
+
Output file path.
|
|
89
|
+
"""
|
|
90
|
+
with open(file_name, "w") as f:
|
|
91
|
+
f.write('<?xml version="1.0"?>\n<root>\n')
|
|
92
|
+
write_node(f, xml_dict, 2)
|
|
93
|
+
f.write("</root>\n")
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def xml2obj(file_name: str) -> Any:
|
|
97
|
+
"""Deserialize an XML file (local or URL) to a Python object.
|
|
98
|
+
|
|
99
|
+
Parameters
|
|
100
|
+
----------
|
|
101
|
+
file_name : str
|
|
102
|
+
Local file path or HTTP(S) URL.
|
|
103
|
+
|
|
104
|
+
Returns
|
|
105
|
+
-------
|
|
106
|
+
Any
|
|
107
|
+
Dynamically typed Python object tree.
|
|
108
|
+
"""
|
|
109
|
+
if file_name.startswith("http"):
|
|
110
|
+
with urllib.request.urlopen(file_name) as f:
|
|
111
|
+
tree = ET.parse(f)
|
|
112
|
+
xml_root = tree.getroot()
|
|
113
|
+
else:
|
|
114
|
+
xml_root = ET.parse(file_name).getroot()
|
|
115
|
+
return _xml2py(xml_root)
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
def get_value(file_name: str, tag: str) -> Any:
|
|
119
|
+
"""Read a single value from an XML file by tag path.
|
|
120
|
+
|
|
121
|
+
Parameters
|
|
122
|
+
----------
|
|
123
|
+
file_name : str
|
|
124
|
+
XML file path.
|
|
125
|
+
tag : str
|
|
126
|
+
XPath-style tag (e.g. ``"section/param"``).
|
|
127
|
+
|
|
128
|
+
Returns
|
|
129
|
+
-------
|
|
130
|
+
Any
|
|
131
|
+
The value, with type conversion applied if a ``type`` attribute exists.
|
|
132
|
+
"""
|
|
133
|
+
xml_root = ET.parse(file_name).getroot()
|
|
134
|
+
node = xml_root.findall(tag)[0]
|
|
135
|
+
val = node.text
|
|
136
|
+
if node.attrib and "type" in node.attrib:
|
|
137
|
+
val = _convert_value(node.text, node.attrib["type"])
|
|
138
|
+
return val
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _convert_value(text: str, type_name: str) -> Any:
|
|
142
|
+
"""Convert a string value based on a type name."""
|
|
143
|
+
if type_name == "float":
|
|
144
|
+
return float(text)
|
|
145
|
+
elif type_name == "int":
|
|
146
|
+
return int(text)
|
|
147
|
+
elif type_name == "datetime":
|
|
148
|
+
return datetime.strptime(text, "%Y%m%d %H%M%S")
|
|
149
|
+
return text
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _xml2py(node: ET.Element) -> Any:
|
|
153
|
+
"""Recursively convert an XML element to a Python object."""
|
|
154
|
+
name = node.tag
|
|
155
|
+
pytype = type(name, (object,), {})
|
|
156
|
+
pyobj = pytype()
|
|
157
|
+
|
|
158
|
+
for attr in node.attrib:
|
|
159
|
+
setattr(pyobj, attr, node.get(attr))
|
|
160
|
+
|
|
161
|
+
if node.text and node.text.strip() not in ("", "\n"):
|
|
162
|
+
setattr(pyobj, "text", node.text)
|
|
163
|
+
setattr(pyobj, "value", node.text)
|
|
164
|
+
if node.attrib and "type" in node.attrib:
|
|
165
|
+
type_name = node.attrib["type"]
|
|
166
|
+
if type_name == "float":
|
|
167
|
+
lst = node.text.split(",")
|
|
168
|
+
pyobj.value = (
|
|
169
|
+
float(node.text) if len(lst) == 1 else [float(s) for s in lst]
|
|
170
|
+
)
|
|
171
|
+
elif type_name == "int":
|
|
172
|
+
if "," in node.text:
|
|
173
|
+
pyobj.value = [int(s) for s in node.text.split(",")]
|
|
174
|
+
else:
|
|
175
|
+
pyobj.value = int(node.text)
|
|
176
|
+
elif type_name == "datetime":
|
|
177
|
+
pyobj.value = datetime.strptime(node.text, "%Y%m%d %H%M%S")
|
|
178
|
+
|
|
179
|
+
for cn in node:
|
|
180
|
+
if not hasattr(pyobj, cn.tag):
|
|
181
|
+
setattr(pyobj, cn.tag, [])
|
|
182
|
+
getattr(pyobj, cn.tag).append(_xml2py(cn))
|
|
183
|
+
|
|
184
|
+
return pyobj
|
cht_utils/fileio/yaml.py
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"""YAML file read/write utilities."""
|
|
2
|
+
|
|
3
|
+
from typing import Any, Dict, Optional
|
|
4
|
+
|
|
5
|
+
import yaml
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def dict2yaml(file_name: str, dct: Dict[str, Any], sort_keys: bool = False) -> None:
|
|
9
|
+
"""Write a dictionary to a YAML file.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
file_name : str
|
|
14
|
+
Output file path.
|
|
15
|
+
dct : Dict[str, Any]
|
|
16
|
+
Dictionary to serialize.
|
|
17
|
+
sort_keys : bool
|
|
18
|
+
Whether to sort keys alphabetically.
|
|
19
|
+
"""
|
|
20
|
+
yaml_string = yaml.dump(dct, sort_keys=sort_keys)
|
|
21
|
+
with open(file_name, "w") as f:
|
|
22
|
+
f.write(yaml_string)
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def yaml2dict(file_name: str) -> Optional[Dict[str, Any]]:
|
|
26
|
+
"""Read a YAML file into a dictionary.
|
|
27
|
+
|
|
28
|
+
Parameters
|
|
29
|
+
----------
|
|
30
|
+
file_name : str
|
|
31
|
+
Input file path.
|
|
32
|
+
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
Dict[str, Any] or None
|
|
36
|
+
Parsed dictionary, or ``None`` for empty files.
|
|
37
|
+
"""
|
|
38
|
+
with open(file_name, "r") as f:
|
|
39
|
+
return yaml.load(f, Loader=yaml.FullLoader)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""File and directory operations."""
|
|
2
|
+
|
|
3
|
+
# Core API
|
|
4
|
+
from cht_utils.fileops.fileops import copy as copy
|
|
5
|
+
|
|
6
|
+
# Backward-compatible aliases
|
|
7
|
+
from cht_utils.fileops.fileops import copy_file as copy_file
|
|
8
|
+
from cht_utils.fileops.fileops import delete as delete
|
|
9
|
+
from cht_utils.fileops.fileops import delete_file as delete_file
|
|
10
|
+
from cht_utils.fileops.fileops import delete_folder as delete_folder
|
|
11
|
+
from cht_utils.fileops.fileops import exists as exists
|
|
12
|
+
from cht_utils.fileops.fileops import file_size as file_size
|
|
13
|
+
from cht_utils.fileops.fileops import find_replace as find_replace
|
|
14
|
+
from cht_utils.fileops.fileops import findreplace as findreplace
|
|
15
|
+
from cht_utils.fileops.fileops import list_all_files as list_all_files
|
|
16
|
+
from cht_utils.fileops.fileops import list_files as list_files
|
|
17
|
+
from cht_utils.fileops.fileops import list_files_recursive as list_files_recursive
|
|
18
|
+
from cht_utils.fileops.fileops import list_folders as list_folders
|
|
19
|
+
from cht_utils.fileops.fileops import mkdir as mkdir
|
|
20
|
+
from cht_utils.fileops.fileops import move as move
|
|
21
|
+
from cht_utils.fileops.fileops import move_file as move_file
|
|
22
|
+
from cht_utils.fileops.fileops import rename as rename
|
|
23
|
+
from cht_utils.fileops.fileops import rm as rm
|
|
24
|
+
from cht_utils.fileops.fileops import rmdir as rmdir
|
|
25
|
+
from cht_utils.fileops.fileops import touch as touch
|