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
12 changes: 0 additions & 12 deletions sap/adt/atc.py
Original file line number Diff line number Diff line change
Expand Up @@ -224,18 +224,6 @@ def run_for(self, obj_sets, max_verdicts=100):

worklist = WorkList()
Marshal.deserialize(resp.text, worklist)

# increase all priorities by 1 to be in sync with SAPGui. ADT protocol sends priorities
# decreased by one
for obj in worklist.objects:
for finding in obj.findings:
# increment only if priority is integer
try:
finding_number = int(finding.priority)
finding.priority = str(finding_number + 1)
except ValueError:
pass

return WorkListRunResult(run_response, worklist)


Expand Down
3 changes: 3 additions & 0 deletions sap/adt/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ def endElement(self, name):
self._collection = None
self._mimetypes = None
elif name == 'app:accept':
if not self._accept:
return

self._mimetypes.append(self._accept)
self._accept = None

Expand Down
4 changes: 2 additions & 2 deletions sap/adt/objects.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,8 @@ def find_mime_version(connection, objtype):
seri_mime = next((mime for mime in mimes if mime in objtype.all_mimetypes), None)
if seri_mime is None:
# pylint: disable=consider-using-f-string
raise SAPCliError('Not supported mimes: {} not in {}'
.format(';'.join(mimes), ';'.join(objtype.all_mimetypes)))
raise SAPCliError('Not supported mimes for {}: "{}" not in "{}"'
.format(objtype.basepath, ';'.join(mimes), ';'.join(objtype.all_mimetypes)))

version = mimetype_to_version(seri_mime)
return (seri_mime, version)
Expand Down
7 changes: 6 additions & 1 deletion sap/platform/abap/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import secrets
import string
import warnings

import sap.adt
import sap.adt.checks
Expand Down Expand Up @@ -90,6 +91,10 @@ def execute_abap(connection, user_code, prefix=DEFAULT_PREFIX, package=DEFAULT_P

result = clas.execute()
finally:
clas.delete()
try:
clas.delete()
except SAPCliError as delete_exception:
warn_message = f'Warning: failed to delete temporary class {class_name}: {str(delete_exception)}'
warnings.warn(warn_message, stacklevel=2)

return result
14 changes: 14 additions & 0 deletions test/unit/fixtures_adt.py
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,20 @@
</adtcomp:templateLinks>
</app:collection>
</app:workspace>
<app:workspace>
<atom:title>Stub Object With Empty Accept</atom:title>
<app:collection href="/sap/bc/adt/stub/test_empty">
<atom:title>Stub Test Object</atom:title>
<app:accept></app:accept>
</app:collection>
</app:workspace>
<app:workspace>
<atom:title>Stub Object With Empty Accept</atom:title>
<app:collection href="/sap/bc/adt/stub/test_accept">
<atom:title>Stub Test Object</atom:title>
<app:accept>application/sapcli.test</app:accept>
</app:collection>
</app:workspace>
</app:service>
'''

Expand Down
2 changes: 1 addition & 1 deletion test/unit/test_sap_adt_atc.py
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ def test_run_for_not_empty(self):
self.assertEqual(len(atcobject.findings), 2)
finding = atcobject.findings[0]

self.assertEqual(finding.priority, '2')
self.assertEqual(finding.priority, '1')
self.assertEqual(finding.check_id, '005056AB5B8D1ED4BFDA1CA5D9EBA6C4')
self.assertEqual(finding.check_title, 'Test Environment (CHK_ZDM)')
self.assertEqual(finding.message_id, '0898')
Expand Down
18 changes: 18 additions & 0 deletions test/unit/test_sap_adt_connection.py
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,24 @@ def test_property_collection_init(self, mock_exec):
self.assertIsNotNone(collection_types)
self.assertIsNotNone(self.connection._collection_types)

self.assertEqual(list(self.connection.collection_types.keys()), [
'/sap/bc/adt/bopf/businessobjects',
'/sap/bc/adt/packages',
'/sap/bc/adt/functions/groups/{groupname}/fmodules',
'/sap/bc/adt/functions/groups/{groupname}/includes',
'/sap/bc/adt/functions/groups',
'/sap/bc/adt/ddic/ddl/formatter/identifiers',
'/sap/bc/adt/sadl/gw/mde',
'/sap/bc/adt/quickfixes/evaluation',
'/sap/bc/adt/wdy/views',
'/sap/bc/adt/stub/test_accept',
])

mime_stub_empty = self.connection.collection_types.get('/sap/bc/adt/stub/test_empty')
self.assertIsNone(mime_stub_empty)

mime_stub_accept = self.connection.collection_types.get('/sap/bc/adt/stub/test_accept')
self.assertEqual(mime_stub_accept, ['application/sapcli.test'])

def test_property_collection_cache(self):
fake_value = Mock()
Expand Down
3 changes: 2 additions & 1 deletion test/unit/test_sap_adt_object.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,8 @@ def test_create_mime_not_found(self):
with self.assertRaises(sap.errors.SAPCliError) as caught:
victory.create()

self.assertEqual(str(caught.exception), 'Not supported mimes: application/something.else+xml not in application/vnd.sap.super.cool.txt+xml;application/vnd.sap.super.cool.txt.v2+xml')
self.assertEqual(str(caught.exception),
'Not supported mimes for awesome/success: "application/something.else+xml" not in "application/vnd.sap.super.cool.txt+xml;application/vnd.sap.super.cool.txt.v2+xml"')

def test_delete(self):
conn = Connection([EMPTY_RESPONSE_OK])
Expand Down
39 changes: 39 additions & 0 deletions test/unit/test_sap_platform_abap_run.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env python3

import unittest
import warnings
from unittest.mock import patch, call

from sap.errors import SAPCliError
Expand Down Expand Up @@ -239,6 +240,44 @@ def test_check_failure_skips_write_and_activate_but_still_deletes(self):
# Delete still happens.
self.assertIn('deletion/delete', connection.execs[-1].adt_uri)

def test_delete_failure_emits_warning_instead_of_exception(self):
connection = Connection([
EMPTY_RESPONSE_OK, # create
_make_check_response(), # check_before_save
LOCK_RESPONSE_OK, # lock
EMPTY_RESPONSE_OK, # write source
EMPTY_RESPONSE_OK, # unlock
EMPTY_RESPONSE_OK, # activate (POST)
_make_activate_response(), # fetch after activate (GET)
Response(text='output', status_code=200,
headers={'Content-Type': 'text/plain'}), # execute
Response(text='Not found', status_code=404, headers={}), # delete fails
])

with patch('sap.platform.abap.run.generate_class_name', return_value=FIXED_CLASS_NAME):
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
result = execute_abap(connection, 'WRITE "hello".')

self.assertEqual(result, 'output')
self.assertEqual(len(caught), 1)
self.assertIn(FIXED_CLASS_NAME, str(caught[0].message))

def test_delete_failure_after_create_failure_emits_warning(self):
connection = Connection([
Response(text='Create failed', status_code=500, headers={}), # create fails
Response(text='Not found', status_code=404, headers={}), # delete fails too
])

with patch('sap.platform.abap.run.generate_class_name', return_value=FIXED_CLASS_NAME):
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter('always')
with self.assertRaises(Exception):
execute_abap(connection, 'WRITE "hello".')

self.assertEqual(len(caught), 1)
self.assertIn(FIXED_CLASS_NAME, str(caught[0].message))

def test_check_disabled_via_env_skips_check_post(self):
connection = Connection([
EMPTY_RESPONSE_OK, # create
Expand Down
Loading