bronx.datagrip.namelist

This module contains:

  • The LiteralParser class in charge of type conversion between FORTRAN literals, represented as strings, and corresponding python types. A detailed exemple is given in the class’s documentation.

  • The NamelistBlock class that contains a single namelist and allows to modify its content.

  • The NamelistSet class that holds a collection of namelist blocks (described by NamelistBlock objects).

  • The NamelistParser class that parse a string, a physical file or File-like object and look for namelist blocks. Upon success, it returns a NamelistSet object

Inital author: Joris Picot (2010-12-08 / CERFACS)

Module Attributes

bronx.datagrip.namelist.NO_SORTING = 0

Do not sort anything

bronx.datagrip.namelist.FIRST_ORDER_SORTING = 1

Sort all keys

bronx.datagrip.namelist.SECOND_ORDER_SORTING = 2

Sort only within indexes or attributes of the same key.

Functions

bronx.datagrip.namelist.namparse(obj, **kwargs)[source]

Raw parsing with an default anonymous fortran parser.

This function is a shortcut to the NamelistParser.parse() method.

Example:

To get a NamelistSet object from a string:

>>> nset = namparse('&NAM1 A=5.69, / &NAM2 B=1 /')
>>> print(nset.dumps())
 &NAM1
   A=5.69,
 /
 &NAM2
   B=1,
 /

Classes

class bronx.datagrip.namelist.LiteralParser(re_flags=18, re_integer='^[+-]?[0-9]+(?:_[A-Z0-9]+)?$', re_boz='^(?:B(?:\'|")[0-1]+(?:\'|")|O(?:\'|")[0-7]+(?:\'|")|Z(?:\'|")[ABCDEF0-9]+(?:\'|"))$', re_real='^[+-]?(?:(?:[0-9]+\\.(?:[0-9]+)?|\\.[0-9]+)(?:[DE][+-]?[0-9]+)?(?:_[A-Z0-9]+)?|[0-9]+[DE][+-]?[0-9]+(?:_[A-Z0-9]+)?)$', re_complex='^[(](?:[+-]?[0-9]+(?:_[A-Z0-9]+)?|[+-]?(?:(?:[0-9]+\\.(?:[0-9]+)?|\\.[0-9]+)(?:[DE][+-]?[0-9]+)?(?:_[A-Z0-9]+)?|[0-9]+[DE][+-]?[0-9]+(?:_[A-Z0-9]+)?)),(?:[+-]?[0-9]+(?:_[A-Z0-9]+)?|[+-]?(?:(?:[0-9]+\\.(?:[0-9]+)?|\\.[0-9]+)(?:[DE][+-]?[0-9]+)?(?:_[A-Z0-9]+)?|[0-9]+[DE][+-]?[0-9]+(?:_[A-Z0-9]+)?))[)]$', re_character='^(?:(?:[A-Z0-9]+_)?\'[^\']*\'|(?:[A-Z0-9]+_)?"[^"]*")$', re_logical='^(?:\\.TRUE\\.(?:_[A-Z0-9]+)?|\\.FALSE\\.(?:_[A-Z0-9]+)?|[TF])$', re_true='\\.T(?:RUE)?\\.|T', re_false='\\.F(?:ALSE)?\\.|F')[source]

Bases: object

Object in charge of parsing literal fortran expressions that could be found in a namelist.

For each literal type (integer, boz, real, complex, character and logical), there is a corresponding function parse_* and a global parser, simply called parse(), choose automatically the appropriate literal type. Here is the type conversion table:

  • integer -> int

  • boz -> int

  • real -> float or Decimal

  • complex -> complex

  • character -> string

  • logical -> bool

For python data, functions are provided for conversion into FORTRAN literals through a LiteralParser. Each literal type has its encode_* function and a global encoder, simply called encode(), chooses automatically the appropriate encoder; python integers will be converted into a FORTRAN integer, hence the only way to produce a FORTRAN boz is to use encode_boz directly.

Example:

A LiteralParser can easily be created:

>>> lp = LiteralParser()
>>> lp 
<bronx.datagrip.namelist.LiteralParser object at 0x...>

