config2py 0.1.26__tar.gz → 0.1.28__tar.gz

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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: config2py
3
- Version: 0.1.26
3
+ Version: 0.1.28
4
4
  Summary: Simplified reading and writing configurations from various sources and formats
5
5
  Home-page: https://github.com/i2mint/config2py
6
6
  Author: OtoSense
@@ -18,4 +18,5 @@ from config2py.util import (
18
18
  get_configs_folder_for_app,
19
19
  is_repl,
20
20
  parse_assignments_from_py_source,
21
+ process_path,
21
22
  )
@@ -0,0 +1,38 @@
1
+ import tempfile
2
+ import os
3
+ import pytest
4
+
5
+
6
+ def test_process_path():
7
+ # Create a temporary directory
8
+ with tempfile.TemporaryDirectory() as temp_dir:
9
+ temp_path = os.path.join(temp_dir, 'foo/bar')
10
+
11
+ output_path = process_path(temp_path)
12
+ assert output_path == temp_path
13
+ assert not os.path.exists(output_path)
14
+
15
+ output_path = process_path(temp_path, expanduser=False)
16
+ assert output_path == temp_path
17
+ assert not os.path.exists(output_path)
18
+
19
+ with pytest.raises(AssertionError):
20
+ output_path = process_path(temp_path, assert_exists=True)
21
+
22
+ output_path = process_path(temp_path, ensure_dir_exists=True)
23
+ assert output_path == temp_path
24
+ assert os.path.exists(output_path)
25
+
26
+ output_path = process_path(temp_path, assert_exists=True)
27
+ assert output_path == temp_path
28
+ assert os.path.exists(output_path)
29
+
30
+ # If path doesn't end with a (system file separator) slash, add one:
31
+ output_path = process_path(temp_path, ensure_endswith_slash=True)
32
+ assert output_path == temp_path + os.path.sep
33
+
34
+ # If path ends with a (system file separator) slash, remove it.
35
+ output_path = process_path(
36
+ temp_path + os.path.sep, ensure_does_not_end_with_slash=True
37
+ )
38
+ assert output_path == temp_path
@@ -37,6 +37,7 @@ def get_configs_local_store(
37
37
  from config2py.s_configparser import ConfigStore
38
38
 
39
39
  return ConfigStore(config_src)
40
+
40
41
  elif os.path.sep not in config_src: # it's just a string
41
42
  # TODO: is "get" the right word, since it makes the folder too
42
43
  path = get_configs_folder_for_app(config_src, configs_name=configs_name)
@@ -4,7 +4,7 @@ import re
4
4
  import os
5
5
  import ast
6
6
  from pathlib import Path
7
- from typing import Optional, Union, Any, Callable, Set
7
+ from typing import Optional, Union, Any, Callable, Set, Iterable
8
8
  import getpass
9
9
 
10
10
  DFLT_APP_NAME = 'config2py'
@@ -167,6 +167,58 @@ DFLT_APP_DATA_FOLDER = os.getenv(
167
167
  )
168
168
 
169
169
 
170
+ def process_path(
171
+ *path: Iterable[str],
172
+ ensure_dir_exists=False,
173
+ assert_exists=False,
174
+ ensure_endswith_slash=False,
175
+ ensure_does_not_end_with_slash=False,
176
+ expanduser=True,
177
+ rootdir: str = '',
178
+ ) -> str:
179
+ """
180
+ Process a path string, ensuring it exists, and optionally expanding user.
181
+
182
+ Args:
183
+ path (Iterable[str]): The path to process. Can be multiple components of a path.
184
+ ensure_dir_exists (bool): Whether to ensure the path exists.
185
+ assert_exists (bool): Whether to assert that the path exists.
186
+ ensure_endswith_slash (bool): Whether to ensure the path ends with a slash.
187
+ ensure_does_not_end_with_slash (bool): Whether to ensure the path does not end with a slash.
188
+ expanduser (bool): Whether to expand the user in the path.
189
+
190
+ Returns:
191
+ str: The processed path.
192
+
193
+ >>> process_path('a', 'b', 'c')
194
+ 'a/b/c'
195
+ >>> from functools import partial
196
+ >>> process_path('a', 'b', 'c', rootdir='/root/dir/', ensure_endswith_slash=True)
197
+ '/root/dir/a/b/c/'
198
+
199
+ """
200
+ path = os.path.join(*path)
201
+ if ensure_endswith_slash and ensure_does_not_end_with_slash:
202
+ raise ValueError(
203
+ 'Cannot ensure both ends with slash and does not end with slash.'
204
+ )
205
+ if rootdir:
206
+ path = os.path.join(rootdir, path)
207
+ if expanduser:
208
+ path = os.path.expanduser(path)
209
+ if ensure_endswith_slash:
210
+ if not path.endswith('/'):
211
+ path = path + '/'
212
+ if ensure_does_not_end_with_slash:
213
+ if path.endswith('/'):
214
+ path = path[:-1]
215
+ if ensure_dir_exists:
216
+ os.makedirs(path, exist_ok=True)
217
+ if assert_exists:
218
+ assert os.path.exists(path), f'Path does not exist: {path}'
219
+ return path
220
+
221
+
170
222
  # Note: First possible i2 dependency -- vendoring for now
171
223
  def get_app_data_rootdir(*, ensure_exists=False) -> str:
172
224
  """
@@ -195,9 +247,7 @@ def get_app_data_rootdir(*, ensure_exists=False) -> str:
195
247
  to use.
196
248
 
197
249
  """
198
- if ensure_exists and not os.path.isdir(DFLT_APP_DATA_FOLDER):
199
- os.mkdir(DFLT_APP_DATA_FOLDER)
200
- return DFLT_APP_DATA_FOLDER
250
+ return process_path(DFLT_APP_DATA_FOLDER, ensure_dir_exists=True)
201
251
 
202
252
 
203
253
  def _default_folder_setup(directory_path: str) -> None:
@@ -223,6 +273,7 @@ def get_app_data_folder(
223
273
  app_name: str = DFLT_APP_NAME,
224
274
  *,
225
275
  setup_callback: Callable[[str], None] = _default_folder_setup,
276
+ ensure_exists: bool = False,
226
277
  ) -> str:
227
278
  """
228
279
  Retrieve or create the app data directory specific to the given app name.
@@ -231,13 +282,39 @@ def get_app_data_folder(
231
282
  - app_name (str): Name of the app for which the data directory is needed.
232
283
  - setup_callback (Callable[[str], None]): A callback function to initialize the directory.
233
284
  Default is _default_folder_setup.
285
+ - ensure_exists (bool): Whether to ensure the directory exists.
234
286
 
235
287
  Returns:
236
288
  - str: Path to the app data directory.
289
+
290
+ By default, the app will be "config2py":
291
+
292
+ >>> get_app_data_folder() # doctest: +ELLIPSIS
293
+ '.../.config/config2py'
294
+
295
+ You can specify a different app name though.
296
+ And if you want, you can also specify a callback function to initialize the
297
+ directory.
298
+
299
+ >>> path = get_app_data_folder('my_app', ensure_exists=True) # doctest: +SKIP
300
+ >>> path # doctest: +SKIP
301
+ '/Users/.../.config/my_app'
302
+ >>> os.path.exists(path) # doctest: +SKIP
303
+
304
+ You can also specify a path relative to the app data root directory
305
+ (on linux/mac systems, this is typically ~/.config)
306
+
307
+ >>> get_app_data_folder('another/app/and/subfolder') # doctest: +SKIP
308
+ '/Users/.../.config/another/app/and/subfolder'
309
+
237
310
  """
238
- app_data_path = os.path.join(get_app_data_rootdir(ensure_exists=True), app_name)
311
+ app_data_path = os.path.join(
312
+ get_app_data_rootdir(ensure_exists=ensure_exists), app_name
313
+ )
314
+ app_data_folder_did_not_exist = not os.path.isdir(app_data_path)
315
+ process_path(app_data_path, ensure_dir_exists=True)
239
316
 
240
- if not os.path.isdir(app_data_path):
317
+ if app_data_folder_did_not_exist:
241
318
  setup_callback(app_data_path)
242
319
  return app_data_path
243
320
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: config2py
3
- Version: 0.1.26
3
+ Version: 0.1.28
4
4
  Summary: Simplified reading and writing configurations from various sources and formats
5
5
  Home-page: https://github.com/i2mint/config2py
6
6
  Author: OtoSense
@@ -1,6 +1,6 @@
1
1
  [metadata]
2
2
  name = config2py
3
- version = 0.1.26
3
+ version = 0.1.28
4
4
  url = https://github.com/i2mint/config2py
5
5
  platforms = any
6
6
  description_file = README.md
@@ -1 +0,0 @@
1
- print(__name__)
File without changes
File without changes
File without changes
File without changes