Skip to content

Commit e0bb1a9

Browse files
authored
Merge pull request #105 from igoropaniuk/feat/pyproject_ruff_mypy_fixes
Introduce pyproject.toml, ruff and mypy for linting and type checking
2 parents 9603b33 + 2b49387 commit e0bb1a9

10 files changed

Lines changed: 242 additions & 171 deletions

File tree

.github/workflows/build.yml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,14 @@ jobs:
1414
with:
1515
fetch-depth: 0
1616

17+
- name: Install linters
18+
run: |
19+
sudo snap install ruff
20+
sudo apt-get update
21+
sudo apt-get install -y mypy
22+
1723
- name: Build all platforms and run tests
1824
run: |
19-
sudo apt install pycodestyle
2025
make lint
2126
make all integration
2227

.gitignore

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,9 @@
11
platforms/**/*.xml
22
platforms/**/*.bin
3+
4+
# Python
5+
__pycache__/
6+
*.pyc
7+
.mypy_cache/
8+
.ruff_cache/
9+
.venv/

Makefile

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,8 @@ all: $(PLATFORMS) $(PARTITIONS_XML) $(CONTENTS_XML)
2525
$(TOPDIR)/gen_contents.py -p $< -t $@.in -o $@ $${BUILD_ID:+ -b $(BUILD_ID)}
2626

2727
lint:
28-
# W605: invalid escape sequence
29-
pycodestyle --select=W605 *.py
30-
31-
# gen_contents.py is nearly perfect except E501: line too long.
32-
# Ensure there are no regressions.
33-
pycodestyle --ignore=E501 gen_contents.py
28+
ruff check *.py
29+
mypy *.py
3430

3531
integration: all
3632
# make sure generated output has created expected files

README.md

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,48 @@ qcom-ptool contains various device partitioning utilities like ptool.py, gen_par
77

88
# Development
99

10+
## Dependencies
11+
12+
The scripts use only the Python standard library (Python 3.8+), so no
13+
runtime dependencies need to be installed.
14+
15+
For development, `make lint` invokes `ruff` and `mypy` directly from the
16+
command line. On Debian/Ubuntu, install them as follows (ruff is not
17+
packaged in apt on all releases/architectures, so we install it from
18+
snap):
19+
20+
```sh
21+
sudo snap install ruff
22+
sudo apt install mypy
23+
```
24+
25+
## Makefile targets
26+
27+
| Target | Description |
28+
|---------------|------------------------------------------------------------|
29+
| `all` | Generate partition XML and GPT binaries for all platforms |
30+
| `lint` | Run ruff (linter) and mypy (type checker) on all scripts |
31+
| `integration` | Build all platforms and verify generated files are present |
32+
| `check` | Run both `lint` and `integration` |
33+
| `install` | Install scripts to `$(DESTDIR)$(PREFIX)/bin` |
34+
| `clean` | Remove generated XML and binary files from platforms/ |
35+
36+
### Quick start
37+
38+
```sh
39+
# install linters (Debian/Ubuntu)
40+
sudo snap install ruff
41+
sudo apt install mypy
42+
43+
# run linters
44+
make lint
45+
46+
# build all platforms and run tests
47+
make check
48+
```
49+
50+
## Code contributions
51+
1052
See [CONTRIBUTING.md file](CONTRIBUTING.md) for instructions on how to send
1153
code contributions to this project. You can also [report an issue on
1254
GitHub](../../issues).

gen_contents.py

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,13 +33,13 @@ def ParseXML(XMLFile):
3333

3434
def UpdateMetaData(TemplateRoot, PartitionRoot, BuildId):
3535
ChipIdList = TemplateRoot.findall("product_info/chipid")
36-
DefaultStorageType = None
36+
DefaultStorageType: str = ""
3737
for ChipId in ChipIdList:
3838
Flavor = ChipId.get("flavor")
3939
StorageType = ChipId.get("storage_type")
4040
print(f"Chipid Flavor: {Flavor} Storage Type: {StorageType}")
4141
if Flavor == "default":
42-
DefaultStorageType = ChipId.get("storage_type")
42+
DefaultStorageType = ChipId.get("storage_type", "")
4343

4444
PhyPartition = PartitionRoot.findall("physical_partition")
4545
Partitions = []
@@ -67,6 +67,8 @@ def _add_file_elements(parent_element, pathname, file_path_flavor=None):
6767
builds = TemplateRoot.findall("builds_flat/build")
6868
for build in builds:
6969
Name = build.find("name")
70+
if Name is None or Name.text is None:
71+
continue
7072
print(f"Build Name: {Name.text}")
7173
new_build_id = ET.SubElement(build, "build_id")
7274
new_build_id.text = BuildId

gen_partition.py

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,11 @@
3232
import sys
3333
import xml.etree.ElementTree as ET
3434
from collections import OrderedDict
35+
from typing import NoReturn
3536
from xml.dom import minidom
3637

