Using adapya-base

Read/Write Buffers with Abuf

Implemented in adapya.base.defs

Read/write buffers are not directly available in Python only indirectly with I/O routines.

The adapya.base.defs.Abuf class implements read/write buffers. They are used for the Adabas control block and other buffers.:

>>> from adapya.base.defs import Abuf # Access Abuf class
>>> a=Abuf(8) # Allocate buffer of 8 bytes
>>> a.value=b'Bell' # store 'Bell' into buffer a
>>> a.raw # show contents of a
b'bell\x00\x00\x00\x00'

>>> a[0:8]   # same in slice notation
b'bell\x00\x00\x00\x00'

>>> a[0:4]  # extract part of buffer
b'bell'

>>> a[0]=b'W' # modify buffer at offset 0
b'Well\x00\x00\x00\x00'

>>> a.read(5) # read() 5 bytes of the buffer
b'Well\x00'

>>> a.read(5) # read() next bytes (only 3 left)
b'\x00\x00\x00'

>>> a.tell() # inquire position
8

>>> a.seek(0) # position to start of buffer
>>> a.write('Sun') # write first 3 characters
b'Sunl\x00\x00\x00\x00'

Working with Structures with Datamap

Implemented in adapya.base.datamap

The datamap module defines the Datamap class that allows to define structure within a byte buffer. This is similar to a DSECT or C struct. This is being used for setting up the Adabas control block and the other buffers like record buffer or value buffer.

Datamap Data Types

The following data types require a name and a length:

String

alpha numeric string

Unicode

Unicode string (in UTF-16, each character takes 2 bytes)

Bytes

similar to String but hexadecimal contents

Packed

integer mapped to P format

Unpacked

integer mapped to U format

The other data types take only the name:

Char

1 byte character

Int1/2/4/8

signed integer of 1, 2, 4 or 8 bytes

Uint1/2/4/8

unsigned integer of 1, 2, 4 or 8 bytes

Float

single precision float (IEEE format)

Double

double precision float (IEEE format)

Basic Usage example

>>> from adapya.base.defs import Abuf
>>> from adapya.base.datamap import Datamap, String, Int2
>>> dm=Datamap('mymap',
        String('name',6),  # List of field definitions. Its order
        Int2('age')) # defines the position in the buffer
>>> dm.getsize() # query the size of the datamap dm
8
>>> a=Abuf(8)
>>> dm.buffer=a  # use buffer a with datamap dm
>>> dm.name='Bell' # assign name
>>> dm.age=64 # assign age
>>> dm.dprint()  # print out all values of datamap dm
mymap
name = "Bell"
age = 64

>>> dm.age  # individual attribute access
64
>>> dm.name
'Bell'
>>> dm.name='12345678' # silent truncation (field size defined = 6)
>>> dm.name
'123456'
>>> dm.name='1234 ' # silent blank truncation on return
>>> dm.name
'1234'

Example showing the different data types

from adapya.base.datamap import Datamap, String, Unicode, Utf8, Bytes,
    Char, Int1, Uint1, Int2, Uint2, Int4, Uint4, Int8, Uint8,
    Float, Double, Unpacked

p = Datamap( 'test_all_formats',
       String( 'str8', 8),
       Unicode('uni4', 4), # unicode 4 chars = 8 bytes
       Utf8( 'utf8', 8),
       Bytes( 'byt4', 4),
       Char( 'cha1'),
       Int1( 'int1'),
       Uint1( 'uin1'),
       Int2( 'int2'),
       Uint2( 'uin2'),
       Int4( 'int4'),
       Uint4( 'uin4', opt=T_STCK), # Uint4 STCK
       Int8( 'int8'),
       Uint8( 'uin8', opt=T_STCK), # Uint8 STCK
       Float( 'flo4'),
       Double( 'dou8'),
       Unpacked( 'dati', 14, dt='DATETIME'), # Python datetime object
       )

With Uint4 and Uint8 the additional option T_STCK indicates that the value is a timestamp value in mainframe STCK format. This is evaluated with the dprint() function to print the timestamp in readable ISO format.

An Unpacked field defined with the dt option (value ‘DATETIME’ or ‘TIMESTAMP’) work with Python datetime() objects:

>>> from datetime import datetime
>>> p.dati = datetime.now()
>>> print p.dati
2010-05-01 11:55:00

>>> _,pos,ln,_,_ = p.keydict['dati']
>>> p.buffer[pos:pos+ln]
'20100501115500'

Note that a datetime value of zero corresponds to the Python None type:

>>> p.dati = None
>>> print p.dati
None
>>> p.buffer[pos:pos+ln]
'00000000000000'

Defining Multiple fields

If the keyword occurs is added to the end of the field definition it becomes a multiple value field.

Note

The field access does not return the field value but an iterator over the occurrences values - see m.languages as in the example below:

>>> from adabas.datamap import Datamap, String
>>> from adabas import Abuf
>>> m = Datamap('mulitple_demo', String('languages', 3, occurs=5),
            buffer=Abuf(100))
>>> m.languages=('ENG','FRA','GER')
>>> m.languages[2]
'GER'
>>> m.languages[2]='RUS'

>>> for lang in m.languages:
      print lang
ENG
FRA
RUS

Defining Periodic Group

If the field definition within a datamap contains a periodic () definition a datamap at the present location is defined.

from adapya.base.datamap import Datamap, String, Packed
p = Datamap( 'Periodics Demo',
             ...
             Periodic(
               Datamap('Income',
                 String( 'currency', 3),
                 Packed( 'annual', 5)
                 ),
               occurs=8),
             ...
             )

>>> print len(p.income)
8

p.income[0].currency = 'EUR'
p.income[0].annual = 99000