Basic fortran types could be checked agains a string value:

>>> lp.check_integer('2')
True
>>> lp.check_integer('2.')
False
>>> lp.check_integer('2x')
False
>>> lp.check_real('1.2E-6')
True
>>> lp.check_logical('.T.')
False
>>> lp.check_logical('.True.')
True
>>> lp.check_complex('(2.,0.)')
True
>>> lp.check_boz("B'11'")
True

After a successful type check, one can parse a specific fortran type according to the corresponding method of the LiteralParser:

>>> s = '1.2E-6'
>>> lp.check_real(s)
True
>>> x = lp.parse_real(s)
>>> print(x)
0.0000012

It could be more convenient to use the generic parse() method:

>>> x = lp.parse('.true.')
>>> print(x)
True
>>> type(x).__name__
'bool'
>>> x = lp.parse('2.')
>>> print(x)
2
>>> type(x)
<class 'decimal.Decimal'>
>>> x = lp.parse('Z"1F"')
>>> print(x)
31
>>> type(x).__name__
'int'

The reverse operation could be achieved through a specific encodingfunction:

>>> x = 2
>>> print(lp.encode_real(x))
2.
>>> print(lp.encode_integer(x))
2
>>> print(lp.encode_complex(x))
(2.,0.)
>>> print(lp.encode_logical(x))
.TRUE.

It is possible to rely on the internal python type to decide which is the appropriate encoding through the generic encode() method:

>>> x = 2
>>> print(lp.encode(x))
2
>>> z = 1 - 2j
>>> print(lp.encode(z))
(1.,-2.)
>>> x = 2.
>>> print(lp.encode(x))
2.
check_boz(string)[source]

Returns True if string could be a binary, octal or hexa number.

check_character(string)[source]

Returns True if string could be a character string.

check_complex(string)[source]

Returns True if string could be a complex number.

check_integer(string)[source]

Returns True if string could be an integer.

check_logical(string)[source]

Returns True if string could be a logical value.

check_real(string)[source]

Returns True if string could be a real number.

encode(value)[source]

Returns the string form of the specified value according to its type.

static encode_boz(value)[source]

Returns the string form of the BOZ value.

static encode_character(value)[source]

Returns the string form of the character string value.

encode_complex(value, fmt='{0:.15G}')[source]

Returns the string form of the complex value.

static encode_integer(value)[source]

Returns the string form of the integer value.

static encode_logical(value)[source]

Returns the string form of the logical value.

static encode_real(value, fmt='{0:.15G}')[source]

Returns the string form of the real value.

parse(string)[source]

Parse a FORTRAN literal and returns the corresponding python type. Resolution order is: integer, boz, real, complex, character and logical.

parse_boz(string)[source]

If the argument looks like a FORTRAN boz, returns the matching python integer.

parse_character(string)[source]

If the argument looks like a FORTRAN character, returns the matching python string.

parse_complex(string)[source]

If the argument looks like a FORTRAN complex, returns the matching python complex.

parse_integer(string)[source]

If the argument looks like a FORTRAN integer, returns the matching python integer.

parse_logical(string)[source]

If the argument looks like a FORTRAN logical, returns the matching python boolean.

parse_real(string)[source]

If the argument looks like a FORTRAN real, returns the matching python float.

class bronx.datagrip.namelist.NamelistBlock(name='UNKNOWN')[source]

Bases: MutableMapping

This class represents a FORTRAN namelist block.

This class defines all the methods of a usual Python’s dictionary. The keys being the namelist’s variable names.

Macros are special values prefixed and suffixed with __ (e.g. __MYMACRO__) that can be substituted at any time using the addmacro() method. NB: They need to be declared using the addmacro() method prior to being used.

Example:

To create an empty NamelistBlock object, just provide the name:

>>> nb1 = NamelistBlock('MYNAM')
>>> nb1 
<bronx.datagrip.namelist.NamelistBlock object at 0x... | name=MYNAM len=0>

From now and on, it’s possible to play around with the namelist block:

>>> nb1['A'] = 1
>>> nb1.B = 2.
>>> nb1.text = 'MyBad'
>>> print(nb1)
 &MYNAM
   A=1,
   B=2.,
   TEXT='MyBad',
 /

