APProcedurePatch: hotfix changing class variables to instance variables (#2996)
* change class variables to instance variables * Update worlds/Files.py Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> * Update worlds/Files.py Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com> * move required_extensions to tuple * fix missing tuple ellipsis * fix classvar mixup * rename tokens to _tokens. use hasattr * type hint cleanup * Update Files.py * check using isinstance instead --------- Co-authored-by: black-sliver <59490463+black-sliver@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									12864f7b24
								
							
						
					
					
						commit
						f4b7c28a33
					
				| 
						 | 
				
			
			@ -7,7 +7,7 @@ from enum import IntEnum
 | 
			
		|||
import os
 | 
			
		||||
import threading
 | 
			
		||||
 | 
			
		||||
from typing import ClassVar, Dict, List, Literal, Tuple, Any, Optional, Union, BinaryIO, overload
 | 
			
		||||
from typing import ClassVar, Dict, List, Literal, Tuple, Any, Optional, Union, BinaryIO, overload, Sequence
 | 
			
		||||
 | 
			
		||||
import bsdiff4
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ class AutoPatchRegister(abc.ABCMeta):
 | 
			
		|||
 | 
			
		||||
class AutoPatchExtensionRegister(abc.ABCMeta):
 | 
			
		||||
    extension_types: ClassVar[Dict[str, AutoPatchExtensionRegister]] = {}
 | 
			
		||||
    required_extensions: List[str] = []
 | 
			
		||||
    required_extensions: Tuple[str, ...] = ()
 | 
			
		||||
 | 
			
		||||
    def __new__(mcs, name: str, bases: Tuple[type, ...], dct: Dict[str, Any]) -> AutoPatchExtensionRegister:
 | 
			
		||||
        # construct class
 | 
			
		||||
| 
						 | 
				
			
			@ -51,7 +51,9 @@ class AutoPatchExtensionRegister(abc.ABCMeta):
 | 
			
		|||
        return new_class
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def get_handler(game: str) -> Union[AutoPatchExtensionRegister, List[AutoPatchExtensionRegister]]:
 | 
			
		||||
    def get_handler(game: Optional[str]) -> Union[AutoPatchExtensionRegister, List[AutoPatchExtensionRegister]]:
 | 
			
		||||
        if not game:
 | 
			
		||||
            return APPatchExtension
 | 
			
		||||
        handler = AutoPatchExtensionRegister.extension_types.get(game, APPatchExtension)
 | 
			
		||||
        if handler.required_extensions:
 | 
			
		||||
            handlers = [handler]
 | 
			
		||||
| 
						 | 
				
			
			@ -191,7 +193,7 @@ class APProcedurePatch(APAutoPatchInterface):
 | 
			
		|||
    hash: Optional[str]  # base checksum of source file
 | 
			
		||||
    source_data: bytes
 | 
			
		||||
    patch_file_ending: str = ""
 | 
			
		||||
    files: Dict[str, bytes] = {}
 | 
			
		||||
    files: Dict[str, bytes]
 | 
			
		||||
 | 
			
		||||
    @classmethod
 | 
			
		||||
    def get_source_data(cls) -> bytes:
 | 
			
		||||
| 
						 | 
				
			
			@ -206,6 +208,7 @@ class APProcedurePatch(APAutoPatchInterface):
 | 
			
		|||
 | 
			
		||||
    def __init__(self, *args: Any, **kwargs: Any):
 | 
			
		||||
        super(APProcedurePatch, self).__init__(*args, **kwargs)
 | 
			
		||||
        self.files = {}
 | 
			
		||||
 | 
			
		||||
    def get_manifest(self) -> Dict[str, Any]:
 | 
			
		||||
        manifest = super(APProcedurePatch, self).get_manifest()
 | 
			
		||||
| 
						 | 
				
			
			@ -277,7 +280,7 @@ class APDeltaPatch(APProcedurePatch):
 | 
			
		|||
        super(APDeltaPatch, self).__init__(*args, **kwargs)
 | 
			
		||||
        self.patched_path = patched_path
 | 
			
		||||
 | 
			
		||||
    def write_contents(self, opened_zipfile: zipfile.ZipFile):
 | 
			
		||||
    def write_contents(self, opened_zipfile: zipfile.ZipFile) -> None:
 | 
			
		||||
        self.write_file("delta.bsdiff4",
 | 
			
		||||
                        bsdiff4.diff(self.get_source_data_with_cache(), open(self.patched_path, "rb").read()))
 | 
			
		||||
        super(APDeltaPatch, self).write_contents(opened_zipfile)
 | 
			
		||||
| 
						 | 
				
			
			@ -296,12 +299,12 @@ class APTokenMixin:
 | 
			
		|||
    """
 | 
			
		||||
    A class that defines functions for generating a token binary, for use in patches.
 | 
			
		||||
    """
 | 
			
		||||
    tokens: List[
 | 
			
		||||
    _tokens: Sequence[
 | 
			
		||||
        Tuple[APTokenTypes, int, Union[
 | 
			
		||||
            bytes,  # WRITE
 | 
			
		||||
            Tuple[int, int],  # COPY, RLE
 | 
			
		||||
            int  # AND_8, OR_8, XOR_8
 | 
			
		||||
        ]]] = []
 | 
			
		||||
        ]]] = ()
 | 
			
		||||
 | 
			
		||||
    def get_token_binary(self) -> bytes:
 | 
			
		||||
        """
 | 
			
		||||
| 
						 | 
				
			
			@ -309,8 +312,8 @@ class APTokenMixin:
 | 
			
		|||
        :return: A bytes object representing the token data.
 | 
			
		||||
        """
 | 
			
		||||
        data = bytearray()
 | 
			
		||||
        data.extend(len(self.tokens).to_bytes(4, "little"))
 | 
			
		||||
        for token_type, offset, args in self.tokens:
 | 
			
		||||
        data.extend(len(self._tokens).to_bytes(4, "little"))
 | 
			
		||||
        for token_type, offset, args in self._tokens:
 | 
			
		||||
            data.append(token_type)
 | 
			
		||||
            data.extend(offset.to_bytes(4, "little"))
 | 
			
		||||
            if token_type in [APTokenTypes.AND_8, APTokenTypes.OR_8, APTokenTypes.XOR_8]:
 | 
			
		||||
