4444#
4545#
4646
47+ # stdlib
4748import os
4849import pathlib
50+ import shutil
51+ from typing import AnyStr , Callable , Union
4952
5053
51- def copytree ( src , dst , symlinks = False , ignore = None ):
54+ def append ( var : AnyStr , filename : Union [ str , pathlib . Path , os . PathLike ] ):
5255 """
53- Because shutil.copytree is borked
56+ Append ``var`` to the file ``filename`` in the current directory.
5457
55- Some of this docstring from https://docs.python.org/3/library/shutil.html
58+ .. warning::
59+
60+ This is currently untested
61+
62+ TODO: make this the file in the given directory, by default the current directory
63+
64+ :param var: The value to append to the file
65+ :param filename: The file to append to
66+ :type filename: str or pathlib.Path or os.PathLike
67+ """
68+
69+ # TODO: docstring
70+
71+ with open (os .path .join (os .getcwd (), filename ), 'a' ) as f :
72+ f .write (var )
73+
74+
75+ def copytree (
76+ src : Union [str , pathlib .Path , os .PathLike ],
77+ dst : Union [str , pathlib .Path , os .PathLike ],
78+ symlinks : bool = False ,
79+ ignore : Callable = None ):
80+ """
81+ Alternative to :func:`shutil.copytree` to work in some situations where it doesn't.
5682
5783 :param src: Source file to copy
58- :type src: str
84+ :type src: str or pathlib.Path or os.PathLike
5985 :param dst: Destination to copy file to
60- :type dst: str
86+ :type dst: str or pathlib.Path or os.PathLike
6187 :param symlinks: Whether to represent symbolic links in the source as symbolic
6288 links in the destination. If false or omitted, the contents and metadata
6389 of the linked files are copied to the new tree. When symlinks is false,
@@ -66,7 +92,7 @@ def copytree(src, dst, symlinks=False, ignore=None):
6692 the copy process. You can set the optional ignore_dangling_symlinks
6793 flag to true if you want to silence this exception. Notice that this
6894 option has no effect on platforms that don’t support :class:`python:os.symlink`.
69- :type symlinks: bool
95+ :type symlinks: bool, optional
7096 :param ignore: A callable that will receive as its arguments the source
7197 directory, and a list of its contents. The ignore callable will be
7298 called once for each directory that is copied. The callable must return
@@ -76,40 +102,56 @@ def copytree(src, dst, symlinks=False, ignore=None):
76102 :class:`python:shutil.ignore_patterns` can be used to create such a callable
77103 that ignores names based on
78104 glob-style patterns.
79-
80- :return:
81- :rtype:
105+ :type ignore: ~typing.Callable, optional
82106 """
83107
84- import shutil
85-
86108 for item in os .listdir (src ):
87109 s = os .path .join (src , item )
88110 d = os .path .join (dst , item )
89111 if os .path .isdir (s ):
90- return shutil .copytree (s , d , symlinks , ignore )
112+ shutil .copytree (s , d , symlinks , ignore )
91113 else :
92- return shutil .copy2 (s , d )
114+ shutil .copy2 (s , d )
93115
94116
95- def maybe_make ( directory , mode = 0o777 , parents = False , exist_ok = False ):
117+ def delete ( filename : Union [ str , pathlib . Path , os . PathLike ] ):
96118 """
97- Create a directory at this given path, but only if the directory does
98- not already exist.
119+ Delete the file in the current directory.
120+
121+ .. warning::
122+
123+ This is currently untested
124+
125+ TODO: make this the file in the given directory, by default the current directory
126+
127+ :param filename: The file to delete
128+ :type filename: str or pathlib.Path or os.PathLike
129+ """
130+
131+ os .remove (os .path .join (os .getcwd (), filename ))
132+
133+
134+ def maybe_make (
135+ directory : Union [str , pathlib .Path , os .PathLike ],
136+ mode = 0o777 ,
137+ parents : bool = False ,
138+ exist_ok : bool = False ):
139+ """
140+ Create a directory at this given path, but only if the directory does not already exist.
99141
100142 :param directory: Directory to create
101- :type directory: str or pathlib.Path
143+ :type directory: str or pathlib.Path or os.PathLike
102144 :param mode: Combined with the process’ umask value to determine the file mode and access flags
103145 :type mode:
104146 :param parents: If ``False`` (the default), a missing parent raises a :class:`~python:FileNotFoundError`.
105147 If ``True``, any missing parents of this path are created as needed; they are created with the
106148 default permissions without taking mode into account (mimicking the POSIX mkdir -p command).
107- :type parents: bool
149+ :type parents: bool, optional
108150 :param exist_ok: If ``False`` (the default), a :class:`~python:FileExistsError` is raised if the
109151 target directory already exists. If ``True``, :class:`~python:FileExistsError` exceptions
110152 will be ignored (same behavior as the POSIX mkdir -p command), but only if the last path
111153 component is not an existing non-directory file.
112- :type exist_ok: bool
154+ :type exist_ok: bool, optional
113155 """
114156
115157 if not isinstance (directory , pathlib .Path ):
@@ -119,12 +161,12 @@ def maybe_make(directory, mode=0o777, parents=False, exist_ok=False):
119161 directory .mkdir (mode , parents , exist_ok )
120162
121163
122- def parent_path (path ) :
164+ def parent_path (path : Union [ str , pathlib . Path , os . PathLike ]) -> pathlib . Path :
123165 """
124166 Returns the path of the parent directory for the given file or directory
125167
126168 :param path: Path to find the parent for
127- :type path: str or pathlib.Path
169+ :type path: str or pathlib.Path or os.PathLike
128170
129171 :return: The parent directory
130172 :rtype: pathlib.Path
@@ -136,46 +178,41 @@ def parent_path(path):
136178 return path .parent
137179
138180
139- # TODO: consolidate
140- def relpath (path , relative_to = None ):
181+ def read (filename : Union [str , pathlib .Path , os .PathLike ]) -> str :
141182 """
142- Returns the path for the given file or directory relative to the given directory
183+ Read a file in the current directory (in text mode)
143184
144- :param path: Path to find the relative path for
145- :type path: str
146- :param relative_to: The directory to find the path relative to.
147- Defaults to the current working directory (i.e. os.getcwd())
148- :type relative_to: str
185+ .. warning::
186+
187+ This is currently untested
149188
150- :return:
189+ TODO: make this the file in the given directory, by default the current directory
190+
191+ :param filename: The file to read from
192+ :type filename: str or pathlib.Path or os.PathLike
193+
194+ :return: The contents of the file
195+ :rtype: str
151196 """
152197
153- if relative_to is None :
154- relative_to = os .getcwd ()
198+ # TODO: docstring
155199
156- # if os.path.normpath(os.path.abspath(path)).startswith(
157- # os.path.normpath(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))):
158- if os .path .normpath (os .path .abspath (path )).startswith (
159- os .path .normpath (os .path .dirname (os .path .dirname (os .path .abspath (relative_to ))))
160- ):
161- return os .path .relpath (os .path .abspath (path ))
162- else :
163- return os .path .abspath (path )
200+ with open (os .path .join (os .getcwd (), filename )) as f :
201+ return f .read ()
164202
165203
166- def relpath2 (path , relative_to = None ):
204+ def relpath (path : Union [ str , pathlib . Path , os . PathLike ], relative_to : Union [ str , pathlib . Path , os . PathLike ] = None ) -> pathlib . Path :
167205 """
168206 Returns the path for the given file or directory relative to the given
169- directory or, if that would require path traversal, returns the
170- absolute path.
207+ directory or, if that would require path traversal, returns the absolute path.
171208
172209 :param path: Path to find the relative path for
173- :type path: str or pathlib.Path
210+ :type path: str or pathlib.Path or os.PathLike
174211 :param relative_to: The directory to find the path relative to.
175212 Defaults to the current directory
176- :type relative_to: str or pathlib.Path
213+ :type relative_to: str or pathlib.Path or os.PathLike, optional
177214
178- :return:
215+ :rtype: pathlib.Path
179216 """
180217
181218 if not isinstance (path , pathlib .Path ):
@@ -197,70 +234,20 @@ def relpath2(path, relative_to=None):
197234 return abs_path
198235
199236
200- def delete (filename ):
201- """
202- Delete the file in the current directory
237+ relpath2 = relpath
203238
204- # TODO: make this the file in the given directory, by default the current directory
205239
206- :param filename:
207-
208- :return:
209- """
210-
211- # TODO: docstring
212-
213- os .remove (os .path .join (os .getcwd (), filename ))
214-
215-
216- def write (var , filename ):
240+ def write (var : AnyStr , filename : Union [str , pathlib .Path , os .PathLike ]):
217241 """
218242 Write a variable to file in the current directory
219243
220- # TODO: make this the file in the given directory, by default the current directory
221-
222- :param var:
223- :param filename:
244+ TODO: make this the file in the given directory, by default the current directory
224245
225- :return:
246+ :param var: The value to write to the file
247+ :param filename: The file to write to
248+ :type filename: str or pathlib.Path or os.PathLike
226249 """
227250
228- # TODO: docstring
229-
230251 with open (os .path .join (os .getcwd (), filename ), 'w' ) as f :
231252 f .write (var )
232253
233-
234- def read (filename ):
235- """
236- Read a file in the current directory; Untested
237-
238- # TODO: make this the file in the given directory, by default the current directory
239-
240- :param filename:
241-
242- :return:
243- """
244-
245- # TODO: docstring
246-
247- with open (os .path .join (os .getcwd (), filename )) as f :
248- return f .read ()
249-
250-
251- def append (var , filename ):
252- """
253- Append `var` to the file `filename` in the current directory; Untested
254-
255- # TODO: make this the file in the given directory, by default the current directory
256-
257- :param var:
258- :param filename:
259-
260- :return:
261- """
262-
263- # TODO: docstring
264-
265- with open (os .path .join (os .getcwd (), filename ), 'a' ) as f :
266- f .write (var )
0 commit comments