>>> for k in nb1:
...     print('Entry {:s}: Value is {!s}'.format(k, nb1[k]))
...
Entry A: Value is 1
Entry B: Value is 2.0
Entry TEXT: Value is MyBad
>>> for k, v in nb1.items():
...     print('Entry {:s}: Value is {!s}'.format(k, v))  
...
Entry A: Value is [1]
Entry B: Value is [2.0]
Entry TEXT: Value is [...'MyBad']
>>> del nb1.B

An example of namelist blocks merge:

>>> nb2 = NamelistBlock('MYNAM')
>>> nb2.A = 3
>>> nb2.todelete('text')
>>> nb1.merge(nb2)
>>> print(nb1)
 &MYNAM
   A=3,
 /

Macros can be defined in a namelist block using the __MACRONAME__ syntax. They can be substituted at anytime:

>>> nb3 = NamelistBlock('MYNAM')
>>> nb3.addmacro('MACRO_A')
>>> nb3.A = '__MACRO_A__'
>>> print(nb3)
 &MYNAM
   A=__MACRO_A__,
 /

>>> nb3.addmacro('MACRO_A', 3)
>>> print(nb3)
 &MYNAM
   A=3,
 /
add_declaredmacro(macro, value=None)[source]

Add a new old-style declared macro to this definition block, and/or set a value.

addmacro(macro, value=None)[source]

Add a new macro to this definition block, and/or set a value.

clear(rmkeys=None)[source]

Remove specified keys (rmkeys) or completely clear the namelist block.

declaredmacros()[source]

Returns the list of old-style declared macros in this block.

delvar(varname)[source]

Delete the specified varname variable from this block.

dumps(literal=None, sorting=0)[source]

Returns a string of the namelist block that will be readable by fortran parsers.

Parameters:

sorting – Sorting option. One of NO_SORTING, FIRST_ORDER_SORTING (sort based on variable names) or SECOND_ORDER_SORTING (sort only within indexes or attributes of the same variable: usefull with arrays).

dumps_values(key, literal=None)[source]

Nice encoded values (incl. list of).

get(*args)[source]

Proxy to the dictionary get mechanism on the internal pool of variables.

getvar(varname)[source]

Get varname variable’s value (this is not case sensitive).

has_key(item)[source]

Returns whether item value is defined as a namelist variable or not.

items()[source]

Iterate over the namelist block’s variables.

iteritems()[source]

Iterate over the namelist block’s variables.

iterkeys()

Iterate through variable names.

keys()[source]

Returns the ordered variable names of the namelist block.

macros()[source]

Returns the list of the macros used in this block.

merge(delta)[source]

Merge the delta provided to the current block.

Parameters:

delta (NamelistBlock) – The namelist block to merge in.

property name

The namelist block name.

nice(item, literal=None)[source]

Nice encoded value of the item, possibly substituted with macros.

pool()[source]

Returns the reference of the internal pool of variables.

possible_macroname(item)[source]

Find whether item is a macro or not.

rmkeys()[source]

Returns a set of key to be deleted in a merge or dump.

set_name(name)[source]

Change the namelist block name.

setvar(varname, value, index=None)[source]

Insert or change a namelist block variable.

Parameters:
  • varname (str) – the variable name

  • value – the variable value

  • index (int) – if given, set the key to the given index in block.

todelete(varname)[source]

Register a key to be deleted.

update(dico)[source]

Updates the pool of keys, and keeps as much as possible the initial order.

values()[source]

Returns the values of the internal pool of variables.

class bronx.datagrip.namelist.NamelistParser(literal=<bronx.datagrip.namelist.LiteralParser object>, macros=None, re_flags=None, re_clean='^(\\s+|![^\\n]*\\n)', re_block='&.*/', re_endblock='^/(end)?', re_bname='[A-Z][A-Z0-9_]*', re_entry='[A-Z][ A-Z0-9_, \\%\\(\\):]*(?=\\s*=)', re_macro='(?P<STRB>[\'"])?\\$?(?P<NAME>[A-Z_][A-Z0-9_]*)(?(STRB)[\'"])', re_freemacro='(?P<STRB>[\'"])?[_]{2}(?P<NAME>[A-Z][A-Z0-9_]*)[_]{2}(?(STRB)[\'"])', re_endol='(?=\\s*(, |/|\\n))', re_comma='\\s*, ')[source]

