Skip to content

Commit 58d9d24

Browse files
authored
Merge pull request #102 from alexander255/master
Add support and tests for several `.add()` options
2 parents 609be64 + b23d5c5 commit 58d9d24

File tree

2 files changed

+160
-68
lines changed

2 files changed

+160
-68
lines changed

ipfsapi/client.py

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ def __init__(self, host=DEFAULT_HOST, port=DEFAULT_PORT,
107107

108108
self._client = self._clientfactory(host, port, base, **defaults)
109109

110-
def add(self, files, recursive=False, pattern='**', **kwargs):
110+
def add(self, files, recursive=False, pattern='**', *args, **kwargs):
111111
"""Add a file, or directory of files to IPFS.
112112
113113
.. code-block:: python
@@ -128,11 +128,35 @@ def add(self, files, recursive=False, pattern='**', **kwargs):
128128
Single `*glob* <https://docs.python.org/3/library/glob.html>`_
129129
pattern or list of *glob* patterns and compiled regular expressions
130130
to match the names of the filepaths to keep
131+
trickle : bool
132+
Use trickle-dag format (optimized for streaming) when generating
133+
the dag; see `the FAQ <https://github.com/ipfs/faq/issues/218>` for
134+
more information (Default: ``False``)
135+
only_hash : bool
136+
Only chunk and hash, but do not write to disk (Default: ``False``)
137+
wrap_with_directory : bool
138+
Wrap files with a directory object to preserve their filename
139+
(Default: ``False``)
140+
chunker : str
141+
The chunking algorithm to use
142+
pin : bool
143+
Pin this object when adding (Default: ``True``)
131144
132145
Returns
133146
-------
134147
dict: File name and hash of the added file node
135148
"""
149+
#PY2: No support for kw-only parameters after glob parameters
150+
opts = {
151+
"trickle": kwargs.pop("trickle", False),
152+
"only-hash": kwargs.pop("only_hash", False),
153+
"wrap-with-directory": kwargs.pop("wrap_with_directory", False),
154+
"pin": kwargs.pop("pin", True)
155+
}
156+
if "chunker" in kwargs:
157+
opts["chunker"] = kwargs.pop("chunker")
158+
kwargs.setdefault("opts", opts)
159+
136160
body, headers = multipart.stream_filesystem_node(
137161
files, recursive, pattern, self.chunk_size
138162
)

test/functional/tests.py

Lines changed: 135 additions & 67 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,10 @@ class IpfsApiTest(unittest.TestCase):
9898
fake_file = 'fake_dir/fsdfgh'
9999
fake_file_only_res = {'Name': 'fsdfgh',
100100
'Hash': 'QmQcCtMgLVwvMQGu6mvsRYLjwqrZJcYtH4mboM9urWW9vX'}
101+
fake_file_dir_res = [
102+
{'Name': 'fsdfgh', 'Hash': 'QmQcCtMgLVwvMQGu6mvsRYLjwqrZJcYtH4mboM9urWW9vX'},
103+
{'Name': '', 'Hash': 'Qme7vmxd4LAAYL7vpho3suQeT3gvMeLLtPdp7myCb9Db55'}
104+
]
101105
fake_file2 = 'fake_dir/popoiopiu'
102106
fake_files_res = [
103107
{'Name': 'fsdfgh', 'Hash': 'QmQcCtMgLVwvMQGu6mvsRYLjwqrZJcYtH4mboM9urWW9vX'},
@@ -162,10 +166,21 @@ def setUp(self):
162166

163167
# Makes all of the diff visible if the hashes change for some reason
164168
self.maxDiff = None
169+
170+
self.pinned = set(self.api.pin_ls(type="recursive")["Keys"])
165171

166172
def tearDown(self):
167173
os.chdir(self._olddir)
168174

175+
def _clean_up_pins(self):
176+
for multihash in self.api.pin_ls(type="recursive")["Keys"]:
177+
if multihash not in self.pinned:
178+
self.api.pin_rm(multihash)
179+
180+
@staticmethod
181+
def _sort_by_key(items, key="Name"):
182+
return sorted(items, key=lambda x: x[key])
183+
169184
#########
170185
# TESTS #
171186
#########
@@ -174,125 +189,178 @@ def test_version(self):
174189
expected = ['Repo', 'Commit', 'Version']
175190
resp_version = self.api.version()
176191
for key in expected:
177-
self.assertTrue(key in resp_version)
192+
assert key in resp_version
178193

179194
def test_id(self):
180195
expected = ['PublicKey', 'ProtocolVersion',
181196
'ID', 'AgentVersion', 'Addresses']
182197
resp_id = self.api.id()
183198
for key in expected:
184-
self.assertTrue(key in resp_id)
199+
assert key in resp_id
185200

186201
def test_add_single_from_str(self):
187-
res = self.api.add(self.fake_file)
188-
self.assertEqual(self.fake_file_only_res, res)
202+
res = self.api.add(self.fake_file, pin=False)
203+
204+
assert self.fake_file_only_res == res
205+
206+
assert res["Hash"] not in self.api.pin_ls(type="recursive")
207+
assert res["Hash"] in list(map(lambda i: i["Ref"], self.api.refs_local()))
189208

190209
def test_add_single_from_fp(self):
191210
with open(self.fake_file, 'rb') as fp:
192-
res = self.api.add(fp)
193-
self.assertEqual(self.fake_file_only_res, res)
211+
res = self.api.add(fp, pin=False)
212+
213+
assert self.fake_file_only_res == res
214+
215+
assert res["Hash"] not in self.api.pin_ls(type="recursive")
216+
assert res["Hash"] in list(map(lambda i: i["Ref"], self.api.refs_local()))
217+
218+
def test_add_single_from_str_with_dir(self):
219+
res = self.api.add(self.fake_file, wrap_with_directory=True)
220+
221+
try:
222+
assert self.fake_file_dir_res == res
223+
224+
dir_hash = None
225+
for item in res:
226+
if item["Name"] == "":
227+
dir_hash = item["Hash"]
228+
assert dir_hash in self.api.pin_ls(type="recursive")["Keys"]
229+
finally:
230+
self._clean_up_pins()
231+
232+
def test_only_hash_file(self):
233+
self.api.repo_gc()
234+
235+
res = self.api.add(self.fake_file, only_hash=True)
236+
237+
assert self.fake_file_only_res == res
238+
239+
assert res["Hash"] not in self.api.pin_ls(type="recursive")
240+
assert res["Hash"] not in list(map(lambda i: i["Ref"], self.api.refs_local()))
194241

195242
def test_add_multiple_from_list(self):
196243
res = self.api.add([self.fake_file, self.fake_file2])
197-
self.assertEqual(self.fake_files_res, res)
244+
245+
try:
246+
assert self.fake_files_res == res
247+
finally:
248+
self._clean_up_pins()
198249

199250
def test_add_multiple_from_dirname(self):
200251
res = self.api.add(self.fake_dir_test2)
201-
self.assertEqual(sorted(self.fake_dir_res,
202-
key=lambda x: x['Name']),
203-
sorted(res,
204-
key=lambda x: x['Name']))
252+
253+
try:
254+
assert self._sort_by_key(self.fake_dir_res) == self._sort_by_key(res)
255+
finally:
256+
self._clean_up_pins()
205257

206258
def test_add_filepattern_from_dirname(self):
207259
res = self.api.add(self.fake_dir, pattern=self.pattern)
208-
self.assertEqual(sorted(self.fake_dir_fnpattern_res,
209-
key=lambda x: x['Name']),
210-
sorted(res,
211-
key=lambda x: x['Name']))
260+
261+
try:
262+
assert self._sort_by_key(self.fake_dir_fnpattern_res) == self._sort_by_key(res)
263+
finally:
264+
self._clean_up_pins()
265+
212266

213267
def test_add_filepattern_subdir_wildcard(self):
214268
res = self.api.add(self.fake_dir, pattern=self.pattern2)
215-
self.assertEqual(sorted(self.fake_dir_fnpattern2_res,
216-
key=lambda x: x['Name']),
217-
sorted(res,
218-
key=lambda x: x['Name']))
269+
270+
try:
271+
assert self._sort_by_key(self.fake_dir_fnpattern2_res) == self._sort_by_key(res)
272+
finally:
273+
self._clean_up_pins()
219274

220275
def test_add_recursive(self):
221276
res = self.api.add(self.fake_dir, recursive=True)
222-
self.assertEqual(sorted(self.fake_dir_recursive_res,
223-
key=lambda x: x['Name']),
224-
sorted(res,
225-
key=lambda x: x['Name']))
277+
278+
try:
279+
assert self._sort_by_key(self.fake_dir_recursive_res) == self._sort_by_key(res)
280+
finally:
281+
self._clean_up_pins()
226282

227283
def test_add_json(self):
228284
data = {'Action': 'Open', 'Type': 'PR', 'Name': 'IPFS', 'Pubkey': 7}
229285
res = self.api.add_json(data)
230-
self.assertEqual(data,
231-
self.api.get_json(res))
286+
287+
try:
288+
assert data == self.api.get_json(res)
232289

233-
# have to test the string added to IPFS, deserializing JSON will not
234-
# test order of keys
235-
self.assertEqual(
236-
'{"Action":"Open","Name":"IPFS","Pubkey":7,"Type":"PR"}',
237-
self.api.cat(res).decode('utf-8')
238-
)
290+
# have to test the string added to IPFS, deserializing JSON will not
291+
# test order of keys
292+
assert '{"Action":"Open","Name":"IPFS","Pubkey":7,"Type":"PR"}' == self.api.cat(res).decode('utf-8')
293+
finally:
294+
self._clean_up_pins()
239295

240296
def test_add_get_pyobject(self):
241297
data = [-1, 3.14, u'Hän€', b'23' ]
242298
res = self.api.add_pyobj(data)
243-
self.assertEqual(data,
244-
self.api.get_pyobj(res))
299+
300+
try:
301+
assert data == self.api.get_pyobj(res)
302+
finally:
303+
self._clean_up_pins()
245304

246305
def test_get_file(self):
247306
self.api.add(self.fake_file)
307+
308+
try:
309+
test_hash = self.fake[0]['Hash']
248310

249-
test_hash = self.fake[0]['Hash']
250-
251-
self.api.get(test_hash)
252-
self.assertIn(test_hash, os.listdir(os.getcwd()))
311+
self.api.get(test_hash)
312+
assert test_hash in os.listdir(os.getcwd())
253313

254-
os.remove(test_hash)
255-
self.assertNotIn(test_hash, os.listdir(os.getcwd()))
314+
os.remove(test_hash)
315+
assert test_hash not in os.listdir(os.getcwd())
316+
finally:
317+
self._clean_up_pins()
256318

257319
def test_get_dir(self):
258320
self.api.add(self.fake_dir, recursive=True)
259-
260-
test_hash = self.fake[8]['Hash']
261-
262-
self.api.get(test_hash)
263-
self.assertIn(test_hash, os.listdir(os.getcwd()))
264-
265-
shutil.rmtree(test_hash)
266-
self.assertNotIn(test_hash, os.listdir(os.getcwd()))
321+
322+
try:
323+
test_hash = self.fake[8]['Hash']
324+
325+
self.api.get(test_hash)
326+
assert test_hash in os.listdir(os.getcwd())
327+
328+
shutil.rmtree(test_hash)
329+
assert test_hash not in os.listdir(os.getcwd())
330+
finally:
331+
self._clean_up_pins()
267332

268333
def test_get_path(self):
269334
self.api.add(self.fake_file)
270-
271-
test_hash = self.fake[8]['Hash'] + '/fsdfgh'
272-
273-
self.api.get(test_hash)
274-
self.assertIn('fsdfgh', os.listdir(os.getcwd()))
275-
276-
os.remove('fsdfgh')
277-
self.assertNotIn('fsdfgh', os.listdir(os.getcwd()))
335+
336+
try:
337+
test_hash = self.fake[8]['Hash'] + '/fsdfgh'
338+
339+
self.api.get(test_hash)
340+
assert 'fsdfgh' in os.listdir(os.getcwd())
341+
342+
os.remove('fsdfgh')
343+
assert 'fsdfgh' not in os.listdir(os.getcwd())
344+
finally:
345+
self._clean_up_pins()
278346

279347
def test_refs(self):
280348
self.api.add(self.fake_dir, recursive=True)
281-
282-
refs = self.api.refs(self.fake[8]['Hash'])
283-
284-
self.assertEqual(sorted(self.refs_res, key=lambda x: x['Ref']),
285-
sorted(refs, key=lambda x: x['Ref']))
286-
287-
def test_refs_local(self):
288-
refs = self.api.refs_local()
289-
290-
self.assertEqual(sorted(refs[0].keys()), ['Err', 'Ref'])
349+
350+
try:
351+
refs = self.api.refs(self.fake[8]['Hash'])
352+
assert self._sort_by_key(self.refs_res, "Ref") == self._sort_by_key(refs, "Ref")
353+
finally:
354+
self._clean_up_pins()
291355

292356
def test_cat_single_file_str(self):
293357
self.api.add(self.fake_file)
294-
res = self.api.cat('QmQcCtMgLVwvMQGu6mvsRYLjwqrZJcYtH4mboM9urWW9vX')
295-
self.assertEqual(b"dsadsad\n", res)
358+
359+
try:
360+
content = self.api.cat('QmQcCtMgLVwvMQGu6mvsRYLjwqrZJcYtH4mboM9urWW9vX')
361+
assert content == b"dsadsad\n"
362+
finally:
363+
self._clean_up_pins()
296364

297365

298366
@skipIfOffline()

0 commit comments

Comments
 (0)