docs: def user_list(user=None, host=None, port=None, maintenance_db=None,
                password=None, runas=None, return_password=False):
      '''
      Return a dict with information about users of a Postgres server.
  
      Set return_password to True to get password hash in the result.
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' postgres.user_list
      '''
  
      ret = {}
  
      ver = _parsed_version(user=user,
                            host=host,
                            port=port,
                            maintenance_db=maintenance_db,
                            password=password,
                            runas=runas)
      if ver:
          if ver >= _LooseVersion('9.1'):
              replication_column = 'pg_roles.rolreplication'
          else:
              replication_column = 'NULL'
          if ver >= _LooseVersion('9.5'):
              rolcatupdate_column = 'NULL'
          else:
              rolcatupdate_column = 'pg_roles.rolcatupdate'
      else:
          log.error('Could not retrieve Postgres version. Is Postgresql server running?')
          return False
  
      # will return empty string if return_password = False
      _x = lambda s: s if return_password else ''
  
      query = (''.join([
          'SELECT '
          'pg_roles.rolname as "name",'
          'pg_roles.rolsuper as "superuser", '
          'pg_roles.rolinherit as "inherits privileges", '
          'pg_roles.rolcreaterole as "can create roles", '
          'pg_roles.rolcreatedb as "can create databases", '
          '{0} as "can update system catalogs", '
          'pg_roles.rolcanlogin as "can login", '
          '{1} as "replication", '
          'pg_roles.rolconnlimit as "connections", '
          '(SELECT array_agg(pg_roles2.rolname)'
          '    FROM pg_catalog.pg_auth_members'
          '    JOIN pg_catalog.pg_roles pg_roles2 ON (pg_auth_members.roleid = pg_roles2.oid)'
          '    WHERE pg_auth_members.member = pg_roles.oid) as "groups",'
          'pg_roles.rolvaliduntil::timestamp(0) as "expiry time", '
          'pg_roles.rolconfig  as "defaults variables" '
          , _x(', COALESCE(pg_shadow.passwd, pg_authid.rolpassword) as "password" '),
          'FROM pg_roles '
          , _x('LEFT JOIN pg_authid ON pg_roles.oid = pg_authid.oid ')
          , _x('LEFT JOIN pg_shadow ON pg_roles.oid = pg_shadow.usesysid')
      ]).format(rolcatupdate_column, replication_column))
  
      rows = psql_query(query,
                        runas=runas,
                        host=host,
                        user=user,
                        port=port,
                        maintenance_db=maintenance_db,
                        password=password)
  
      def get_bool(rowdict, key):
          '''
          Returns the boolean value of the key, instead of 't' and 'f' strings.
          '''
          if rowdict[key] == 't':
              return True
          elif rowdict[key] == 'f':
              return False
          else:
              return None
  
      for row in rows:
          retrow = {}
          for key in ('superuser', 'inherits privileges', 'can create roles',
                      'can create databases', 'can update system catalogs',
                      'can login', 'replication', 'connections'):
              retrow[key] = get_bool(row, key)
          for date_key in ('expiry time',):
              try:
                  retrow[date_key] = datetime.datetime.strptime(
                      row[date_key], '%Y-%m-%d %H:%M:%S')
              except ValueError:
                  retrow[date_key] = None
          retrow['defaults variables'] = row['defaults variables']
          if return_password:
              retrow['password'] = row['password']
          # use csv reader to handle quoted roles correctly
          retrow['groups'] = list(csv.reader([row['groups'].strip('{}')]))[0]
          ret[row['name']] = retrow
  
      return ret