• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

Beakerboy / MS-OVBA / 24314004353

12 Apr 2026 06:59PM UTC coverage: 88.889%. First build
24314004353

Pull #98

github

web-flow
Merge 924012907 into b766bdecc
Pull Request #98: Update module_base.py

966 of 1092 new or added lines in 23 files covered. (88.46%)

1008 of 1134 relevant lines covered (88.89%)

4.44 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

94.74
/src/ms_ovba/Models/Entities/module_base.py
1
import uuid
5✔
2
from ms_ovba_compression.ms_ovba import MsOvba
5✔
3
from ms_ovba.Models.Fields.doubleEncodedString import (
5✔
4
    DoubleEncodedString
5
)
6
from ms_ovba.Models.Fields.packed_data import PackedData
5✔
7
from ms_ovba.Models.Fields.idSizeField import IdSizeField
5✔
8
from typing import Literal, TypeAlias, TypeVar
5✔
9

10

11
T = TypeVar('T', bound='ModuleBase')
5✔
12

13

14
WorkspaceType: TypeAlias = (
5✔
15
    tuple[int, int, int, int, Literal['C', 'I', 'Z']] |
16
    None
17
)
18

19

20
class ModuleBase():
5✔
21
    def __init__(self: T, name: str) -> None:
5✔
22
        """
23
        Initialize the module record
24
        """
25
        self.modName = DoubleEncodedString([0x0019, 0x0047], name)
5✔
26
        self.streamName = DoubleEncodedString([0x001A, 0x0032], name)
5✔
27
        self.docString = DoubleEncodedString([0x001C, 0x0048], "")
5✔
28
        self.helpContext = IdSizeField(0x001E, 4, 0)
5✔
29
        self._cookie = IdSizeField(0x002C, 2, 0xFFFF)
5✔
30

31
        # self.readonly = SimpleRecord(0x001E, 4, helpContext)
32
        # self.private = SimpleRecord(0x001E, 4, helpContext)
33
        self._cache = b''
5✔
34
        self.workspace: WorkspaceType = None
5✔
35
        self.type = ''
5✔
36
        self.created = 0
5✔
37
        self.modified = 0
5✔
38
        self._fileSize = 0
5✔
39
        self._size = 0
5✔
40

41
        # GUIDs
42
        self._guids: list[uuid.UUID] = []
5✔
43

44
    @property
5✔
45
    def guids(self: T) -> list[uuid.UUID]:
5✔
NEW
46
        return self._guids
×
47

48
    @guids.setter
5✔
49
    def guids(self: T, guid: uuid.UUID | list[uuid.UUID]) -> None:
5✔
NEW
50
        if isinstance(guid, list):
×
NEW
51
            self._guids = guid
×
52
        else:
NEW
53
            self._guids = [guid]
×
54

55
    def add_guid(self: T, guid: uuid.UUID) -> None:
5✔
56
        """
57
        Append a guid to the list
58
        """
59
        self._guids += [guid]
5✔
60

61
    @property
5✔
62
    def cache(self: T) -> bytes:
5✔
63
        return self._cache
5✔
64

65
    @cache.setter
5✔
66
    def cache(self: T, cache: bytes) -> None:
5✔
67
        self._cache = cache
5✔
68

69
    @property
5✔
70
    def cookie(self: T) -> int:
5✔
71
        return self._cookie.value
5✔
72

73
    @cookie.setter
5✔
74
    def cookie(self: T, value: int) -> None:
5✔
75
        self._cookie = IdSizeField(0x002C, 2, value)
5✔
76

77
    @property
5✔
78
    def name(self: T) -> str:
5✔
79
        return self.modName.value
5✔
80

81
    @property
5✔
82
    def bin_path(self: T) -> str:
5✔
83
        return self._file_path + ".bin"
5✔
84

85
    def add_workspace(self: T, val1: int, val2: int,
5✔
86
                      val3: int, val4: int,
87
                      val5: Literal['C', 'I', 'Z']) -> None:
88
        self.workspace = (val1, val2, val3, val4, val5)
5✔
89

90
    def pack(self: T, endien: str, cp_name: str) -> bytes:
5✔
91
        """
92
        Pack the metadata for use in the dir stream.
93
        """
94
        typeid_value = 0x0022 if self.type == 'Document' else 0x0021
5✔
95
        type_id = PackedData("HI", typeid_value, 0)
5✔
96
        self.offsetRec = IdSizeField(0x0031, 4, len(self._cache))
5✔
97
        output = (self.modName.pack(endien, cp_name)
5✔
98
                  + self.streamName.pack(endien, cp_name)
99
                  + self.docString.pack(endien, cp_name)
100
                  + self.offsetRec.pack(endien)
101
                  + self.helpContext.pack(endien, cp_name)
102
                  + self._cookie.pack(endien)
103
                  + type_id.pack(endien))
104
        footer = PackedData("HI", 0x002B, 0)
5✔
105
        output += footer.pack(endien)
5✔
106
        return output
5✔
107

108
    def to_project_module_string(self: T) -> str:
5✔
109
        return self.type + "=" + self.modName.value
5✔
110

111
    def add_file(self: T, file_path: str) -> None:
5✔
112
        self._file_path = file_path
5✔
113

114
    def write_file(self: T) -> None:
5✔
115
        bin_f = open(self._file_path + ".bin", "wb")
5✔
116
        bin_f.write(self._cache)
5✔
117
        with open(self._file_path + ".new", mode="rb") as new_f:
5✔
118
            contents = new_f.read()
5✔
119
        ms_ovba = MsOvba()
5✔
120
        compressed = ms_ovba.compress(contents)
5✔
121
        bin_f.write(compressed)
5✔
122
        bin_f.close()
5✔
123

124
    def _attr(self: T, name: str, value: str) -> str:
5✔
125
        return 'Attribute VB_' + name + ' = ' + value + '\n'
5✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc