Skip to content

Commit e3b7df7

Browse files
authored
Merge pull request #62 from homebysix/python-black
Consider using Python Black for automatic formatting consistency
2 parents 11433b6 + 3d1fbc2 commit e3b7df7

14 files changed

+1480
-1453
lines changed

jamf/admin.py

+151-131
Large diffs are not rendered by default.

jamf/api.py

+37-27
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
Modifications by Tony Williams ([email protected]) (ARW)
77
"""
88

9-
__author__ = 'Sam Forester'
10-
__email__ = '[email protected]'
11-
__copyright__ = 'Copyright (c) 2020 University of Utah, Marriott Library'
12-
__license__ = 'MIT'
9+
__author__ = "Sam Forester"
10+
__email__ = "[email protected]"
11+
__copyright__ = "Copyright (c) 2020 University of Utah, Marriott Library"
12+
__license__ = "MIT"
1313
__version__ = "0.4.7"
1414

1515
import html.parser
@@ -27,20 +27,24 @@
2727

2828
LOGLEVEL = logging.INFO
2929

30-
#pylint: disable=unnecessary-pass
30+
# pylint: disable=unnecessary-pass
3131
class Error(Exception):
32-
""" just passing through """
32+
"""just passing through"""
33+
3334
pass
3435

3536

36-
#pylint: disable=super-init-not-called
37+
# pylint: disable=super-init-not-called
3738
class APIError(Error):
38-
""" Error in our call """
39+
"""Error in our call"""
40+
3941
def __init__(self, response):
4042
self.response = response
4143
err = parse_html_error(response.text)
42-
self.message = ": ".join(err) or 'failed'
43-
print(f"{response}: {response.request.method} - {response.url}: \n{self.message}")
44+
self.message = ": ".join(err) or "failed"
45+
print(
46+
f"{response}: {response.request.method} - {response.url}: \n{self.message}"
47+
)
4448

4549
def __getattr__(self, attr):
4650
"""
@@ -54,8 +58,10 @@ def __str__(self):
5458

5559

5660
class Singleton(type):
57-
""" allows us to share a single object """
61+
"""allows us to share a single object"""
62+
5863
_instances = {}
64+
5965
def __call__(cls, *a, **kw):
6066
if cls not in cls._instances:
6167
cls._instances[cls] = super(Singleton, cls).__call__(*a, **kw)
@@ -66,14 +72,12 @@ class API(metaclass=Singleton):
6672
"""
6773
Class for making api calls to JSS
6874
"""
75+
6976
session = False
7077

71-
def __init__(self,
72-
config_path=None,
73-
hostname=None,
74-
username=None,
75-
password=None,
76-
prompt=True):
78+
def __init__(
79+
self, config_path=None, hostname=None, username=None, password=None, prompt=True
80+
):
7781
"""
7882
Create requests.Session with JSS address and authentication
7983
@@ -88,25 +92,27 @@ def __init__(self,
8892
self.log = logging.getLogger(f"{__name__}.API")
8993
self.log.setLevel(LOGLEVEL)
9094
# Load Prefs and Init session
91-
conf = config.Config(config_path=config_path,
92-
hostname=hostname,
93-
username=username,
94-
password=password,
95-
prompt=prompt)
95+
conf = config.Config(
96+
config_path=config_path,
97+
hostname=hostname,
98+
username=username,
99+
password=password,
100+
prompt=prompt,
101+
)
96102
hostname = hostname or conf.hostname
97103
username = username or conf.username
98104
password = password or conf.password
99105

100106
if not hostname and not username and not password:
101107
print("No jamf hostname or credentials could be found.")
102108
exit(1)
103-
if hostname[-1] == '/':
109+
if hostname[-1] == "/":
104110
self.url = f"{hostname}JSSResource"
105111
else:
106112
self.url = f"{hostname}/JSSResource"
107113
self.session = requests.Session()
108114
self.session.auth = (username, password)
109-
self.session.headers.update({'Accept': 'application/xml'})
115+
self.session.headers.update({"Accept": "application/xml"})
110116

111117
def get(self, endpoint, raw=False):
112118
"""
@@ -229,7 +235,8 @@ def __del__(self):
229235
self.log.debug("closing session")
230236
self.session.close()
231237

232-
#pylint: disable=too-few-public-methods, abstract-method
238+
239+
# pylint: disable=too-few-public-methods, abstract-method
233240
class _DummyTag:
234241
"""
235242
Minimal mock implementation of bs4.element.Tag (only has text attribute)
@@ -238,6 +245,7 @@ class _DummyTag:
238245
>>> eg.text
239246
'some text'
240247
"""
248+
241249
def __init__(self, text):
242250
self.text = text
243251

@@ -250,6 +258,7 @@ class JSSErrorParser(html.parser.HTMLParser):
250258
['Unauthorized', 'The request requires user authentication',
251259
'You can get technical details here. {...}']
252260
"""
261+
253262
def __init__(self, _html):
254263
super().__init__()
255264
self._data = {}
@@ -265,7 +274,7 @@ def find_all(self, tag):
265274
"""
266275
return self._data.get(tag, [])
267276

268-
#pylint: disable=attribute-defined-outside-init
277+
# pylint: disable=attribute-defined-outside-init
269278
def handle_data(self, data):
270279
"""
271280
override HTMLParser().handle_data()
@@ -284,6 +293,7 @@ def handle_endtag(self, tag):
284293
self._data.setdefault(tag, [])
285294
self._data[tag].append(self._dummytag)
286295

296+
287297
def parse_html_error(error):
288298
"""
289299
Get meaningful error information from JSS Error response HTML
@@ -298,4 +308,4 @@ def parse_html_error(error):
298308
# 'You can get technical details here. (...)']
299309
# NOTE: get first two <p> tags from HTML error response
300310
# 3rd <p> is always 'You can get technical details here...'
301-
return [t.text for t in soup.find_all('p')][0:2]
311+
return [t.text for t in soup.find_all("p")][0:2]

jamf/config.py

