Giter VIP home page Giter VIP logo

nibble's Introduction

nibble

image

image

image

image

image

image

Speed, distance and time calculations around quantities of digital information.

Installation

$ pip install nibble

Demo

The following snippet provides an example of Nibble's ability to format and manipulate quantities of information, durations and speeds. For explanations of what's going on, see each class's section below.

from nibble import Information, Duration, Speed


information = Information(123, Information.GIBIBITS)
print('{0}'.format(information))               # '15.38 GiB'
print('{0:GB}'.format(information))            # '16.51GB'
print('{0: GB}'.format(information))           # '16.51 GB'
print('{0:,.2f| Mb}'.format(information))      # '132,070.24 Mb'

speed = Speed(Information(20, Information.MEGABITS), Duration.SECOND)
print('{0}'.format(speed))                     # '2.38 MiB/s'
print('{0:Mb}'.format(speed))                  # '20Mb/s'
print('{0: Gb/w}'.format(speed))               # '12,096 Gb/w'
print(Speed.TEN_GIGABIT / 10
      == Speed.HUNDRED_MEGABIT * 10
      == Speed.GIGABIT)                        # True
print('{0: dB/y}'.format(Speed.TEN_GIGABIT))   # '39.42 PB/y'
print('{0:.2f| bB/mo}'.format(Speed.GIGABIT))  # '298.77 TiB/mo'

Information

Nibble represents all quantities of information in terms of the smallest unit: bits. The syntax for formatting Information objects is:

[number format|][ ][unit symbol or category]
  • [number format|] is a valid floating point format specification followed by a pipe symbol so it can be distinguished from the rest of the format string
  • [ ] is an optional blank space separating the number from the unit symbol
  • [unit symbol or category] is either a single unit to represent the information in, e.g. Gb, or a category of units (see below), in which case Nibble will choose the most appropriate one

The default format specification is '.2f| bB'.

Units

At the lower end, Nibble supports bits, nibbles (of course) and bytes. Larger units fall into one of four categories. They are either binary or decimal (they can be expressed as 2n or 10n respectively), or bit or byte based:

Base Suffix Unit Example Information
Binary Bit -ib Kibibit (Kib) 220 bits
Binary Byte -iB Kibibyte (KiB) 220 bytes
Decimal Bit -b Kilobit (Kb) 106 bits
Decimal Byte -B Kilobyte (kB) 106 bytes

It is a common misconception that there are 1024 bytes in a kilobyte. If you'd like to work in multiples of 1024, use the -ibibyte units instead.

Nibble supports all of the above units with prefixes from Ki- to Yi-. For the full list, consult the _SYMBOLS dict in the Information class.

Categories

In addition to representing a quantity of information in a specific unit, nibble can determine the most appropriate one to use from a range. These ranges are called categories, and correspond to rows in the table above.

Category Base Suffix Smallest Unit Largest Unit
bb Binary Bit Bit Yobibit
bB Binary Byte Byte Yobibyte
db Decimal Bit Bit Yottabit
dB Decimal Byte Byte Yottabyte

The first letter of the category refers to the base, b and d for binary and decimal respectively. The second letter refers to the suffix, b and B for bit and byte respectively. Therefore, to format an amount of information in the bits, kilobits, megabits, gigabits etc., use '{0:db}'.format(...).

The only remaining ambiguity is how Nibble determines the best unit to use in each category. It simply chooses the largest unit where the amount of information to represent is >=1 of that unit, falling back on the smallest unit where that's not possible (e.g. representing less than 1 byte in bB or dB). For example, 1 GiB would be shown in GiB. One bit less would be shown in MiB.

Shortcuts

The following class constants are provided for common quantities of information:

Constant Equivalent
ZERO 0 b

Duration

This class is Nibble's equivalent of datetime.timedelta(). Why re-implement? Because that only goes down to microsecond precision, and lacks months and years. To make working with this class as easy as possible, a from_timedelta() method and timedelta property are provided - however bear in mind these will lose precision by virtue of working at a coarser level of granularity.

The syntax for formatting Duration objects is:

[number format|][ ][unit symbol]
  • [number format|] is a valid floating point format specification followed by a pipe symbol so it can be distinguished from the rest of the format string
  • [ ] is an optional blank space separating the number from the unit symbol
  • [unit symbol] is a time unit to represent the duration in (see below)

