Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

convert all members of a group to string #102

Merged
merged 5 commits into from
Nov 5, 2019
Merged

Conversation

3c2b2ff5
Copy link
Contributor

@3c2b2ff5 3c2b2ff5 commented Nov 4, 2019

This is the critical part:

      for record in data:
        # If the dn is requested, return it along with the payload,
        # otherwise ignore it.
        for key in record[1]:
          if isinstance(record[1][key][0], bytes) and key != 'objectSid':
            value = record[1][key][0].decode('utf-8')
            record[1][key] = [value]
        if self._dn_requested:
          merged_records = {'dn': record[0]}
          merged_records.update(record[1])
          yield merged_records
        else:
          yield record[1]

member list is > 1, so it converts the first member only, we need to check the length of the list, as for members it is not always 1, as for the other attributes. My solution would be:

      for record in data:
        # If the dn is requested, return it along with the payload,
        # otherwise ignore it.
        for key in record[1]:
          if len(record[1][key]) > 1:
            for i, item in enumerate(record[1][key]):
              if isinstance(item, bytes) and key != 'objectSid':
                value = item.decode('utf-8')
                record[1][key][i] = value
          else:
            if isinstance(record[1][key][0], bytes) and key != 'objectSid':
              value = record[1][key][0].decode('utf-8')
              record[1][key] = [value]
        if self._dn_requested:
          merged_records = {'dn': record[0]}
          merged_records.update(record[1])
          yield merged_records
        else:
          yield record[1]

I'll create a pull request, please modify as needed.

@jaqx0r
Copy link
Contributor

jaqx0r commented Nov 4, 2019

Is this to fix issue #101 you just filed?

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

Yes. The members list of a group can have many users, with the original implementation only the first member is mapped. With this fix I check the length of a list and convert each member to string and replace it accordingly.

Maybe it is better to specify the key member when checking the list items.

If you have a better idea, pleas modify it.

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

may be:

if key == 'member':

would be better than:

if len(record[1][key]) > 1:

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

like this:

      for record in data:
        # If the dn is requested, return it along with the payload,
        # otherwise ignore it.
        for key in record[1]:
          if key == 'member':
            for i, item in enumerate(record[1]['member']):
              if isinstance(item, bytes):
                value = item.decode('utf-8')
                record[1][key][i] = value
          else:
            if isinstance(record[1][key][0], bytes) and key != 'objectSid':
              value = record[1][key][0].decode('utf-8')
              record[1][key] = [value]
        if self._dn_requested:
          merged_records = {'dn': record[0]}
          merged_records.update(record[1])
          yield merged_records
        else:
          yield record[1]

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

I think this is easier and will make it as well:

      for record in data:
        # If the dn is requested, return it along with the payload,
        # otherwise ignore it.
        for key in record[1]:
          for i, item in enumerate(record[1][key]):
            if isinstance(item, bytes) and key != 'objectSid':
              value = item.decode('utf-8')
              record[1][key][i] = value
        if self._dn_requested:
          merged_records = {'dn': record[0]}
          merged_records.update(record[1])
          yield merged_records
        else:
          yield record[1]

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

I don't know what is the pythonic way to check it correctly.

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

It would make sense to compare the returned members list with the given one in ldapsource_test.py, or at least the length of the list.

if isinstance(record[1][key][0], bytes) and key != 'objectSid':
value = record[1][key][0].decode('utf-8')
record[1][key] = [value]
if len(record[1][key]) > 1:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Avoid the if statement here, by using a temporary list we can append to, then finally assign record[1][key] = tmp_list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is possible as well.

value = record[1][key][0].decode('utf-8')
record[1][key] = [value]
if len(record[1][key]) > 1:
for i, item in enumerate(record[1][key]):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Then i think we can avoid the enumerate() line by juster iterating over record[1][key],

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this will fail the runtests.py as far as I remember.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if record[1][key] is a string this will not work, right?

Copy link
Contributor Author

@3c2b2ff5 3c2b2ff5 Nov 4, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we need to consider, that there one element lists, where the iteration will be over the string characters instead of the list elements. So applying the following:

for item in record[1][key]:

Won't work on [b'Test User']:
will iterate over the string characters

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

may be using range is a better way?

for i, item in enumerate(record[1][key]):
if isinstance(item, bytes) and key != 'objectSid':
value = item.decode('utf-8')
record[1][key][i] = value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this line becomes tmp_list.append(value)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

of course on way or another.

else:
if isinstance(record[1][key][0], bytes) and key != 'objectSid':
value = record[1][key][0].decode('utf-8')
record[1][key] = [value]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and all of this doesn't need to exist, and instead finally set record[1][key] = tmp_list.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMHO I think the only way to make it work for the tests as well, of course it will work with a tmp_list:

      for record in data:
        # If the dn is requested, return it along with the payload,
        # otherwise ignore it.
        for key in record[1]:
          for i, item in enumerate(record[1][key]):
            if isinstance(item, bytes) and key != 'objectSid':
              value = item.decode('utf-8')
              record[1][key][i] = value
        if self._dn_requested:
          merged_records = {'dn': record[0]}
          merged_records.update(record[1])
          yield merged_records
        else:
          yield record[1]

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a possible solution as well:

        for key in record[1]:
          for i in range(len(record[1][key])):
            if isinstance(record[1][key][i], bytes) and key != 'objectSid':
              value = record[1][key][i].decode('utf-8')
              record[1][key][i] = value

@jaqx0r
Copy link
Contributor

jaqx0r commented Nov 4, 2019

Why is key = 'member' worth special casing?

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

Why is key = 'member' worth special casing?

Nothing special, it is just an example for the members list, which can be memberUid as well.

@3c2b2ff5
Copy link
Contributor Author

3c2b2ff5 commented Nov 4, 2019

If your suggestions work, I'll apply it, until now I couldn't make it work.

@jaqx0r jaqx0r merged commit 9665918 into google:master Nov 5, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants