gc3libs.quantity¶
Manipulation of quantities with units attached with automated conversion among compatible units.
For details and the discussion leading up to this, see: <https://github.com/uzh/gc3pie/issues/47>

class
gc3libs.quantity.
Duration
¶ Represent the duration of a time lapse.
Construction of a duration can be done by parsing a string specification; several formats are accepted:
A duration is an aggregate of days, hours, minutes and seconds:
>>> l3 = Duration('1day 4hours 9minutes 16seconds') >>> l3.amount(Duration.s) # convert to seconds 101356
Any of the terms can be omitted (in which case it defaults to zero):
>>> l4 = Duration('1day 4hours 16seconds') >>> l4 == l3  Duration('9 minutes') True
The unit names can be singular or plural, and any amount of space can be added between the time unit name and the associated amount:
>>> l5 = Duration('3 hour 42 minute') >>> l6 = Duration('3 hours 42 minutes') >>> l7 = Duration('3hours 42minutes') >>> l5 == l6 == l7 True
Unit names can also be abbreviated using just the leading letter:
>>> l8 = Duration('3h 42m') >>> l9 = Duration('3h42m') >>> l8 == l9 True
The abbreviated formats HH:MM:SS and DD:HH:MM:SS are also accepted:
>>> # 1 hour + 1 minute + 1 second >>> l1 = Duration('01:01:01') >>> l1 == Duration('3661 s') True >>> # 1 day, 2 hours, 3 minutes, 4 seconds >>> l2 = Duration('01:02:03:04') >>> l2.amount(Duration.s) 93784
However, the formats HH:MM and MM:SS are rejected as ambiguous:
>>> # is this hours:minutes or minutes:seconds ? >>> l0 = Duration('01:02') Traceback (most recent call last): ... ValueError: Duration '01:02' is ambiguous: use '1m 2s' ...
Finally, you can specify a duration like any other quantity, as an integral amount of a given time unit:
>>> l1 = Duration('1 day') >>> l2 = Duration('86400 s') >>> l1 == l2 True
A new quantity can also be defined as a multiple of an existing one:
>>> an_hour = Duration('1 hour') >>> a_day = 24 * an_hour >>> a_day.amount(Duration.h) 24
The quantities
Duration.hours
,Duration.minutes
andDuration.seconds
(and their singleletter abbreviationsh
,m
,s
) are predefined with their obvious meaning.Also modulelevel aliases
hours
,minutes
andseconds
(and the oneletter forms) are available:>>> a_day1 = 24*hours >>> a_day2 = 1440*minutes >>> a_day3 = 86400*seconds
This allows for yet another way of constructing duration objects, i.e., by passing the amount and the unit separately to the constructor:
>>> a_day4 = Duration(24, hours)
Two durations are equal if they indicate the exact same amount in seconds:
>>> a_day1 == a_day2 True >>> a_day1.amount(s) 86400 >>> a_day2.amount(s) 86400 >>> a_day == an_hour False >>> a_day.amount(minutes) 1440 >>> an_hour.amount(minutes) 60
Basic arithmetic is possible with durations:
>>> two_hours = an_hour + an_hour >>> two_hours == 2*an_hour True >>> an_hour == two_hours / 2 True >>> one_hour = two_hours  an_hour >>> one_hour.amount(seconds) 3600
It is also possible to add duration quantities defined with different units; the result is naturally expressed in the smaller unit of the two:
>>> one_hour_and_half = an_hour + 30*minutes >>> one_hour_and_half Duration(90, unit=m)
Note that the two unit class and numeric amount are accessible through the unit and
amount()
attributes:>>> one_hour_and_half.unit Duration(1, unit=m) >>> one_hour_and_half.amount() 90
The
amount()
method accepts an optional specification of an alternate unit to express the amount into:>>> one_hour_and_half.amount(Duration.hours) 1
An optional conv argument is available to specify a numerical domain for conversion, in case the default integer arithmetic is not precise enough:
>>> one_hour_and_half.amount(Duration.hours, conv=float) 1.5
The
to_str()
method allows representing a duration as a string, and provides choice of the output format and unit. The format string should contain exactly two%
specifiers: the first one is used to format the numerical amount, and the second one to format the measurement unit name.By default, the unit used originally for defining the quantity is used:
>>> '1 [hour]' == an_hour.to_str('%d [%s]') True
This can be overridden by specifying an optional second argument unit:
>>> '60 [m]' == an_hour.to_str('%d [%s]', unit=Duration.m) True
A third optional argument conv can set the numerical type to be used for conversion computations:
>>> '60.0 [m]' == an_hour.to_str('%.1f [%s]', unit=Duration.m, conv=float) True
The default numerical type is int, which in particular implies that you get a null amount if the requested unit is larger than the quantity:
>>> '0 [days]' == an_hour.to_str('%d [%s]', unit=Duration.days) True
Conversion to string uses the unit originally used for defining the quantity and the
%g%s
format:>>> str(an_hour) '1hour'

to_timedelta
()¶ Convert a duration into a Python datetime.timedelta object.
This is useful to operate on Python’s datetime.time and datetime.date objects, which can be added or subtracted to datetime.timedelta.

class
gc3libs.quantity.
Memory
¶ Represent an amount of RAM.
Construction of a memory quantity can be done by parsing a string specification (amount followed by unit):
>>> byte = Memory('1 B') >>> kilobyte = Memory('1 kB')
A new quantity can also be defined as a multiple of an existing one:
>>> a_thousand_kB = 1000*kilobyte
The base10 units (up to TB, Terabytes) and base2 (up to TiB, TiBiBytes) are available as attributes of the Memory class. This allows for a third way of constructing quantity objects, i.e., by passing the amount and the unit separately to the constructor:
>>> a_megabyte = Memory(1, Memory.MB) >>> a_mibibyte = Memory(1, Memory.MiB) >>> a_gigabyte = 1*Memory.GB >>> a_gibibyte = 1*Memory.GiB >>> two_terabytes = 2*Memory.TB >>> two_tibibytes = 2*Memory.TiB
Two memory quantities are equal if they indicate the exact same amount in bytes:
>>> kilobyte == 1000*byte True >>> a_megabyte == a_mibibyte False >>> a_megabyte < a_mibibyte True >>> a_megabyte > a_gigabyte False
Basic arithmetic is possible with memory quantities:
>>> two_bytes = byte + byte >>> two_bytes == 2*byte True >>> half_gigabyte = a_gigabyte / 2 >>> a_gigabyte == half_gigabyte * 2 True >>> a_megabyte == a_gigabyte / 1000 True
The ratio of two memory quantities is correctly computed as a pure (floatingpoint) number:
>>> a_gigabyte / a_megabyte 1000.0
It is also possible to add memory quantities defined with different units; the result is naturally expressed in the smaller unit of the two:
>>> one_gigabyte_and_half = 1*Memory.GB + 500*Memory.MB >>> one_gigabyte_and_half Memory(1500, unit=MB)
Note that the two unit class and numeric amount are accessible through the unit and
amount()
attributes:>>> one_gigabyte_and_half.unit Memory(1, unit=MB) >>> one_gigabyte_and_half.amount() 1500
The
amount()
method accepts an optional specification of an alternate unit to express the amount into:>>> one_gigabyte_and_half.amount(Memory.GB) 1
An optional conv argument is available to specify a numerical domain for conversion, in case the default integer arithmetic is not precise enough:
>>> one_gigabyte_and_half.amount(Memory.GB, conv=float) 1.5
The
to_str()
method allows representing a quantity as a string, and provides choice of the output format and unit. The format string should contain exactly two%
specifiers: the first one is used to format the numerical amount, and the second one to format the measurement unit name.By default, the unit used originally for defining the quantity is used:
>>> '1 [MB]' == a_megabyte.to_str('%d [%s]') True
This can be overridden by specifying an optional second argument unit:
>>> '1000 [kB]' == a_megabyte.to_str('%d [%s]', unit=Memory.kB) True
A third optional argument conv can set the numerical type to be used for conversion computations:
>>> '0.001GB' == a_megabyte.to_str('%g%s', unit=Memory.GB, conv=float) True
The default numerical type is int, which in particular implies that you get a null amount if the requested unit is larger than the quantity:
>>> '0GB' == a_megabyte.to_str('%g%s', unit=Memory.GB, conv=int) True
Conversion to string uses the unit originally used for defining the quantity and the
%g%s
format:>>> str(a_megabyte) '1MB'

class
gc3libs.quantity.
Quantity
(base_unit_name, **other_units)¶ Metaclass for creating quantity classes.
This factory creates subclasses of
_Quantity
and bootstraps the base unit.The name of the base unit is given as argument to the metaclass instance:
>>> @add_metaclass(Quantity('B')) ... class Memory1(object): ... pass ... >>> B = Memory1('1 B') >>> print (2*B) 2B
Optional keyword arguments create additional units; the argument key gives the unit name, and its value gives the ratio of the new unit to the base unit. For example:
>>> @add_metaclass(Quantity('B', kB=1000, MB=1000*1000)) ... class Memory2(object): ... pass ... >>> a_thousand_kB = Memory2('1000kB') >>> MB = Memory2('1 MB') >>> a_thousand_kB == MB True
Note that the units (base and additional) are also available as class attributes for easier referencing in Python code:
>>> a_thousand_kB == Memory2.MB True