Bitmath Save

Python module for representing file sizes with different prefix notations

Project README

.. image:: https://api.travis-ci.org/tbielawa/bitmath.png :target: https://travis-ci.org/tbielawa/bitmath/ :align: right :height: 19 :width: 77

.. image:: https://coveralls.io/repos/tbielawa/bitmath/badge.png?branch=master :target: https://coveralls.io/r/tbielawa/bitmath?branch=master :align: right :height: 19 :width: 77

.. image:: https://readthedocs.org/projects/bitmath/badge/?version=latest :target: http://bitmath.rtfd.org/ :align: right :height: 19 :width: 77

bitmath

bitmath <http://bitmath.readthedocs.org/en/latest/>_ simplifies many facets of interacting with file sizes in various units. Originally focusing on file size unit conversion, functionality now includes:

  • Converting between SI and NIST prefix units (kB to GiB)
  • Converting between units of the same type (SI to SI, or NIST to NIST)
  • Automatic human-readable prefix selection (like in hurry.filesize <https://pypi.python.org/pypi/hurry.filesize>_)
  • Basic arithmetic operations (subtracting 42KiB from 50GiB)
  • Rich comparison operations (1024 Bytes == 1KiB)
  • bitwise operations (<<, >>, &, |, ^)
  • Reading a device's storage capacity (Linux/OS X support only)
  • argparse <https://docs.python.org/2/library/argparse.html>_ integration as a custom type
  • click <https://click.palletsprojects.com/>_ integration as a custom parameter type
  • progressbar <https://code.google.com/p/python-progressbar/>_ integration as a better file transfer speed widget
  • String parsing
  • Sorting

In addition to the conversion and math operations, bitmath provides human readable representations of values which are suitable for use in interactive shells as well as larger scripts and applications. The format produced for these representations is customizable via the functionality included in stdlibs string.format <https://docs.python.org/2/library/string.html>_.

In discussion we will refer to the NIST units primarily. I.e., instead of "megabyte" we will refer to "mebibyte". The former is 10^3 = 1,000,000 bytes, whereas the second is 2^20 = 1,048,576 bytes. When you see file sizes or transfer rates in your web browser, most of the time what you're really seeing are the base-2 sizes/rates.

Don't Forget! The source for bitmath is available on GitHub <https://github.com/tbielawa/bitmath>_.

And did we mention there's almost 200 unittests? Check them out for yourself <https://github.com/tbielawa/bitmath/tree/master/tests>_.

Running the tests should be as simple as calling the ci-all target in the Makefile: make ci-all. Please file a bug report if you run into issues.

Installation

The easiest way to install bitmath is via dnf (or yum) if you're on a Fedora/RHEL based distribution. bitmath is available in the main Fedora repositories, as well as the EPEL6 <http://download.fedoraproject.org/pub/epel/6/i386/repoview/epel-release.html>_ and EPEL7 <http://download.fedoraproject.org/pub/epel/7/x86_64/repoview/epel-release.html>_ repositories. There are now dual python2.x and python3.x releases available.

Python 2.x:

.. code-block:: bash

$ sudo dnf install python2-bitmath

Python 3.x:

.. code-block:: bash

$ sudo dnf install python3-bitmath

.. note::

Upgrading: If you have the old python-bitmath package installed presently, you could also run sudo dnf update python-bitmath instead

PyPi:

You could also install bitmath from PyPi <https://pypi.python.org/pypi/bitmath>_ if you like:

.. code-block:: bash

$ sudo pip install bitmath

.. note::

pip installs need pip >= 1.1. To workaround this, download bitmath <https://pypi.python.org/pypi/bitmath/#downloads>, from PyPi and then pip install bitmath-x.y.z.tar.gz. See issue #57 <https://github.com/tbielawa/bitmath/issues/57#issuecomment-227018168> for more information.

PPA:

Ubuntu Xenial, Wily, Vivid, Trusty, and Precise users can install bitmath from the launchpad PPA <https://launchpad.net/~tbielawa/+archive/ubuntu/bitmath>_:

.. code-block:: bash

$ sudo add-apt-repository ppa:tbielawa/bitmath $ sudo apt-get update $ sudo apt-get install python-bitmath

Source:

Or, if you want to install from source:

.. code-block:: bash

$ sudo python ./setup.py install

If you want the bitmath manpage installed as well:

.. code-block:: bash

$ sudo make install

Documentation

The main documentation lives at http://bitmath.readthedocs.org/en/latest/ <http://bitmath.readthedocs.org/en/latest/>_.

Topics include:

  • The bitmath Module

    • Utility Functions
    • Context Managers
    • Module Variables
    • argparse integration
    • click integration
    • progressbar integration
  • The bitmath command-line Tool

  • Classes

    • Initializing
    • Available Classes
    • Class Methods
  • Instances

    • Instance Attributes
    • Instance Methods
    • Instance Properties
    • The Formatting Mini-Language
  • Getting Started

    • Tables of Supported Operations
    • Basic Math
    • Unit Conversion
    • Rich Comparison
    • Sorting
  • Real Life Examples

    • Download Speeds
    • Calculating how many files fit on a device
    • Printing Human-Readable File Sizes in Python
    • Calculating Linux BDP and TCP Window Scaling
  • Contributing to bitmath

  • Appendices

    • Rules for Math
    • On Units
    • Who uses Bitmath
    • Related Projects
  • NEWS

  • Copyright

Examples

Arithmetic

.. code-block:: python

import bitmath log_size = bitmath.kB(137.4) log_zipped_size = bitmath.Byte(987) print "Compression saved %s space" % (log_size - log_zipped_size) Compression saved 136.413kB space thumb_drive = bitmath.GiB(12) song_size = bitmath.MiB(5) songs_per_drive = thumb_drive / song_size print songs_per_drive 2457.6

Convert Units

File size unit conversion:

.. code-block:: python

from bitmath import * dvd_size = GiB(4.7) print "DVD Size in MiB: %s" % dvd_size.to_MiB() DVD Size in MiB: 4812.8 MiB

Select a human-readable unit

.. code-block:: python

small_number = kB(100) ugly_number = small_number.to_TiB()

print ugly_number 9.09494701773e-08 TiB print ugly_number.best_prefix() 97.65625 KiB

Rich Comparison

.. code-block:: python

cd_size = MiB(700) cd_size > dvd_size False cd_size < dvd_size True MiB(1) == KiB(1024) True MiB(1) <= KiB(1024) True

Sorting

.. code-block:: python

sizes = [KiB(7337.0), KiB(1441.0), KiB(2126.0), KiB(2178.0), KiB(2326.0), KiB(4003.0), KiB(48.0), KiB(1770.0), KiB(7892.0), KiB(4190.0)]

print sorted(sizes) [KiB(48.0), KiB(1441.0), KiB(1770.0), KiB(2126.0), KiB(2178.0), KiB(2326.0), KiB(4003.0), KiB(4190.0), KiB(7337.0), KiB(7892.0)]

Custom Formatting

  • Use of the custom formatting system
  • All of the available instance properties

Example:

.. code-block:: python

longer_format = """Formatting attributes for %s ...: This instances prefix unit is {unit}, which is a {system} type unit ...: The unit value is {value} ...: This value can be truncated to just 1 digit of precision: {value:.1f} ...: In binary this looks like: {binary} ...: The prefix unit is derived from a base of {base} ...: Which is raised to the power {power} ...: There are {bytes} bytes in this instance ...: The instance is {bits} bits large ...: bytes/bits without trailing decimals: {bytes:.0f}/{bits:.0f}""" % str(ugly_number)

print ugly_number.format(longer_format) Formatting attributes for 5.96046447754 MiB This instances prefix unit is MiB, which is a NIST type unit The unit value is 5.96046447754 This value can be truncated to just 1 digit of precision: 6.0 In binary this looks like: 0b10111110101111000010000000 The prefix unit is derived from a base of 2 Which is raised to the power 20 There are 6250000.0 bytes in this instance The instance is 50000000.0 bits large bytes/bits without trailing decimals: 6250000/50000000

Utility Functions

bitmath.getsize()

.. code-block:: python

print bitmath.getsize('python-bitmath.spec') 3.7060546875 KiB

bitmath.parse_string()

Parse a string with standard units:

.. code-block:: python

import bitmath a_dvd = bitmath.parse_string("4.7 GiB") print type(a_dvd) <class 'bitmath.GiB'> print a_dvd 4.7 GiB

bitmath.parse_string_unsafe()

Parse a string with ambiguous units:

.. code-block:: python

import bitmath a_gig = bitmath.parse_string_unsafe("1gb") print type(a_gig) <class 'bitmath.GB'> a_gig == bitmath.GB(1) True bitmath.parse_string_unsafe('1gb') == bitmath.parse_string_unsafe('1g') True

bitmath.query_device_capacity()

.. code-block:: python

import bitmath with open('/dev/sda') as fp: ... root_disk = bitmath.query_device_capacity(fp) ... print root_disk.best_prefix() ... 238.474937439 GiB

bitmath.listdir()

.. code-block:: python

for i in bitmath.listdir('./tests/', followlinks=True, relpath=True, bestprefix=True): ... print i ... ('tests/test_file_size.py', KiB(9.2900390625)) ('tests/test_basic_math.py', KiB(7.1767578125)) ('tests/init.py', KiB(1.974609375)) ('tests/test_bitwise_operations.py', KiB(2.6376953125)) ('tests/test_context_manager.py', KiB(3.7744140625)) ('tests/test_representation.py', KiB(5.2568359375)) ('tests/test_properties.py', KiB(2.03125)) ('tests/test_instantiating.py', KiB(3.4580078125)) ('tests/test_future_math.py', KiB(2.2001953125)) ('tests/test_best_prefix_BASE.py', KiB(2.1044921875)) ('tests/test_rich_comparison.py', KiB(3.9423828125)) ('tests/test_best_prefix_NIST.py', KiB(5.431640625)) ('tests/test_unique_testcase_names.sh', Byte(311.0)) ('tests/.coverage', KiB(3.1708984375)) ('tests/test_best_prefix_SI.py', KiB(5.34375)) ('tests/test_to_built_in_conversion.py', KiB(1.798828125)) ('tests/test_to_Type_conversion.py', KiB(8.0185546875)) ('tests/test_sorting.py', KiB(4.2197265625)) ('tests/listdir_symlinks/10_byte_file_link', Byte(10.0)) ('tests/listdir_symlinks/depth1/depth2/10_byte_file', Byte(10.0)) ('tests/listdir_nosymlinks/depth1/depth2/10_byte_file', Byte(10.0)) ('tests/listdir_nosymlinks/depth1/depth2/1024_byte_file', KiB(1.0)) ('tests/file_sizes/kbytes.test', KiB(1.0)) ('tests/file_sizes/bytes.test', Byte(38.0)) ('tests/listdir/10_byte_file', Byte(10.0))

Formatting

.. code-block:: python

with bitmath.format(fmt_str="[{value:.3f}@{unit}]"): ... for i in bitmath.listdir('./tests/', followlinks=True, relpath=True, bestprefix=True): ... print i[1] ... [9.290@KiB] [7.177@KiB] [1.975@KiB] [2.638@KiB] [3.774@KiB] [5.257@KiB] [2.031@KiB] [3.458@KiB] [2.200@KiB] [2.104@KiB] [3.942@KiB] [5.432@KiB] [311.000@Byte] [3.171@KiB] [5.344@KiB] [1.799@KiB] [8.019@KiB] [4.220@KiB] [10.000@Byte] [10.000@Byte] [10.000@Byte] [1.000@KiB] [1.000@KiB] [38.000@Byte] [10.000@Byte]

argparse Integration

Example script using bitmath.integrations.bmargparse.BitmathType as an argparser argument type:

.. code-block:: python

import argparse from bitmath.integrations.bmargparse import BitmathType parser = argparse.ArgumentParser( description="Arg parser with a bitmath type argument") parser.add_argument('--block-size', type=BitmathType, required=True)

results = parser.parse_args() print "Parsed in: {PARSED}; Which looks like {TOKIB} as a Kibibit".format( PARSED=results.block_size, TOKIB=results.block_size.Kib)

If ran as a script the results would be similar to this:

.. code-block:: bash

$ python ./bmargparse.py --block-size 100MiB Parsed in: 100.0 MiB; Which looks like 819200.0 Kib as a Kibibit

click Integration

Example script using bitmath.integrations.bmclick.BitmathType as an click parameter type:

.. code-block:: python

import click from bitmath.integrations.bmclick import BitmathType

@click.command() @click.argument('size', type=BitmathType()) def best_prefix(size): click.echo(size.best_prefix())

If ran as a script the results should be similar to this:

.. code-block:: bash

$ python ./bestprefix.py "1024 KiB" 1.0 MiB

progressbar Integration

Use bitmath.integrations.bmprogressbar.BitmathFileTransferSpeed as a progressbar file transfer speed widget to monitor download speeds:

.. code-block:: python

import requests import progressbar import bitmath from bitmath.integrations.bmprogressbar import BitmathFileTransferSpeed

FETCH = 'https://www.kernel.org/pub/linux/kernel/v3.0/patch-3.16.gz' widgets = ['Bitmath Progress Bar Demo: ', ' ', progressbar.Bar(marker=progressbar.RotatingMarker()), ' ', BitmathFileTransferSpeed()]

r = requests.get(FETCH, stream=True) size = bitmath.Byte(int(r.headers['Content-Length'])) pbar = progressbar.ProgressBar(widgets=widgets, maxval=int(size), term_width=80).start() chunk_size = 2048 with open('/dev/null', 'wb') as fd: for chunk in r.iter_content(chunk_size): fd.write(chunk) if (pbar.currval + chunk_size) < pbar.maxval: pbar.update(pbar.currval + chunk_size) pbar.finish()

If ran as a script the results would be similar to this:

.. code-block:: bash

$ python ./smalldl.py Bitmath Progress Bar Demo: ||||||||||||||||||||||||||||||||||||||||| 1.58 MiB/s

Open Source Agenda is not affiliated with "Bitmath" Project. README Source: tbielawa/bitmath
Stars
90
Open Issues
19
Last Commit
1 week ago
Repository
License
MIT

Open Source Agenda Badge

Open Source Agenda Rating