Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/python.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: ["3.10", "3.11", "3.12", "3.13"]
steps:
- name: Install ldap dependencies
run: sudo apt-get update && sudo apt-get install libldap2-dev libsasl2-dev
Expand Down
30 changes: 13 additions & 17 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -1,33 +1,29 @@
[MASTER]
ignore = ,input
ignore-paths=input
persistent = yes

[MESSAGES CONTROL]
disable =
missing-docstring,
fixme,
duplicate-code,
no-member,
parse-error,
bad-continuation,
too-few-public-methods,
global-statement,
cyclic-import,
locally-disabled,
file-ignored,
fixme,
duplicate-code,
no-member,
parse-error,
too-few-public-methods,
global-statement,
cyclic-import,
locally-disabled,
file-ignored,
import-error,
unused-import

[REPORTS]
output-format = text
files-output = no
reports = no

[FORMAT]
max-line-length = 120
max-statement-lines = 75
single-line-if-stmt = no
no-space-check = trailing-comma,dict-separator
max-module-lines = 1000
indent-string = ' '

Expand Down Expand Up @@ -75,8 +71,8 @@ good-names=logger,id,ID
# Bad variable names which should always be refused, separated by a comma
bad-names=foo,bar,baz,toto,tutu,tata

# List of builtins function names that should not be used, separated by a comma
bad-functions=apply,input
# Note: bad-functions option was removed in modern pylint versions
# Use specific pylint checks instead


[DESIGN]
Expand All @@ -92,4 +88,4 @@ min-public-methods = 2
max-public-methods = 20

[EXCEPTIONS]
overgeneral-exceptions = Exception
overgeneral-exceptions = builtins.Exception
19 changes: 7 additions & 12 deletions csh_ldap/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class CSHLDAP:
__domain__ = "csh.rit.edu"

