0

I have ldif file as below, I want to extract only the dn and changetype here using the ldif parser of python-ldap package.

dn: cn=abc, cn=def, cn="dc=grid,dc=mycompany,dc=com", cn=tree, cn=config
changetype: add
objectClass: top   
cn: abc
description: myserver

I have written parser code as below:

from ldif import LDIFParser, LDIFRecordList
parser = LDIFRecordList(open("cluster1.ldif", "r"))
parser.parse()


for dn, entry in parser.all_records:
   print(dn)
   print(entry)

but this reads everything and skips the changetype key am not sure what is causing that. Is there a better way to parse the ldif file?

Adding output of requested commands in comment:

python -c 'import sys; import ldap; print("\n".join([sys.version, ldap.__version__]))'
2.7.5 (default, May 31 2018, 09:41:32) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-28)]
2.4.15
4
  • What do you mean by "skips the changetype key"? If I run your code with your sample input, print(entry) shows {'changetype': [b'add'], 'objectClass': [b'top '], 'cn': [b'abc'], 'description': [b'myserver']}, which includes the changetype key. Commented Jul 29, 2021 at 13:48
  • thats strange. I see all tuples except changetype. Is there a way to do this without using ldifrecordlist too? Commented Jul 29, 2021 at 13:58
  • I mean...you could subclass ldif.LDIFParser and write your own handle method, but I suspect you're going to see the same behavior. Commented Jul 29, 2021 at 14:11
  • am not succeding in doing that too. It is failing with error. Can you give me an example code? Commented Jul 29, 2021 at 15:10

2 Answers 2

1

Update

You appear to be using a very old version of the python-ldap module. Version 2.4.15 was released over seven years ago. The current release is 3.3.1, which is what you get if you pip install python-ldap.

Python 2 itself went end-of-life in Janurary 2020, and version 2.7.5 was released back in 2013.

The software you're working with is very old and has bugs that were fixed in more recent versions. You should upgrade.


As I mentioned in comments, I'm not able to reproduce the behavior you've described. If I put your sample LDIF content into cluster1.ldif, I see:

>>> from ldif import LDIFParser, LDIFRecordList
>>> parser = LDIFRecordList(open("cluster1.ldif", "r"))
>>> parser.parse()
>>> for dn, entry in parser.all_records:
...     print(dn)
...     print(entry)
...
cn=abc, cn=def, cn="dc=grid,dc=mycompany,dc=com", cn=tree, cn=config
{'changetype': [b'add'], 'objectClass': [b'top   '], 'cn': [b'abc'], 'description': [b'myserver']}
>>>

You asked about an alternative to use LDIFRecordList. You can of course write your own handler by subclassing LDIFParser, but the underlying LDIF parsing is still going to be the same. That would look something like:

from ldif import LDIFParser, LDIFRecordList


class MyParser(LDIFParser):
    def __init__(self, *args, **kwargs):
        self.records = []
        super().__init__(*args, **kwargs)

    def handle(self, dn, entry):
        self.records.append((dn, entry))


parser = MyParser(open("cluster1.ldif", "r"))
parser.parse()
for dn, entry in parser.records:
    print(dn)
    print(entry)

...but that's really just re-implementing LDIFRecordList, so I don't think you obtain any benefit from doing this.

I'm using python 3.9.6 and python-ldap 3.3.1. If you continue to see different behavior, would you update your question to include the output of python -c 'import sys; import ldap; print("\n".join([sys.version, lda p.__version__]))'

Sign up to request clarification or add additional context in comments.

1 Comment

added the output
0

If I understand right, you want something like this:

#!/usr/bin/python

from ldif import LDIFParser
from sys import argv

class myParser( LDIFParser ):

   def handle( self, dn, entry ):
        print( "DN:", dn )
        print( "CT:", entry['changetype'], "\n" )

parser = myParser( open( argv[1] ) )
parser.parse()

LDIFParser.handle() method is invoked for every DN of your LDIF and in it you have direct access to DN (dn variable) and AVPs (entry variable), latter being a dictionary of attribute names with associated values as byte arrays.

Does that help?

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.