By default, durations will be shown in the largest unit where the time period is greater or equal to 1 of that unit. For example, 1 minute would be shown as 1 m. One nanosecond less would be shown as 60.00s.

Units

Symbol Meaning
ns Nanoseconds
us Microseconds
ms Milliseconds
s Seconds
m Minutes
h Hours
d Days
w Weeks
mo Months
y Years

Shortcuts

The following class constants are provided for common durations:

Constant Equivalent
ZERO 0 ns
SECOND 1 s

Speed

Speeds can be created using the standard constructor, or by calling .in_duration()` with aDurationon anInformationobject. The syntax for formattingSpeedobjects is: :: [number format|][ ][unit symbol or category][/time unit] -[number format bB/s'. Shortcuts ~~~~~~~~~ The following class constants are provided for common speeds: +---------------------+--------------+ | Constant | Equivalent | +=====================+==============+ |ZERO| 0 b/s | +---------------------+--------------+ |TEN_MEGABIT| 10 Mb/s | +---------------------+--------------+ |HUNDRED_MEGABIT| 100 Mb/s | +---------------------+--------------+ |GIGABIT| 1 Gb/s | +---------------------+--------------+ |TEN_GIGABIT| 10 Gb/s | +---------------------+--------------+ |FORTY_GIGABIT| 40 Gb/s | +---------------------+--------------+ |HUNDRED_GIGABIT| 100 Gb/s | +---------------------+--------------+ |E0/DS0| 64 Kb/s | +---------------------+--------------+ |E1| 2.048 Mb/s | +---------------------+--------------+ |E2| 8.448 Mb/s | +---------------------+--------------+ |E3| 34.368 Mb/s | +---------------------+--------------+ |E4| 139.264 Mb/s | +---------------------+--------------+ |E5| 565.148 Mb/s | +---------------------+--------------+ |T1/DS1| 1.544 Mb/s | +---------------------+--------------+ |T1C/DS1C| 3.152 Mb/s | +---------------------+--------------+ |T2/DS2| 6.312 Mb/s | +---------------------+--------------+ |T3/DS3| 44.736 Mb/s | +---------------------+--------------+ |T4/DS4| 274.176 Mb/s | +---------------------+--------------+ |T5/DS5`` | 400.352 Mb/s | +---------------------+--------------+

Issues

A library like this is useless if not correct, which is why I've invested so much time in test coverage. If you find an incorrect result, please create a new issue with the input as well as expected and actual output.

nibble's People

Contributors

gebn avatar

Stargazers

 avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

nibble's Issues

Values that are 0.00 to 2 decimal places are rounded to 0

This is an issue for things like representing a second in terms of years (0y instead of 0.000000032y). Rather than display floats to 2dp, we want to display 2 non-zero dp. If a float is integral, we display it as an integer, otherwise we show as many decimal places as necessary to get to a non-zero decimal place, then display 2 of them.

Sphinx Documentation

This project is crying out for a reference of properties and methods available on each of the three primary types, and a healthy set of example snippets. The README should be an introduction, not the documentation.

Conversion of `Information`s between units

You seem to have managed to avoid providing a way to get an Information object in a particular unit. Intuitively, you expect to be able to do information.bytes or information.gigabytes. Consider implementing __getattr__(). You could implement it as a method that takes a unit constant, but which of these would you prefer to see?

  • int(math.ceil(size.bits / 8e+9))
  • size.to(Information.GIGABYTES)
  • size.gigabytes

Go with the last one. Should you be returning floats or decimals? Bits should always return int.

Support piping from stdin, similar to bc

Use case: stream of data quantities, one per line, e.g.

6.9Gi
13Gi
64Gi
256Mi
12Gi
40Gi
13.9375Gi
12Gi
40Gi
64Gi
.5625Gi

Want to be able to | paste -sd+ | nibble to add up.

Large inputs

Both Google and Wolfram Alpha struggle to evaluate really long expressions (partly due to URL length limits). Ensure Nibble works with such inputs, and parsing/evaluation is not prohibitively slow. E.g.

57.1GB + 59.8GB + 59.3GB + 63.6GB + 61.1GB + 59GB + 58.2GB + 59.1GB + 59.2GB + 58.1GB + 54.7GB + 58.5GB + 50.6GB + 54.6GB + 57.7GB + 56.4GB + 59.6GB + 57.5GB + 52.8GB + 58.9GB + 48.4GB + 55.3GB + 51.5GB + 52.2GB + 49.4GB + 43.7GB + 47GB + 53.6GB + 52.5GB + 49.1GB + 51.2GB + 52.8GB + 42.1GB + 40.3GB + 38.9GB + 31.6MB + 29.2MB + 15.3MB + 18.2MB + 14.9MB + 19.8MB + 12.4MB + 11.4MB + 18.5MB + 10.9MB + 12.7MB + 9.1MB + 9.6MB + 14.9MB + 10.7MB + 13.6MB + 6.9MB + 1.8MB + 11.7MB + 11.9MB + 21.3MB + 9.3MB + 4MB + 8.9MB + 10.7MB + 7.2MB + 11.8MB + 10.2MB + 10.2MB + 5.5MB + 7.7MB + 7MB + 7.6MB + 6.9MB + 7.6MB + 6.1MB + 5.7MB + 2.7MB + 2.6MB + 2.9MB + 1.9MB + 7.5MB + 3.4MB + 2MB + 2.2MB + 1.4MB + 2.2MB + 1.5MB + 1.7MB + 1.5MB + 1.8MB + 3MB + 1.4MB + 1.8MB + 1.4MB + 1.3MB + 1.5MB + 1.3MB + 6.8MB + 1.2MB + 1.2MB + 972.6KB + 1.9MB + 3MB + 984.8KB + 964.4KB + 975.1KB + 2.3MB + 961.2KB + 947.2KB + 1.2MB + 2.4MB + 1MB + 1MB + 2.2MB + 853KB + 806.6KB + 3.3MB + 1.5MB + 1MB + 1.8MB + 3.1MB + 1MB + 1.7MB + 1.8MB + 2.3MB + 7MB + 1.4MB + 4.5MB + 3.4MB + 1.8MB + 2.3MB + 683.4KB + 698KB + 698KB + 656.7KB + 717.3KB + 2.5MB + 1.5MB + 653.7KB + 1.3MB + 671.6KB + 1.1MB + 1.4MB + 672KB + 1.1MB + 997.6KB + 628.3KB + 608.6KB + 592.8KB + 748.6KB + 2.4MB + 1.5MB + 1.2MB + 643.6KB + 539KB + 1.2MB + 3MB + 1.5MB + 1MB + 568.7KB + 542.6KB + 543.7KB + 557.3KB + 565.2KB + 1.2MB + 550.3KB + 553.4KB + 521.5KB + 533.5KB + 532.9KB + 951.5KB + 1.6MB + 842.5KB + 1.4MB + 760.1KB + 1.2MB + 524.5KB + 492.5KB + 1.6MB + 626.5KB + 1.6MB + 1.6MB + 497.3KB + 490KB + 478.7KB + 452.6KB + 3.8MB + 780.7KB + 447.1KB + 471KB + 2.1MB + 446.1KB + 445KB + 851.5KB + 1.7MB + 1.2MB + 395.3KB + 419.3KB + 461.1KB + 992.9KB + 1.1MB + 1.1MB + 398.1KB + 361.7KB + 640.6KB + 953.6KB + 1.1MB + 326.4KB + 498.9KB + 284.6KB + 578.5KB + 577.9KB + 800.9KB + 1.5MB + 552.9KB + 110.6KB + 290.3KB + 314.9KB + 481KB + 299.1KB + 315.5KB + 311.8KB + 661.7KB + 170.9KB + 1.2MB + 260.5KB + 244.2KB + 1.3MB + 485.7KB + 245.7KB + 636.5KB + 172.7KB + 264.1KB + 238.1KB + 264.1KB + 756.2KB + 239.4KB + 219.8KB + 238.1KB + 500.6KB + 193.9KB + 691KB + 807.5KB + 89.8KB + 567.5KB + 313.8KB + 329.7KB + 156.9KB + 802.8KB + 177.7KB + 211.5KB + 211.5KB + 457.4KB + 193.6KB + 211.9KB + 211.9KB + 398.4KB + 172.2KB + 246.3KB + 510.9KB + 333.9KB + 333.8KB + 186.8KB + 186.1KB + 197.3KB + 181.8KB + 213KB + 196.1KB + 187.6KB + 186.8KB + 178.1KB + 176.1KB + 185.9KB + 121.8KB + 117.4KB + 751.9KB + 152.7KB + 225.8KB + 496.1KB + 164.4KB + 148.5KB + 395.4KB + 143.2KB + 159.7KB + 159KB + 159.7KB + 79.8KB + 176.6KB + 102.5KB + 138.2KB + 81.1KB + 452.8KB + 302.1KB + 119.4KB + 305.8KB + 607.4KB + 147.1KB + 144KB + 115.4KB + 115.5KB + 111.5KB + 116KB + 133KB + 144KB + 126.9KB + 135KB + 117.9KB + 134.8KB + 122.1KB + 134.9KB + 117.1KB + 73.1KB + 125KB + 134.8KB + 57KB + 195.1KB + 272.3KB + 143.4KB + 80.7KB + 273.8KB + 288.5KB + 108.1KB + 88.4KB + 107.1KB + 107.1KB + 107.1KB + 107.1KB + 107.1KB + 108.7KB + 145.4KB + 108.8KB + 771.1KB + 108.1KB + 225.1KB + 82.1KB + 100.1KB + 100.1KB + 107.4KB + 107.4KB + 84.8KB + 215.8KB + 132.8KB + 160.3KB + 242.9KB + 64.9KB + 42.4KB + 81.4KB + 81.7KB + 82.7KB + 82.6KB + 95.6KB + 82.8KB + 85.9KB + 82.5KB + 64.5KB + 64.7KB + 82.8KB + 74KB + 259KB + 49.6KB + 82.5KB + 82.6KB + 19.5KB + 39KB + 57.8KB + 227.7KB + 47.7KB + 57.9KB + 57.8KB + 63.8KB + 57.8KB + 64.4KB + 52.8KB + 34.2KB + 56.4KB + 55.8KB + 25.2KB + 57.5KB + 56.5KB + 313.2KB + 56.4KB + 56.4KB + 56.4KB + 136.1KB + 12KB + 22KB + 68.1KB + 22KB + 14.4KB + 22KB + 31.1KB + 22KB + 30.6KB + 31.1KB + 31.1KB + 31.1KB + 30.5KB + 19.3KB + 70.6KB + 31.1KB + 19.1KB + 12.4KB + 29.4KB + 29.4KB + 30.6KB + 30.5KB + 30.5KB + 30.6KB + 207.1KB + 22KB + 30.4KB + 30.5KB + 30.3KB + 30.3KB + 69.9KB + 70.6KB + 53KB + 69.9KB + 69.9KB + 4.5KB

Do not regenerate the LALR table each execution

You can generate it once at build time, and include it in the release so clients do not have to build their own at all. Take a look at the optimize and picklefile options on yacc.yacc(). lex.lex() has similar features available. Pre-generate preferably, or cache.

Overflow tests

Python 2 does not have arbitrary length ints. People will want to know what happens should the sum of two large quantities overflow.

Sample expressions

Tracking issue for queries to handle:

  • 5 petabytes / 730 hours in Gb/s

Remember the unit category when an `Information` object is created

This behaviour is unintuitive:

print(Information(123, Information.GIBIBITS))  # '15.38 GiB'

It would be less so if the Information class remembered the unit category with which it was created, and defaulted to this category (only falling back on bB) when formatting:

print(Information(123, Information.GIBIBITS))  # '123 Gib'
print(Information(15000, Information.GIGABITS))  # '15 Tb'
print(Information(47508345203, Information.BITS))  # '5.53 GiB'

Log list of tokens when debugging

This is not currently exposed in the debug output:

$ nibble -vv 400GiB at .85Mb/s
DEBUG Namespace(expression=[u'400GiB', u'at', u'.85Mb/s'], verbosity=2)
Generating LALR tables
DEBUG information = number 400.0, information unit GiB
DEBUG duration = 1 of duration unit s
DEBUG speed unit = information unit Mb per duration 1 second
DEBUG speed = number 0.85, speed unit (u'Mb', <Duration(1000000000)>)
DEBUG duration = information 400 GiB at speed 103.76 KiB/s
DEBUG expression = duration 1 month 2 weeks 2 days 8 hours 52 minutes 2 seconds 160 milliseconds 941 microseconds 177 nanoseconds
1 month 2 weeks 2 days 8 hours 52 minutes 2 seconds 160 milliseconds 941 microseconds 177 nanoseconds
DEBUG Returning exit status 0

Use sane rounding

Rarely do you care about more than 1 decimal place. Wolfram Alpha gets this right.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.