@reconnect_on_fail
def __init__(self, bind_dn, bind_pw, batch_mods=False,
def __init__(self, bind_dn, bind_pw, *, batch_mods=False,
sasl=False, ro=False):
"""Handler for bindings to CSH LDAP.

Expand Down Expand Up @@ -74,7 +74,7 @@ def get_member_ibutton(self, val):
members = self.__con__.search_s(
CSHMember.__ldap_user_ou__,
ldap.SCOPE_SUBTREE,
"(ibutton=%s)" % val,
f"(ibutton={val})",
['ipaUniqueID'])
if members:
return CSHMember(
Expand All @@ -96,7 +96,7 @@ def get_member_slackuid(self, slack):
members = self.__con__.search_s(
CSHMember.__ldap_user_ou__,
ldap.SCOPE_SUBTREE,
"(slackuid=%s)" % slack,
f"(slackuid={slack})",
['ipaUniqueID'])
if members:
return CSHMember(
Expand Down Expand Up @@ -132,7 +132,7 @@ def get_directorship_heads(self, val):
res = self.__con__.search_s(
__ldap_group_ou__,
ldap.SCOPE_SUBTREE,
"(cn=eboard-%s)" % val,
f"(cn=eboard-{val})",
['member'])

ret = []
Expand Down Expand Up @@ -176,19 +176,14 @@ def flush_mod(self):
mod_str = "ADD"
else:
mod_str = "REPLACE"
print("{} VALUE {} = {} FOR {}".format(mod_str,
mod[1],
mod[2],
dn))
print(f"{mod_str} VALUE {mod[1]} = {mod[2]} FOR {dn}")
else:
self.__con__.modify_s(dn, self.__mod_queue__[dn])
except ldap.TYPE_OR_VALUE_EXISTS:
print("Error! Conflicting Batch Modification: %s"
% str(self.__mod_queue__[dn]))
print(f"Error! Conflicting Batch Modification: {self.__mod_queue__[dn]}")
continue
except ldap.NO_SUCH_ATTRIBUTE:
print("Error! Conflicting Batch Modification: %s"
% str(self.__mod_queue__[dn]))
print(f"Error! Conflicting Batch Modification: {self.__mod_queue__[dn]}")
continue
self.__mod_queue__[dn] = None
self.__pending_mod_dn__ = []
13 changes: 6 additions & 7 deletions csh_ldap/group.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ def __init__(self, lib, search_val):
res = self.__con__.search_s(
self.__ldap_group_ou__,
ldap.SCOPE_SUBTREE,
"(cn=%s)" % search_val,
f"(cn={search_val})",
['cn'])

if res:
Expand All @@ -35,7 +35,7 @@ def get_members(self):
res = self.__con__.search_s(
self.__ldap_base_dn__,
ldap.SCOPE_SUBTREE,
"(memberof=%s)" % self.__dn__,
f"(memberof={self.__dn__})",
['uid'])

ret = []
Expand Down Expand Up @@ -69,13 +69,13 @@ def check_member(self, member, dn=False):
res = self.__con__.search_s(
self.__dn__,
ldap.SCOPE_BASE,
"(member=%s)" % dn,
f"(member={dn})",
['ipaUniqueID'])
else:
res = self.__con__.search_s(
self.__dn__,
ldap.SCOPE_BASE,
"(member=%s)" % member.get_dn(),
f"(member={member.get_dn()})",
['ipaUniqueID'])
return len(res) > 0

Expand Down Expand Up @@ -105,7 +105,7 @@ def add_member(self, member, dn=False):
mod_attrs = [mod]
self.__con__.modify_s(self.__dn__, mod_attrs)
else:
print("ADD VALUE member = {} FOR {}".format(mod[2], self.__dn__))
print(f"ADD VALUE member = {mod[2]} FOR {self.__dn__}")

@reconnect_on_fail
def del_member(self, member, dn=False):
Expand Down Expand Up @@ -133,5 +133,4 @@ def del_member(self, member, dn=False):
mod_attrs = [mod]
self.__con__.modify_s(self.__dn__, mod_attrs)
else:
print("DELETE VALUE member = {} FOR {}".format(mod[2],
self.__dn__))
print(f"DELETE VALUE member = {mod[2]} FOR {self.__dn__}")
15 changes: 6 additions & 9 deletions csh_ldap/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,13 @@ def __init__(self, lib, search_val, uid):
res = self.__con__.search_s(
self.__ldap_user_ou__,
ldap.SCOPE_SUBTREE,
"(uid=%s)" % search_val,
f"(uid={search_val})",
['ipaUniqueID'])
else:
res = self.__con__.search_s(
self.__ldap_user_ou__,
ldap.SCOPE_SUBTREE,
"(ipaUniqueID=%s)" % search_val,
f"(ipaUniqueID={search_val})",
['uid'])

if res:
Expand All @@ -51,15 +51,15 @@ def __hash__(self):
def __repr__(self):
"""Generate a str representation of the bound CSH LDAP member object.
"""
return "CSH Member(dn: %s)" % self.__dn__
return f"CSH Member(dn: {self.__dn__})"

def get(self, key):
"""Get an attribute from the bound CSH LDAP member object.

Arguments:
key -- the attribute to get the value of
"""
return self.__getattr__(key, as_list=True)
return self._get_attr(key, as_list=True)

@reconnect_on_fail
def groups(self):
Expand Down Expand Up @@ -91,7 +91,7 @@ def get_dn(self):
return self.__dn__

@reconnect_on_fail
def __getattr__(self, key, as_list=False):
def _get_attr(self, key, as_list=False):
res = self.__con__.search_s(
self.__dn__,
ldap.SCOPE_BASE,
Expand Down Expand Up @@ -153,7 +153,4 @@ def __setattr__(self, key, value):
mod_str = "ADD"
else:
mod_str = "REPLACE"
print("{} FIELD {} WITH {} FOR {}".format(mod_str,
key,
value,
self.__dn__))
print(f"{mod_str} FIELD {key} WITH {value} FOR {self.__dn__}")
7 changes: 5 additions & 2 deletions csh_ldap/utility.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,14 @@ def wrapper(*method_args, **method_kwargs):
:return: result of method call
"""
max_reconnects = MAX_RECONNECTS
is_cshldap = lambda arg: any(

def is_cshldap(arg):
return any(
filter(
lambda t: t.__name__ == 'CSHLDAP',
type(arg).__mro__
)
)
)
ldap_obj = next(filter(is_cshldap, method_args)) \
if any(filter(is_cshldap, method_args)) \
else method_args[0].__lib__
Expand All @@ -55,5 +57,6 @@ def wrapper(*method_args, **method_kwargs):
max_reconnects -= 1
if max_reconnects == 0:
raise
return None

return wrapper
2 changes: 1 addition & 1 deletion requirements-test.txt
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
pycodestyle==2.4.0
pylint==2.5.2
pylint==3.3.8