def test_download(self): """Test full download routine.""" with TransportSessionClient( SqliteSession, URI, file_destination=None ) as session: images = self.setup_buffers1(session) session.commit() with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: city.CityWrapper(session=session) session.load(images[0].uid) session.load(images[1].uid) session.load(images[2].uid) self.assertEqual(set(os.listdir(CLIENT_DIR)), {FILES[0], FILES[2]}) # download again and check that no errors occur # and that the duplicates are still # in the download folder (and not more) number_of_downloaded_files = len(os.listdir(CLIENT_DIR)) with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: city.CityWrapper(session=session) session.load(images[0].uid) session.load(images[1].uid) session.load(images[2].uid) self.assertEqual( number_of_downloaded_files, len(os.listdir(CLIENT_DIR)) )
def test_serialize_buffers(self): """Test correct handling of files when serializing the buffers.""" # without providing target path with TransportSessionClient(SqliteSession, URI) as session: self.setup_buffers1(session) _, result = serialize_buffers( session, buffer_context=BufferContext.USER, target_directory=None, ) self.assertEqual( sorted(map(os.path.abspath, [FILE_PATHS[0], FILE_PATHS[2]])), sorted(result), ) # provide target path --> move files with TransportSessionClient(SqliteSession, URI) as session: images = self.setup_buffers1(session) _, result = serialize_buffers( session, buffer_context=BufferContext.USER, target_directory=CLIENT_DIR, ) target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_full_path = [os.path.join(CLIENT_DIR, t) for t in target] self.assertEqual( sorted([target_full_path[0], target_full_path[2]]), sorted(result), ) self.maxDiff = None
def test_store(self): """Test storing of cuds_object.""" client = TransportSessionClient(TestWrapperSession, None) client._engine = MockEngine() # first item c1 = create_recycle(oclass=city.CityWrapper, kwargs={}, uid=1, session=client, fix_neighbors=False) # store will be called here self.assertEqual(client._engine._sent_command, INITIALIZE_COMMAND) assertJsonLdEqual(self, json.loads(client._engine._sent_data), INIT_DATA) self.assertEqual(set(client._registry.keys()), {c1.uid}) # second item client._engine._sent_data = None client._engine._sent_command = None c2 = create_recycle(oclass=city.City, kwargs={"name": "Freiburg"}, uid=2, session=client, fix_neighbors=False) self.assertEqual(client._engine._sent_command, None) self.assertEqual(client._engine._sent_data, None) self.assertEqual(set(client._registry.keys()), {c1.uid, c2.uid}) client.close()
def test_upload(self): """Test full upload routine.""" # with given file destination on client with TransportSessionClient(SqliteSession, URI, file_destination=CLIENT_DIR) as session: images = self.setup_buffers1(session) session.commit() target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] self.assertEqual(set(os.listdir(SERVER_DIR)), {target[0], target[2]}) self.assertEqual(set(os.listdir(CLIENT_DIR)), {target[0], target[2]}) self.assertEqual(os.listdir(FILES_DIR), FILES) self.tearDown() self.setUp() # With no given file destination on client with TransportSessionClient(SqliteSession, URI, file_destination=None) as session: images = self.setup_buffers1(session) session.commit() target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] self.assertEqual(set(os.listdir(SERVER_DIR)), {target[0], target[2]}) self.assertEqual(set(os.listdir(CLIENT_DIR)), set()) self.assertEqual(os.listdir(FILES_DIR), FILES)
def test_init(self): """Test if first level of children are loaded automatically.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Anna") p3 = city.Citizen(name="Julia") c.add(p1, p2, p3, rel=city.hasInhabitant) p1.add(p3, rel=city.hasChild) p2.add(p3, rel=city.hasChild) with SqliteSession(DB) as session: wrapper = city.CityWrapper(session=session) wrapper.add(c) session.commit() with TransportSessionClient(SqliteSession, URI, path=DB) \ as session: wrapper = city.CityWrapper(session=session) self.assertEqual(set(session._registry.keys()), {c.uid, wrapper.uid}) self.assertEqual(wrapper.get(c.uid).name, "Freiburg") self.assertEqual( session._registry.get(c.uid)._neighbors[city.hasInhabitant], {p1.uid: p1.oclasses, p2.uid: p2.oclasses, p3.uid: p3.oclasses}) self.assertEqual( session._registry.get(c.uid)._neighbors[city.isPartOf], {wrapper.uid: wrapper.oclasses})
def test_refresh(self): """Test refreshing CUDS objects.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Anna") p3 = city.Citizen(name="Julia") c.add(p1, p2, p3, rel=city.hasInhabitant) p1.add(p3, rel=city.hasChild) p2.add(p3, rel=city.hasChild) with TransportSessionClient(SqliteSession, URI, path=DB) \ as session: wrapper = city.CityWrapper(session=session) cw = wrapper.add(c) p1w, p2w, p3w = cw.get(p1.uid, p2.uid, p3.uid) session.commit() self.assertEqual(cw.name, "Freiburg") self.assertEqual(p1w.name, "Peter") self.assertEqual(p2w.name, "Anna") self.assertEqual(p3w.name, "Julia") self.assertEqual(session._expired, {wrapper.uid}) update_db(DB, c, p1, p2, p3) session.refresh(cw, p1w, p2w, p3w) self.assertEqual(cw.name, "Paris") self.assertEqual(p1w.name, "Maria") self.assertEqual(set(cw.get()), {p1w}) self.assertEqual(p2w.get(), list()) self.assertFalse(hasattr(p3w, "name")) self.assertNotIn(p3w.uid, session._registry)
def test_expiring(self): """Test expiring with transport + db session.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Anna") p3 = city.Citizen(name="Julia") c.add(p1, p2, p3, rel=city.hasInhabitant) p1.add(p3, rel=city.hasChild) p2.add(p3, rel=city.hasChild) with TransportSessionClient(SqliteSession, URI, path=DB)\ as session: wrapper = city.CityWrapper(session=session) cw = wrapper.add(c) p1w, p2w, p3w = cw.get(p1.uid, p2.uid, p3.uid) session.commit() # p1w is no longer expired after the following assert self.assertEqual(p1w.name, "Peter") update_db(DB, c, p1, p2, p3) self.assertEqual(cw.name, "Paris") self.assertEqual(p1w.name, "Peter") session.expire_all() self.assertEqual(p1w.name, "Maria") self.assertEqual(set(cw.get()), {p1w}) self.assertEqual(p2w.get(), list()) self.assertFalse(hasattr(p3w, "name")) self.assertNotIn(p3w.uid, session._registry)
def _run_simulation(simulation, host, port): """ Exposes the CUDS object from the oclass `onto.Simulation` to the desired port with the `TransportSessionClient`. The simulation is started with `wrapper.session.run()` whereas the updated CUDS object with the attached output is received by `wrapper.get(simulation.uid)` Parameters ---------- simulation : osp.core.cuds.Cuds CUDS object from the oclass of `onto.simulation` holding the semantic and syntactic input information being passed to the simulation engine host : str Host name the `TransportSessionClient` shall be wired to port : int Port the `TransportSessionClient` shall be wired to Returns ------- outputfiles : list List class containing the paths to the output files described in the used ontology. """ print("Sending cuds object to", host, "with uid =", simulation.uid) with TransportSessionClient(SimWrapperSession, host, port) as session: wrapper = onto["ForceOfiWrapper"](session=session) wrapper.add(simulation) wrapper.session.run() simulation = wrapper.get(simulation.uid) return _cuds_output_to_file(simulation)
def test_deserialize_buffers(self): """Test correct file handling when deserializing buffers.""" with TransportSessionClient(SqliteSession, URI) as session: images = self.setup_buffers2(session) deserialize_buffers( session, buffer_context=BufferContext.USER, data=SERIALIZED_BUFFERS, temp_directory=None, target_directory=CLIENT_DIR, ) added, updated, deleted = session._buffers[BufferContext.USER] self.assertEqual(len(added), 1) self.assertEqual(len(updated), 2) self.assertEqual(len(deleted), 1) images = images + [added[uuid.UUID(int=3)]] target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_full_path = [os.path.join(CLIENT_DIR, t) for t in target] self.assertEqual(added[uuid.UUID(int=3)].path, target_full_path[2]) self.assertEqual( updated[uuid.UUID(int=1)].path, target_full_path[0] ) self.assertRaises( AttributeError, getattr, deleted[uuid.UUID(int=2)], "path" )
def test_auth(self): """Test authentication.""" with TransportSessionClient(AuthSession, URI_CORRECT1, path=DB) as session: city.CityWrapper(session=session) with TransportSessionClient(AuthSession, URI_WRONG1, path=DB) as session: self.assertRaises(RuntimeError, city.CityWrapper, session=session) with TransportSessionClient(SimpleAuthSession, URI_CORRECT2, path=DB) as session: city.CityWrapper(session=session) with TransportSessionClient(SimpleAuthSession, URI_WRONG2, path=DB) as session: self.assertRaises(RuntimeError, city.CityWrapper, session=session)
def test_send(self): """Test sending data to the server.""" client = TransportSessionClient(TestWrapperSession, None) client._engine = MockEngine() client._send("command", True, "hello", bye="bye") self.assertEqual(client._engine._sent_command, "command") self.assertEqual( client._engine._sent_data, ('{"added": [], "updated": [], "deleted": [], "expired": [], ' '"args": ["hello"], "kwargs": {"bye": "bye"}}')) client.close()
def test_insert(self): """Test inserting in the sqlite table.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Georg") c.add(p1, p2, rel=city.hasInhabitant) with TransportSessionClient(SqliteSession, URI, path=DB) as session: wrapper = city.CityWrapper(session=session) wrapper.add(c) session.commit() check_state(self, c, p1, p2, db=DB)
def test_load_by_oclass(self): """Load elements by ontology class via transport + db session.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Anna") p3 = city.Citizen(name="Julia") c.add(p1, p2, p3, rel=city.hasInhabitant) p1.add(p3, rel=city.hasChild) p2.add(p3, rel=city.hasChild) with TransportSessionClient(SqliteSession, URI, path=DB) as session: wrapper = city.CityWrapper(session=session) wrapper.add(c) session.commit() with TransportSessionClient(SqliteSession, URI, path=DB) as session: wrapper = city.CityWrapper(session=session) cs = wrapper.get(c.uid) r = session.load_by_oclass(city.City) self.assertIs(next(iter(r)), cs) r = session.load_by_oclass(city.Citizen) self.assertEqual(set(r), {p1, p2, p3}) r = session.load_by_oclass(city.Person) self.assertEqual(set(r), {p1, p2, p3})
def test_receive(self): """Test the receive method.""" client = TransportSessionClient(TestWrapperSession, None) client._engine = MockEngine() w = city.CityWrapper(session=client) self.assertRaises(RuntimeError, client._receive, "ERROR: Error!", None) client._receive(json.dumps(SERIALIZED_BUFFERS2), None) self.assertEqual(set(client._registry.keys()), {uuid.UUID(int=42), w.uid}) self.assertEqual(client._buffers[BufferContext.USER], [dict(), dict(), dict()]) self.assertEqual( list(map(dict.keys, client._buffers[BufferContext.ENGINE])), [set([uuid.UUID(int=42)]), set(), set()]) client.close()
def test_delete(self): """Test to delete cuds_objects from the sqlite table.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Georg") p3 = city.Citizen(name="Hans") c.add(p1, p2, p3, rel=city.hasInhabitant) with TransportSessionClient(SqliteSession, URI, path=DB) as session: wrapper = city.CityWrapper(session=session) cw = wrapper.add(c) session.commit() cw.remove(p3.uid) session.prune() session.commit() check_state(self, c, p1, p2, db=DB)
def test_getattr(self): """Test the __getatt__ magic method.""" def command(*args, **kwargs): pass TestWrapperSession.command = consumes_buffers(command) client = TransportSessionClient(TestWrapperSession, None) client._engine = MockEngine() client.command("arg1", "arg2", kwarg="kwarg") self.assertEqual(client._engine._sent_command, "command") self.assertEqual( client._engine._sent_data, ('{"added": [], "updated": [], "deleted": [], "expired": [], ' '"args": ["arg1", "arg2"], "kwargs": {"kwarg": "kwarg"}}')) self.assertRaises(AttributeError, getattr, client, "run") client.close()
def test_load_missing(self): """Test if missing objects are loaded automatically.""" c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Anna") p3 = city.Citizen(name="Julia") c.add(p1, p2, p3, rel=city.hasInhabitant) p1.add(p3, rel=city.hasChild) p2.add(p3, rel=city.hasChild) with SqliteSession(DB) as session: wrapper = city.CityWrapper(session=session) wrapper.add(c) session.commit() with TransportSessionClient(SqliteSession, URI, path=DB) as session: wrapper = city.CityWrapper(session=session) self.assertEqual(set(session._registry.keys()), {c.uid, wrapper.uid}) cw = wrapper.get(c.uid) p1w = cw.get(p1.uid) p2w = cw.get(p2.uid) p3w = p1w.get(p3.uid) self.assertEqual( set(session._registry.keys()), {c.uid, wrapper.uid, p1.uid, p2.uid, p3.uid}, ) self.assertEqual(p1w.name, "Peter") self.assertEqual(p2w.name, "Anna") self.assertEqual(p3w.name, "Julia") self.assertEqual( p3w._neighbors[city.isChildOf], { p1.uid: p1.oclasses, p2.uid: p2.oclasses }, ) self.assertEqual(p2w._neighbors[city.hasChild], {p3.uid: p3.oclasses}) self.assertEqual( p2w._neighbors[city.INVERSE_OF_hasInhabitant], {c.uid: c.oclasses}, )
def test_dummy_sim_wrapper(self): """Create a dummy simulation syntactic layer + test it.""" with TransportSessionClient(SimDummySession, URI) as session: wrapper = city.CitySimWrapper(numSteps=1, session=session) c = city.City(name="Freiburg") p1 = city.Person(name="Hans", age=34) p2 = city.Person(name="Renate", age=54) cw, _, _ = wrapper.add(c, p1, p2) session.run() self.assertEqual( len(wrapper.get(oclass=city.Person, rel=city.hasPart)), 1) self.assertEqual( len(cw.get(oclass=city.Citizen, rel=city.hasInhabitant)), 1) self.assertEqual(wrapper.get(p2.uid).name, "Renate") self.assertEqual(wrapper.get(p2.uid).age, 55) self.assertEqual(cw.get(p1.uid).name, "Hans") self.assertEqual(cw.get(p1.uid).age, 35) session.run() wrapper.add(city.Person(name="Peter")) self.assertRaises(RuntimeError, session.run)
def test_user_parameterize(self): """Test parameterizing the dataspace as a client.""" with TransportSessionClient(DbWrapperSession, URI, path="dataspace.db") as session: self.assertRaises(RuntimeError, city.CityWrapper, session=session)
try: # Construct the Datastructure. c = city.City(name="Freiburg") p1 = city.Citizen(name="Peter") p2 = city.Citizen(name="Hans") p3 = city.Citizen(name="Michel") n = city.Neighborhood(name="Zähringen") s = city.Street(name="Le street") b = city.Building(name="Theater") a = city.Address(postalCode=79123, name='Le street', number=12) c.add(p1, p2, p3, rel=city.hasInhabitant) c.add(n).add(s).add(b).add(a) print("Connect to DB via transport session") with TransportSessionClient( SqliteSession, "ws://localhost:8688", path="test.db" ) as session: wrapper = city.CityWrapper(session=session) wrapper.add(c) wrapper.session.commit() print("Reconnect and check if data is still there") with TransportSessionClient( SqliteSession, "ws://localhost:8688", path="test.db" ) as session: wrapper = city.CityWrapper(session=session) c = wrapper.get(oclass=city.City)[0] pretty_print(c) print("Reconnect and make some changes") with TransportSessionClient(
def test_load(self): """Test loading from server.""" client = TransportSessionClient(TestWrapperSession, None) client.root = 1 c1 = create_recycle(oclass=city.City, kwargs={"name": "Freiburg"}, uid=1, session=client, fix_neighbors=False) c2 = city.City(name="London", uid=2) c3 = create_recycle(oclass=city.City, kwargs={"name": "Paris"}, uid=3, session=client, fix_neighbors=False) client._reset_buffers(BufferContext.USER) client.expire(c3.uid) def on_send(command, data): with EngineContext(client): create_from_cuds_object(c2, client) return [c2, None] client._engine = MockEngine(on_send) result = list( client.load(uuid.UUID(int=1), uuid.UUID(int=2), uuid.UUID(int=3))) self.assertEqual(client._engine._sent_command, LOAD_COMMAND) self.assertEqual( client._engine._sent_data, '{"expired": [{"UUID": "00000000-0000-0000-0000-000000000003"}], ' '"uids": [{"UUID": "00000000-0000-0000-0000-000000000002"}, ' '{"UUID": "00000000-0000-0000-0000-000000000003"}]}') self.assertEqual(result, [c1, c2, None]) self.assertEqual(set(client._registry.keys()), {c1.uid, c2.uid}) self.assertEqual( client._buffers, [[dict(), dict(), dict()], [dict(), dict(), dict()]]) client.close()
def test_upload(self): """Test full upload routine.""" # with given file destination on client with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: images, images_second = self.setup_buffers3(session) session.commit() target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_second = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images_second, FILES) ] self.assertEqual( set(os.listdir(SERVER_DIR)), { target[0], target[1], target[2], target_second[0], target_second[1], }, ) self.assertEqual( set(os.listdir(CLIENT_DIR)), { FILES[0], FILES[1], FILES[2], os.path.splitext(FILES[1])[0] + f" ({images_second[1].uid})" + os.path.splitext(FILES[1])[1], }, ) self.assertEqual(set(os.listdir(FILES_DIR)), set(FILES)) self.assertEqual(set(os.listdir(SECOND_FILES_DIR)), set(FILES)) self.tearDown() self.setUp() # With no given file destination on client with TransportSessionClient( SqliteSession, URI, file_destination=None ) as session: images, images_second = self.setup_buffers3(session) session.commit() target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_second = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images_second, FILES) ] self.assertEqual( set(os.listdir(SERVER_DIR)), { target[0], target[1], target[2], target_second[0], target_second[1], }, ) self.assertEqual(set(os.listdir(CLIENT_DIR)), set()) self.assertEqual(set(os.listdir(FILES_DIR)), set(FILES)) self.assertEqual(set(os.listdir(SECOND_FILES_DIR)), set(FILES))
def test_move_files(self): """Test moving the files.""" with TransportSessionClient(SqliteSession, URI) as session: # Image path is full path wrapper = city.CityWrapper(session=session) images = wrapper.add( city.Image(path=FILE_PATHS[0]), city.Image(path=FILE_PATHS[1]), city.Image(path=FILE_PATHS[2]), ) result = move_files(images, None, CLIENT_DIR) target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_full_path = [os.path.join(CLIENT_DIR, t) for t in target] self.assertEqual(set(os.listdir(FILES_DIR)), set(FILES)) self.assertEqual(set(os.listdir(CLIENT_DIR)), set(target)) self.assertEqual(result, target_full_path) self.tearDown() self.setUp() # Image path is path on a different system paths = [ FILES[0], os.path.join("foo", "bar", FILES[1]), os.path.abspath(".").split(os.path.sep)[0] + os.path.sep + FILES[2], ] images = wrapper.add( city.Image(path=paths[0]), city.Image(path=paths[1]), city.Image(path=paths[2]), ) result = move_files(images, FILES_DIR, CLIENT_DIR) target = [ "%s-%s" % (image.uid.hex, file) for image, file in zip(images, FILES) ] target_full_path = [os.path.join(CLIENT_DIR, t) for t in target] self.assertEqual(set(os.listdir(CLIENT_DIR)), set(target)) self.assertEqual(result, target_full_path) self.tearDown() self.setUp() # Not target given --> Nothing will be moved images = wrapper.add( city.Image(path=paths[0]), city.Image(path=paths[1]), city.Image(path=paths[2]), ) result = move_files(images, FILES_DIR, None) self.assertEqual(set(os.listdir(CLIENT_DIR)), set()) self.assertEqual(result, paths) # Target does not exist images = wrapper.add( city.Image(path=paths[0]), city.Image(path=paths[1]), city.Image(path=paths[2]), ) result = move_files(images, FILES_DIR, "not-existent") self.assertEqual(set(os.listdir(CLIENT_DIR)), set()) self.assertEqual(result, list()) # paths don't exist images = wrapper.add( city.Image(path=paths[0]), city.Image(path=paths[1]), city.Image(path=paths[2]), ) result = move_files(images, None, CLIENT_DIR) self.assertEqual(set(os.listdir(CLIENT_DIR)), set()) self.assertEqual(result, list())
def test_path(self): """Tests that the path of the CUBA file on the client is correct. Created due to issue #652. """ # Upload file and retrieve twice. Both paths should be correct. with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) file = cuba.File(path=FILE_PATHS[1]) # `f1.jpg` wrapper.add(file) session.commit() with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) file = wrapper.get(file.uid) path1 = file.path with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) file = wrapper.get(file.uid) path2 = file.path self.assertEqual(os.path.dirname(path1), CLIENT_DIR) self.assertEqual(os.path.dirname(path2), CLIENT_DIR) # Upload two identical instances of the same file, also upload two # different files with the same name. # The CLIENT_DIR is not cleaned up on purpose. with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) file1 = cuba.File(path=FILE_PATHS[0]) # `f0` file2 = cuba.File(path=FILE_PATHS[0]) # `f0` file3 = cuba.File(path=FILE_PATHS[1]) # `f1.jpg` file4 = cuba.File(path=SECOND_FILE_PATHS[1]) # `f1.jpg` (second # file) wrapper.add(file1, file2, file3, file4) session.commit() with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) path1 = wrapper.get(file1.uid).path path2 = wrapper.get(file2.uid).path path3 = wrapper.get(file3.uid).path path4 = wrapper.get(file4.uid).path self.assertTrue( all( path.startswith(CLIENT_DIR) for path in (path1, path2, path3, path4) ), True, ) self.assertEqual(path1, path2) self.assertNotEqual(path3, path4) # Now clean up the folder (make sure that the server can find the # files, that is, the path is correct for the server). for file in os.listdir(CLIENT_DIR): os.remove(os.path.join(CLIENT_DIR, file)) with TransportSessionClient( SqliteSession, URI, file_destination=CLIENT_DIR ) as session: wrapper = city.CityWrapper(session=session) path1 = wrapper.get(file1.uid).path path2 = wrapper.get(file2.uid).path path3 = wrapper.get(file3.uid).path path4 = wrapper.get(file4.uid).path self.assertTrue( all( path.startswith(CLIENT_DIR) for path in (path1, path2, path3, path4) ), True, ) self.assertEqual(path1, path2) self.assertNotEqual(path3, path4)