Skip to content

Commit

Permalink
adt: generalise walk over ADT objects
Browse files Browse the repository at this point in the history
Not only packages, but other ADT objects can use walk function to
discover its components. To limit the code redundancy I created a
walk_step method which discovers components of the highest level.
  • Loading branch information
palubaj authored and jfilak committed Jul 27, 2023
1 parent 66c20d4 commit a4df89e
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 13 deletions.
14 changes: 1 addition & 13 deletions sap/adt/package.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""ABAP Package (DEV/C) ADT functionality module"""

from types import SimpleNamespace
from collections import deque

# pylint: disable=unused-import
Expand Down Expand Up @@ -206,18 +205,7 @@ def walk(package):

while toexplore:
explored, path = toexplore.pop()
root_node = repository.read_node(explored)

subpackages = [subpkg.OBJECT_NAME for subpkg in root_node.objects]

nodekeys = [objtyp.NODE_ID for objtyp in root_node.types if objtyp.OBJECT_TYPE != 'DEVC/K']
if nodekeys:
objects_node = repository.read_node(explored, nodekeys=nodekeys)
objects = [SimpleNamespace(typ=obj.OBJECT_TYPE, name=obj.OBJECT_NAME, uri=obj.OBJECT_URI)
for obj in objects_node.objects]
else:
objects = []

subpackages, objects = repository.walk_step(explored)
toexplore.extendleft(((Package(package.connection, subpkg), path + [subpkg]) for subpkg in subpackages))

yield (path, subpackages, objects)
16 changes: 16 additions & 0 deletions sap/adt/repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,3 +123,19 @@ def read_node(self, adt_object, withdescr=False, nodekeys=None):
xml.sax.parseString(resp.text, parser)

return SimpleNamespace(objects=parser.tree_content, types=parser.object_types, categories=parser.categories)

def walk_step(self, adt_object, withdescr=False):
"""Returns list of intermediate subpackages and objects"""

root_node = self.read_node(adt_object, withdescr=withdescr)
subpackages = [subpkg.OBJECT_NAME for subpkg in root_node.objects]

nodekeys = [objtyp.NODE_ID for objtyp in root_node.types if objtyp.OBJECT_TYPE != 'DEVC/K']
if nodekeys:
objects_node = self.read_node(adt_object, withdescr=withdescr, nodekeys=nodekeys)
objects = [SimpleNamespace(typ=obj.OBJECT_TYPE, name=obj.OBJECT_NAME, uri=obj.OBJECT_URI)
for obj in objects_node.objects]
else:
objects = []

return subpackages, objects
39 changes: 39 additions & 0 deletions test/unit/test_sap_adt_repository.py
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,45 @@ def test_read_node_not_unique_nodekeys(self):

self.assertEqual(connection.execs[0].body, PACKAGE_SOURCE_LIBRARY_REQUEST_XML)

def test_walk_step(self):
subpackages = [SimpleNamespace(OBJECT_NAME='SUBPACKAGE1'), SimpleNamespace(OBJECT_NAME='SUBPACKAGE2')]
types = [SimpleNamespace(NODE_ID='000005', OBJECT_TYPE='CLAS/OC'),
SimpleNamespace(NODE_ID='000011', OBJECT_TYPE='DEVC/K')]
first_call = SimpleNamespace(objects=subpackages, types=types)

objects = [SimpleNamespace(OBJECT_NAME='OBJECT1', OBJECT_TYPE='PROG', OBJECT_URI='URI'),
SimpleNamespace(OBJECT_NAME='OBJECT2', OBJECT_TYPE='FUGR/F', OBJECT_URI='URI')]
second_call = SimpleNamespace(objects=objects)

self.patch('sap.adt.repository.Repository.read_node', side_effect=[first_call, second_call])

repository = sap.adt.Repository(None)
actual_subpackages, actual_objects = repository.walk_step('PACKAGE')

self.assertEqual(actual_subpackages, [subpackage.OBJECT_NAME for subpackage in subpackages])
self.assertEqual(actual_objects,
[SimpleNamespace(typ=obj.OBJECT_TYPE, name=obj.OBJECT_NAME, uri=obj.OBJECT_URI) for obj in objects])

def test_walk_step_empty_nodekeys(self):
subpackages = [SimpleNamespace(OBJECT_NAME='SUBPACKAGE1'), SimpleNamespace(OBJECT_NAME='SUBPACKAGE2')]
types = [SimpleNamespace(NODE_ID='000005', OBJECT_TYPE='DEVC/K')]
first_call = SimpleNamespace(objects=subpackages, types=types)
self.patch('sap.adt.repository.Repository.read_node', side_effect=[first_call])

repository = sap.adt.Repository(None)
actual_subpackages, actual_objects = repository.walk_step('PACKAGE')

self.assertEqual(actual_subpackages, [subpackage.OBJECT_NAME for subpackage in subpackages])
self.assertEqual(actual_objects, [])

def test_walk_step_with_description(self):
fake_read_node = self.patch('sap.adt.repository.Repository.read_node')

repository = sap.adt.Repository(None)
repository.walk_step('PACKAGE', withdescr=True)

fake_read_node.assert_called_once_with('PACKAGE', withdescr=True)


if __name__ == '__main__':
unittest.main()

0 comments on commit a4df89e

Please sign in to comment.