diff --git a/addons/source-python/packages/source-python/stringtables/downloads.py b/addons/source-python/packages/source-python/stringtables/downloads.py old mode 100644 new mode 100755 index dc2a2bf46..e4aef4410 --- a/addons/source-python/packages/source-python/stringtables/downloads.py +++ b/addons/source-python/packages/source-python/stringtables/downloads.py @@ -15,6 +15,10 @@ # Stringtables from stringtables import string_tables +# Site-Package Imports +# Path +from path import Path + # ============================================================================= # >> ALL DECLARATION @@ -29,11 +33,17 @@ class Downloadables(AutoUnload, set): """Class used to store downloadables for a script.""" - def __init__(self): - """Add the instance to the downloadables list.""" - super().__init__() + def __init__(self, *items): + """Add the instance to the downloadables list. + + :param iterable items: + The paths to add to the downloadables. + """ + super().__init__(*items) _downloadables_list.append(self) + self._set_all_downloads() + def add(self, item): """Add an item to the downloadables for a script. @@ -52,6 +62,25 @@ def add(self, item): # Add the item to the script's downloadables super().add(item) + def update(self, items=None): + """Add an items to the downloadables. + + :param iterable items: + The paths to add to the downloadables. + """ + if items is None: + return + + for item in items: + # Is the item not in the list? + if item not in self: + + # Add the item to the downloadables stringtable + _downloadables_list._add_to_download_table(item) + + # Add the items to the downloadables + super().update(items) + def add_directory(self, directory): """Add all files in the given directory to the downloadables. @@ -85,6 +114,36 @@ def remove_directory(self, directory): # Remove the item from the set self.remove(item) + def add_from_file(self, file_path, encoding='utf-8'): + """Add all the paths listed in the file to the downloadables. + + :param str file_path: + The file that contains the paths to add to the downloadables. + Lines that starts with '#' or '//' will be ignored. + :return: + Return the number of files that have been added. + :rtype: int + """ + lines = self._get_lines_from_file(file_path, encoding) + + # Remove comments and empty lines + items = list( + filter(lambda x:x and not x.startswith(('#', '//')), lines)) + + self.update(items) + + return len(items) + + def remove_from_file(self, file_path, encoding='utf-8'): + """Remove all the paths listed in the file from the downloadables. + + :param str file_path: + The file that contains the paths to remove from the downloadables. + """ + lines = self._get_lines_from_file(file_path, encoding) + + self.difference_update(lines) + def _set_all_downloads(self): """Add all downloadables for the script on level init.""" # Loop through all items in the list @@ -93,6 +152,27 @@ def _set_all_downloads(self): # Add the item to the downloadables stringtable _downloadables_list._add_to_download_table(item) + @classmethod + def _get_lines_from_file(cls, file_path, encoding): + """Checks the file path and then return the lines.""" + file_path = Path(file_path) + + # If the file or directory exists, ignore it + if not file_path.exists(): + + # File does not exist, search for it with GAME_PATH + with_game_path = GAME_PATH / file_path + if with_game_path.exists(): + file_path = with_game_path + + if not file_path.isfile(): + raise FileNotFoundError(f'No file found at "{file_path}"') + + with file_path.open('r', encoding=encoding) as file: + lines = [line.strip() for line in file.readlines()] + + return lines + def _unload_instance(self): """Remove the instance from the downloadables list.""" _downloadables_list.remove(self)