+40-39
Original file line numberDiff line numberDiff line change
@@ -4,32 +4,35 @@
44
Configuration for jamfutil
55
"""
66

7-
__author__ = 'Sam Forester'
8-
__email__ = '[email protected]'
9-
__copyright__ = 'Copyright (c) 2020 University of Utah, Marriott Library'
10-
__license__ = 'MIT'
7+
__author__ = "Sam Forester"
8+
__email__ = "[email protected]"
9+
__copyright__ = "Copyright (c) 2020 University of Utah, Marriott Library"
10+
__license__ = "MIT"
1111
__version__ = "1.2.4"
1212

1313
import getpass
1414
import logging
1515
import plistlib
1616
import keyring
1717
from os import path, remove
18-
LINUX_PREFS_TILDA = '~/.edu.utah.mlib.jamfutil.plist'
19-
MACOS_PREFS_TILDA = '~/Library/Preferences/edu.utah.mlib.jamfutil.plist'
20-
AUTOPKG_PREFS_TILDA = '~/Library/Preferences/com.github.autopkg.plist'
21-
JAMF_PREFS = '/Library/Preferences/com.jamfsoftware.jamf.plist'
18+
19+
LINUX_PREFS_TILDA = "~/.edu.utah.mlib.jamfutil.plist"
20+
MACOS_PREFS_TILDA = "~/Library/Preferences/edu.utah.mlib.jamfutil.plist"
21+
AUTOPKG_PREFS_TILDA = "~/Library/Preferences/com.github.autopkg.plist"
22+
JAMF_PREFS = "/Library/Preferences/com.jamfsoftware.jamf.plist"
2223
logging.getLogger(__name__).addHandler(logging.NullHandler())
2324

2425

2526
class Config:
26-
def __init__(self,
27-
config_path=None,
28-
hostname=None,
29-
username=None,
30-
password=None,
31-
prompt=False,
32-
explain=False):
27+
def __init__(
28+
self,
29+
config_path=None,
30+
hostname=None,
31+
username=None,
32+
password=None,
33+
prompt=False,
34+
explain=False,
35+
):
3336
self.log = logging.getLogger(f"{__name__}.{self.__class__.__name__}")
3437
self.prompt = prompt
3538
self.hostname = hostname
@@ -42,39 +45,39 @@ def __init__(self,
4245
autopkg_prefs = path.expanduser(AUTOPKG_PREFS_TILDA)
4346
if path.exists(macos_prefs):
4447
if explain:
45-
print("Using macos: "+macos_prefs)
48+
print("Using macos: " + macos_prefs)
4649
config_path = macos_prefs
4750
elif path.exists(linux_prefs):
4851
if explain:
49-
print("Using linux: "+linux_prefs)
52+
print("Using linux: " + linux_prefs)
5053
config_path = linux_prefs
5154
elif path.exists(autopkg_prefs):
5255
if explain:
53-
print("Using autopkg: "+autopkg_prefs)
56+
print("Using autopkg: " + autopkg_prefs)
5457
config_path = autopkg_prefs
5558
elif path.exists(JAMF_PREFS):
5659
if explain:
57-
print("Using jamf: "+JAMF_PREFS)
60+
print("Using jamf: " + JAMF_PREFS)
5861
config_path = JAMF_PREFS
5962
else:
6063
if explain:
61-
print("Using "+macos_prefs+" but it doesn't exist yet.")
64+
print("Using " + macos_prefs + " but it doesn't exist yet.")
6265
config_path = macos_prefs
6366
elif explain:
64-
print("Using "+config_path+" because you said so.")
67+
print("Using " + config_path + " because you said so.")
6568

66-
if config_path[0] == '~':
69+
if config_path[0] == "~":
6770
config_path = path.expanduser(config_path)
6871
if explain:
69-
print("Expanding the path. Using "+config_path)
72+
print("Expanding the path. Using " + config_path)
7073

7174
if not self.hostname and not self.username and not self.password:
7275
if path.exists(config_path):
73-
fptr = open(config_path, 'rb')
76+
fptr = open(config_path, "rb")
7477
prefs = plistlib.load(fptr)
7578
fptr.close()
76-
if 'JSSHostname' in prefs:
77-
if 'Credentials' in prefs:
79+
if "JSSHostname" in prefs:
80+
if "Credentials" in prefs:
7881
cmessage = f"""
7982
ATTENTION
8083
To improve security with storing credentials used with the jctl tool, we have
@@ -87,15 +90,16 @@ def __init__(self,
8790
the "./jamf/setconfig.py" script.
8891
"""
8992
raise Exception(cmessage)
90-
self.hostname = prefs['JSSHostname']
91-
self.username = prefs['Username']
92-
self.password = keyring.get_password(self.hostname,
93-
self.username)
94-
elif 'JSS_URL' in prefs:
93+
self.hostname = prefs["JSSHostname"]
94+
self.username = prefs["Username"]
95+
self.password = keyring.get_password(
96+
self.hostname, self.username
97+
)
98+
elif "JSS_URL" in prefs:
9599
self.hostname = prefs["JSS_URL"]
96100
self.username = prefs["API_USERNAME"]
97101
self.password = prefs["API_PASSWORD"]
98-
elif 'jss_url' in prefs:
102+
elif "jss_url" in prefs:
99103
self.hostname = prefs["jss_url"]
100104
# No auth in that file
101105
else:
@@ -112,16 +116,13 @@ def __init__(self,
112116
if not self.password:
113117
self.password = getpass.getpass()
114118
elif not self.hostname and not self.username and not self.password:
115-
raise Exception('No jamf config file could be found and prompt is off.')
119+
raise Exception("No jamf config file could be found and prompt is off.")
116120

117121
def save(self, config_path=None):
118122
keyring.set_password(self.hostname, self.username, self.password)
119-
data = {
120-
'JSSHostname': self.hostname,
121-
'Username': self.username
122-
}
123+
data = {"JSSHostname": self.hostname, "Username": self.username}
123124
self.log.info(f"saving: {config_path}")
124-
fptr = open(config_path, 'wb')
125+
fptr = open(config_path, "wb")
125126
plistlib.dump(data, fptr)
126127
fptr.close()
127128

@@ -131,4 +132,4 @@ def reset(self, path):
131132

132133

133134
def prompt_hostname():
134-
return input('Hostname (don\'t forget https:// and :8443): ')
135+
return input("Hostname (don't forget https:// and :8443): ")

jamf/convert.py

+8-7
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
XML and JSON data conversion functions
55
"""
66

7-
__author__ = 'Sam Forester'
8-
__email__ = '[email protected]'
9-
__copyright__ = 'Copyright (c) 2019 University of Utah, Marriott Library'
10-
__license__ = 'MIT'
7+
__author__ = "Sam Forester"
8+
__email__ = "[email protected]"
9+
__copyright__ = "Copyright (c) 2019 University of Utah, Marriott Library"
10+
__license__ = "MIT"
1111
__version__ = "0.2.2"
1212

1313
from xml.etree import cElementTree as ElementTree
@@ -16,7 +16,8 @@
1616

1717

1818
class Error(Exception):
19-
""" just passing through """
19+
"""just passing through"""
20+
2021
pass
2122

2223

@@ -35,7 +36,7 @@ def etree_to_dict(elem):
3536
defd[key].append(val)
3637
result = {
3738
elem.tag: {
38-
key:val[0] if len(val) == 1 else val for key, val in defd.items()
39+
key: val[0] if len(val) == 1 else val for key, val in defd.items()
3940
}
4041
}
4142
elif elem.text:
@@ -49,7 +50,7 @@ def dict_to_xml(data):
4950
:returns: xml string
5051
"""
5152
if isinstance(data, dict):
52-
xml_str = ''
53+
xml_str = ""
5354
for key, value in data.items():
5455
if value is None:
5556
xml_str += f"<{key}/>"

0 commit comments

Comments
 (0)