diff --git a/bcml/__init__.py b/bcml/__init__.py index 04a3060f..d87c5049 100644 --- a/bcml/__init__.py +++ b/bcml/__init__.py @@ -242,7 +242,7 @@ def SelectItem(self): mod = self.listWidget.selectedItems()[0].data(QtCore.Qt.UserRole) if mod not in self._mod_infos: - rules = ConfigParser() + rules = util.RulesParser() rules.read(str(mod.path / 'rules.txt')) font_met = QtGui.QFontMetrics(self.lblModInfo.font()) path = str(mod.path) @@ -486,7 +486,7 @@ def resort_mods(self): for mod in mods_to_change: new_path = util.get_modpack_dir() / util.get_mod_id(mod.name, mod.priority) shutil.move(str(mod.path), str(new_path)) - rules = ConfigParser() + rules = util.RulesParser() rules.read(str(new_path / 'rules.txt')) rules['Definition']['fsPriority'] = str(mod.priority) with (new_path / 'rules.txt').open('w', encoding='utf-8') as rf: @@ -799,7 +799,7 @@ def BrowseContentClicked(self): path = path.parent self.txtFolder.setText(str(path.resolve())) if (path / 'rules.txt').exists(): - rules = ConfigParser() + rules = util.RulesParser() rules.read(str(path / 'rules.txt')) if 'name' in rules['Definition'] and not self.txtName.text(): self.txtName.setText(str(rules['Definition']['name'])) diff --git a/bcml/data/version.txt b/bcml/data/version.txt index d5f80cb6..a75200ff 100644 --- a/bcml/data/version.txt +++ b/bcml/data/version.txt @@ -1 +1 @@ -version='2.5.0' +version='2.5.1' diff --git a/bcml/install.py b/bcml/install.py index 7747cf93..c3af86cb 100644 --- a/bcml/install.py +++ b/bcml/install.py @@ -282,7 +282,7 @@ def refresh_cemu_mods(): settings.writexml(setpath.open('w', encoding='utf-8'), addindent=' ', newl='\n') -def install_mod(mod: Path, verbose: bool = False, options: dict = {}, wait_merge: bool = False, +def install_mod(mod: Path, verbose: bool = False, options: dict = None, wait_merge: bool = False, insert_priority: int = 0): """ Installs a graphic pack mod, merging RSTB changes and optionally packs and texts @@ -319,7 +319,7 @@ def install_mod(mod: Path, verbose: bool = False, options: dict = {}, wait_merge return try: - rules = ConfigParser() + rules = util.RulesParser() rules.read(tmp_dir / 'rules.txt') mod_name = str(rules['Definition']['name']).strip(' "\'') print(f'Identified mod: {mod_name}') @@ -360,7 +360,7 @@ def install_mod(mod: Path, verbose: bool = False, options: dict = {}, wait_merge new_id = util.get_mod_id(existing_mod.name, priority_shifted) new_path = util.get_modpack_dir() / new_id shutil.move(str(existing_mod.path), str(new_path)) - existing_mod_rules = ConfigParser() + existing_mod_rules = util.RulesParser() existing_mod_rules.read(str(new_path / 'rules.txt')) existing_mod_rules['Definition']['fsPriority'] = str(priority_shifted) with (new_path / 'rules.txt').open('w', encoding='utf-8') as r_file: @@ -421,6 +421,8 @@ def install_mod(mod: Path, verbose: bool = False, options: dict = {}, wait_merge else: try: print('Performing merges...') + if not options: + options = {} if 'disable' not in options: options['disable'] = [] for merger in mergers.sort_mergers([cls() for cls in mergers.get_mergers() \ @@ -542,7 +544,7 @@ def change_mod_priority(path: Path, new_priority: int, wait_merge: bool = False, new_mod_id = util.get_mod_id(mod[0], mod[1]) shutil.move(str(mod[2]), str(mod[2].parent / new_mod_id)) - rules = ConfigParser() + rules = util.RulesParser() rules.read(str(mod.path.parent / new_mod_id / 'rules.txt')) rules['Definition']['fsPriority'] = str(mod[1]) with (mod[2].parent / new_mod_id / 'rules.txt').open('w', encoding='utf-8') as r_file: @@ -617,7 +619,7 @@ def _clean_sarc(file: Path, hashes: dict, tmp_dir: Path): new_sarc.write(s_file) -def create_bnp_mod(mod: Path, output: Path, options: dict = {}): +def create_bnp_mod(mod: Path, output: Path, options: dict = None): """[summary] :param mod: [description] @@ -658,6 +660,8 @@ def create_bnp_mod(mod: Path, output: Path, options: dict = {}): folder.write_bytes(sarc_bytes) shutil.rmtree(new_tmp) + if not options: + options = {} options['texts'] = {'user_only': False} logged_files = generate_logs(tmp_dir, options=options) diff --git a/bcml/util.py b/bcml/util.py index 4a548fd5..6fae46b1 100644 --- a/bcml/util.py +++ b/bcml/util.py @@ -11,11 +11,11 @@ import unicodedata import urllib.error import urllib.request -from collections import namedtuple +from collections import namedtuple, OrderedDict from collections.abc import Mapping from configparser import ConfigParser from pathlib import Path -from typing import List, Union +from typing import Union from PySide2.QtGui import QIcon, QPixmap import byml @@ -662,7 +662,7 @@ def inject_file_into_bootup(file: str, data: bytes, create_bootup: bool = False) def get_mod_info(rules_path: Path) -> BcmlMod: """ Gets the name and priority of a mod from its rules.txt """ - rules: ConfigParser = ConfigParser() + rules: ConfigParser = RulesParser() rules.read(str(rules_path)) name = str(rules['Definition']['name']).strip('" \'').replace('_', ' ') try: @@ -692,7 +692,7 @@ def get_mod_preview(mod: BcmlMod, rules: ConfigParser = None) -> QPixmap: :rtype: QPixmap """ if not rules: - rules = ConfigParser() + rules = RulesParser() rules.read(str(mod.path / 'rules.txt')) if 'url' in rules['Definition']: url = str(rules['Definition']['url']) @@ -912,3 +912,25 @@ def create_schema_handler(): else: return winreg.SetValueEx(key2, '', 0, winreg.REG_SZ, f'"{exec_path.resolve()}" "%1"') + + +class RulesParser(ConfigParser): + def __init__(self): + ConfigParser.__init__(self, dict_type=MultiDict) + + def write(self, fileobject): + from io import StringIO + buf = StringIO() + ConfigParser.write(self, buf) + config_str = re.sub(r'\[Preset[0-9]+\]', '[Preset]', buf.getvalue()) + fileobject.write(config_str) + + +class MultiDict(OrderedDict): + _unique = 0 + + def __setitem__(self, key, val): + if isinstance(val, dict) and key == 'Preset': + self._unique += 1 + key += str(self._unique) + OrderedDict.__setitem__(self, key, val) \ No newline at end of file diff --git a/installer.cfg b/installer.cfg index 630e408c..22983a8e 100644 --- a/installer.cfg +++ b/installer.cfg @@ -1,6 +1,6 @@ [Application] name=BCML -version=2.5.0 +version=2.5.1 entry_point=bcml.__init__:main icon=bcml/data/bcml.ico diff --git a/setup.py b/setup.py index 0ee9afee..bb7b13a8 100644 --- a/setup.py +++ b/setup.py @@ -13,7 +13,7 @@ setup( name='bcml', - version='2.5.0', + version='2.5.1', author='NiceneNerd', author_email='macadamiadaze@gmail.com', description='A mod manager for The Legend of Zelda: Breath of the Wild on Cemu',