# Buggy code
def parse_role_attrs(cursor, role_attr_flags):
    """
    Parse role attributes string for user creation.
    Format:

        attributes[,attributes,...]

    Where:

        attributes := CREATEDB,CREATEROLE,NOSUPERUSER,...
        [ "[NO]SUPERUSER","[NO]CREATEROLE", "[NO]CREATEUSER", "[NO]CREATEDB",
                            "[NO]INHERIT", "[NO]LOGIN", "[NO]REPLICATION",
                            "[NO]BYPASSRLS" ]

    Note: "[NO]BYPASSRLS" role attribute introduced in 9.5

    """
    flags = frozenset(role.upper() for role in role_attr_flags.split(",") if role)

    valid_flags = frozenset(itertools.chain(FLAGS, get_valid_flags_by_version(cursor)))
    valid_flags = frozenset(
        itertools.chain(valid_flags, ("NO%s" % flag for flag in valid_flags))
    )

    if not flags.issubset(valid_flags):
        raise InvalidFlagsError(
            "Invalid role_attr_flags specified: %s"
            % " ".join(flags.difference(valid_flags))
        )

    return " ".join(flags)


# Traceback (nKeyError)
TASK [postgresql : Create PostgreSQL roles] ************************************
changed: [centos7-1.ru] => (item={u'priv': [u'ALL'], u'password': u'test324234', u'db': u'timevizor_applp', u'role_attr_flags': [u'NOCREATEUSER', u'CREATEDB'], u'name': u'timevizor_applp'})

TASK [postgresql : Create PostgreSQL roles] ************************************
failed: [centos7-1.ru] (item={u'priv': [u'ALL'], u'password': u'test324234', u'db': u'timevizor_applp', u'role_attr_flags': [u'NOCREATEUSER', u'CREATEDB'], u'name': u'timevizor_applp'}) => {"failed": true, "item": {"db": "timevizor_applp", "name": "timevizor_applp", "password": "test324234", "priv": ["ALL"], "role_attr_flags": ["NOCREATEUSER", "CREATEDB"]}, "module_stderr": "Shared connection to 192.168.0.227 closed.\r\n", "module_stdout": "Traceback (most recent call last):\r\n  File \"/tmp/ansible_qJnmMu/ansible_module_postgresql_user.py\", line 666, in <module>\r\n    main()\r\n  File \"/tmp/ansible_qJnmMu/ansible_module_postgresql_user.py\", line 621, in main\r\n    changed = user_alter(cursor, module, user, password, role_attr_flags, encrypted, expires, no_password_changes)\r\n  File \"/tmp/ansible_qJnmMu/ansible_module_postgresql_user.py\", line 274, in user_alter\r\n    if current_role_attrs[PRIV_TO_AUTHID_COLUMN[role_attr_name]] != role_attr_value:\r\n  File \"/usr/lib64/python2.7/site-packages/psycopg2/extras.py\", line 144, in __getitem__\r\n    x = self._index[x]\r\nKeyError: 'rolcreateuser'\r\n", "msg": "MODULE FAILURE"}
to retry, use: --limit @/tmp/cloud.retry

PLAY RECAP *********************************************************************
centos7-1.ru               : ok=2    changed=1    unreachable=0    failed=1

# Fixed code
def parse_role_attrs(cursor, role_attr_flags):
    """
    Parse role attributes string for user creation.
    Format:

        attributes[,attributes,...]

    Where:

        attributes := CREATEDB,CREATEROLE,NOSUPERUSER,...
        [ "[NO]SUPERUSER","[NO]CREATEROLE", "[NO]CREATEDB",
                            "[NO]INHERIT", "[NO]LOGIN", "[NO]REPLICATION",
                            "[NO]BYPASSRLS" ]

    Note: "[NO]BYPASSRLS" role attribute introduced in 9.5
    Note: "[NO]CREATEUSER" role attribute is deprecated.

    """
    flags = frozenset(role.upper() for role in role_attr_flags.split(",") if role)

    valid_flags = frozenset(itertools.chain(FLAGS, get_valid_flags_by_version(cursor)))
    valid_flags = frozenset(
        itertools.chain(valid_flags, ("NO%s" % flag for flag in valid_flags))
    )

    if not flags.issubset(valid_flags):
        raise InvalidFlagsError(
            "Invalid role_attr_flags specified: %s"
            % " ".join(flags.difference(valid_flags))
        )

    return " ".join(flags)