besapi 4.0.2__tar.gz → 4.1.4__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {besapi-4.0.2/src/besapi.egg-info → besapi-4.1.4}/PKG-INFO +1 -1
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/besapi.py +97 -4
- {besapi-4.0.2 → besapi-4.1.4/src/besapi.egg-info}/PKG-INFO +1 -1
- {besapi-4.0.2 → besapi-4.1.4}/tests/test_besapi.py +52 -0
- {besapi-4.0.2 → besapi-4.1.4}/LICENSE.txt +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/MANIFEST.in +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/README.md +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/pyproject.toml +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/setup.cfg +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/setup.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/__init__.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/__main__.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/plugin_utilities.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/plugin_utilities_win.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/schemas/BES.xsd +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/schemas/BESAPI.xsd +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi/schemas/BESActionSettings.xsd +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi.egg-info/SOURCES.txt +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi.egg-info/dependency_links.txt +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi.egg-info/requires.txt +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/besapi.egg-info/top_level.txt +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/bescli/__init__.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/bescli/__main__.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/src/bescli/bescli.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/tests/test_plugin_utilities.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/tests/test_plugin_utilities_logging.py +0 -0
- {besapi-4.0.2 → besapi-4.1.4}/tests/tests.py +0 -0
|
@@ -29,7 +29,7 @@ import lxml.objectify
|
|
|
29
29
|
import requests
|
|
30
30
|
import urllib3.poolmanager
|
|
31
31
|
|
|
32
|
-
__version__ = "4.
|
|
32
|
+
__version__ = "4.1.4"
|
|
33
33
|
|
|
34
34
|
besapi_logger = logging.getLogger("besapi")
|
|
35
35
|
|
|
@@ -249,6 +249,96 @@ def validate_xml_bes_file(file_path):
|
|
|
249
249
|
return validate_xsd(file_data)
|
|
250
250
|
|
|
251
251
|
|
|
252
|
+
def action_xml_from_bes_file(file_path, targets="<AllComputers>"):
|
|
253
|
+
"""Create action XML from bes file with fixlet or task or singleaction."""
|
|
254
|
+
# default to empty string:
|
|
255
|
+
custom_relevance_xml = ""
|
|
256
|
+
|
|
257
|
+
if not validate_xml_bes_file(file_path):
|
|
258
|
+
err_msg = "bes file is not valid according to XML Schema!"
|
|
259
|
+
logging.error(err_msg)
|
|
260
|
+
raise ValueError(err_msg)
|
|
261
|
+
|
|
262
|
+
tree = lxml.etree.parse(file_path)
|
|
263
|
+
|
|
264
|
+
# //BES/*[self::Task or self::Fixlet]/*[@id='elid']/name()
|
|
265
|
+
bes_type = str(
|
|
266
|
+
tree.xpath("//BES/*[self::Task or self::Fixlet or self::SingleAction]")[0].tag
|
|
267
|
+
)
|
|
268
|
+
|
|
269
|
+
logging.debug("BES Type: %s", bes_type)
|
|
270
|
+
|
|
271
|
+
title = tree.xpath(f"//BES/{bes_type}/Title/text()")[0]
|
|
272
|
+
|
|
273
|
+
logging.debug("Title: %s", title)
|
|
274
|
+
|
|
275
|
+
try:
|
|
276
|
+
actionscript = tree.xpath(
|
|
277
|
+
f"//BES/{bes_type}/DefaultAction/ActionScript/text()"
|
|
278
|
+
)[0]
|
|
279
|
+
except IndexError:
|
|
280
|
+
# handle SingleAction case:
|
|
281
|
+
actionscript = tree.xpath(f"//BES/{bes_type}/ActionScript/text()")[0]
|
|
282
|
+
|
|
283
|
+
logging.debug("ActionScript: %s", actionscript)
|
|
284
|
+
|
|
285
|
+
try:
|
|
286
|
+
if bes_type != "SingleAction":
|
|
287
|
+
success_criteria = tree.xpath(
|
|
288
|
+
f"//BES/{bes_type}/DefaultAction/SuccessCriteria/@Option"
|
|
289
|
+
)[0]
|
|
290
|
+
else:
|
|
291
|
+
success_criteria = tree.xpath(f"//BES/{bes_type}/SuccessCriteria/@Option")[
|
|
292
|
+
0
|
|
293
|
+
]
|
|
294
|
+
except IndexError:
|
|
295
|
+
# set success criteria if missing: (default)
|
|
296
|
+
success_criteria = "RunToCompletion"
|
|
297
|
+
if bes_type == "Fixlet":
|
|
298
|
+
# set success criteria if missing: (Fixlet)
|
|
299
|
+
success_criteria = "OriginalRelevance"
|
|
300
|
+
|
|
301
|
+
if success_criteria == "CustomRelevance":
|
|
302
|
+
if bes_type != "SingleAction":
|
|
303
|
+
custom_relevance = tree.xpath(
|
|
304
|
+
f"//BES/{bes_type}/DefaultAction/SuccessCriteria/text()"
|
|
305
|
+
)[0]
|
|
306
|
+
else:
|
|
307
|
+
custom_relevance = tree.xpath(f"//BES/{bes_type}/SuccessCriteria/text()")[0]
|
|
308
|
+
|
|
309
|
+
custom_relevance_xml = f"<![CDATA[{custom_relevance}]]>"
|
|
310
|
+
|
|
311
|
+
logging.debug("success_criteria: %s", success_criteria)
|
|
312
|
+
|
|
313
|
+
relevance_clauses = tree.xpath(f"//BES/{bes_type}/Relevance/text()")
|
|
314
|
+
|
|
315
|
+
logging.debug("Relevances: %s", relevance_clauses)
|
|
316
|
+
|
|
317
|
+
relevance_clauses_combined = get_action_combined_relevance(relevance_clauses)
|
|
318
|
+
|
|
319
|
+
logging.debug("Relevance Combined: %s", relevance_clauses_combined)
|
|
320
|
+
|
|
321
|
+
action_xml = f"""<?xml version="1.0" encoding="UTF-8"?>
|
|
322
|
+
<BES xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="BES.xsd">
|
|
323
|
+
<SingleAction>
|
|
324
|
+
<Title>{title}</Title>
|
|
325
|
+
<Relevance><![CDATA[{relevance_clauses_combined}]]></Relevance>
|
|
326
|
+
<ActionScript MIMEType="application/x-Fixlet-Windows-Shell"><![CDATA[// Start:
|
|
327
|
+
{actionscript}
|
|
328
|
+
// End]]></ActionScript>
|
|
329
|
+
<SuccessCriteria Option="{success_criteria}">{custom_relevance_xml}</SuccessCriteria>
|
|
330
|
+
<Target>
|
|
331
|
+
{get_target_xml(targets)}
|
|
332
|
+
</Target>
|
|
333
|
+
</SingleAction>
|
|
334
|
+
</BES>
|
|
335
|
+
"""
|
|
336
|
+
|
|
337
|
+
logging.debug("Action XML:\n%s", action_xml)
|
|
338
|
+
|
|
339
|
+
return action_xml
|
|
340
|
+
|
|
341
|
+
|
|
252
342
|
def get_bes_conn_using_env():
|
|
253
343
|
"""Get BESConnection using environment variables."""
|
|
254
344
|
username = os.getenv("BES_USER_NAME")
|
|
@@ -357,14 +447,17 @@ def get_bes_conn_interactive(
|
|
|
357
447
|
try:
|
|
358
448
|
return BESConnection(user, password, root_server)
|
|
359
449
|
except requests.exceptions.HTTPError as err:
|
|
360
|
-
print("Bad Password, Try again!")
|
|
450
|
+
print("Bad Username or Bad Password, Try again!")
|
|
361
451
|
logging.debug(err)
|
|
452
|
+
print(" BES_ROOT_SERVER: ", root_server)
|
|
362
453
|
return get_bes_conn_interactive(
|
|
363
|
-
user=
|
|
454
|
+
user=None, password=None, root_server=root_server, force_prompt=force_prompt
|
|
364
455
|
)
|
|
365
456
|
except requests.exceptions.ConnectionError as err:
|
|
366
457
|
print("Bad Root Server Specified, Try again!")
|
|
367
458
|
logging.debug("Connection Error: %s", err)
|
|
459
|
+
print(" BES_USER_NAME: ", user)
|
|
460
|
+
print("BES_PASSWORD length: ", len(password))
|
|
368
461
|
return get_bes_conn_interactive(
|
|
369
462
|
user=user, password=password, root_server=None, force_prompt=force_prompt
|
|
370
463
|
)
|
|
@@ -612,7 +705,7 @@ class BESConnection:
|
|
|
612
705
|
return RESTResult(
|
|
613
706
|
self.session.post(
|
|
614
707
|
self.url("query"),
|
|
615
|
-
data=f"relevance={urllib.parse.quote(relevance, safe='
|
|
708
|
+
data=f"relevance={urllib.parse.quote(relevance, safe=':')}",
|
|
616
709
|
verify=self.verify,
|
|
617
710
|
**kwargs,
|
|
618
711
|
)
|
|
@@ -312,6 +312,58 @@ def test_bes_conn_json():
|
|
|
312
312
|
assert result is not None
|
|
313
313
|
assert "TestString" in result
|
|
314
314
|
assert "BES Support" in result
|
|
315
|
+
print("testing session relevance with + in relevance")
|
|
316
|
+
str_relevance_plus = 'lengths of first matches (regex " +") of " "'
|
|
317
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
318
|
+
print(result)
|
|
319
|
+
assert result is not None
|
|
320
|
+
else:
|
|
321
|
+
pytest.skip("Skipping BESConnection test, no config file or login failed.")
|
|
322
|
+
|
|
323
|
+
|
|
324
|
+
def test_bes_conn_session_relevance_with_plus():
|
|
325
|
+
"""Test the BESConnection class with JSON output."""
|
|
326
|
+
|
|
327
|
+
bes_conn = besapi.plugin_utilities.get_besapi_connection(None)
|
|
328
|
+
|
|
329
|
+
if bes_conn and bes_conn.login():
|
|
330
|
+
print("testing session relevance with + in relevance")
|
|
331
|
+
str_relevance_plus = 'lengths of first matches (regex " +") of " "'
|
|
332
|
+
str_relevance_answer = "8"
|
|
333
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
334
|
+
print(result)
|
|
335
|
+
assert result is not None
|
|
336
|
+
print(result.request.request.body)
|
|
337
|
+
assert f'<Answer type="integer">{str_relevance_answer}</Answer>' in str(result)
|
|
338
|
+
result = bes_conn.session_relevance_json_string(str_relevance_plus)
|
|
339
|
+
print(result)
|
|
340
|
+
assert result is not None
|
|
341
|
+
assert str_relevance_answer in str(result)
|
|
342
|
+
result = bes_conn.session_relevance_json(str_relevance_plus)
|
|
343
|
+
print(result)
|
|
344
|
+
assert result is not None
|
|
345
|
+
assert f"[{str_relevance_answer}]" in str(result["result"])
|
|
346
|
+
result = bes_conn.session_relevance_string(str_relevance_plus)
|
|
347
|
+
print(result)
|
|
348
|
+
assert result is not None
|
|
349
|
+
assert str_relevance_answer in str(result)
|
|
350
|
+
result = bes_conn.session_relevance_array(str_relevance_plus)
|
|
351
|
+
print(result)
|
|
352
|
+
assert result is not None
|
|
353
|
+
assert f"['{str_relevance_answer}']" in str(result)
|
|
354
|
+
result = bes_conn.session_relevance_json_array(str_relevance_plus)
|
|
355
|
+
print(result)
|
|
356
|
+
assert result is not None
|
|
357
|
+
assert f"[{str_relevance_answer}]" in str(result)
|
|
358
|
+
|
|
359
|
+
# test already escaped +
|
|
360
|
+
str_relevance_plus = r'lengths of first matches (regex " %2b") of " "'
|
|
361
|
+
print(str_relevance_plus)
|
|
362
|
+
result = bes_conn.session_relevance_xml(str_relevance_plus)
|
|
363
|
+
print(result)
|
|
364
|
+
assert result is not None
|
|
365
|
+
print(result.request.request.body)
|
|
366
|
+
assert f'<Answer type="integer">{str_relevance_answer}</Answer>' in str(result)
|
|
315
367
|
else:
|
|
316
368
|
pytest.skip("Skipping BESConnection test, no config file or login failed.")
|
|
317
369
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|