python-backpack 1.0.5__py3-none-any.whl → 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.
backpack/strings.py CHANGED
@@ -8,63 +8,67 @@ import contextlib
8
8
  import re
9
9
 
10
10
 
11
- def reformat_input_string(input_string: str,
12
- under_spaces: bool = True,
13
- under_hyphen: bool = True) -> str:
14
- ''' Reformat the user input string.
15
- leaves only alphanumeric chars
16
- replaces spaces and hyphens for underscores.
11
+ def normalize_input_string(
12
+ input_string: str,
13
+ under_spaces: bool = True,
14
+ under_hyphen: bool = True,
15
+ replacer: str = '_',
16
+ ) -> str:
17
+ """Reformat the user input string.
18
+
19
+ leaves only alphanumeric chars
20
+ replaces spaces and hyphens for underscores.
17
21
 
18
22
  Args:
19
23
  input_string (str): input string to reformat
20
24
  under_spaces (bool, optional): replaces spaces. Defaults to True.
21
25
  under_hyphen (bool, optional): replaces hyphens. Defaults to True.
26
+ replacer (str, optional): char to replace spaces and hyphens. Defaults to '_'.
22
27
 
23
28
  Returns:
24
29
  str: reformatted string
25
- '''
30
+ """
26
31
 
27
32
  # re-encode string to valid chars
28
33
  with contextlib.suppress(UnicodeDecodeError):
29
34
  regex = re.sub('[^A-Za-z0-9 _-]+', '', input_string)
30
35
 
31
36
  for char in regex:
32
-
33
- # replacing " " for "_"
37
+ # replacing " " for replacer
34
38
  if under_spaces and char == ' ':
35
- regex = regex.replace(' ', '_')
39
+ regex = regex.replace(' ', replacer)
36
40
 
37
- # replacing "-" for "_"
41
+ # replacing "-" for replacer
38
42
  if under_hyphen and char == '-':
39
- regex = regex.replace('-', '_')
43
+ regex = regex.replace('-', replacer)
40
44
 
41
45
  return regex
42
46
 
43
47
 
44
48
  def begin_or_end_with_numbers(input_string: str) -> bool:
45
- ''' Returns true if the input string begins or ends with number '''
49
+ """Returns true if the input string begins or ends with number."""
46
50
  return _char_is_number(input_string[0]) or _char_is_number(input_string[-1])
47
51
 
48
52
 
49
53
  def begin_with_number(input_string: str) -> bool:
50
- ''' Returns true if the input string begins with numbers '''
54
+ """Returns true if the input string begins with numbers."""
51
55
  return _char_is_number(input_string[0])
52
56
 
53
57
 
54
58
  def has_numbers(input_string: str) -> bool:
55
- ''' returns true if the input string has numbers '''
59
+ """Returns true if the input string has numbers."""
56
60
  return any(_char_is_number(char) for char in input_string)
57
61
 
58
62
 
59
63
  def _char_is_number(char: str) -> bool:
60
- ''' Check if a string is a number
64
+ """Check if a string is a number.
61
65
 
62
66
  Args:
63
67
  char (str): character to evaluate
64
68
 
65
69
  Returns:
66
70
  bool: True if is a int
67
- '''
71
+ """
68
72
 
69
73
  try:
70
74
  int(char)
@@ -74,7 +78,7 @@ def _char_is_number(char: str) -> bool:
74
78
 
75
79
 
76
80
  def camelcase_to_snakecase(input_string: str) -> str:
77
- ''' Convert a CamelCase string to snake_case string.
81
+ """Convert a CamelCase string to snake_case string.
78
82
 
79
83
  Args:
80
84
  input_string (str): The CamelCase string to be converted.
@@ -85,31 +89,41 @@ def camelcase_to_snakecase(input_string: str) -> str:
85
89
  Examples:
86
90
  OneDayCaseChar > one_day_case_char
87
91
  oneCamelCaseChar > one_camel_case_char
92
+ HTTPServer > http_server
88
93
  _TwoCamel_CaseChar > _two_camel_case_char
89
94
  _LeadingUnderscore_case_ > _leading_underscore_case_
90
- '''
95
+ """
91
96
 
92
97
  snake_str = ''
93
98
 
94
99
  # iterate over the string
95
100
  for index, char in enumerate(input_string):
96
-
97
101
  if not char.isalnum():
98
102
  snake_str += char
99
103
  continue
100
104
 
101
- if char.isupper() and index == 0:
102
- snake_str += char.lower()
103
- continue
104
-
105
- if char.isupper():
106
- if input_string[index - 1] != '_':
107
- snake_str += '_' + char.lower()
108
- else:
109
- snake_str += char.lower()
110
-
105
+ if not char.isupper():
106
+ snake_str += char
111
107
  continue
112
108
 
113
- snake_str += char
109
+ prev_char = input_string[index - 1] if index > 0 else ''
110
+ next_char = input_string[index + 1] if index + 1 < len(input_string) else ''
111
+
112
+ # Add underscore only at real word boundaries.
113
+ # This keeps acronyms together: HTTPServer -> http_server.
114
+ should_add_underscore = (
115
+ index > 0
116
+ and prev_char != '_'
117
+ and (
118
+ prev_char.islower()
119
+ or prev_char.isdigit()
120
+ or (prev_char.isupper() and next_char.islower())
121
+ )
122
+ )
123
+
124
+ if should_add_underscore:
125
+ snake_str += '_'
126
+
127
+ snake_str += char.lower()
114
128
 
115
129
  return snake_str
backpack/test_utils.py CHANGED
@@ -3,31 +3,31 @@
3
3
  # Maximiliano Rocamora / maxirocamora@gmail.com
4
4
  # https://github.com/MaxRocamora/python-backpack
5
5
  # ----------------------------------------------------------------------------------------
6
- import time
7
6
  import random
8
7
  import string
8
+ import time
9
9
 
10
10
  from backpack.logger import get_logger
11
11
 
12
12
  log = get_logger('Python Backpack - TestUtils')
13
13
 
14
14
 
