Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-parted for openSUSE:Factory checked in at 2022-01-11 21:20:06 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-parted (Old) and /work/SRC/openSUSE:Factory/.python-parted.new.1892 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-parted" Tue Jan 11 21:20:06 2022 rev:4 rq:945553 version:3.11.7 Changes: -------- --- /work/SRC/openSUSE:Factory/python-parted/python-parted.changes 2020-06-03 20:32:59.669261382 +0200 +++ /work/SRC/openSUSE:Factory/.python-parted.new.1892/python-parted.changes 2022-01-11 21:24:18.177171245 +0100 @@ -1,0 +2,61 @@ +Tue Jan 11 10:09:22 UTC 2022 - Dirk M??ller <dmuel...@suse.com> + +- update to 3.11.7: + * Do not remove the generated tarballs. + * Update the RELEASE file. + * tests: Fix flag_get_name tests + * Avoid potential NULL dereferences in pydisk.c and pytimer.c + * New - example to query device capacity + * correct spelling mistake + * Make the partition name a property on parted.Partition objects + * 'from collections' -> 'from collections.abc' + * Add some more examples + * Small correction to the PED_EXCEPTION_FIX handling. + * Restore returning None for get_name + * Handle PED_EXCEPTION_FIX + * check for undefined flags + * added support for newer pyparted versions + * Support pypi.python.org for releases + * Forgot the "/" in the path name + * Remove assumption that temp devices get created in /tmp + * Adjust test case numbers for GeometryWriteTestCase again + * Revert "Use copy.deepcopy() rather than .duplicate()" + * Remove another unnecessary os.close() from baseclass.py + * Remove rogue close() call in baseclass.py + * Ignore the 'const' and just use these values as 'char *' + * Use copy.deepcopy + * More file descriptor close statements. + * Fixes for the RequiresDeviceNode class + * Use a smaller length for GeometryWriteTestCase + * Close the RequiresDeviceNode file descriptor before removal. + * Fix writing NULL sectors using a Geometry object + * Use Decimal + * Fix reference to fedorahosted.org in README + * Check for PartedException for upper disk and partition get flag ops. + * Only define PARTITION_ESP if libparted provides PED_PARTITION_ESP + * Only define PARTITION_IRST if libparted provides PED_PARTITION_IRST + * I did not remember, Debian spells it "libparted-dev". + * Add support for RISC-V + * Typo fix: mimimum -> minimum + * Replace 'iff' with 'if and only if' in pynatmath.h. + * Fix a type for the get_max_primary_partition_count() doc string. + * Remove *_LAST_FLAG checks + * Use Decimal for Device.getSize + * Update the 'twine upload' line in the Makefile + * Don't intentionally prohibit Python 2 usage + * mips64 support + * Require at least libparted 3.3 and python 3.7 + * pedmodule.c: Fix partition enum flag handling + * Add support for chromeos_kernel and bls_boot partition flags + * Move exception declarations to _pedmodule.c + * Use preprocessor for the _ped module and what constants to include. + * Reduce libparted requirement to 3.2 + * Update the pypi target in the Makefile + * Reduce minimum Python required to 3.5 + * Set PY_SSIZE_T_CLEAN for the build + * add nvme support + * Update RELEASE file to make last step be "make pypi" +- drop no-last-flag-check.patch, python-parted-unittests.patch: obsolete +- drop -fcommon, obsolete + +------------------------------------------------------------------- Old: ---- no-last-flag-check.patch pyparted-3.11.1.tar.gz python-parted-unittests.patch New: ---- pyparted-3.11.7.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-parted.spec ++++++ --- /var/tmp/diff_new_pack.oFAkVx/_old 2022-01-11 21:24:18.673171594 +0100 +++ /var/tmp/diff_new_pack.oFAkVx/_new 2022-01-11 21:24:18.677171597 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-parted # -# Copyright (c) 2020 SUSE LLC +# Copyright (c) 2022 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -19,18 +19,15 @@ %define srcname pyparted %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-parted -Version: 3.11.1 +Version: 3.11.7 Release: 0 Summary: Python module for GNU parted License: GPL-2.0-or-later Group: Development/Languages/Python URL: https://github.com/dcantrell/pyparted/ -Source0: https://github.com/dcantrell/pyparted/archive/v3.11.1.tar.gz#/%{srcname}-%{version}.tar.gz +Source0: https://github.com/dcantrell/pyparted/archive/v%{version}.tar.gz#/%{srcname}-%{version}.tar.gz # catch exception for unknown 'disk flag', kkae...@suse.de Patch0: pyparted-3.10.patch -# do not check for PED_PARTITION)_LAST_FLAG as it is not part of ABI -Patch1: no-last-flag-check.patch -Patch2: python-parted-unittests.patch Patch3: python-parted-parted-binary.patch Patch4: python-parted-featurestest.patch BuildRequires: %{python_module devel} @@ -54,8 +51,6 @@ %autopatch -p1 %build -export CFLAGS="%{optflags} -fcommon" -export CXXFLAGS="%{optflags} -fcommon" %python_build %install ++++++ pyparted-3.11.1.tar.gz -> pyparted-3.11.7.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/.gitignore new/pyparted-3.11.7/.gitignore --- old/pyparted-3.11.1/.gitignore 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/.gitignore 2020-10-23 21:39:49.000000000 +0200 @@ -1,10 +1,11 @@ *.pyc *.swp +.coverage +.tox ChangeLog MANIFEST build +coverage-report.log dist pyparted.spec -.tox -.coverage -coverage-report.log +tests/pylint/.pylint.d diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/.travis.yml new/pyparted-3.11.7/.travis.yml --- old/pyparted-3.11.1/.travis.yml 1970-01-01 01:00:00.000000000 +0100 +++ new/pyparted-3.11.7/.travis.yml 2020-10-23 21:39:49.000000000 +0200 @@ -0,0 +1,24 @@ +language: python +python: + - "3.5" + - "3.6" + +matrix: + include: + - python: 3.7 + dist: xenial + sudo: true + +before_install: + - sudo apt-get update + - sudo apt-get install -y libparted-dev + - pip install --upgrade pip setuptools pytest + - pip install coverage + +script: + - travis_wait env PYTHON=python3 make test coverage COVERAGE=coverage + +notifications: + email: + on_success: change + on_failure: change diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/Makefile new/pyparted-3.11.7/Makefile --- old/pyparted-3.11.1/Makefile 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/Makefile 2020-10-23 21:39:49.000000000 +0200 @@ -69,11 +69,23 @@ release: tag ( cd dist ; gzip -dc $(PACKAGE)-$(VERSION).tar.gz | tar -xvf - ) ( cd dist/$(PACKAGE)-$(VERSION) && $(PYTHON) setup.py build ) || exit 1 - rm -rf dist MANIFEST @echo @echo "$(PACKAGE)-$(VERSION) can be pushed to the git repo:" @echo " git push && git push --tags" @echo + @echo "*** Remember to run 'make pypi' afterwards ***" + @echo + +pypi: + @echo "************************************************************************" + @echo "* Username and password are for your pypi.org login. *" + @echo "* NOTE: You must be a listed maintainer for pyparted for this to work. *" + @echo "* See ~/.pypirc *" + @echo "************************************************************************" + @echo + twine upload \ + dist/$(PACKAGE)-$(VERSION).tar.gz \ + dist/$(PACKAGE)-$(VERSION).tar.gz.asc rpmlog: @prevtag="$$(git tag -l | grep -v "^start$$" | tail -n 2 | head -n 1)" ; \ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/README new/pyparted-3.11.7/README --- old/pyparted-3.11.1/README 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/README 2020-10-23 21:39:49.000000000 +0200 @@ -60,7 +60,7 @@ Fedora release you are using. Alternatively, you can file bugs directly on the project page: -http://fedorahosted.org/pyparted/ +https://github.com/dcantrell/pyparted/issues If you just have questions about pyparted, you can email us directly using the contact information in the AUTHORS file. We will do our best diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/RELEASE new/pyparted-3.11.7/RELEASE --- old/pyparted-3.11.1/RELEASE 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/RELEASE 2020-10-23 21:39:49.000000000 +0200 @@ -1,16 +1,19 @@ Instructions for making a new release: -1) git checkout master -2) git clean -d -x -f # I hope you've commited or stashed everything - # you are working on -2) git fetch -3) git rebase origin -4) make bumpver -5) git commit -a -m "New version." -6) git clean -d -x -f -7) make dist -8) gpg --detach-sign -a dist/$(make verrel).tar.gz -8) twine upload dist/$(make verrel).tar.gz $(make verrel).tar.gz.asc + 1) git checkout master + 2) git clean -d -x -f # I hope you've committed or stashed everything + # you are working on + 3) git fetch + 4) git rebase origin + 5) make bumpver + 6) git commit -a -m "New version." + 7) git clean -d -x -f + 8) make release + 9) gpg --detach-sign -a dist/$(make verrel).tar.gz +10) make pypi + +The tar.gz and tar.gz.asc files should be uploaded as release artifacts to +github as a new release. If packaging in RPM format, you might find the 'make rpmlog' target useful. It gives you an RPM spec file formatted changelog block that contains the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/examples/dump_partitions.py new/pyparted-3.11.7/examples/dump_partitions.py --- old/pyparted-3.11.1/examples/dump_partitions.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyparted-3.11.7/examples/dump_partitions.py 2020-10-23 21:39:49.000000000 +0200 @@ -0,0 +1,90 @@ +#!/usr/bin/env python3 +# +# Copyright 2019 Geoff Williams <ge...@declarativesystems.com> +# +# This example script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version so long as this copyright notice remains intact. +# +# This example script is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this example script. If not, see <http://www.gnu.org/licenses/>. + +__author__ = """Geoff Williams <ge...@declarativesystems.com>""" +__copyright__ = """Copyright 2019 Geoff Williams""" + +""" +print the partitions in a device/file according to pyparted +""" + +import parted + +# adjust as needed, eg /dev/sdc.. +device="sdcard.img" + +# A device is a "thing" with own properties (type, manufacturer etc) - its a +# high level abstraction that lets you just identify you have the right device +device = parted.getDevice(device) + +# grab a "disk" instance - the other choice is `freshDisk`, wheras `newDisk` +# seems to just read an existing disk (which is what we want for adding new +# partition) +disk = parted.newDisk(device) + +print("***** sanity check *****") +print(f"result: {disk.check()}") + +print("===== device ====") +print(f" model: {device.model}") +print(f" path: {device.path}") +print(f" sectorSize: {device.sectorSize}") +print(f" physicalSectorSize: {device.physicalSectorSize}") +print(f" length: {device.length}") +# this next line can crash if you have a wonky GPT... +# print(f" size (MB): {device.getSize()}") + +print("===== disk ====") +print(f" type: {disk.type}") +print(f" lastPartitionNumber: {disk.lastPartitionNumber}") +print(f" primaryPartitionCount: {disk.primaryPartitionCount}") +print( " free space regions:") +free_space_regions = disk.getFreeSpaceRegions() +for i, free_space_region in enumerate(free_space_regions): + print(f" {i}:") + print(f" start: {free_space_region.start}") + print(f" end: {free_space_region.end}") + print(f" length: {free_space_region.length}") + + +print("===== partitions ====") +for partition in disk.partitions: + # print(str(partition)) - gives a nice human-readable dump + print(f"Partition {partition.number}:") + print(f" length: {partition.getLength()}") + print(f" active: {partition.active}") + print(f" busy: {partition.busy}") + print(f" path: {partition.path}") + print(f" type: {partition.type}") + print(f" size(MB): {partition.getSize()}") + + # supported only by GPT partition tables + # will throw exception on MSDOS partition tables (fixed upstream) + print(f" name: {partition.name}") + filesystem = partition.fileSystem + print(f" filesystem:") + if filesystem: + print(f" type: {filesystem.type}") + print(f" checked: {filesystem.checked}") + else: + print(f" Filesystem info missing! you have an unformatted partition...") + + geometry = partition.geometry + print(f" geometry:") + print(f" start: {geometry.start}") + print(f" end: {geometry.end}") + print(f" length: {geometry.length}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/examples/fill_free_space_with_new_partition.py new/pyparted-3.11.7/examples/fill_free_space_with_new_partition.py --- old/pyparted-3.11.1/examples/fill_free_space_with_new_partition.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyparted-3.11.7/examples/fill_free_space_with_new_partition.py 2020-10-23 21:39:49.000000000 +0200 @@ -0,0 +1,83 @@ +#!/usr/bin/env python3 +# +# Copyright 2019 Geoff Williams <ge...@declarativesystems.com> +# +# This example script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version so long as this copyright notice remains intact. +# +# This example script is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this example script. If not, see <http://www.gnu.org/licenses/>. + +__author__ = """Geoff Williams <ge...@declarativesystems.com>""" +__copyright__ = """Copyright 2019 Geoff Williams""" + +""" +Allocate free space to a partition. This demo is setup for a raw image file +`sdcard.img` which is assumed to already contain partitions but with some +unallocated space at the end of the drive. If you have an image file that you +have _grown_ for this purpose (eg with `dd` or `truncate`) and it is GPT, you +need to run: + + sgdisk -e FILE + +before running this script since GPT demands 33 backup blocks at the end of +the disk. If you forget to do this you will get errors like this: + + File "/home/geoff/.local/lib/python3.7/site-packages/parted/decorators.py", line 42, in new + ret = fn(*args, **kwds) + File "/home/geoff/.local/lib/python3.7/site-packages/parted/disk.py", line 245, in addPartition + constraint.getPedConstraint()) +_ped.PartitionException: Unable to satisfy all constraints on the partition. + +Lets grow our SD card image: + $ dd if=/dev/zero bs=1M count=100 >> sdcard.img + $ sgdisk -e sdcard.img +""" + +# pip3 install pyparted +import parted + +# adjust as needed, eg /dev/sdc.. +device="sdcard.img" +device = parted.getDevice(device) +disk = parted.newDisk(device) +free_space_regions = disk.getFreeSpaceRegions() + +# grab the free space region at the end of the disk +geometry = free_space_regions[-1] + +# filesystem will be shown as blank by parted until it has been _formatted_ +filesystem = parted.FileSystem(type='ext4', geometry=geometry) +new_partition = parted.Partition( + disk=disk, + type=parted.PARTITION_NORMAL, + fs = filesystem, + geometry=geometry +) + +# name isn't in the constructor but we can set it separately +new_partition.name = "bob" + +disk.addPartition(partition=new_partition, + constraint=device.optimalAlignedConstraint) + +disk.commit() +print("created partition OK") + +# Now you can format the partition in the image file after setting it up as a +# loopback device, eg: +# sudo losetup -f -P sdcard.img +# sudo mkfs.ext4 /dev/loop6p3 +# Partitions are `1` indexed so `p3` is the third partition, not the fourth +# After formatting, the filesystem will be shown as `ext4` in `parted` and the +# new partition is ready to use. +# +# Cleanup your loopback device: +# sudo losetup -d /dev/loop6 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/examples/import_partition.py new/pyparted-3.11.7/examples/import_partition.py --- old/pyparted-3.11.1/examples/import_partition.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyparted-3.11.7/examples/import_partition.py 2020-10-23 21:39:49.000000000 +0200 @@ -0,0 +1,167 @@ +#!/usr/bin/env python3 +# +# Copyright 2019 Geoff Williams <ge...@declarativesystems.com> +# +# This example script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version so long as this copyright notice remains intact. +# +# This example script is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this example script. If not, see <http://www.gnu.org/licenses/>. + +__author__ = """Geoff Williams <ge...@declarativesystems.com>""" +__copyright__ = """Copyright 2019 Geoff Williams""" + +""" +Import a filesystem dump from file `new_partition.img` into a raw GPT image +`sdcard.img` as a new partition. +""" + +# pip3 install pyparted +import parted +import pprint +import subprocess +import os + +def pad_block(image_file): + """ + Pad a block to the nearest 1MiB (2048 sectors) + """ + # how many sectors (LBAs) does the whole disk use right now? + sector_count = int(os.path.getsize(image_file) / 512) + + # partitions need to start at 1MiB offsets + sector_alignment = sector_count % 2048 + + if sector_alignment == 0: + print("PADDING: already OK") + else: + padding_needed = 2048 - (sector_count % 2048) + + print(f"Padding {padding_needed} sectors to fill 1MiB block") + with open(image_file, 'ab') as file: + file.write(bytearray(padding_needed * 512)) + + new_sectors = int(os.path.getsize(image_file) / 512) + print(f"Padded {sector_count} --> {new_sectors}") + + +# Example using a raw image file created with `dd` (already contains partitions) +sdcard="sdcard.img" + +# 100MiB file created with `dd`, formatted ext4 +new_partition_file = "new_partition.img" + +# Grab the sizes of the SD card and the new partition before we start work +new_partition_size = os.path.getsize(new_partition_file) +new_partition_size_sectors = int(new_partition_size/512) +sdcard_original_size = os.path.getsize(sdcard) +original_sectors = int(sdcard_original_size/512) + + +# GPT stores a backup at the end of the drive that uses 33 blocks of 512 byte +# sectors - see https://en.wikipedia.org/wiki/GUID_Partition_Table and this +# second copy is required to both exist and be in the right place for the disk +# to be readable. If we just append our new partition, we can use `sgdisk -e` to +# move the backup back to the end of the disk, however, it will leave a gap that +# breaks both our alignment and starting sector calculation so we will write out +# the current GPT to a backup file, pad the image, append our new filesystem, +# pad the imagage again and restore the backup GPT to give us a layout like: +# +# | existing data | +# | padding to 1MiB boundary | +# | ------------------------ | +# | new partition | +# | padding to 1MiB boundary | +# | ------------------------ | +# | restored GPT | + +gpt_backup = "gpt.dat" +gpt_offset = -1 +gpt_size = 33 * 512 +print("Taking backup of GPT") +with open(sdcard, 'rb') as file: + + # seek to the start of the GPT data 33 LBA from the end of the disk, then + # read it into a `gpt_data` + file.seek(- gpt_size, os.SEEK_END) # Note minus sign, doesn't work in `wb` mode(?) + gpt_offset = file.tell(); + print(f"GPT offset: {gpt_offset}") + gpt_data = file.read() + + # sanity check that we read the right amount of data + gpt_data_len = len(gpt_data) + if gpt_data_len != gpt_size: + raise ValueError(f"GPT backup bad: {gpt_data_len} != {gpt_size}") + + # write out our GPT backup + with open(gpt_backup, 'wb') as g: + g.write(gpt_data) + + # sanity check we wrote the right amount of data + gpt_backup_len = os.path.getsize(gpt_backup) + if gpt_backup_len != gpt_size: + raise ValueError(f"GPT backup bad: {gpt_backup_len} != {gpt_size}") + +# Truncate the last 33 LBA (GPT backup) +with open(sdcard, 'rb+') as file: + file.truncate(gpt_offset) + +new_sectors = int(os.path.getsize(sdcard)/512) + +if (original_sectors - new_sectors) != 33: + raise ValueError(f"bad truncation {original_sectors} - {new_sectors} != 33") + +# now that the GPT is gone, pad out the image file ready for the new partition +# and record the resulting image size. This gives us the starting point for our +# new partition aligned to a 1MiB boundary +pad_block(sdcard) +partition_insertion_point = os.path.getsize(sdcard) +partition_insertion_point_sector = int(partition_insertion_point / 512) +subprocess.run(f"cat {new_partition_file} >> {sdcard}", shell=True, capture_output=True, check=True) + +# pad out the block after writing our new partition +pad_block(sdcard) + +# Restore the backup GPT +subprocess.run(f"cat {gpt_backup} >> {sdcard}", shell=True, capture_output=True, check=True) + +# Fix the backup GPT by "moving" it to end of disk (its already there but +# contains checksums that needs recomputing as well as pointers to its position +# on disk) +subprocess.run(f"sgdisk -e {sdcard}", shell=True, capture_output=True, check=True) + + +# Now the disk image contains the new partition and the GPT is adjusted for the +# new free space. We just have to add our new partition and its ready to use +device = parted.getDevice(sdcard) +disk = parted.newDisk(device) + +geometry = parted.Geometry( + device, + start=partition_insertion_point_sector, + length=new_partition_size_sectors +) + +print(f"New partition geometry:\n{geometry}") + +filesystem = parted.FileSystem(type='ext2', geometry=geometry) +new_partition = parted.Partition( + disk=disk, + type=parted.PARTITION_NORMAL, + fs = filesystem, + geometry=geometry +) +# name isn't in the constructor but we can set it separately +new_partition.name = "myimportedpartition" +disk.addPartition(partition=new_partition, + constraint=parted.Constraint(exactGeom=geometry)) + +disk.commit() +print("created partition OK") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/examples/query_device_capacity.py new/pyparted-3.11.7/examples/query_device_capacity.py --- old/pyparted-3.11.1/examples/query_device_capacity.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pyparted-3.11.7/examples/query_device_capacity.py 2020-10-23 21:39:49.000000000 +0200 @@ -0,0 +1,54 @@ +# coding=utf-8 +# +# Copyright 2017 John Florian <jflor...@doubledog.org> +# +# This example script is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by the Free +# Software Foundation, either version 3 of the License, or (at your option) any +# later version so long as this copyright notice remains intact. +# +# This example script is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more +# details. +# +# You should have received a copy of the GNU General Public License along with +# this example script. If not, see <http://www.gnu.org/licenses/>. + +__author__ = """John Florian <jflor...@doubledog.org>""" +__copyright__ = """Copyright 2017 John Florian""" + +""" +An example program that queries the capacity of a device that supports +removable media, such as CompactFlash card reader. +""" +import parted + +device_name = '/dev/sdd' + + +def to_mebibytes(value): + return value / (2 ** 20) + +def to_megabytes(value): + return value / (10 ** 6) + +while True: + print('press Enter after inserting a new card and letting things settle') + input() + dev = parted.getDevice(device_name) + capacity = dev.length * dev.sectorSize + print( + '{} has a capacity of {:n} bytes ' + '({:n} MB or {:n} MiB)'.format( + device_name, + capacity, + to_megabytes(capacity), + to_mebibytes(capacity), + ) + ) + + # Important! parted caches details so it's necessary to invalidate its + # cache to ensure accurate results when using removable media. See + # https://github.com/dcantrell/pyparted/issues/33 for more details. + dev.removeFromCache() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/include/docstrings/pydisk.h new/pyparted-3.11.7/include/docstrings/pydisk.h --- old/pyparted-3.11.1/include/docstrings/pydisk.h 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/include/docstrings/pydisk.h 2020-10-23 21:39:49.000000000 +0200 @@ -136,7 +136,7 @@ PyDoc_STRVAR(disk_get_max_primary_partition_count_doc, "get_max_primary_partition_count(self) -> integer\n\n" -"Get the maximum number of primary partitions spported by the disk label."); +"Get the maximum number of primary partitions supported by the disk label."); PyDoc_STRVAR(disk_get_max_supported_partition_count_doc, "get_max_supported_partition_count(self) -> integer\n\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/include/docstrings/pynatmath.h new/pyparted-3.11.7/include/docstrings/pynatmath.h --- old/pyparted-3.11.1/include/docstrings/pynatmath.h 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/include/docstrings/pynatmath.h 2020-10-23 21:39:49.000000000 +0200 @@ -35,11 +35,11 @@ PyDoc_STRVAR(alignment_intersect_doc, "intersect(self, Alignment) -> _ped.Alignment\n\n" "Create a new Alignment that describes the intersection of self and\n" -"Alignment. A sector will satisfy the new Alignment iff it satisfies both\n" -"of the original alignments, where 'satisfy' is determined by is_aligned().\n" -"The proof of this is relatively complicated and is described thoroughly\n" -"in the libparted source. This method raises ArithmeticError if no\n" -"intersection can be found."); +"Alignment. A sector will satisfy the new Alignment if and only if it\n" +"satisfies both of the original alignments, where 'satisfy' is determined\n" +"by is_aligned(). The proof of this is relatively complicated and is\n" +"described thoroughly in the libparted source. This method raises\n" +"ArithmeticError if no intersection can be found."); PyDoc_STRVAR(alignment_align_up_doc, "align_up(self, Geometry, Sector) -> Sector\n\n" diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/include/exceptions.h new/pyparted-3.11.7/include/exceptions.h --- old/pyparted-3.11.1/include/exceptions.h 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/include/exceptions.h 2020-10-23 21:39:49.000000000 +0200 @@ -1,7 +1,7 @@ /* * exceptions.h * - * Copyright (C) 2007-2013 Red Hat, Inc. + * Copyright (C) 2007-2020 Red Hat, Inc. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions of @@ -27,21 +27,21 @@ #include <Python.h> /* custom exceptions for _ped */ -PyObject *AlignmentException; -PyObject *CreateException; -PyObject *ConstraintException; -PyObject *DeviceException; -PyObject *DiskException; -PyObject *DiskLabelException; -PyObject *FileSystemException; -PyObject *GeometryException; -PyObject *IOException; -PyObject *NotNeededException; -PyObject *PartedException; -PyObject *PartitionException; -PyObject *TimerException; -PyObject *UnknownDeviceException; -PyObject *UnknownTypeException; +extern PyObject *AlignmentException; +extern PyObject *CreateException; +extern PyObject *ConstraintException; +extern PyObject *DeviceException; +extern PyObject *DiskException; +extern PyObject *DiskLabelException; +extern PyObject *FileSystemException; +extern PyObject *GeometryException; +extern PyObject *IOException; +extern PyObject *NotNeededException; +extern PyObject *PartedException; +extern PyObject *PartitionException; +extern PyObject *TimerException; +extern PyObject *UnknownDeviceException; +extern PyObject *UnknownTypeException; extern unsigned int partedExnRaised; extern char *partedExnMessage; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/include/typeobjects/pyconstraint.h new/pyparted-3.11.7/include/typeobjects/pyconstraint.h --- old/pyparted-3.11.1/include/typeobjects/pyconstraint.h 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/include/typeobjects/pyconstraint.h 2020-10-23 21:39:49.000000000 +0200 @@ -59,7 +59,7 @@ static PyGetSetDef _ped_Constraint_getset[] = { {"min_size", (getter) _ped_Constraint_get, (setter) _ped_Constraint_set, - "The mimimum size in _ped.Sectors of the partition.", "min_size"}, + "The minimum size in _ped.Sectors of the partition.", "min_size"}, {"max_size", (getter) _ped_Constraint_get, (setter) _ped_Constraint_set, "The maximum size in _ped.Sectors of the partition.", "max_size"}, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/setup.py new/pyparted-3.11.7/setup.py --- old/pyparted-3.11.1/setup.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/setup.py 2020-10-23 21:39:49.000000000 +0200 @@ -32,11 +32,11 @@ from distutils.core import Extension from distutils.version import LooseVersion -pyparted_version = '3.11.1' +pyparted_version = '3.11.7' python_version = sys.version_info -need_libparted_version = '2.3' -need_python_version = (2, 7) +need_libparted_version = '3.2' +need_python_version = (3, 5) if python_version < need_python_version: raise RuntimeError("pyparted requires Python version %d.%d or higher" @@ -62,7 +62,8 @@ # This list is in the format necessary for the define_macros parameter # for an Extension() module definition. See: # http://docs.python.org/distutils/setupscript.html#preprocessor-options -features = [('PYPARTED_VERSION', "\"%s\"" % pyparted_version)] +features = [('PYPARTED_VERSION', "\"%s\"" % pyparted_version), + ('PY_SSIZE_T_CLEAN', None)] setup(name='pyparted', version=pyparted_version, diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/_pedmodule.c new/pyparted-3.11.7/src/_pedmodule.c --- old/pyparted-3.11.1/src/_pedmodule.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/_pedmodule.c 2020-10-23 21:39:49.000000000 +0200 @@ -5,7 +5,7 @@ * Python module that implements the libparted functionality via Python * classes and other high level language features. * - * Copyright (C) 2007-2015 Red Hat, Inc. + * Copyright (C) 2007-2020 Red Hat, Inc. * * This copyrighted material is made available to anyone wishing to use, * modify, copy, or redistribute it subject to the terms and conditions of @@ -42,19 +42,29 @@ #include "pytimer.h" #include "pyunit.h" -#if PED_DISK_LAST_FLAG < 2 -#define PED_DISK_GPT_PMBR_BOOT 2 -#endif - -#if PED_PARTITION_LAST_FLAG < 15 -#define PED_PARTITION_LEGACY_BOOT 15 -#endif - char *partedExnMessage = NULL; unsigned int partedExnRaised = 0; PyObject *exn_handler = NULL; +/* custom exceptions for _ped */ +/* These are declared in exceptions.h for use elsewhere. */ +PyObject *AlignmentException; +PyObject *CreateException; +PyObject *ConstraintException; +PyObject *DeviceException; +PyObject *DiskException; +PyObject *DiskLabelException; +PyObject *FileSystemException; +PyObject *GeometryException; +PyObject *IOException; +PyObject *NotNeededException; +PyObject *PartedException; +PyObject *PartitionException; +PyObject *TimerException; +PyObject *UnknownDeviceException; +PyObject *UnknownTypeException; + /* Docs strings are broken out of the module structure here to be at least a * little bit readable. */ @@ -415,43 +425,46 @@ * py_ped_register_exn_handler function. */ static PedExceptionOption partedExnHandler(PedException *e) { + PedExceptionOption ret; + switch (e->type) { - /* Raise yes/no exceptions so the caller can deal with them, + /* Raise yes/no/fix exceptions so the caller can deal with them, * otherwise ignore */ case PED_EXCEPTION_INFORMATION: case PED_EXCEPTION_WARNING: if (e->options == PED_EXCEPTION_YES_NO) { - partedExnRaised = 1; - partedExnMessage = strdup(e->message); + ret = PED_EXCEPTION_NO; + } else if (e->options & PED_EXCEPTION_IGNORE) { + ret = PED_EXCEPTION_IGNORE; + } else { + partedExnRaised = 0; + return PED_EXCEPTION_UNHANDLED; + } - if (partedExnMessage == NULL) - PyErr_NoMemory(); - else if (exn_handler && PyCallable_Check(exn_handler)) { - PyObject *args, *retval; - - args = PyTuple_New(3); - PyTuple_SetItem(args, 0, PyLong_FromLong(e->type)); - PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); - PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); - - retval = PyObject_CallObject(exn_handler, args); - Py_DECREF(args); - if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) - return PyLong_AsLong(retval); - else - /* Call failed, use the default value. */ - return PED_EXCEPTION_NO; - } - else { - /* If no exception handling function was registered to - * tell us what to do, return "no" for any yes/no - * questions to prevent any potential disk destruction. - */ - return PED_EXCEPTION_NO; + partedExnRaised = 1; + partedExnMessage = strdup(e->message); + + if (partedExnMessage == NULL) { + PyErr_NoMemory(); + } else if (exn_handler && PyCallable_Check(exn_handler)) { + PyObject *args, *retval; + + args = PyTuple_New(3); + PyTuple_SetItem(args, 0, PyLong_FromLong(e->type)); + PyTuple_SetItem(args, 1, PyLong_FromLong(e->options)); + PyTuple_SetItem(args, 2, PyUnicode_FromString(e->message)); + + retval = PyObject_CallObject(exn_handler, args); + Py_DECREF(args); + if (retval != NULL && (PyLong_AsLong(retval) == PED_EXCEPTION_UNHANDLED || (PyLong_AsLong(retval) & e->options) > 0)) { + return PyLong_AsLong(retval); } } else { - partedExnRaised = 0; - return PED_EXCEPTION_IGNORE; + /* If no exception handling function was registered to + * tell us what to do, return "no" for any yes/no + * questions to prevent any potential disk destruction. + */ + return ret; } /* Set global flags so parted module methods can raise specific @@ -561,6 +574,7 @@ PyModule_AddIntConstant(m, "DEVICE_XVD", PED_DEVICE_XVD); PyModule_AddIntConstant(m, "DEVICE_SDMMC", PED_DEVICE_SDMMC); PyModule_AddIntConstant(m, "DEVICE_VIRTBLK", PED_DEVICE_VIRTBLK); + PyModule_AddIntConstant(m, "DEVICE_NVME", PED_DEVICE_NVME); /* add PedTimer type as _ped.Timer */ if (PyType_Ready(&_ped_Timer_Type_obj) < 0) @@ -634,9 +648,28 @@ PyModule_AddIntConstant(m, "PARTITION_BIOS_GRUB", PED_PARTITION_BIOS_GRUB); PyModule_AddIntConstant(m, "PARTITION_DIAG", PED_PARTITION_DIAG); PyModule_AddIntConstant(m, "PARTITION_LEGACY_BOOT", PED_PARTITION_LEGACY_BOOT); + + /* NOTE: You cannot evaluate the enum PED_PARTITION_* values using the + * preprocessor. DO NOT use #if or #ifdef with them. + * + * Conditionally add constants, based on PED_PARTITION_LAST_FLAG, and what + * we know about parted/disk.h + */ +#if defined(PED_PARTITION_MSFT_DATA) PyModule_AddIntConstant(m, "PARTITION_MSFT_DATA", PED_PARTITION_MSFT_DATA); +#endif +#if defined(PED_PARTITION_IRST) PyModule_AddIntConstant(m, "PARTITION_IRST", PED_PARTITION_IRST); +#endif +#if defined(PED_PARTITION_ESP) PyModule_AddIntConstant(m, "PARTITION_ESP", PED_PARTITION_ESP); +#endif +#if defined(PED_PARTITION_CHROMEOS_KERNEL) + PyModule_AddIntConstant(m, "PARTITION_CHROMEOS_KERNEL", PED_PARTITION_CHROMEOS_KERNEL); +#endif +#if defined(PED_PARTITION_BLS_BOOT) + PyModule_AddIntConstant(m, "PARTITION_BLS_BOOT", PED_PARTITION_BLS_BOOT); +#endif PyModule_AddIntConstant(m, "DISK_CYLINDER_ALIGNMENT", PED_DISK_CYLINDER_ALIGNMENT); PyModule_AddIntConstant(m, "DISK_GPT_PMBR_BOOT", PED_DISK_GPT_PMBR_BOOT); diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/parted/__init__.py new/pyparted-3.11.7/src/parted/__init__.py --- old/pyparted-3.11.1/src/parted/__init__.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/parted/__init__.py 2020-10-23 21:39:49.000000000 +0200 @@ -98,6 +98,7 @@ from _ped import DEVICE_XVD from _ped import DEVICE_SDMMC from _ped import DEVICE_VIRTBLK +from _ped import DEVICE_NVME from _ped import PARTITION_NORMAL from _ped import PARTITION_LOGICAL @@ -133,6 +134,12 @@ if hasattr(_ped, 'PARTITION_NONFS'): # pylint: disable=E0611 from _ped import PARTITION_NONFS +if hasattr(_ped, 'PARTITION_CHROMEOS_KERNEL'): + # pylint: disable=E0611 + from _ped import PARTITION_CHROMEOS_KERNEL +if hasattr(_ped, 'PARTITION_BLS_BOOT'): + # pylint: disable=E0611 + from _ped import PARTITION_BLS_BOOT from _ped import DISK_CYLINDER_ALIGNMENT from _ped import DISK_GPT_PMBR_BOOT @@ -325,7 +332,10 @@ 'ppc64le': ['msdos', 'gpt'], 'x86_64': ['msdos', 'gpt'], 'aarch64': ['msdos', 'gpt'], - 'armv7l': ['msdos', 'gpt']} + 'mips64': ['msdos','gpt'], + 'armv7l': ['msdos', 'gpt'], + 'riscv32': ['msdos', 'gpt'], + 'riscv64': ['msdos', 'gpt']} # Adapted from: # http://stackoverflow.com/questions/922550/how-to-mark-a-global-as-deprecated-in-python @@ -362,9 +372,9 @@ __archLabels = (('amiga', 'ppc(64)?$'), ('bsd', 'alpha$'), ('dasd', 's390x?$'), - ('gpt', 'i[3-6]86$|x86_64$|ia64$|ppc(64|64le)?$|aarch64$|armv7l$'), + ('gpt', 'i[3-6]86$|x86_64$|ia64$|ppc(64|64le)?$|aarch64$|armv7l$|riscv(32|64)$'), ('mac', 'ppc(64)?$'), - ('msdos', 'i[3-6]86$|x86_64$|s390x?$|alpha$|ia64$|ppc(64|64le)?$|aarch64$|armv7l$'), + ('msdos', 'i[3-6]86$|x86_64$|s390x?$|alpha$|ia64$|ppc(64|64le)?$|aarch64$|mips64$|armv7l$|riscv(32|64)$'), ('sun', 'sparc(64)?$')) def getLabels(arch=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/parted/cachedlist.py new/pyparted-3.11.7/src/parted/cachedlist.py --- old/pyparted-3.11.1/src/parted/cachedlist.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/parted/cachedlist.py 2020-10-23 21:39:49.000000000 +0200 @@ -1,7 +1,7 @@ # # Python bindings for libparted (built on top of the _ped Python module). # -# Copyright (C) 2009 Red Hat, Inc. +# Copyright (C) 2009-2020 Red Hat, Inc. # # This copyrighted material is made available to anyone wishing to use, # modify, copy, or redistribute it subject to the terms and conditions of @@ -18,9 +18,15 @@ # Red Hat, Inc. # # Red Hat Author(s): Chris Lumens <clum...@redhat.com> +# David Cantrell <dcantr...@redhat.com> # -from collections import Sequence +import sys + +if sys.version_info.major >= 3 and sys.version_info.minor >= 3: + from collections.abc import Sequence +else: + from collections import Sequence class CachedList(Sequence): """CachedList() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/parted/device.py new/pyparted-3.11.7/src/parted/device.py --- old/pyparted-3.11.1/src/parted/device.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/parted/device.py 2020-10-23 21:39:49.000000000 +0200 @@ -27,6 +27,7 @@ long = int import math +from decimal import Decimal import warnings import parted @@ -261,14 +262,14 @@ """Return the closest cylinder (round down) to sector on this Device.""" (_, heads, sectors) = self.biosGeometry - return long(math.floor((float(sector) / (heads * sectors)) + 1)) + return long(math.floor((Decimal(sector) / (heads * sectors)) + 1)) @localeC def endSectorToCylinder(self, sector): """Return the closest cylinder (round up) to sector on this Device.""" (_, heads, sectors) = self.biosGeometry - return long(math.ceil(float((sector + 1)) / (heads * sectors))) + return long(math.ceil(Decimal((sector + 1)) / (heads * sectors))) @localeC def startCylinderToSector(self, cylinder): @@ -296,11 +297,11 @@ if lunit not in parted._exponent.keys(): raise SyntaxError("invalid unit %s given" % (unit)) - size = float(self.__device.length) - size /= math.pow(1024.0, parted._exponent[lunit]) - size *= self.sectorSize + size = Decimal(self.__device.length) + size /= Decimal(math.pow(1024.0, parted._exponent[lunit])) + size *= Decimal(self.sectorSize) - return size + return float(size) @localeC def getLength(self, unit='sectors'): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/parted/partition.py new/pyparted-3.11.7/src/parted/partition.py --- old/pyparted-3.11.1/src/parted/partition.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/parted/partition.py 2020-10-23 21:39:49.000000000 +0200 @@ -121,23 +121,27 @@ return self.__partition.get_path() @property + def number(self): + """The partition number.""" + return self.__partition.num + @localeC - def name(self): - """The name of this partition.""" + def set_name(self, name): + """Set the partition name to the given string, on supported labels.""" + self.getPedPartition().set_name(name) + + def get_name(self): + """The partition name, on supported labels.""" try: return self.__partition.get_name() except parted.PartitionException: return None - @property - def number(self): - """The partition number.""" - return self.__partition.num - fileSystem = property(lambda s: s._fileSystem, lambda s, v: setattr(s, "_fileSystem", v)) geometry = property(lambda s: s._geometry, lambda s, v: setattr(s, "_geometry", v)) system = property(lambda s: s.__writeOnly("system"), lambda s, v: s.__partition.set_system(v)) type = property(lambda s: s.__partition.type, lambda s, v: setattr(s.__partition, "type", v)) + name = property(get_name, set_name) @localeC def getFlag(self, flag): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pyconstraint.c new/pyparted-3.11.7/src/pyconstraint.c --- old/pyparted-3.11.1/src/pyconstraint.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pyconstraint.c 2020-10-23 21:39:49.000000000 +0200 @@ -98,26 +98,22 @@ char *start_align = NULL, *end_align = NULL; char *start_range = NULL, *end_range = NULL; - start_align = -PyUnicode_AsUTF8(_ped_Alignment_Type_obj.tp_repr(self->start_align)); + start_align = (char *) PyUnicode_AsUTF8(_ped_Alignment_Type_obj.tp_repr(self->start_align)); if (start_align == NULL) { return NULL; } - end_align = -PyUnicode_AsUTF8(_ped_Alignment_Type_obj.tp_repr(self->end_align)); + end_align = (char *) PyUnicode_AsUTF8(_ped_Alignment_Type_obj.tp_repr(self->end_align)); if (end_align == NULL) { return NULL; } - start_range = -PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->start_range)); + start_range = (char *) PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->start_range)); if (start_range == NULL) { return NULL; } - end_range = -PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->end_range)); + end_range = (char *) PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->end_range)); if (end_range == NULL) { return NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pydevice.c new/pyparted-3.11.7/src/pydevice.c --- old/pyparted-3.11.1/src/pydevice.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pydevice.c 2020-10-23 21:39:49.000000000 +0200 @@ -188,12 +188,12 @@ char *ret = NULL; char *hw_geom = NULL, *bios_geom = NULL; - hw_geom = PyUnicode_AsUTF8(_ped_CHSGeometry_Type_obj.tp_repr(self->hw_geom)); + hw_geom = (char *) PyUnicode_AsUTF8(_ped_CHSGeometry_Type_obj.tp_repr(self->hw_geom)); if (hw_geom == NULL) { return NULL; } - bios_geom = PyUnicode_AsUTF8(_ped_CHSGeometry_Type_obj.tp_repr(self->bios_geom)); + bios_geom = (char *) PyUnicode_AsUTF8(_ped_CHSGeometry_Type_obj.tp_repr(self->bios_geom)); if (bios_geom == NULL) { return NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pydisk.c new/pyparted-3.11.7/src/pydisk.c --- old/pyparted-3.11.1/src/pydisk.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pydisk.c 2020-10-23 21:39:49.000000000 +0200 @@ -100,17 +100,17 @@ char *ret = NULL; char *disk = NULL, *fs_type = NULL, *geom = NULL; - disk = PyUnicode_AsUTF8(_ped_Disk_Type_obj.tp_repr(self->disk)); + disk = (char *) PyUnicode_AsUTF8(_ped_Disk_Type_obj.tp_repr(self->disk)); if (disk == NULL) { return NULL; } - fs_type = PyUnicode_AsUTF8(_ped_FileSystemType_Type_obj.tp_repr(self->fs_type)); + fs_type = (char *) PyUnicode_AsUTF8(_ped_FileSystemType_Type_obj.tp_repr(self->fs_type)); if (fs_type == NULL) { return NULL; } - geom = PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->geom)); + geom = (char *) PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->geom)); if (geom == NULL) { return NULL; } @@ -210,7 +210,11 @@ PyErr_SetString(PartitionException, partedExnMessage); } } else { - PyErr_Format(PartitionException, "Could not create new partition on device %s", disk->dev->path); + if (disk == NULL) { + PyErr_Format(PartitionException, "Could not create new partition"); + } else { + PyErr_Format(PartitionException, "Could not create new partition on device %s", disk->dev->path); + } } self->disk = self->fs_type = NULL; @@ -344,12 +348,12 @@ char *ret = NULL; char *dev = NULL, *type = NULL; - dev = PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->dev)); + dev = (char *) PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->dev)); if (dev == NULL) { return NULL; } - type = PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->type)); + type = (char *) PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->type)); if (type == NULL) { return NULL; } @@ -1020,7 +1024,7 @@ return NULL; } - if ((flag < PED_DISK_FIRST_FLAG) || (flag > PED_DISK_LAST_FLAG)) { + if (flag < PED_DISK_FIRST_FLAG) { PyErr_SetString(PyExc_ValueError, "Invalid flag provided."); return NULL; } @@ -1263,23 +1267,19 @@ return NULL; } - if (part) { - ret = ped_partition_set_name(part, in_name); - if (ret == 0) { - if (partedExnRaised) { - partedExnRaised = 0; + ret = ped_partition_set_name(part, in_name); + if (ret == 0) { + if (partedExnRaised) { + partedExnRaised = 0; - if (!PyErr_ExceptionMatches(PartedException) && - !PyErr_ExceptionMatches(PyExc_NotImplementedError)) - PyErr_SetString(PartitionException, partedExnMessage); + if (!PyErr_ExceptionMatches(PartedException) && + !PyErr_ExceptionMatches(PyExc_NotImplementedError)) { + PyErr_SetString(PartitionException, partedExnMessage); } - else - PyErr_Format(PartitionException, "Could not set name on partition %s%d", part->disk->dev->path, part->num); - - return NULL; + } else { + PyErr_Format(PartitionException, "Could not set name on partition %s%d", part->disk->dev->path, part->num); } - } - else { + return NULL; } @@ -1305,23 +1305,19 @@ return NULL; } - if (part) { - ret = (char *) ped_partition_get_name(part); - if (ret == NULL) { - if (partedExnRaised) { - partedExnRaised = 0; + ret = (char *) ped_partition_get_name(part); + if (ret == NULL) { + if (partedExnRaised) { + partedExnRaised = 0; - if (!PyErr_ExceptionMatches(PartedException) && - !PyErr_ExceptionMatches(PyExc_NotImplementedError)) - PyErr_SetString(PartitionException, partedExnMessage); + if (!PyErr_ExceptionMatches(PartedException) && + !PyErr_ExceptionMatches(PyExc_NotImplementedError)) { + PyErr_SetString(PartitionException, partedExnMessage); } - else - PyErr_Format(PartitionException, "Could not read name on partition %s%d", part->disk->dev->path, part->num); - - return NULL; + } else { + PyErr_Format(PartitionException, "Could not read name on partition %s%d", part->disk->dev->path, part->num); } - } - else { + return NULL; } @@ -1406,7 +1402,7 @@ return NULL; } - if ((flag < PED_PARTITION_FIRST_FLAG) || (flag > PED_PARTITION_LAST_FLAG)) { + if (flag < PED_PARTITION_FIRST_FLAG) { PyErr_SetString(PyExc_ValueError, "Invalid flag provided."); return NULL; } @@ -2010,7 +2006,11 @@ !PyErr_ExceptionMatches(PyExc_NotImplementedError)) PyErr_SetString(DiskException, partedExnMessage); } else { - PyErr_Format(DiskException, "Could not create new disk label on %s", disk->dev->path); + if (disk->dev == NULL) { + PyErr_Format(DiskException, "Could not create new disk label"); + } else { + PyErr_Format(DiskException, "Could not create new disk label on %s", disk->dev->path); + } } return NULL; @@ -2042,7 +2042,11 @@ !PyErr_ExceptionMatches(PyExc_NotImplementedError)) PyErr_SetString(DiskException, partedExnMessage); } else { - PyErr_Format(DiskException, "Could not create new disk label on %s", disk->dev->path); + if (disk->dev == NULL) { + PyErr_Format(DiskException, "Could not create new disk label"); + } else { + PyErr_Format(DiskException, "Could not create new disk label on %s", disk->dev->path); + } } return NULL; diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pyfilesys.c new/pyparted-3.11.7/src/pyfilesys.c --- old/pyparted-3.11.1/src/pyfilesys.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pyfilesys.c 2020-10-23 21:39:49.000000000 +0200 @@ -173,12 +173,12 @@ char *ret = NULL; char *type = NULL, *geom = NULL; - type = PyUnicode_AsUTF8(_ped_FileSystem_Type_obj.tp_repr(self->type)); + type = (char *) PyUnicode_AsUTF8(_ped_FileSystem_Type_obj.tp_repr(self->type)); if (type == NULL) { return NULL; } - geom = PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->geom)); + geom = (char *) PyUnicode_AsUTF8(_ped_Geometry_Type_obj.tp_repr(self->geom)); if (geom == NULL) { return NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pygeom.c new/pyparted-3.11.7/src/pygeom.c --- old/pyparted-3.11.1/src/pygeom.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pygeom.c 2020-10-23 21:39:49.000000000 +0200 @@ -88,7 +88,7 @@ char *ret = NULL; char *dev = NULL; - dev = PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->dev)); + dev = (char *) PyUnicode_AsUTF8(_ped_Device_Type_obj.tp_repr(self->dev)); if (dev == NULL) { return NULL; } @@ -629,10 +629,11 @@ PyObject *py_ped_geometry_write(PyObject *s, PyObject *args) { int ret = -1; char *in_buf = NULL; + Py_ssize_t in_buflen; PedGeometry *geom = NULL; PedSector offset, count; - if (!PyArg_ParseTuple(args, "sLL", &in_buf, &offset, &count)) { + if (!PyArg_ParseTuple(args, "s#LL", &in_buf, &in_buflen, &offset, &count)) { return NULL; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/src/pytimer.c new/pyparted-3.11.7/src/pytimer.c --- old/pyparted-3.11.1/src/pytimer.c 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/src/pytimer.c 2020-10-23 21:39:49.000000000 +0200 @@ -113,16 +113,10 @@ PyErr_SetString(PyExc_NotImplementedError, NULL); return -1; - if (kwds == NULL) { - if (!PyArg_ParseTuple(args, "|fdddz", &self->frac, &self->start, - &self->now, &self->predicted_end, - &self->state_name)) - return -1; - } else { - if (!PyArg_ParseTupleAndKeywords(args, kwds, "|fdddz", kwlist, - &self->frac, &self->start, &self->now, - &self->predicted_end, &self->state_name)) - return -2; + if (!PyArg_ParseTupleAndKeywords(args, kwds, "|fdddz", kwlist, + &self->frac, &self->start, &self->now, + &self->predicted_end, &self->state_name)) { + return -1; } /* self->state_name now points to the internal buffer of a PyUnicode object, @@ -194,7 +188,7 @@ return -1; } } else if (!strcmp(member, "state_name")) { - self->state_name = PyUnicode_AsUTF8(value); + self->state_name = (char *) PyUnicode_AsUTF8(value); if (PyErr_Occurred()) { return -1; } diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/baseclass.py new/pyparted-3.11.7/tests/baseclass.py --- old/pyparted-3.11.1/tests/baseclass.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/baseclass.py 2020-10-23 21:39:49.000000000 +0200 @@ -29,12 +29,15 @@ def setUp(self): self.addCleanup(self.removeTempDevice) - (fd, self.path) = tempfile.mkstemp(prefix="temp-device-") - f = os.fdopen(fd) - f.seek(140000) - os.write(fd, b"0") + self.temp_prefix = "temp-device-" + (self.fd, self.path) = tempfile.mkstemp(prefix=self.temp_prefix) + self.f = os.fdopen(self.fd) + self.f.seek(140000) + os.write(self.fd, b"0") def removeTempDevice(self): + os.close(self.fd) + if self.path and os.path.exists(self.path): os.unlink(self.path) @@ -62,11 +65,12 @@ except (IndexError, TypeError, _ped.UnknownTypeException): break - (fd, self.path,) = tempfile.mkstemp(prefix="temp-device-") - f = os.fdopen(fd) - f.seek(140000) - os.write(fd, b"0") - f.close() + self.temp_prefix = "temp-device-" + (self.fd, self.path,) = tempfile.mkstemp(prefix=self.temp_prefix) + self.f = os.fdopen(self.fd) + self.f.seek(140000) + os.write(self.fd, b"0") + self.f.close() os.system("mke2fs -F -q %s" % (self.path,)) @@ -142,6 +146,13 @@ self._disk = _ped.disk_new_fresh(self._device, _ped.disk_type_get("msdos")) self.disk = parted.Disk(PedDisk=self._disk) +# Base class for any test case that requires a GPT-labeled _ped.Disk or parted.Disk. +class RequiresGPTDisk(RequiresDevice): + def setUp(self): + RequiresDevice.setUp(self) + self._disk = _ped.disk_new_fresh(self._device, _ped.disk_type_get("gpt")) + self.disk = parted.Disk(PedDisk=self._disk) + # Base class for any test case that requires a filesystem made and mounted. class RequiresMount(RequiresDevice): def setUp(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/test__ped_partition.py new/pyparted-3.11.7/tests/test__ped_partition.py --- old/pyparted-3.11.1/tests/test__ped_partition.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/test__ped_partition.py 2020-10-23 21:39:49.000000000 +0200 @@ -122,7 +122,8 @@ 'PARTITION_APPLE_TV_RECOVERY', 'PARTITION_BIOS_GRUB', 'PARTITION_DIAG', 'PARTITION_MSFT_DATA', 'PARTITION_IRST', - 'PARTITION_ESP', 'PARTITION_NONFS']: + 'PARTITION_ESP', 'PARTITION_NONFS', + 'PARTITION_CHROMEOS_KERNEL', 'PARTITION_BLS_BOOT']: if not hasattr(_ped, f): continue attr = getattr(_ped, f) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/test__ped_ped.py new/pyparted-3.11.7/tests/test__ped_ped.py --- old/pyparted-3.11.1/tests/test__ped_ped.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/test__ped_ped.py 2020-10-23 21:39:49.000000000 +0200 @@ -41,14 +41,15 @@ 'PARTITION_APPLE_TV_RECOVERY', 'PARTITION_BIOS_GRUB', 'PARTITION_DIAG', 'PARTITION_MSFT_DATA', 'PARTITION_IRST', - 'PARTITION_ESP', 'PARTITION_NONFS']: + 'PARTITION_ESP', 'PARTITION_NONFS', + 'PARTITION_CHROMEOS_KERNEL', 'PARTITION_CHROMEOS_KERNEL']: if not hasattr(_ped, f): continue attr = getattr(_ped, f) self.assertNotEqual(_ped.partition_flag_get_name(attr), "", "Could not get name for flag _ped.%s" % f) self.assertRaises(ValueError, _ped.partition_flag_get_name, -1) - self.assertRaises(ValueError, _ped.partition_flag_get_name, 1000) + self.assertRaises(_ped.PartedException, _ped.partition_flag_get_name, 1000) class PartitionFlagGetByNameTestCase(unittest.TestCase): def runTest(self): @@ -82,7 +83,7 @@ self.assertNotEqual(_ped.disk_flag_get_name(f), "", "Could not get name for flag %s" % f) self.assertRaises(ValueError, _ped.disk_flag_get_name, -1) - self.assertRaises(ValueError, _ped.disk_flag_get_name, 1000) + self.assertRaises(_ped.PartedException, _ped.disk_flag_get_name, 1000) class DiskFlagGetByNameTestCase(unittest.TestCase): def runTest(self): @@ -224,10 +225,11 @@ # results. _ped.device_probe_all() lst = self.getDeviceList(_ped.device_get_next) + prefix = self.path[:self.path.index(self.temp_prefix) - 1] + "/" + self.temp_prefix self.assertGreater(len(lst), 0) self.assertGreater( - len([e for e in lst if e.path.startswith("/tmp/temp-device-")]), 0) + len([e for e in lst if e.path.startswith(prefix)]), 0) class DeviceFreeAllTestCase(RequiresDevice): def runTest(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/test_parted_geometry.py new/pyparted-3.11.7/tests/test_parted_geometry.py --- old/pyparted-3.11.1/tests/test_parted_geometry.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/test_parted_geometry.py 2020-10-23 21:39:49.000000000 +0200 @@ -108,11 +108,16 @@ # TODO self.fail("Unimplemented test case.") -@unittest.skip("Unimplemented test case.") -class GeometryWriteTestCase(unittest.TestCase): +class GeometryWriteTestCase(RequiresDevice): + def setUp(self): + RequiresDevice.setUp(self) + self.geom = parted.Geometry(self.device, start=10, length=100) + def runTest(self): - # TODO - self.fail("Unimplemented test case.") + self._device.open() + self.assertTrue(self.geom.write("".join(["\x00"] * self.device.sectorSize), 0, 1)) + self.assertTrue(self.geom.write("".join(["\x01"] * self.device.sectorSize), 0, 1)) + self._device.close() @unittest.skip("Unimplemented test case.") class GeometryGetPedGeometryTestCase(unittest.TestCase): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/test_parted_parted.py new/pyparted-3.11.7/tests/test_parted_parted.py --- old/pyparted-3.11.1/tests/test_parted_parted.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/test_parted_parted.py 2020-10-23 21:39:49.000000000 +0200 @@ -63,6 +63,8 @@ self.assertSetEqual(parted.getLabels('ia64'), {'gpt', 'msdos'}) self.assertSetEqual(parted.getLabels('aarch64'), {'gpt', 'msdos'}) self.assertSetEqual(parted.getLabels('armv7l'), {'gpt', 'msdos'}) + self.assertSetEqual(parted.getLabels('riscv32'), {'gpt', 'msdos'}) + self.assertSetEqual(parted.getLabels('riscv64'), {'gpt', 'msdos'}) class GetDeviceTestCase(RequiresDeviceNode): def runTest(self): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pyparted-3.11.1/tests/test_parted_partition.py new/pyparted-3.11.7/tests/test_parted_partition.py --- old/pyparted-3.11.1/tests/test_parted_partition.py 2017-06-26 17:20:05.000000000 +0200 +++ new/pyparted-3.11.7/tests/test_parted_partition.py 2020-10-23 21:39:49.000000000 +0200 @@ -24,6 +24,7 @@ import unittest from tests.baseclass import RequiresDisk +from tests.baseclass import RequiresGPTDisk # One class per method, multiple tests per class. For these simple methods, # that seems like good organization. More complicated methods may require @@ -55,6 +56,29 @@ geometry=self.geom) self.assertIsInstance(part_nofs, parted.Partition) +class PartitionGPTNewTestCase(RequiresGPTDisk): + """ + Like PartitionNewTestCase but with a GPT-labeled disk image. + """ + def setUp(self): + super(PartitionGPTNewTestCase, self).setUp() + self.geom = parted.Geometry(self.device, start=100, length=100) + self.fs = parted.FileSystem(type='ext2', geometry=self.geom) + self.part = parted.Partition(self.disk, parted.PARTITION_NORMAL, + geometry=self.geom, fs=self.fs) + + def runTest(self): + # Check that not passing args to parted.Partition.__init__ is caught. + with self.assertRaises((parted.PartitionException,)): + parted.Partition() + + self.assertIsInstance(self.part, parted.Partition) + # You don't need to pass a filesystem type at all, since this partition + # might be FREESPACE or METADATA. + part_nofs = parted.Partition(self.disk, parted.PARTITION_NORMAL, + geometry=self.geom) + self.assertIsInstance(part_nofs, parted.Partition) + class PartitionGetSetTestCase(PartitionNewTestCase): """ PartitionGetSet tests "part" instance @@ -79,16 +103,29 @@ with self.assertRaises(exn): self.part.active = True with self.assertRaises(exn): - self.part.name = "blah" - with self.assertRaises(exn): self.part.type = "blah" with self.assertRaises(exn): self.part.disk = self.disk + # DOS disklabels don't support names + self.assertEqual(self.part.name, None) + with self.assertRaises(parted.PartitionException): + self.part.name = "root" + # Check that looking for invalid attributes fails properly. with self.assertRaises((AttributeError)): print(self.part.blah) +class PartitionGetSetGPTTestCase(PartitionGPTNewTestCase): + """ + Like PartitionGetSetTestCase, but with a GPT-labeled test + image to work with rather than a DOS-labeled test image. + """ + def runTest(self): + # GPT labeled disks can support partition names + print(self.part.name) + self.part.name = "root" + class PartitionSetFlagTestCase(PartitionNewTestCase): """ Method setFlag should return True, if flag was set to "on" state. @@ -160,7 +197,8 @@ 'PARTITION_APPLE_TV_RECOVERY', 'PARTITION_BIOS_GRUB', 'PARTITION_DIAG', 'PARTITION_MSFT_DATA', 'PARTITION_IRST', - 'PARTITION_ESP', 'PARTITION_NONFS']: + 'PARTITION_ESP', 'PARTITION_NONFS', + 'PARTITION_CHROMEOS_KERNEL', 'PARTITION_BLS_BOOT']: if not hasattr(parted, f): continue attr = getattr(parted, f) ++++++ python-parted-parted-binary.patch ++++++ --- /var/tmp/diff_new_pack.oFAkVx/_old 2022-01-11 21:24:18.817171695 +0100 +++ /var/tmp/diff_new_pack.oFAkVx/_new 2022-01-11 21:24:18.821171698 +0100 @@ -1,17 +1,17 @@ -Index: pyparted-3.11.1/tests/baseclass.py +Index: pyparted-3.11.7/tests/baseclass.py =================================================================== ---- pyparted-3.11.1.orig/tests/baseclass.py -+++ pyparted-3.11.1/tests/baseclass.py -@@ -68,7 +68,7 @@ class RequiresFileSystem(unittest.TestCa - os.write(fd, b"0") - f.close() +--- pyparted-3.11.7.orig/tests/baseclass.py ++++ pyparted-3.11.7/tests/baseclass.py +@@ -72,7 +72,7 @@ class RequiresFileSystem(unittest.TestCa + os.write(self.fd, b"0") + self.f.close() - os.system("mke2fs -F -q %s" % (self.path,)) + os.system("/usr/sbin/mke2fs -F -q %s" % (self.path,)) self._device = _ped.device_get(self.path) self._geometry = _ped.Geometry(self._device, 0, self._device.length - 1) -@@ -133,7 +133,7 @@ class RequiresDeviceAlignment(RequiresDe +@@ -137,7 +137,7 @@ class RequiresDeviceAlignment(RequiresDe class RequiresLabeledDevice(RequiresDevice): def setUp(self): RequiresDevice.setUp(self) @@ -20,7 +20,7 @@ # Base class for any test case that requires a _ped.Disk or parted.Disk. class RequiresDisk(RequiresDevice): -@@ -150,7 +150,7 @@ class RequiresMount(RequiresDevice): +@@ -161,7 +161,7 @@ class RequiresMount(RequiresDevice): self.mountpoint = None def mkfs(self):