Bases: object

Parser that creates a NamelistSet object from a namelist file or a string.

Macros (i.e. __SOMETHING__ values) are properly dealt with.

Example:

To get a NamelistSet object from a string:

>>> np = NamelistParser()
>>> nset = np.parse('&NAM1 A=5.69, / &NAM2 B=__MYMACRO__ /')
>>> print(nset.dumps())
 &NAM1
   A=5.69,
 /
 &NAM2
   B=__MYMACRO__,
 /

>>> nset.dumps_needs_update
False
>>> nset.setmacro('MYMACRO', 'toto')
>>> nset.dumps_needs_update
True
>>> print(nset.dumps())
 &NAM1
   A=5.69,
 /
 &NAM2
   B='toto',
 /
addmacro(macro)[source]

Add an extra declared macro name (without associated value).

property literal

The literal parser used to process variable values.

parse(obj)[source]

Parse a string or a file.

Returns a NamelistSet object.

class bronx.datagrip.namelist.NamelistSet(blocks_set=None)[source]

Bases: MutableMapping

A set of namelist blocks (see NamelistBlock).

This class defines all the methods of a usual Python’s dictionary. The keys being the namelist names and the values the corresponding namelist blocks.

Example:

To create a NamelistSet object populated with a pre-existing namelist block:

>>> nb = NamelistBlock('MYNAM')
>>> nb.A = 3
>>> nset = NamelistSet([nb, ])

It’s possible to add a new block and customise it:

>>> newblock = nset.newblock('TESTNAM')
>>> newblock.A = 1
>>> nset['TESTNAM'].B = 5.
>>> print(nset.dumps())
 &MYNAM
   A=3,
 /
 &TESTNAM
   A=1,
   B=5.,
 /

For instance, this block can be renamed and the previous one deleted:

>>> nset.mvblock('TESTNAM', 'MYNAM2')
>>> del nset['MYNAM']
>>> print(nset.dumps())
 &MYNAM2
   A=1,
   B=5.,
 /

The merge() method allows to merge two namelist sets:

>>> nset2 = NamelistSet([nb, ])
>>> newblock = nset2.newblock('MYNAM2')
>>> newblock.A = 999
>>> print(nset2.dumps())
 &MYNAM
   A=3,
 /
 &MYNAM2
   A=999,
 /

>>> nset.merge(nset2)
>>> print(nset.dumps())
 &MYNAM
   A=3,
 /
 &MYNAM2
   A=999,
   B=5.,
 /
Parameters:

blocks_set (list[NamelistBlock]) – A list of NamelistBlock objects (if missing, an empty list is assumed).

add(namblock)[source]

Add a namelist block object to the present namelist set.

Parameters:

namblock (NamelistBlock) – The namelist block to add.

as_dict(deepcopy=False)[source]

Return the actual namelist set as a dictionary.

as_list(deepcopy=False)[source]

Return the actual namelist set as a list.

dumps(sorting=0, block_sorting=True)[source]

Join the fortran’s strings dumped by each namelist block.

Parameters:
  • sorting – Sorting option. One of NO_SORTING, FIRST_ORDER_SORTING (sort based on variable names) or SECOND_ORDER_SORTING (sort only within indexes or attributes of the same variable: usefull with arrays).

  • block_sorting (bool) – if True, namelist blocks are ordered based on their name.

merge(delta, rmkeys=None, rmblocks=None, clblocks=None)[source]

Merge of the current namelist set with the set of namelist blocks provided.

mvblock(sourcename, destname)[source]

Rename a namelist block.

newblock(name=None)[source]

Construct a new block.

Parameters:

name (str) – the name of the new block. If omitted a block new block name will be generated (something like AUTOBLOCKnnn).

setmacro(item, value)[source]

Set macro value for further substitution (in all of the namelist blocks).