15
- def random_string(length: str = 10) -> str:
16
- '''Generates a random string of fixed length
15
+ def random_string(length: int = 10) -> str:
16
+ """Generates a random string of fixed length.
17
17
 
18
18
  Args:
19
19
  length (int, optional): max string length. Defaults to 10.
20
20
 
21
21
  Returns:
22
22
  str: random string
23
- '''
23
+ """
24
24
 
25
25
  letters = string.ascii_lowercase
26
26
  return ''.join(random.choice(letters) for _ in range(length))
27
27
 
28
28
 
29
29
  def time_function_decorator(method: type):
30
- ''' decorator to measure methods execution time '''
30
+ """Decorator to measure methods execution time."""
31
31
 
32
32
  def timed(*args, **kw):
33
33
  ts = time.time()
backpack/version.py CHANGED
@@ -4,11 +4,17 @@
4
4
  # 1.0.3 07/2022 - JsonMetaFile, JsonUserSettings
5
5
  # 1.0.4 04/2023 - Added camelcase_to_snakecase function
6
6
  # 1.0.5 05/2023 - Refactor JsonMetaFile, Added Cache, Some type hints / docstrings
7
+ # 1.1.0 01/2024 - Ruff Formatting
8
+ # 1.1.1 07/2025 - Update Python version matrix to include 3.10 and 3.11, update actions versions
9
+ # 1.1.2 07/2025 - Update actions versions, remove unused badge from README
10
+ # 1.1.3 07/2025 - Improve test class names and docstrings for clarity, ruff formatting
11
+ # 1.1.4 07/2025 - Moved from pipenv to poetry for dependency management.toml
12
+ # 2.0.0 03/2026 - Remove tox workflow and setup.py, standardize Poetry + coverage tooling
7
13
  # ----------------------------------------------------------------------------------------
8
14
 
9
- VERSION_MAJOR = 1
15
+ VERSION_MAJOR = 2
10
16
  VERSION_MINOR = 0
11
- VERSION_PATCH = 5
17
+ VERSION_PATCH = 0
12
18
 
13
19
  version = f'{VERSION_MAJOR}.{VERSION_MINOR}.{VERSION_PATCH}'
14
20
 
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.4
2
+ Name: python-backpack
3
+ Version: 2.0.0
4
+ Summary: A collection of personal scripts for json, File/Folder Operations, String Validation, Custom Errors, Cache and stuff.
5
+ License-File: LICENSE
6
+ Author: Maximiliano Rocamora
7
+ Requires-Python: >=3.11,<4.0
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: 3.11
10
+ Classifier: Programming Language :: Python :: 3.12
11
+ Classifier: Programming Language :: Python :: 3.13
12
+ Classifier: Programming Language :: Python :: 3.14
@@ -0,0 +1,17 @@
1
+ backpack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ backpack/cache.py,sha256=NlKyeGSXHaA9-RFLSN9Dblt0s7kL9fKzqQhGPHpgGbM,2508
3
+ backpack/custom_errors.py,sha256=tkn0AnV-Ihnge9X197nPeRpCFD6Feu9lLntejNTNpik,1358
4
+ backpack/file_utils.py,sha256=neJN9PL866H8gNFJMbWe06PqENY9UKO61YQa39ujjgY,2743
5
+ backpack/folder_utils.py,sha256=RxfVHBLDTL2EdU2w_EMOWsdtCQh-f5BHMzGIRo3UEI8,2983
6
+ backpack/json_metadata.py,sha256=KHsXTCDcrKa68p_HgtQfy_AjXmDCxiA99NIuZfKn2I8,4561
7
+ backpack/json_user_settings.py,sha256=RwdxIZYD4jkcIrWxMn7ZrlKejaGIYOt2TXTGob7nCUg,2676
8
+ backpack/json_utils.py,sha256=ZMl_aGb6oU9sQByOqT5OFTdgAKL2iB-DxsVkVuSCOjA,1324
9
+ backpack/logger.py,sha256=yoo4_4Ok9MAdd3GSTeeSGaIKJ4c-KwdhI6q7lg_39oo,518
10
+ backpack/patterns.py,sha256=qBwgbpfzMrap4KHtLLsg1CJmsmstGGXfzYLpkuUdbMI,889
11
+ backpack/strings.py,sha256=boYfBi1wPtfkngpb2uIAxiJC2yo32EaL5wUD_3JjWGo,3811
12
+ backpack/test_utils.py,sha256=0VqVZB6snc_XM6MsmIanlFGWo5T2zswFq9Cn-HpZntE,1165
13
+ backpack/version.py,sha256=WBEIf90Avless1yHQdpQSg-8LGK2ekKoGI1aSbhFXvs,1073
14
+ python_backpack-2.0.0.dist-info/licenses/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
15
+ python_backpack-2.0.0.dist-info/METADATA,sha256=Tx9wVjs9b5jS_296ngOXGCHkiRdGIxjgUNTGx4B2TbU,518
16
+ python_backpack-2.0.0.dist-info/WHEEL,sha256=Vz2fHgx6HFtSwhs8KvkHLqH5Ea4w1_rner5uNVGCeIE,88
17
+ python_backpack-2.0.0.dist-info/RECORD,,
@@ -1,5 +1,4 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.40.0)
2
+ Generator: poetry-core 2.3.2
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
-
@@ -1,74 +0,0 @@
1
- Metadata-Version: 2.1
2
- Name: python-backpack
3
- Version: 1.0.5
4
- Summary: Python Utilities
5
- Home-page: https://github.com/MaxRocamora/python-backpack
6
- Author: Maximiliano Rocamora
7
- Author-email: maxirocamora@gmail.com
8
- License: GNU GENERAL PUBLIC LICENSE
9
- Project-URL: Source, https://github.com/MaxRocamora/python-backpack
10
- Classifier: Programming Language :: Python :: 3.7
11
- Classifier: Programming Language :: Python :: 3.9
12
- Classifier: Programming Language :: Python :: 3.10
13
- Classifier: Programming Language :: Python :: 3.11
14
- Classifier: License :: OSI Approved :: GNU General Public License (GPL)
15
- Classifier: Operating System :: OS Independent
16
- Classifier: Intended Audience :: Developers
17
- Classifier: Topic :: Software Development :: Libraries :: Python Modules
18
- Requires-Python: >=3.7
19
- Description-Content-Type: text/markdown
20
- License-File: LICENSE
21
-
22
- [![PyPI Supported Python Versions](https://img.shields.io/pypi/pyversions/python-backpack.svg?style=flat-square&logo=appveyor)](https://pypi.python.org/pypi/python-backpack/)
23
- [![PyPI version](https://badge.fury.io/py/python-backpack.svg?style=flat-square&logo=appveyor)](https://badge.fury.io/py/python-backpack)
24
- [![GitHub version](https://badge.fury.io/gh/MaxRocamora%2Fpython-backpack.svg?style=flat-square&logo=appveyor)](https://badge.fury.io/gh/MaxRocamora%2Fpython-backpack)
25
- [![codecov](https://codecov.io/gh/MaxRocamora/python-backpack/branch/main/graph/badge.svg?token=6D1xwYdXW2)](https://codecov.io/gh/MaxRocamora/python-backpack)
26
- [![Message](https://img.shields.io/badge/python--backpack-python-blue?style=flat-square&logo=appveyor)](https://github.com/MaxRocamora/python-backpack)
27
-
28
-
29
- # Python-Backpack
30
- A collection of personal scripts for JSON, File/Folder Operations, String Validation, Custom Errors, Cache and stuff.
31
-
32
-
33
- ## Json
34
- + json_load()
35
- + json_save()
36
- + jsonMetaFile()
37
- + jsonUserSettings()
38
-
39
- ## Files & Folders
40
- + browse_folder()
41
- + create_folders()
42
- + create_folder()
43
- + remove_files_in_dir()
44
- + recursive_dir_copy()
45
- + replace_strings_in_file()
46
- + remove_line_from_file()
47
- + file_is_writeable()
48
-
49
- ## String Validation
50
- + reformat_input_string()
51
- + begin_or_end_with_numbers()
52
- + begin_with_number()
53
- + has_numbers()
54
- + camelcase_to_snakecase()
55
-
56
- ## Custom Errors
57
- + EnvironmentVariableNotFound()
58
- + ApplicationNotFound()
59
-
60
- ## Cache
61
- + timed_lru_cache
62
-
63
- ## Test Utils
64
- + time_function_decorator()
65
- + random_string()
66
-
67
- ## Others / Patterns
68
- + Singleton()
69
-
70
- ---
71
-
72
- ### pip install
73
- pip install python-backpack
74
-
@@ -1,29 +0,0 @@
1
- backpack/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
- backpack/cache.py,sha256=2B3umkkhBfsn4dFpZ79o-uvsmefA8qcQgXGKRggP0Ms,2219
3
- backpack/custom_errors.py,sha256=51Eq89WmOvCPyBO4mEBJKsgAEFKK3WTO7v83LJeGEkg,1268
4
- backpack/file_utils.py,sha256=nz3SAGA4fH9xNwJvrpYhiSsXyyk-7JZopk_cMtgz4Ew,2519
5
- backpack/folder_utils.py,sha256=6ccbMWE6ldHEMh1_EYWn_jkp5TMRksYB31yLyvGipUw,2975
6
- backpack/json_metadata.py,sha256=5mi21S4ly15S_vDVe_aOGLMHHos-CI2x0CbGsnbULlI,4599
7
- backpack/json_user_settings.py,sha256=9X-uhkVw12YeejRx0_43cRvcXTjJGByFWcfknXwKBsI,2539
8
- backpack/json_utils.py,sha256=DL7guKwYnzJYwQFrBmS9GG1paG9sdOx9i89ev_P3UbA,1301
9
- backpack/logger.py,sha256=Qln0FVcpBfotT2JBhSKOV58cQ4Hao4pcQijCpZ7F4V0,464
10
- backpack/patterns.py,sha256=jYIjMVLqObq6XtXIcA9DV5im3rI7PSrtgrT3GpotZ1g,848
11
- backpack/strings.py,sha256=JP9-2S3nZ5Jho3uYb8NeCPHV7J_nt8-7QvHt6Ws4LN8,3289
12
- backpack/test_utils.py,sha256=5LStFAKbB5pnvghhcyiGX7yahKj0vBcJQ9_eqcguULo,1165
13
- backpack/version.py,sha256=RzYPFfZCrgYlVntohAkBo_r2ki4pgAgdDqWMYZ3hEyo,607
14
- tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
- tests/test_cache.py,sha256=BXRileSg4S2Im7TkdzcjswNEifvOo064eicYfwedHKQ,888
16
- tests/test_errors.py,sha256=eoX7RBejDhMYDrCOBqs53_W0fQrv1JJp3R-9CcTjU1E,1580
17
- tests/test_file_utils.py,sha256=El-YyQf-88MOjimCc9vhkYEca10qi9UioLNmDyFzWNc,1836
18
- tests/test_folder_utils.py,sha256=M9z6GZ7XUbCWJaq9TShIEY0-owkrKUHi3lBUKdYX5BQ,3123
19
- tests/test_json_user_settings.py,sha256=CDgJUOWliKTiBFct7moLf5nvkr274aBX0BJ0YIbfvv0,2224
20
- tests/test_json_utils.py,sha256=HYexm7xGx3cff9pYJ7RgR2HwAj_m_-JyC1CZsr4R7o0,1616
21
- tests/test_jsonmd.py,sha256=nlUvu34nQ3Wk7oLIQ9GxHxAeF-pSwxeEVYYMIbzKdv4,2551
22
- tests/test_misc.py,sha256=McfYUEg1da4kAwKC0Jh1oGyyUXCj4RG0cR2fC5l7SqM,1675
23
- tests/test_strings.py,sha256=69wWWF5Rn33Eg6osm6JxiFOk0t6x545bGPP6j8k-Ync,3704
24
- tests/test_test_utils.py,sha256=upFG5qN-WVB7t6sHurTQLdyEvZ24TT_Rl4qugnKt-RQ,1191
25
- python_backpack-1.0.5.dist-info/LICENSE,sha256=IwGE9guuL-ryRPEKi6wFPI_zOhg7zDZbTYuHbSt_SAk,35823
26
- python_backpack-1.0.5.dist-info/METADATA,sha256=Nx-GbdFgI72qwLwdvFBKuyJqn_64DTyBOihKh1Pc_jk,2511
27
- python_backpack-1.0.5.dist-info/WHEEL,sha256=pkctZYzUS4AYVn6dJ-7367OJZivF2e8RA9b_ZBjif18,92
28
- python_backpack-1.0.5.dist-info/top_level.txt,sha256=2w70HD8s6Z74zVMHouhcZ093sMqEMvQLvejexStCMLE,15
29
- python_backpack-1.0.5.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- backpack
2
- tests
tests/__init__.py DELETED
File without changes
tests/test_cache.py DELETED
@@ -1,27 +0,0 @@
1
- # ----------------------------------------------------------------------------------------
2
- # Python-Backpack - Custom Exceptions UnitTest
3
- # Maximiliano Rocamora / maxirocamora@gmail.com
4
- # https://github.com/MaxRocamora/python-backpack
5
- # ----------------------------------------------------------------------------------------
6
-
7
- import unittest
8
-
9
- from backpack.cache import timed_lru_cache
10
-
11
-
12
- class Test_Cache(unittest.TestCase):
13
-
14
- @timed_lru_cache(seconds=1)
15
- def test_function(self):
16
- # some heavy process here to be cached
17
- return True
18
-
19
- def test_cache(self):
20
- ''' testing module '''
21
- self.assertTrue(self.test_function())
22
- self.assertEqual(True, self.test_function(force_clear=True))
23
- self.assertEqual(True, self.test_function(force_clear=True, show_log=True))
24
-
25
-
26
- if __name__ == '__main__':
27
- unittest.main()
tests/test_errors.py DELETED
@@ -1,50 +0,0 @@
1
- # ----------------------------------------------------------------------------------------
2
- # Python-Backpack - Custom Exceptions UnitTest
3
- # Maximiliano Rocamora / maxirocamora@gmail.com
4
- # https://github.com/MaxRocamora/python-backpack
5
- # ----------------------------------------------------------------------------------------
6
-
7
- import os
8
- import sys
9
- import unittest
10
-
11
- from backpack.custom_errors import EnvironmentVariableNotFound
12
- from backpack.custom_errors import ApplicationNotFound
13
-
14
- mod_path = os.path.dirname(__file__)
15
- if mod_path not in sys.path:
16
- sys.path.append(mod_path)
17
-
18
-
19
- def get_env_var(name: str):
20
- ''' call for an env var or raise EnvironmentVariableNotFound '''
21
- try:
22
- value = os.environ[name]
23
- except KeyError as e:
24
- raise EnvironmentVariableNotFound(name) from e
25
- return value
26
-
27
-
28
- def get_app(name: str):
29
- ''' raisers error '''
30
- raise ApplicationNotFound(f'Background executable not found {name}')
31
-
32
-
33
- class Test_Errors(unittest.TestCase):
34
-
35
- def test_env_var_error(self):
36
- ''' testing module '''
37
- self.assertRaises(EnvironmentVariableNotFound, get_env_var, 'my_env_var')
38
- error = EnvironmentVariableNotFound('my_env_var')
39
- self.assertEqual(str(error), error.message)
40
-
41
- def test_env_app_error(self):
42
- ''' testing module '''
43
- self.assertRaises(ApplicationNotFound, get_app, 'my_app.exe')
44
-
45
- error = ApplicationNotFound('my_app.exe')
46
- self.assertEqual(str(error), error.message)
47
-
48
-
49
- if __name__ == '__main__':
50
- unittest.main()
tests/test_file_utils.py DELETED
@@ -1,49 +0,0 @@
1
- # ----------------------------------------------------------------------------------------
2
- # Python-Backpack - FolderUtils Tests
3
- # Maximiliano Rocamora / maxirocamora@gmail.com
4
- # https://github.com/MaxRocamora/python-backpack
5
- # ----------------------------------------------------------------------------------------
6
-
7
- import os
8
- import sys
9
- import unittest
10
- import shutil
11
-
12
- from backpack.file_utils import replace_strings_in_file, remove_line_from_file
13
- from backpack.file_utils import file_is_writeable
14
-
15
- mod_path = os.path.dirname(__file__)
16
- if mod_path not in sys.path:
17
- sys.path.append(mod_path)
18
-
19
- # test folders
20
- BASE_FILE = os.path.join(mod_path, 'test_files', 'origin.txt')
21
- EDITED_FILE = os.path.join(mod_path, 'test_files', 'edited.txt')
22
- STRINGS = ['to be replaced!', 'also replaced']
23
- NEW_STRING = 'REPLACED'
24
- LOCKED_FILE = os.path.join(mod_path, 'test_files', 'locked_file.txt')
25
- UNLOCKED_FILE = os.path.join(mod_path, 'test_files', 'unlocked_file.txt')
26
- NO_FILE = os.path.join(mod_path, 'test_files', 'no_file.txt')
27
-
28
-
29
- class Test_Errors(unittest.TestCase):
30
-
31
- def test_replace_strings_in_file(self):
32
- ''' testing module '''
33
- shutil.copy(BASE_FILE, EDITED_FILE)
34
- replace_strings_in_file(EDITED_FILE, STRINGS, NEW_STRING)
35
-
36
- def test_remove_line_from_file(self):
37
- ''' testing module '''
38
- source_file = os.path.join(mod_path, 'test_files', 'origin_remove.txt')
39
- test_file = os.path.join(mod_path, 'test_files', 'edited_remove.txt')
40
- shutil.copy(source_file, test_file)
41
- remove_line_from_file(test_file, ['REMOVE_ME', 'to be replaced!'])
42
-
43
- def test_locked_file(self):
44
- self.assertTrue(file_is_writeable(UNLOCKED_FILE))
45
- self.assertFalse(file_is_writeable(NO_FILE))
46
-
47
-
48
- if __name__ == '__main__':
49
- unittest.main()
@@ -1,96 +0,0 @@
1
- # ----------------------------------------------------------------------------------------
2
- # Python-Backpack - FolderUtils Tests
3
- # Maximiliano Rocamora / maxirocamora@gmail.com
4
- # https://github.com/MaxRocamora/python-backpack
5
- # ----------------------------------------------------------------------------------------
6
-
7
- import os
8
- import sys
9
- import unittest
10
- import mock
11
-
12
- from backpack.folder_utils import create_folders, browse_folder, create_folder
13
- from backpack.folder_utils import remove_files_in_dir, recursive_dir_copy
14
-
15
- mod_path = os.path.dirname(__file__)
16
- if mod_path not in sys.path:
17
- sys.path.append(mod_path)
18
-
19
- # test folders
20
- BASE_PATH = os.path.join(mod_path, 'test_folder')
21
- FOLDERS = [os.path.join(BASE_PATH, 'ALPHA'),
22
- os.path.join(BASE_PATH, 'BETA'),
23
- ]
24
- FOLDER_FILES = os.path.join(BASE_PATH, 'files')
25
- FILES = ['readme.txt']
26
-
27
-
28
- def create_file(path):
29
- ''' creates a temp txt file '''
30
- with open(os.path.join(path, 'temp.txt'), 'w'):
31
- pass
32
-
33
-
34
- class Test_Errors(unittest.TestCase):
35
-
36
- def setUp(self):
37
- pass
38
-
39
- def test_create_folders(self):
40
- ''' testing module '''
41
- create_folders(FOLDERS, verbose=True)
42
- # check folders and files exists
43
- for f in FOLDERS:
44
- self.assertEqual(os.path.exists(f), True)
45
-
46
- # delete folders
47
- remove_files_in_dir(BASE_PATH)
48
-
49
- create_folders(FOLDERS, verbose=True, force_empty=True)
50
- # check folders and files exists
51
- for f in FOLDERS:
52
- self.assertEqual(os.path.exists(f), True)
53
-
54
- # test osError
55
- create_folder('X:/tests/force_oserror')
56
-
57
- # test force_empty, calling twice to ensure folder existence
58
- create_folders(FOLDERS, verbose=True, force_empty=False)
59
- create_folders(FOLDERS, verbose=True, force_empty=True)
60
-
61
- # delete folders
62
- remove_files_in_dir(BASE_PATH)
63
-
64
- @mock.patch('subprocess.Popen')
65
- def test_browse(self, mock_browse):
66
- # mocked Popen, create folder, browse, delete
67
- create_folder(FOLDERS[0])
68
- browse_folder(FOLDERS[0])
69
- # force false
70
- browse_folder(None)
71
-
72
- def test_remove_dir(self):
73
- ''' creates a folder with files and remove it '''
74
- test_dir = os.path.join(BASE_PATH, 'remove_dir')
75
- create_folder(test_dir)
76
- create_file(test_dir)
77
- remove_files_in_dir(test_dir)
78
-
79
- def test_recursive_dir(self):
80
- ''' creates a dir with sub dirs and files and copy them '''
81
- test_dir = os.path.join(BASE_PATH, 'recursive_dir')
82
- create_folder(test_dir)
83
- create_file(test_dir)
84
- sub_dir = os.path.join(test_dir, 'recursive_sub_dir')
85
- create_folder(sub_dir)
86
- create_file(sub_dir)
87
- target_dir = os.path.join(BASE_PATH, 'recursive_target')
88
- recursive_dir_copy(test_dir, target_dir)
89
- # clear everything
90
- remove_files_in_dir(test_dir)
91
- remove_files_in_dir(sub_dir)
92
- remove_files_in_dir(target_dir)
93
-
94
-
95
- if __name__ == '__main__':
96
- unittest.main()
@@ -1,76 +0,0 @@
1
- # ----------------------------------------------------------------------------------------
2
- # Python-Backpack - json user settings Tests
3
- # Maximiliano Rocamora / maxirocamora@gmail.com
4
- # https://github.com/MaxRocamora/python-backpack
5
- # ----------------------------------------------------------------------------------------
6
-
7
- import contextlib
8
- from backpack.json_user_settings import JsonUserSettings
9
-
10
- import unittest
11
- import os
12
- import sys
13
-
14
- mod_path = os.path.dirname(__file__)
15
- if mod_path not in sys.path:
16
- sys.path.append(mod_path)
17
-
18
-
19
- # test path & name
20
- FOLDER = 'tox_test_folder'
21
- TEST_FOLDER = os.path.join(os.path.expanduser('~'), FOLDER)
22
-
23
-
24
- class Test_windows(unittest.TestCase):
25
-
26
- @classmethod
27
- def setUp(cls):
28
- # remove test files
29
- with contextlib.suppress(OSError):
30
- os.remove(TEST_FOLDER)
31
-
32
- @classmethod
33
- def tearDownClass(cls):
34
- # remove test files
35
- with contextlib.suppress(OSError):
36
- os.remove(TEST_FOLDER)
37
-
38
- def test_json_user_settings(self):
39
-
40
- # make sure folder does not exist
41
- with contextlib.suppress(PermissionError, OSError):
42
- if os.path.exists(TEST_FOLDER):
43
- os.removedirs(TEST_FOLDER)
44
-
45
- # class and properties
46
- js = JsonUserSettings(FOLDER, 'user')
47
- assert (js.filepath)
48
- assert (os.path.exists(js.os_user_folder))
49
- assert (isinstance(js.user_data, dict))
50
-
51
- # load from a missing file
52
- js.filename = 'random_file'
53
- self.assertFalse(js.load_settings())
54
-
55
- def test_json_settings_save(self):
56
- ''' test json settings: save '''
57
-
58
- # save a setting
59
- js = JsonUserSettings(FOLDER, 'tox')
60
- data = {'age': 99}
61
- assert (js.save_settings(data))
62
-
63
- # load it back
64
- js = JsonUserSettings(FOLDER, 'tox')
65
- data = js.load_settings()
66
- assert (data['age'] == 99)
67
- # save custom setting
68
- js.user_data = {'custom': 'value'}
69
- assert (js.save_settings())
70
- # load it back
71
- data = js.load_settings()
72
- assert (data['custom'] == 'value')
73
-
74
-
75
- if __name__ == '__main__':
76
- unittest.main()