3738

38-
def usage():
39+
def usage() -> NoReturn:
3940
print(
4041
"\n\tUsage: %s -i <input> -o <output> -m [partition_name1=image_filename1,partition_name2=image_filename2,...]\n\tVersion 1.0\n"
4142
% (sys.argv[0])
@@ -72,7 +73,7 @@ def usage():
7273
disk_entry = None
7374
partition_entries = []
7475
# store partition image map passed from command line
75-
partition_image_map = {}
76+
partition_image_map: dict[str, str] = {}
7677
input_file = None
7778
output_xml = None
7879

@@ -92,19 +93,23 @@ def disk_options(argv):
9293
disk_params["GROW_LAST_PARTITION_TO_FILL_DISK"] = "true"
9394
elif opt in ["--align-partitions"]:
9495
disk_params["ALIGN_PARTITIONS_TO_PERFORMANCE_BOUNDARY"] = "true"
95-
disk_params["PERFORMANCE_BOUNDARY_IN_KB"] = int(arg) // 1024
96+
disk_params["PERFORMANCE_BOUNDARY_IN_KB"] = str(int(arg) // 1024)
9697
return disk_params
9798

9899

99100
def partition_size_in_kb(size):
100101
if not re.search("[a-zA-Z]+", size):
101102
return int(size) // 1024
102-
if re.search("([0-9])*(?=([Kk]([Bb])*))", size):
103-
return int(re.search("([0-9])*(?=([Kk]([Bb])*))", size).group(0))
104-
if re.search("([0-9])*(?=([Mm]([Bb])*))", size):
105-
return int(re.search("([0-9])*(?=([Mm]([Bb])*))", size).group(0)) * 1024
106-
if re.search("([0-9])*(?=([Gg]([Bb])*))", size):
107-
return int(re.search("([0-9])*(?=([Gg]([Bb])*))", size).group(0)) * 1024 * 1024
103+
m = re.search("([0-9]+)(?=[Kk][Bb]?)", size)
104+
if m:
105+
return int(m.group(0))
106+
m = re.search("([0-9]+)(?=[Mm][Bb]?)", size)
107+
if m:
108+
return int(m.group(0)) * 1024
109+
m = re.search("([0-9]+)(?=[Gg][Bb]?)", size)
110+
if m:
111+
return int(m.group(0)) * 1024 * 1024
112+
raise ValueError("Unrecognized size format: '%s'" % size)
108113

109114

110115
def partition_options(argv):
@@ -134,19 +139,19 @@ def partition_options(argv):
134139
partition_entry["filename"] = arg
135140
elif opt in ["--sparse"]:
136141
partition_entry["sparse"] = arg
137-
if partition_entry["label"] in partition_image_map.keys():
142+
if partition_entry["label"] in partition_image_map:
138143
partition_entry["filename"] = partition_image_map[partition_entry["label"]]
139144
return phys_part, partition_entry
140145

141146

142147
def parse_partition_entries(partition_entries):
143-
partitions_params = {}
148+
partitions_params: dict[int, list[dict[str, str]]] = {}
144149

145150
for partition_entry in partition_entries:
146151
opts_list = list(partition_entry.split(" "))
147152
if opts_list[0] == "--partition":
148153
try:
149-
options, remainders = getopt.gnu_getopt(
154+
options, _remainders = getopt.gnu_getopt(
150155
opts_list[1:],
151156
"",
152157
[
@@ -173,7 +178,7 @@ def parse_disk_entry(disk_entry):
173178
opts_list = list(disk_entry.split(" "))
174179
if opts_list[0] == "--disk":
175180
try:
176-
options, remainders = getopt.gnu_getopt(
181+
options, _remainders = getopt.gnu_getopt(
177182
opts_list[1:],
178183
"",
179184
[
@@ -196,12 +201,12 @@ def generate_multi_lun_xml(disk_params, partitions, output_xml):
196201
parser_instruction_text = ""
197202

198203
for key, value in disk_params.items():
199-
if not key == "size" and not key == "type":
204+
if key != "size" and key != "type":
200205
parser_instruction_text += "\n\t" + str(key) + "=" + str(value) + "\n\t"
201206

202207
ET.SubElement(root, "parser_instructions").text = parser_instruction_text
203208

204-
for phys_part, entries in sorted(partitions.items(), key=lambda item: int(item[0])):
209+
for _phys_part, entries in sorted(partitions.items(), key=lambda item: int(item[0])):
205210
found = False
206211
for part_entry in entries:
207212

@@ -257,6 +262,8 @@ def generate_partition_xml(disk_params, partitions, output_xml):
257262
except Exception as argerr:
258263
print(str(argerr))
259264
usage()
265+
if input_file is None or output_xml is None:
266+
usage()
260267
f = open(input_file)
261268
line = f.readline()
262269
while line:

0 commit comments

Comments
 (0)