Merge lp:~milo/linaro-image-tools/bug1004199 into lp:linaro-image-tools/11.11
- bug1004199
- Merge into trunk
Status: | Merged | ||||
---|---|---|---|---|---|
Approved by: | Данило Шеган | ||||
Approved revision: | 527 | ||||
Merge reported by: | Milo Casagrande | ||||
Merged at revision: | not available | ||||
Proposed branch: | lp:~milo/linaro-image-tools/bug1004199 | ||||
Merge into: | lp:linaro-image-tools/11.11 | ||||
Diff against target: |
314 lines (+91/-44) 2 files modified
linaro_image_tools/media_create/partitions.py (+34/-12) linaro_image_tools/media_create/tests/test_media_create.py (+57/-32) |
||||
To merge this branch: | bzr merge lp:~milo/linaro-image-tools/bug1004199 | ||||
Related bugs: |
|
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Данило Шеган (community) | Approve | ||
Review via email: mp+108747@code.launchpad.net |
Commit message
Description of the change
Hello,
the proposed branch should fix the image size problem.
Thanks to Michael suggestion, and after a brief chat with him on IRC, I reworked the convert_
I added also a new method, _check_min_size, to ensure that we have at least 1MiB image size (this was the bit discussed on IRC).
I reworked and adapted a little bit the tests too. I added a new test for the exception that was not tested before; added a new one for the default size and fixed the other tests in order to address the changes in the function. One test has been removed since it was not really relevant anymore.
Cheers.
Milo Casagrande (milo) wrote : | # |
Hello Danilo,
On Wed, Jun 6, 2012 at 9:55 AM, Данило Шеган <email address hidden> wrote:
>
> With these changes, the name of the method might not make that much
> sense anymore. It should be
>
> round_to_
>
> Perhaps use something that describes the nature of the method is now
> more appropriate (i.e. "get_partition_
> similar).
I will use your suggestion for the method name. :-)
>> I added also a new method, _check_min_size, to ensure that we have at least 1MiB image size (this was the bit discussed on IRC).
>
> It would be good to add a few minimal tests for it as well :)
Added two new tests: one for a smaller value, one for a bigger one.
I added also a comment on _check_min_size, in order to avoid testing
passing size as a string: in the function "size" is a number. I used
"@param", is it the blessed way or is it better to use ":param"?
> I'd rather if we express this as two separate values, even if one is
> defined through the other. Eg.
>
> ROUND_IMAGE_TO = 2 ** 20
> MIN_IMAGE_SIZE = ROUND_IMAGE_TO
Fixed.
>> @@ -481,11 +484,12 @@
>> def convert_
>> """Convert a size string in Kbytes, Mbytes or Gbytes to bytes."""
>
> It'd be nice to extend this to document the new features (min size,
> rounding).
Added a small description of what is happening, another note on this
follows on the comment below.
>>...
>> + # Guarantee that is a multiple of 1MiB, defined in ROUND_IMAGE_TO
>> + real_size = _check_
>> + ROUND_IMAGE_TO)
>
> Better way to do the rounding is always to add half of ROUND_IMAGE_TO
> and then simply round() it. This will ensure that you've got enough
> space at all times.
> Eg.
>
> round((real_size + ROUND_IMAGE_
>
> will give you an image size which will be able to fit the requested
> number of KBs or MBs (eg. asking for '1024.4K' will give you 2MB which
> can really fit the requested number of kilobytes; it'd be even worse if
> you ask for 1500K and get 1MB).
Hmm... OK, got your point to have always enough space, although in
this case if we ask for '1M' we receive back a size of 2MiB, and
always a little bit more for all the other values. I hope it is not an
issue with space on users side if they want a better precision.
Changing this introduced a regression on another test, specifically
'test_setup_
image size in bytes here is used with 'dd'.
I changed the behavior of the converting functions, saying also that
the conversion in bytes is "deliberaltey inaccurate" (in the sense
that we add a small delta).
Fixed now, and also the tests and their values. :-)
>> +def _check_
>> + """Check that the image size is at least 1MiB (expressed in bytes)."""
>
> Hard-coding a value here which is not really hard-coded doesn't make
> much sense. Why not make it 'is at least MIN_IMAGE_SIZE bytes.'
> instead?
Fixed.
>> === modified file 'linaro_
>
> These are not of your doing, bu...
Данило Шеган (danilo) wrote : | # |
Hi Milo,
Sorry for taking this long to respond: it got off my radar. Please feel
free to ping and poke me to be faster about finishing a review for you.
Thanks for all the fixes, it looks much better now. Just a few small
notes now.
У сре, 06. 06 2012. у 16:22 +0000, Milo Casagrande пише:
> Added two new tests: one for a smaller value, one for a bigger one.
> I added also a comment on _check_min_size, in order to avoid testing
> passing size as a string: in the function "size" is a number. I used
> "@param", is it the blessed way or is it better to use ":param"?
It's better to use :param since it's used in the rest of the code-base.
> Hmm... OK, got your point to have always enough space, although in
> this case if we ask for '1M' we receive back a size of 2MiB, and
> always a little bit more for all the other values. I hope it is not an
> issue with space on users side if they want a better precision.
Let's fix that as well :)
Would doing "- 0.5" (in bytes) before division by ROUND_TO_SIZE and
rounding help with that without breaking anything else? Will this
simplistic formula work for a case where we ask for 1.000001M (when we
do want 2M)?
To clarify the algorithm I proposed though, the "trick" of adding
ROUND_TO_SIZE/2 is a common approach to round up ("ceil"), and that's
all we are doing. So, the docstring should only mention rounding up,
and we should fix it up so that's all it does. Perhaps we can instead
do a math.ceil which I wanted to avoid for no particular reason other
than looking smarter than I am :)
> Changing this introduced a regression on another test, specifically
> 'test_setup_
> image size in bytes here is used with 'dd'.
Right, we might need to update a test or two with these changes.
> I changed the behavior of the converting functions, saying also that
> the conversion in bytes is "deliberaltey inaccurate" (in the sense
> that we add a small delta).
I'd rather we fix the problem and just describe it as "we round up and
in multiples of 1MB" or something.
Cheers,
Danilo
Milo Casagrande (milo) wrote : | # |
Hello Danilo,
thanks for the review!
The final bits for the conversion should now be fixed.
We will use math.ceil, and return the correct rounded-up size for the image.
I added also a new test, based on your example, so that we can see the
difference and the correctness of asking 1M (that will return exactly
1MiB) compared to asking 1.0000001M (that will return 2MiB).
There might be also other changes, since I merged from trunk.
Ciao.
--
Milo Casagrande
Infrastructure Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs
Данило Шеган (danilo) wrote : | # |
Looks good, thanks for all the effort you expended on this bug :)
Данило Шеган (danilo) wrote : | # |
Actually, we should simply use ceil, and get rid of the + 0.5 trick altogether.
I.e.
real_size = _check_
- 527. By Milo Casagrande
-
Removed round function.
Milo Casagrande (milo) wrote : | # |
On Wed, Jun 13, 2012 at 3:33 PM, Данило Шеган <email address hidden> wrote:
>
> Actually, we should simply use ceil, and get rid of the + 0.5 trick altogether.
>
> I.e.
>
> real_size = _check_
With latest push I removed the "round" function, keeping only the
"int" conversion here, instead of doing it in the return statement,
sice we will execute _check_min_size anyway with MIN_IMAGE_SIZE that
is an int.
--
Milo Casagrande
Infrastructure Engineer
Linaro.org <www.linaro.org> │ Open source software for ARM SoCs
Данило Шеган (danilo) wrote : | # |
Looks good, thanks!
Preview Diff
1 | === modified file 'linaro_image_tools/media_create/partitions.py' |
2 | --- linaro_image_tools/media_create/partitions.py 2012-05-09 21:25:20 +0000 |
3 | +++ linaro_image_tools/media_create/partitions.py 2012-06-13 13:45:20 +0000 |
4 | @@ -17,15 +17,16 @@ |
5 | # You should have received a copy of the GNU General Public License |
6 | # along with Linaro Image Tools. If not, see <http://www.gnu.org/licenses/>. |
7 | |
8 | +from contextlib import contextmanager |
9 | +from math import ceil |
10 | import atexit |
11 | -from contextlib import contextmanager |
12 | +import dbus |
13 | import glob |
14 | import logging |
15 | import re |
16 | import subprocess |
17 | import time |
18 | |
19 | -import dbus |
20 | from parted import ( |
21 | Device, |
22 | Disk, |
23 | @@ -35,7 +36,6 @@ |
24 | |
25 | from linaro_image_tools import cmd_runner |
26 | |
27 | - |
28 | HEADS = 128 |
29 | SECTORS = 32 |
30 | SECTOR_SIZE = 512 # bytes |
31 | @@ -45,13 +45,17 @@ |
32 | # Max number of attempts to sleep (total sleep time in seconds = |
33 | # 1+2+...+MAX_TTS) |
34 | MAX_TTS = 10 |
35 | +# Image size should be a multiple of 1MiB, expressed in bytes. This is also |
36 | +# the minimum image size possible. |
37 | +ROUND_IMAGE_TO = 2 ** 20 |
38 | +MIN_IMAGE_SIZE = ROUND_IMAGE_TO |
39 | |
40 | |
41 | def setup_android_partitions(board_config, media, image_size, bootfs_label, |
42 | should_create_partitions, should_align_boot_part=False): |
43 | cylinders = None |
44 | if not media.is_block_device: |
45 | - image_size_in_bytes = convert_size_to_bytes(image_size) |
46 | + image_size_in_bytes = get_partition_size_in_bytes(image_size) |
47 | cylinders = image_size_in_bytes / CYLINDER_SIZE |
48 | proc = cmd_runner.run( |
49 | ['dd', 'of=%s' % media.path, |
50 | @@ -131,7 +135,7 @@ |
51 | """ |
52 | cylinders = None |
53 | if not media.is_block_device: |
54 | - image_size_in_bytes = convert_size_to_bytes(image_size) |
55 | + image_size_in_bytes = get_partition_size_in_bytes(image_size) |
56 | cylinders = image_size_in_bytes / CYLINDER_SIZE |
57 | proc = cmd_runner.run( |
58 | ['dd', 'of=%s' % media.path, |
59 | @@ -478,14 +482,20 @@ |
60 | path, 'DeviceFile', dbus_interface=DBUS_PROPERTIES)) |
61 | |
62 | |
63 | -def convert_size_to_bytes(size): |
64 | - """Convert a size string in Kbytes, Mbytes or Gbytes to bytes.""" |
65 | +def get_partition_size_in_bytes(size): |
66 | + """Convert a size string in Kbytes, Mbytes or Gbytes to bytes. |
67 | + |
68 | + The conversion rounds-up the size to the nearest MiB, considering a minimum |
69 | + size of MIN_IMAGE_SIZE bytes. The conversion always assures to have a big |
70 | + enough size for the partition. |
71 | + """ |
72 | unit = size[-1].upper() |
73 | + real_size = float(size[:-1]) |
74 | + |
75 | # no unit? (ends with a digit) |
76 | if unit in '0123456789': |
77 | - return int(round(float(size))) |
78 | - real_size = float(size[:-1]) |
79 | - if unit == 'K': |
80 | + real_size = float(size) |
81 | + elif unit == 'K': |
82 | real_size = real_size * 1024 |
83 | elif unit == 'M': |
84 | real_size = real_size * 1024 * 1024 |
85 | @@ -494,8 +504,20 @@ |
86 | else: |
87 | raise ValueError("Unknown size format: %s. Use K[bytes], M[bytes] " |
88 | "or G[bytes]" % size) |
89 | - |
90 | - return int(round(real_size)) |
91 | + # Guarantee that is a multiple of ROUND_IMAGE_TO |
92 | + real_size = _check_min_size(int(ceil(real_size / ROUND_IMAGE_TO) * |
93 | + ROUND_IMAGE_TO)) |
94 | + return real_size |
95 | + |
96 | + |
97 | +def _check_min_size(size): |
98 | + """Check that the image size is at least MIN_IMAGE_SIZE bytes. |
99 | + |
100 | + :param size: The size of the image to check, as a number. |
101 | + """ |
102 | + if (size < MIN_IMAGE_SIZE): |
103 | + size = MIN_IMAGE_SIZE |
104 | + return size |
105 | |
106 | |
107 | def run_sfdisk_commands(commands, heads, sectors, cylinders, device, |
108 | |
109 | === modified file 'linaro_image_tools/media_create/tests/test_media_create.py' |
110 | --- linaro_image_tools/media_create/tests/test_media_create.py 2012-06-07 13:12:42 +0000 |
111 | +++ linaro_image_tools/media_create/tests/test_media_create.py 2012-06-13 13:45:20 +0000 |
112 | @@ -38,11 +38,11 @@ |
113 | from linaro_image_tools import cmd_runner |
114 | import linaro_image_tools.media_create |
115 | from linaro_image_tools.media_create import ( |
116 | + android_boards, |
117 | + boards, |
118 | check_device, |
119 | - boards, |
120 | partitions, |
121 | rootfs, |
122 | - android_boards, |
123 | ) |
124 | from linaro_image_tools.media_create.boards import ( |
125 | SECTOR_SIZE, |
126 | @@ -64,8 +64,8 @@ |
127 | BoardConfig, |
128 | ) |
129 | from linaro_image_tools.media_create.android_boards import ( |
130 | + AndroidSnowballEmmcConfig, |
131 | android_board_configs, |
132 | - AndroidSnowballEmmcConfig, |
133 | ) |
134 | from linaro_image_tools.media_create.chroot_utils import ( |
135 | copy_file, |
136 | @@ -79,23 +79,25 @@ |
137 | ) |
138 | from linaro_image_tools.media_create.partitions import ( |
139 | HEADS, |
140 | + MIN_IMAGE_SIZE, |
141 | + Media, |
142 | SECTORS, |
143 | + _check_min_size, |
144 | + _get_device_file_for_partition_number, |
145 | + _parse_blkid_output, |
146 | + calculate_android_partition_size_and_offset, |
147 | calculate_partition_size_and_offset, |
148 | - calculate_android_partition_size_and_offset, |
149 | - convert_size_to_bytes, |
150 | create_partitions, |
151 | ensure_partition_is_not_mounted, |
152 | + get_android_loopback_devices, |
153 | get_boot_and_root_loopback_devices, |
154 | - get_android_loopback_devices, |
155 | get_boot_and_root_partitions_for_media, |
156 | - Media, |
157 | + get_partition_size_in_bytes, |
158 | + get_uuid, |
159 | partition_mounted, |
160 | run_sfdisk_commands, |
161 | setup_partitions, |
162 | - get_uuid, |
163 | - _parse_blkid_output, |
164 | wait_partition_to_settle, |
165 | - _get_device_file_for_partition_number, |
166 | ) |
167 | from linaro_image_tools.media_create.rootfs import ( |
168 | append_to_fstab, |
169 | @@ -104,8 +106,8 @@ |
170 | move_contents, |
171 | populate_rootfs, |
172 | rootfs_mount_options, |
173 | + update_network_interfaces, |
174 | write_data_to_protected_file, |
175 | - update_network_interfaces, |
176 | ) |
177 | from linaro_image_tools.media_create.tests.fixtures import ( |
178 | CreateTarballFixture, |
179 | @@ -492,7 +494,9 @@ |
180 | |
181 | class config(BoardConfig): |
182 | pass |
183 | - self.assertRaises(AssertionError, config.set_metadata, 'ahwpack.tar.gz') |
184 | + self.assertRaises(AssertionError, |
185 | + config.set_metadata, |
186 | + 'ahwpack.tar.gz') |
187 | |
188 | |
189 | class TestGetMLOFile(TestCaseWithFixtures): |
190 | @@ -767,8 +771,11 @@ |
191 | uboot_file = os.path.join(uboot_dir, 'u-boot.bin') |
192 | uboot_relative_file = uboot_file.replace(self.tempdir, '') |
193 | with open(cfg_file, 'w') as f: |
194 | - f.write('%s %s %i %#x %s\n' % ('NORMAL', uboot_relative_file, 0, |
195 | - 0xBA0000, '9')) |
196 | + f.write('%s %s %i %#x %s\n' % ('NORMAL', |
197 | + uboot_relative_file, |
198 | + 0, |
199 | + 0xBA0000, |
200 | + '9')) |
201 | with open(uboot_file, 'w') as f: |
202 | file_info = boards.SnowballEmmcConfig.get_file_info( |
203 | self.tempdir, self.temp_bootdir_path) |
204 | @@ -781,8 +788,10 @@ |
205 | with open(cfg_file, 'w') as f: |
206 | f.write('%s %s %i %#x %s\n' % ('NORMAL', 'u-boot.bin', 0, |
207 | 0xBA0000, '9')) |
208 | - self.assertRaises(AssertionError, boards.SnowballEmmcConfig.get_file_info, |
209 | - self.tempdir, self.temp_bootdir_path) |
210 | + self.assertRaises(AssertionError, |
211 | + boards.SnowballEmmcConfig.get_file_info, |
212 | + self.tempdir, |
213 | + self.temp_bootdir_path) |
214 | |
215 | def test_file_name_size(self): |
216 | ''' Test using a to large toc file ''' |
217 | @@ -961,7 +970,8 @@ |
218 | super(TestBootSteps, self).setUp() |
219 | self.funcs_calls = [] |
220 | self.mock_all_boards_funcs() |
221 | - linaro_image_tools.media_create.boards.BoardConfig.hwpack_format = '1.0' |
222 | + linaro_image_tools.media_create.boards.BoardConfig.hwpack_format = \ |
223 | + '1.0' |
224 | |
225 | def mock_all_boards_funcs(self): |
226 | """Mock functions of boards module with a call tracer.""" |
227 | @@ -1037,8 +1047,8 @@ |
228 | lambda: '1.0') |
229 | self.make_boot_files(boards.SMDKV310Config) |
230 | expected = [ |
231 | - 'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage', |
232 | - 'make_uInitrd', 'make_boot_script'] |
233 | + 'install_samsung_boot_loader', 'make_flashable_env', '_dd', |
234 | + 'make_uImage', 'make_uInitrd', 'make_boot_script'] |
235 | self.assertEqual(expected, self.funcs_calls) |
236 | |
237 | def test_origen_steps(self): |
238 | @@ -1058,8 +1068,8 @@ |
239 | lambda: '1.0') |
240 | self.make_boot_files(boards.OrigenConfig) |
241 | expected = [ |
242 | - 'install_samsung_boot_loader', 'make_flashable_env', '_dd', 'make_uImage', |
243 | - 'make_uInitrd', 'make_boot_script'] |
244 | + 'install_samsung_boot_loader', 'make_flashable_env', '_dd', |
245 | + 'make_uImage', 'make_uInitrd', 'make_boot_script'] |
246 | self.assertEqual(expected, self.funcs_calls) |
247 | |
248 | def test_ux500_steps(self): |
249 | @@ -2424,32 +2434,46 @@ |
250 | '98367,-,E\n98367,65536,L\n294975,131072,L\n' \ |
251 | '426047,,,-', '%s' % self.android_image_size) |
252 | |
253 | + def test_check_min_size_small(self): |
254 | + """Check that we get back the minimum size as expeceted.""" |
255 | + self.assertEqual(MIN_IMAGE_SIZE, _check_min_size(12345)) |
256 | + |
257 | + def test_check_min_size_big(self): |
258 | + """Check that we get back the same value we pass.""" |
259 | + self.assertEqual(MIN_IMAGE_SIZE * 3, _check_min_size(3145728)) |
260 | + |
261 | + def test_convert_size_wrong_suffix(self): |
262 | + self.assertRaises(ValueError, get_partition_size_in_bytes, "123456H") |
263 | + |
264 | def test_convert_size_no_suffix(self): |
265 | - self.assertEqual(524288, convert_size_to_bytes('524288')) |
266 | + self.assertEqual(2 ** 20, get_partition_size_in_bytes('123456')) |
267 | + |
268 | + def test_convert_size_one_mbyte(self): |
269 | + self.assertEqual(2 ** 20, get_partition_size_in_bytes('1M')) |
270 | |
271 | def test_convert_size_in_kbytes_to_bytes(self): |
272 | - self.assertEqual(512 * 1024, convert_size_to_bytes('512K')) |
273 | + self.assertEqual(2 * 2 ** 20, get_partition_size_in_bytes('2048K')) |
274 | |
275 | def test_convert_size_in_mbytes_to_bytes(self): |
276 | - self.assertEqual(100 * 1024 ** 2, convert_size_to_bytes('100M')) |
277 | + self.assertEqual(100 * 2 ** 20, get_partition_size_in_bytes('100M')) |
278 | |
279 | def test_convert_size_in_gbytes_to_bytes(self): |
280 | - self.assertEqual(12 * 1024 ** 3, convert_size_to_bytes('12G')) |
281 | + self.assertEqual(12 * 2 ** 30, get_partition_size_in_bytes('12G')) |
282 | |
283 | def test_convert_size_float_no_suffix(self): |
284 | - self.assertEqual(1539, convert_size_to_bytes('1539.49')) |
285 | - |
286 | - def test_convert_size_float_round_up(self): |
287 | - self.assertEqual(1540, convert_size_to_bytes('1539.50')) |
288 | + self.assertEqual(3 * 2 ** 20, get_partition_size_in_bytes('2348576.91')) |
289 | |
290 | def test_convert_size_float_in_kbytes_to_bytes(self): |
291 | - self.assertEqual(int(round(234.8 * 1024)), convert_size_to_bytes('234.8K')) |
292 | + self.assertEqual(3 * 2 ** 20, get_partition_size_in_bytes('2345.8K')) |
293 | + |
294 | + def test_convert_size_float_in_mbytes_to_bytes_double(self): |
295 | + self.assertEqual(2 * 2 ** 20, get_partition_size_in_bytes('1.0000001M')) |
296 | |
297 | def test_convert_size_float_in_mbytes_to_bytes(self): |
298 | - self.assertEqual(int(round(876.123 * 1024 ** 2)), convert_size_to_bytes('876.123M')) |
299 | + self.assertEqual(877 * 2 ** 20, get_partition_size_in_bytes('876.123M')) |
300 | |
301 | def test_convert_size_float_in_gbytes_to_bytes(self): |
302 | - self.assertEqual(int(round(1.9 * 1024 ** 3)), convert_size_to_bytes('1.9G')) |
303 | + self.assertEqual(1946 * 2 ** 20, get_partition_size_in_bytes('1.9G')) |
304 | |
305 | def test_calculate_partition_size_and_offset(self): |
306 | tmpfile = self._create_tmpfile() |
307 | @@ -3400,6 +3424,7 @@ |
308 | |
309 | # Ensure the list of cleanup functions gets cleared to make sure tests |
310 | # don't interfere with one another. |
311 | + |
312 | def clear_atexits(): |
313 | linaro_image_tools.media_create.chroot_utils.local_atexit = [] |
314 | self.addCleanup(clear_atexits) |
Hi Milo,
Thanks for working on this fix. Overall, it looks great. A few
suggestions are inline, though.
У уто, 05. 06 2012. у 13:53 +0000, Milo Casagrande пише:
> the proposed branch should fix the image size problem. size_to_ byte method to address the 1MiB multiple
>
> Thanks to Michael suggestion, and after a brief chat with him on IRC, I
> reworked the convert_
> image size problem: I kept only one exit point for the method; added
> the final check on the size just before returning the value; added the
> comparable value at the beginning of the file as a constant named
> ROUND_IMAGE_TO; imported the math.floor function since the final check
> relies on that.
With these changes, the name of the method might not make that much
sense anymore. It should be
round_ to_megs_ ensure_ larger_ than_one_ meg_and_ convert_ to_bytes :)
Perhaps use something that describes the nature of the method is now size_in_ bytes" or something
more appropriate (i.e. "get_partition_
similar).
> I added also a new method, _check_min_size, to ensure that we have at least 1MiB image size (this was the bit discussed on IRC).
It would be good to add a few minimal tests for it as well :)
> I reworked and adapted a little bit the tests too. I added a new test
> for the exception that was not tested before; added a new one for the
> default size and fixed the other tests in order to address the changes
> in the function. One test has been removed since it was not really
> relevant anymore.
They look great, thanks.
> разлике међу датотекама прилог (review-diff.txt) image_tools/ media_create/ partitions. py'
> === modified file 'linaro_
...
> @@ -45,6 +45,9 @@
> # Max number of attempts to sleep (total sleep time in seconds =
> # 1+2+...+MAX_TTS)
> MAX_TTS = 10
> +# Image size should be a multiple of 1MiB, expressed in bytes. This is also
> +# the minimum image size possible.
> +ROUND_IMAGE_TO = 2 ** 20
I'd rather if we express this as two separate values, even if one is
defined through the other. Eg.
ROUND_IMAGE_TO = 2 ** 20
MIN_IMAGE_SIZE = ROUND_IMAGE_TO
> @@ -481,11 +484,12 @@ size_to_ bytes(size) :
> def convert_
> """Convert a size string in Kbytes, Mbytes or Gbytes to bytes."""
It'd be nice to extend this to document the new features (min size,
rounding).
>... min_size( floor(real_ size / ROUND_IMAGE_TO) *
> + # Guarantee that is a multiple of 1MiB, defined in ROUND_IMAGE_TO
> + real_size = _check_
> + ROUND_IMAGE_TO)
Better way to do the rounding is always to add half of ROUND_IMAGE_TO
and then simply round() it. This will ensure that you've got enough
space at all times.
Eg.
round((real_size + ROUND_IMAGE_ TO/2)/ROUND_ IMAGE_TO) * ROUND_IMAGE_TO
will give you an image size which will be able to fit the requested
number of KBs or MBs (eg. asking for '1024.4K' will give you 2MB which
can really fit the requested number of kilobytes; it'd be even worse if
you ask for 1500K and get 1MB).
> return int(round( real_size) ) min_size( size):
>
>
> +def _check_
> + """Check that the image size is at least 1MiB (expressed in bytes)."""
Hard-coding a value here which is not really hard-coded doesn't make
much sense. ...