python-backpack 1.0.4__tar.gz → 1.1.4__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.
Files changed (36) hide show
  1. python_backpack-1.1.4/PKG-INFO +12 -0
  2. python_backpack-1.1.4/backpack/cache.py +68 -0
  3. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/custom_errors.py +9 -8
  4. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/file_utils.py +30 -21
  5. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/folder_utils.py +15 -14
  6. python_backpack-1.1.4/backpack/json_metadata.py +132 -0
  7. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/json_user_settings.py +30 -27
  8. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/json_utils.py +19 -12
  9. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/logger.py +2 -2
  10. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/patterns.py +5 -3
  11. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/strings.py +15 -16
  12. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/test_utils.py +9 -6
  13. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/version.py +7 -1
  14. python_backpack-1.1.4/pyproject.toml +23 -0
  15. python-backpack-1.0.4/MANIFEST.in +0 -1
  16. python-backpack-1.0.4/PKG-INFO +0 -70
  17. python-backpack-1.0.4/README.md +0 -50
  18. python-backpack-1.0.4/backpack/json_metadata.py +0 -155
  19. python-backpack-1.0.4/python_backpack.egg-info/PKG-INFO +0 -70
  20. python-backpack-1.0.4/python_backpack.egg-info/SOURCES.txt +0 -30
  21. python-backpack-1.0.4/python_backpack.egg-info/dependency_links.txt +0 -1
  22. python-backpack-1.0.4/python_backpack.egg-info/top_level.txt +0 -2
  23. python-backpack-1.0.4/setup.cfg +0 -4
  24. python-backpack-1.0.4/setup.py +0 -36
  25. python-backpack-1.0.4/tests/__init__.py +0 -0
  26. python-backpack-1.0.4/tests/test_errors.py +0 -50
  27. python-backpack-1.0.4/tests/test_file_utils.py +0 -49
  28. python-backpack-1.0.4/tests/test_folder_utils.py +0 -96
  29. python-backpack-1.0.4/tests/test_json_user_settings.py +0 -76
  30. python-backpack-1.0.4/tests/test_json_utils.py +0 -46
  31. python-backpack-1.0.4/tests/test_jsonmd.py +0 -90
  32. python-backpack-1.0.4/tests/test_misc.py +0 -54
  33. python-backpack-1.0.4/tests/test_strings.py +0 -94
  34. python-backpack-1.0.4/tests/test_test_utils.py +0 -45
  35. {python-backpack-1.0.4 → python_backpack-1.1.4}/LICENSE +0 -0
  36. {python-backpack-1.0.4 → python_backpack-1.1.4}/backpack/__init__.py +0 -0
@@ -0,0 +1,12 @@
1
+ Metadata-Version: 2.1
2
+ Name: python-backpack
3
+ Version: 1.1.4
4
+ Summary: A collection of personal scripts for json, File/Folder Operations, String Validation, Custom Errors, Cache and stuff.
5
+ Author: Maximiliano Rocamora
6
+ Requires-Python: >=3.9,<4.0
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.9
9
+ Classifier: Programming Language :: Python :: 3.10
10
+ Classifier: Programming Language :: Python :: 3.11
11
+ Classifier: Programming Language :: Python :: 3.12
12
+ Classifier: Programming Language :: Python :: 3.13
@@ -0,0 +1,68 @@
1
+ # ----------------------------------------------------------------------------------------
2
+ # Python-Backpack - Pattern Utilities
3
+ # Maximiliano Rocamora / maxirocamora@gmail.com
4
+ # https://github.com/MaxRocamora/python-backpack
5
+ # ----------------------------------------------------------------------------------------
6
+ from datetime import datetime, timedelta, timezone
7
+ from functools import lru_cache, wraps
8
+
9
+ from backpack.logger import get_logger
10
+
11
+ log = get_logger('Python Backpack - Cache')
12
+
13
+
14
+ def timed_lru_cache(seconds: int, maxsize: int = 128):
15
+ """Lru_cache with expiration time.
16
+
17
+ Args:
18
+ seconds (int): expiration time in seconds
19
+ maxsize (int): maxsize for lru_cache
20
+ Note:
21
+ Wrapped function can be forced to clear cache with: force_clear=True
22
+ Wrapped function can show log on clear with: show_log=True
23
+ Returns:
24
+ function result
25
+
26
+ # * Usage:
27
+
28
+ # * Add the decorator to your function
29
+
30
+ @timed_lru_cache(seconds=60)
31
+ def my_function():
32
+ return 'Hello World'
33
+
34
+ # * to clear the cache, use force_clear=True on the function call
35
+ my_function(force_clear=True)
36
+
37
+ """
38
+
39
+ def wrapper_cache(func):
40
+ func = lru_cache(maxsize=maxsize)(func)
41
+ func.lifetime = timedelta(seconds=seconds)
42
+ func.expiration = datetime.now(timezone.utc) + func.lifetime
43
+
44
+ @wraps(func)
45
+ def wrapped_func(*args, force_clear: bool = False, show_log: bool = False, **kwargs):
46
+ """Wrapper function for lru_cache with expiration time.
47
+
48
+ Args:
49
+ *args: function arguments
50
+ force_clear (bool): forces a clear cache
51
+ show_log (bool): show log on clear
52
+ **kwargs: function keyword arguments
53
+ Returns:
54
+ function result
55
+ """
56
+
57
+ if force_clear or datetime.now(timezone.utc) >= func.expiration:
58
+ if show_log:
59
+ log.debug(f'Cache cleared for {func.__name__}')
60
+
61
+ func.cache_clear()
62
+ func.expiration = datetime.now(timezone.utc) + func.lifetime
63
+
64
+ return func(*args, **kwargs)
65
+
66
+ return wrapped_func
67
+
68
+ return wrapper_cache
@@ -4,33 +4,34 @@
4
4
  # https://github.com/MaxRocamora/python-backpack
5
5
  # ----------------------------------------------------------------------------------------
6
6
 
7
- class EnvironmentVariableNotFound(Exception):
8
7
 
8
+ class EnvironmentVariableNotFoundError(Exception):
9
9
  def __init__(self, var_name: str) -> None:
10
- '''Error Raised when a required environment variable is missing from os.
10
+ """Error Raised when a required environment variable is missing from os.
11
11
 
12
12
  Args:
13
13
  var_name (str): name of the required variable missing
14
- '''
14
+ """
15
15
  self.var_name = var_name
16
- self.message = f'System required ({var_name}) Environment Variable not found.'
16
+ self.message = f'Required Environment Variable [{var_name}] not found.'
17
17
  super().__init__(self.message)
18
18
 
19
19
  def __str__(self):
20
+ """Return the error message."""
20
21
  return self.message
21
22
 
22
23
 
23
- class ApplicationNotFound(Exception):
24
-
24
+ class ApplicationNotFoundError(Exception):
25
25
  def __init__(self, app_name: str) -> None:
26
- '''Error Raised when an Application Name required is not found.
26
+ """Error Raised when an Application Name required is not found.
27
27
 
28
28
  Args:
29
29
  app_name (str): name of the required application missing
30
- '''
30
+ """
31
31
  self.app_name = app_name
32
32
  self.message = f'Application ({app_name}) not found.'
33
33
  super().__init__(self.message)
34
34
 
35
35
  def __str__(self):
36
+ """Return the error message."""
36
37
  return self.message
@@ -8,23 +8,25 @@ import contextlib
8
8
 
9
9
  from backpack.logger import get_logger
10
10
 
11
- log = get_logger('FileUtils')
11
+ log = get_logger('Python Backpack - FileUtils')
12
12
 
13
13
 
14
- def replace_strings_in_file(ascii_file: str, strings: list, new_string: str):
15
- ''' Opens ascii file and replaces all occurrences from strings into new_string.
14
+ def replace_strings_in_file(ascii_file: str, strings: list, new_string: str) -> None:
15
+ """Opens ascii file and replaces all occurrences from strings into new_string.
16
+
16
17
  In this class we use a full path to avoid use of os.dirname, which
17
18
  causes string encode problems.
19
+
18
20
  Args:
19
- ascii_file (fullpath) file to open
20
- strings (list) strings to replace
21
- new_string (string) new string or path to set
22
- '''
21
+ ascii_file: (fullpath string) file to open
22
+ strings: (list) strings to replace
23
+ new_string: (string) new string or path to set
24
+ """
23
25
 
24
26
  # force forward slashes
25
- new_string = new_string.replace("\\", "/")
27
+ new_string = new_string.replace('\\', '/')
26
28
 
27
- log.info(f"Replacing Strings, Opening File: {ascii_file}")
29
+ log.info(f'Replacing Strings, Opening File: {ascii_file}')
28
30
 
29
31
  with open(ascii_file) as f:
30
32
  file_data = f.read()
@@ -37,41 +39,48 @@ def replace_strings_in_file(ascii_file: str, strings: list, new_string: str):
37
39
  with open(ascii_file, 'w') as f:
38
40
  f.write(file_data)
39
41
  f.close()
40
- log.info(f"Closing File: {ascii_file}")
42
+ log.info(f'Closing File: {ascii_file}')
43
+
41
44
 
45
+ def remove_line_from_file(ascii_file: str, strings: list, verbose: bool = False) -> None:
46
+ """Removes given lines from ascii file.
42
47
 
43
- def remove_line_from_file(ascii_file: str, strings: str):
44
- ''' removes given lines from ascii file.
45
48
  Args:
46
- ascii_file (path) ASCII file to process
47
- strings (list) match lines to remove
48
- '''
49
+ ascii_file: (string path) ASCII file to process
50
+ strings: (list) match lines to remove
51
+ verbose: (bool) if true, prints removed lines
52
+ """
49
53
 
50
54
  with open(ascii_file) as f:
51
55
  file_content = f.read().splitlines()
52
56
 
53
57
  for line in file_content:
54
- print('file line', line)
58
+ if verbose:
59
+ log.info(f'Checking line: {line}')
55
60
  with contextlib.suppress(ValueError):
56
61
  if line in strings:
62
+ if verbose:
63
+ log.info(f'Removing line: {line}')
57
64
  file_content.pop(file_content.index(line))
58
65
 
59
- with open(ascii_file, "w") as f:
60
- contents = "\n".join(file_content)
66
+ with open(ascii_file, 'w') as f:
67
+ contents = '\n'.join(file_content)
61
68
  f.write(contents)
62
69
 
63
70
 
64
71
  def file_is_writeable(filepath: str) -> bool:
65
- ''' checks if a file is locked and can be overwritten
72
+ """Checks if a file is locked and can be overwritten.
73
+
66
74
  Args:
67
- filepath (str)) file to check
75
+ filepath: (str) file to check
68
76
  Returns:
69
77
  bool : true if file is writeable
70
- '''
78
+ """
71
79
  try:
72
80
  with open(filepath, 'r+') as _:
73
81
  return True
74
82
  except OSError as x:
75
83
  log.warning(f'{filepath} is locked ')
76
84
  log.info(x.strerror)
85
+
77
86
  return False
@@ -10,42 +10,43 @@ import subprocess
10
10
 
11
11
  from backpack.logger import get_logger
12
12
 
13
- log = get_logger('FolderUtils')
13
+ log = get_logger('Python Backpack - FolderUtils')
14
14
 
15
15
 
16
16
  def browse_folder(folder: str) -> bool:
17
- ''' Open windows explorer on folder
17
+ """Open windows explorer on folder.
18
+
18
19
  Args:
19
- folder (path) folder to open
20
- '''
20
+ folder: (string path) folder to open
21
+ """
21
22
  if folder and os.path.isdir(folder):
22
- subprocess.Popen(f"explorer {os.path.abspath(folder)}")
23
+ subprocess.Popen(f'explorer {os.path.abspath(folder)}')
23
24
  return True
24
25
 
25
- log.warning(f"Unable to open folder {folder}")
26
+ log.warning(f'Unable to open folder {folder}')
26
27
  return False
27
28
 
28
29
 
29
30
  def create_folders(folders: list, force_empty: bool = False, verbose: bool = False):
30
- ''' Creates multiple folders on disc.
31
+ """Creates multiple folders on disc.
31
32
 
32
33
  Args:
33
34
  folders (list): folder list
34
35
  force_empty (bool, optional): forces clearing folder content. Defaults to False.
35
36
  verbose (bool, optional):shows log. Defaults to False.
36
- '''
37
+ """
37
38
  for folder in folders:
38
39
  create_folder(folder, force_empty=force_empty, verbose=verbose)
39
40
 
40
41
 
41
42
  def create_folder(path: str, force_empty: bool = False, verbose: bool = True):
42
- '''creates a folder
43
+ """Creates a folder.
43
44
 
44
45
  Args:
45
46
  path (str): folder path
46
47
  force_empty (bool, optional): forces clearing folder content. Defaults to False.
47
48
  verbose (bool, optional): show log. Defaults to True.
48
- '''
49
+ """
49
50
  abspath = os.path.abspath(path)
50
51
  if verbose:
51
52
  log.info(f'Creating Folder {abspath}')
@@ -56,14 +57,14 @@ def create_folder(path: str, force_empty: bool = False, verbose: bool = True):
56
57
  elif force_empty:
57
58
  remove_files_in_dir(abspath)
58
59
  except OSError as e:
59
- log.warning(f"Unable to create folder: {path}")
60
+ log.warning(f'Unable to create folder: {path}')
60
61
  log.error(str(e))
61
62
 
62
63
  return True
63
64
 
64
65
 
65
66
  def remove_files_in_dir(path: str):
66
- ''' clears all content in given directory '''
67
+ """Clears all content in given directory."""
67
68
  for root, dirs, files in os.walk(path):
68
69
  for f in files:
69
70
  os.unlink(os.path.join(root, f))
@@ -72,12 +73,12 @@ def remove_files_in_dir(path: str):
72
73
 
73
74
 
74
75
  def recursive_dir_copy(source_path: str, target_path: str):
75
- ''' Copy all files src dir to dest dir, including sub-directories.
76
+ """Copy all files src dir to dest dir, including sub-directories.
76
77
 
77
78
  Args:
78
79
  source_path (str): source path
79
80
  target_path (str): destination path
80
- '''
81
+ """
81
82
 
82
83
  create_folder(source_path)
83
84
  create_folder(target_path)
@@ -0,0 +1,132 @@
1
+ # ----------------------------------------------------------------------------------------
2
+ # Python-Backpack - JsonMetadata
3
+ # Maximiliano Rocamora / maxirocamora@gmail.com
4
+ # https://github.com/MaxRocamora/python-backpack
5
+ # ----------------------------------------------------------------------------------------
6
+ import inspect
7
+ import os
8
+ import platform
9
+ import sys
10
+ import time
11
+ from datetime import datetime
12
+ from typing import Any
13
+
14
+ from backpack.json_utils import json_load, json_save
15
+ from backpack.version import version
16
+
17
+
18
+ class JsonMetaFile:
19
+ PREFIX = 'MD_'
20
+
21
+ def __init__(self, name: str, path: str) -> None:
22
+ """saves/load a class/dict as a json metadata file.
23
+
24
+ Args:
25
+ name (str): name of the file/class
26
+ path (str, optional): filepath. Defaults to None.
27
+ """
28
+ self._name = name
29
+ self._path = path
30
+ self._data = {'_about': {'package': 'python-backpack', 'version': self.version}}
31
+
32
+ @property
33
+ def name(self) -> str:
34
+ """Name of this metadata class."""
35
+ return self._name
36
+
37
+ @property
38
+ def version(self) -> str:
39
+ """Version of this metadata class."""
40
+ return version
41
+
42
+ @property
43
+ def filename(self) -> str:
44
+ """Returns default filename with prefix and extension."""
45
+ return self.PREFIX + self.name + '.json'
46
+
47
+ @property
48
+ def filepath(self) -> str:
49
+ """Full json metadata filepath."""
50
+ return os.path.join(self.path, self.filename)
51
+
52
+ @property
53
+ def path(self) -> str:
54
+ """Base path location of metadata json file."""
55
+ return self._path
56
+
57
+ def has_file(self) -> bool:
58
+ """Returns true if file exists."""
59
+ return os.path.exists(self.filepath)
60
+
61
+ # ------------------------------------------------------------------------------------
62
+ # LOAD/INSERT/REMOVE/SAVE
63
+ # ------------------------------------------------------------------------------------
64
+
65
+ def load(self) -> None:
66
+ """Loads metadata from disk."""
67
+ self._data = json_load(self.filepath) if self.has_file() else {}
68
+
69
+ def insert(self, key: str, value: Any) -> None:
70
+ """Inserts value into metadata."""
71
+ self._data[key] = value
72
+
73
+ def remove(self, key: str) -> None:
74
+ """Remove key from metadata."""
75
+ if key in self._data.keys():
76
+ del self._data[key]
77
+
78
+ def save(self) -> None:
79
+ """Save current metadata into json file."""
80
+ if not os.path.exists(self.path):
81
+ os.makedirs(self.path)
82
+
83
+ self._data['system'] = self._system_data()
84
+ json_save(self._data, self.filepath)
85
+
86
+ # ------------------------------------------------------------------------------------
87
+ # CLASS MODE METHODS
88
+ # ------------------------------------------------------------------------------------
89
+
90
+ def load_as_class(self) -> type:
91
+ """Returns the metadata dict as a class obj."""
92
+ metadata_class = type(self.name, (), self._data)
93
+ return metadata_class
94
+
95
+ def insert_class(self, _class: type) -> None:
96
+ """Load all attributes from a given class into this class metadata."""
97
+ attributes = {}
98
+ for name in dir(_class):
99
+ value = getattr(_class, name)
100
+ if not name.startswith('__') and not inspect.ismethod(value):
101
+ attributes[name] = value
102
+
103
+ self._data = attributes
104
+
105
+ # ------------------------------------------------------------------------------------
106
+ # SYSTEM METADATA OS/USER/TIME
107
+ # ------------------------------------------------------------------------------------
108
+
109
+ def _system_data(self) -> dict:
110
+ """Add system metadata to the default data before save."""
111
+ return {
112
+ 'name': self.name,
113
+ 'app': os.path.basename(sys.executable),
114
+ 'PC': str(platform.node()),
115
+ 'python_version': sys.version,
116
+ 'User': str(os.getenv('username')),
117
+ 'time': self._current_time_metadata(),
118
+ }
119
+
120
+ def _current_time_metadata(self) -> dict:
121
+ """Get export time info."""
122
+ ftime = time.strftime('%Y,%b,%d,%j,%H:%M', time.localtime())
123
+ times = ftime.split(',')
124
+ td = {
125
+ 'year': times[0],
126
+ 'month': times[1],
127
+ 'day': times[2],
128
+ 'year_day': times[3],
129
+ 'time': times[4],
130
+ 'save_time': datetime.now().ctime(),
131
+ }
132
+ return td
@@ -1,68 +1,71 @@
1
- # -*- coding: utf-8 -*-
2
- # --------------------------------------------------------------------------------------------
1
+ # ----------------------------------------------------------------------------------------
3
2
  # Json Settings Class
4
3
  # This class handle load/save json files on win/linux local user folder
5
- ''' Usage:
4
+
5
+ """Usage.
6
+
6
7
  us = JsonUserSettings('my_app')
7
8
  us.save(someDict)
8
9
  data = us.load()
9
10
 
10
- '''
11
- # --------------------------------------------------------------------------------------------
11
+ """
12
+ # ----------------------------------------------------------------------------------------
12
13
  import os
13
14
 
15
+ from backpack.json_utils import json_load, json_save
14
16
  from backpack.logger import get_logger
15
- from backpack.json_utils import json_save, json_load
16
17
 
17
- log = get_logger('UserSettings')
18
+ log = get_logger('Python Backpack - UserSettings')
18
19
 
19
20
 
20
- class JsonUserSettings():
21
- def __init__(self, folder: str, name: str):
22
- '''Manages saving/loading json file on local user folder
21
+ class JsonUserSettings:
22
+ def __init__(self, folder: str, name: str) -> None:
23
+ """Manages saving/loading json file on local user folder.
23
24
 
24
25
  Args:
25
26
  folder (str): name of sub folder inside user path. Defaults to 'json_settings'.
26
- filename (str): name used for the json file. Defaults to 'user_data'.
27
- '''
27
+ name (str): name used for the json file. Defaults to 'user_data'.
28
+ """
28
29
  self.name = name
29
30
  self.folder = folder
30
31
  self._user_data = {}
31
32
  self._verify_path()
32
33
 
33
34
  @property
34
- def filepath(self):
35
- ''' Returns user filepath '''
36
- path = os.path.join(self.os_user_folder, self.folder, self.name + '.json')
35
+ def filepath(self) -> str:
36
+ """Returns user filepath."""
37
+ path = os.path.join(self.os_user_folder, self.folder, f'{self.name}.json')
37
38
  return os.path.abspath(path)
38
39
 
39
40
  @property
40
- def os_user_folder(self):
41
- ''' returns os users home directory '''
41
+ def os_user_folder(self) -> str:
42
+ """Returns os users home directory."""
42
43
  return os.path.expanduser('~')
43
44
 
44
45
  @property
45
- def user_data(self):
46
- ''' override this property to modify saving dict '''
46
+ def user_data(self) -> dict:
47
+ """Override this property to modify saving dict."""
47
48
  return self._user_data
48
49
 
49
50
  @user_data.setter
50
- def user_data(self, v):
51
+ def user_data(self, v: dict) -> None:
51
52
  self._user_data = v
52
53
 
53
- def _verify_path(self):
54
- ''' Checks for target directory or make it '''
54
+ def _verify_path(self) -> bool:
55
+ """Checks for target directory or make it."""
55
56
  path = os.path.dirname(self.filepath)
56
57
  if not os.path.exists(path):
57
58
  os.makedirs(path)
59
+
58
60
  return True
59
61
 
60
- def save_settings(self, data=False):
61
- ''' Saves a dictionary into a json file (os user path)
62
+ def save_settings(self, data=False) -> bool:
63
+ """Saves a dictionary into a json file (os user path).
64
+
62
65
  Args:
63
66
  data (dictionary) : info dictionary to save, if set to False,
64
67
  saves instead local self.user_data property
65
- '''
68
+ """
66
69
  if not data:
67
70
  data = self.user_data
68
71
 
@@ -71,8 +74,8 @@ class JsonUserSettings():
71
74
  log.info('json settings file saved! [%s]', self.filepath)
72
75
  return r
73
76
 
74
- def load_settings(self):
75
- ''' Load json file from path and returns its contents '''
77
+ def load_settings(self) -> dict:
78
+ """Load json file from path and returns its contents."""
76
79
  try:
77
80
  return json_load(self.filepath)
78
81
  except OSError:
@@ -1,36 +1,43 @@
1
- import os
2
1
  import json
2
+ import os
3
3
 
4
4
  from backpack.logger import get_logger
5
5
 
6
- log = get_logger('JsonUtils')
6
+ log = get_logger('Python Backpack - JsonUtils')
7
7
 
8
8
 
9
9
  def json_load(json_file: str) -> dict:
10
- ''' Reads a json file
10
+ """Reads a json file.
11
+
11
12
  Args:
12
- json_file (filepath) json file to read data.
13
+ json_file: (string filepath) json file to read data.
14
+
13
15
  Returns:
14
16
  dict (file content)
15
- '''
17
+ """
16
18
  if not os.path.exists(json_file):
17
- raise OSError(f"json_load: File not found: {json_file}.")
19
+ raise OSError(f'json_load: File not found: {json_file}.')
18
20
 
19
21
  with open(json_file) as json_file_opened:
20
22
  try:
21
23
  value = json.load(json_file_opened)
22
24
  except ValueError as e:
23
25
  json_file_opened.close()
24
- raise OSError(f"{json_file} \n JSON File issue: {str(e)}") from e
26
+ raise OSError(f'{json_file} \n JSON File issue: {str(e)}') from e
27
+
25
28
  return value
26
29
 
27
30
 
28
- def json_save(data: dict, json_file: str):
29
- ''' Saves a dictionary into a json file
31
+ def json_save(data: dict, json_file: str) -> bool:
32
+ """Saves a dictionary into a json file.
33
+
30
34
  Args:
31
- data (dict) : dictionary to save
32
- json_file (filepath) json file to save data.
33
- '''
35
+ data: (dict) dictionary to save
36
+ json_file: (string filepath) json file to save data.
37
+
38
+ Returns:
39
+ bool (True if success)
40
+ """
34
41
 
35
42
  if not os.path.exists(os.path.dirname(json_file)):
36
43
  os.makedirs(os.path.dirname(json_file))
@@ -1,8 +1,8 @@
1
1
  import logging
2
2
 
3
3
 
4
- def get_logger(name: str):
5
- ''' basic log'''
4
+ def get_logger(name: str) -> logging.Logger:
5
+ """Returns a logger object with a stream handler."""
6
6
  _log = logging.getLogger(name)
7
7
  _log.propagate = False
8
8
  _log.setLevel(logging.DEBUG)
@@ -5,8 +5,9 @@
5
5
  # ----------------------------------------------------------------------------------------
6
6
 
7
7
 
8
- class Singleton():
9
- ''' Python Singleton BaseClass
8
+ class Singleton:
9
+ """Python Singleton BaseClass.
10
+
10
11
  Usage:
11
12
 
12
13
  class MyClass(Singleton, otherClass):
@@ -14,11 +15,12 @@ class Singleton():
14
15
 
15
16
  obj = MyClass() # any new object will be taken from the same instance
16
17
 
17
- '''
18
+ """
18
19
 
19
20
  _instance = None
20
21
 
21
22
  def __new__(cls, *args, **kwargs):
23
+ """Singleton __new__ method."""
22
24
  if not isinstance(cls._instance, cls):
23
25
  # print(f'Initializing {cls.__name__}')
24
26
  cls._instance = object.__new__(cls)