| 
						 | 
				
			
			@ -351,11 +354,14 @@ class APTokenMixin:
 | 
			
		|||
                    data: bytes) -> None:
 | 
			
		||||
        ...
 | 
			
		||||
 | 
			
		||||
    def write_token(self, token_type: APTokenTypes, offset: int, data: Union[bytes, Tuple[int, int], int]):
 | 
			
		||||
    def write_token(self, token_type: APTokenTypes, offset: int, data: Union[bytes, Tuple[int, int], int]) -> None:
 | 
			
		||||
        """
 | 
			
		||||
        Stores a token to be used by patching.
 | 
			
		||||
        """
 | 
			
		||||
        self.tokens.append((token_type, offset, data))
 | 
			
		||||
        if not isinstance(self._tokens, list):
 | 
			
		||||
            assert len(self._tokens) == 0, f"{type(self)}._tokens was tampered with."
 | 
			
		||||
            self._tokens = []
 | 
			
		||||
        self._tokens.append((token_type, offset, data))
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class APPatchExtension(metaclass=AutoPatchExtensionRegister):
 | 
			
		||||
| 
						 | 
				
			
			@ -371,10 +377,10 @@ class APPatchExtension(metaclass=AutoPatchExtensionRegister):
 | 
			
		|||
    Patch extension functions must return the changed bytes.
 | 
			
		||||
    """
 | 
			
		||||
    game: str
 | 
			
		||||
    required_extensions: List[str] = []
 | 
			
		||||
    required_extensions: ClassVar[Tuple[str, ...]] = ()
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def apply_bsdiff4(caller: APProcedurePatch, rom: bytes, patch: str):
 | 
			
		||||
    def apply_bsdiff4(caller: APProcedurePatch, rom: bytes, patch: str) -> bytes:
 | 
			
		||||
        """Applies the given bsdiff4 from the patch onto the current file."""
 | 
			
		||||
        return bsdiff4.patch(rom, caller.get_file(patch))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -411,7 +417,7 @@ class APPatchExtension(metaclass=AutoPatchExtensionRegister):
 | 
			
		|||
        return bytes(rom_data)
 | 
			
		||||
 | 
			
		||||
    @staticmethod
 | 
			
		||||
    def calc_snes_crc(caller: APProcedurePatch, rom: bytes):
 | 
			
		||||
    def calc_snes_crc(caller: APProcedurePatch, rom: bytes) -> bytes:
 | 
			
		||||
        """Calculates and applies a valid CRC for the SNES rom header."""
 | 
			
		||||
        rom_data = bytearray(rom)
 | 
			
		||||
        if len(rom) < 0x8000:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in New Issue