Skip to content

Commit 660451a

Browse files
authored
Merge pull request #46 from ibmjstart/master
Document, test, and improve functionality.
2 parents 31ca71e + bcff3c5 commit 660451a

26 files changed

+2492
-300
lines changed

.coveragerc-py35

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[html]
2+
directory = htmlcov-py35

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,4 @@ htmlcov*
1010
**/__pycache__/
1111
.cache
1212
docs/build/
13+
.python-version

fake_dir/fsdfgh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dsadsad

fake_dir/popoiopiu

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
oooofiopfsdpio

fake_dir/test2/fssdf

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dsdsdsadsdsad

fake_dir/test2/llllg

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dsdsadjs

fake_dir/test3/ppppoooooooooo

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dsasasd

ipfsApi/__init__.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,4 @@
22

33
from .client import *
44

5-
65
__version__ = '0.2.3'

ipfsApi/client.py

Lines changed: 544 additions & 114 deletions
Large diffs are not rendered by default.

ipfsApi/commands.py

Lines changed: 129 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
"""Defines the skeleton of different command structures.
2+
3+
Classes:
4+
Command -- A simple command that can make requests to a path.
5+
ArgCommand -- A Command subclass for commands with arguments.
6+
FileCommand -- A Command subclass for file-manipulation commands.
7+
DownloadCommand -- A Command subclass for file download commands.
8+
"""
9+
110
from __future__ import absolute_import
211

312
import os
@@ -10,35 +19,105 @@
1019

1120

1221
class Command(object):
22+
"""Defines a command.
23+
24+
Public methods:
25+
__init__ -- creates a Command that will make requests to a given path
26+
request -- make a request to this command's path
27+
28+
Instance variables:
29+
path -- the url path that this Command will make requests to
30+
"""
1331

1432
def __init__(self, path):
33+
"""Creates a Command.
34+
35+
Keyword arguments:
36+
path -- the url path that this Command makes requests to
37+
"""
1538
self.path = path
1639

1740
def request(self, client, *args, **kwargs):
41+
"""Makes a request to the client with arguments.
42+
43+
Keyword arguments:
44+
client -- the HTTP client to use for the request
45+
args -- unused unnamed arguments
46+
kwargs -- additional arguments to HTTP client's request
47+
"""
1848
return client.request(self.path, **kwargs)
1949

2050

2151
class ArgCommand(Command):
52+
"""Defines a command that takes arguments.
53+
54+
Subclass of Command.
55+
56+
Public methods:
57+
__init__ -- extends Command constructor to also take a number of required
58+
arguments
59+
request -- makes a request to the ArgCommand's path with given arguments
60+
61+
Instance variables:
62+
path -- the url path of that this command will send data to
63+
argc -- the number of arguments required by this command
64+
"""
2265

2366
def __init__(self, path, argc=None):
67+
"""Creates an ArgCommand.
68+
69+
Keyword arguments:
70+
path -- the url path to which the command with send data
71+
argc -- the number of arguments required by this command
72+
"""
2473
Command.__init__(self, path)
2574
self.argc = argc
2675

2776
def request(self, client, *args, **kwargs):
77+
"""Makes a request to the client with arguments.
78+
79+
Can raise an InvalidArgument if the wrong number of arguments is
80+
provided.
81+
82+
Keyword arguments:
83+
client -- the HTTP client to use for the request
84+
args -- the arguments to the HTTP client's request
85+
kwargs -- additional arguments to HTTP client's request
86+
"""
2887
if self.argc and len(args) != self.argc:
2988
raise InvalidArguments("[%s] command requires %d arguments." % (
3089
self.path, self.argc))
3190
return client.request(self.path, args=args, **kwargs)
3291

3392

3493
class FileCommand(Command):
94+
"""Defines a command for manipulating files.
95+
96+
Subclass of Command.
97+
98+
Public methods:
99+
request -- overrides Command's request to access a file or files
100+
files -- adds file-like objects as a multipart request to IPFS
101+
directory -- loads a directory recursively into IPFS
102+
103+
Instance variables:
104+
path -- the path to make the file requests to
105+
"""
35106

36107
def request(self, client, args, f, **kwargs):
37-
"""
38-
Takes either a file object, a filename, an iterable of filenames, an
39-
iterable of file objects, or a heterogeneous iterable of file objects
40-
and filenames. Can only take one directory at a time, which will be
108+
"""Makes a request for a file or files.
109+
110+
Can only take one directory at a time, which will be
41111
traversed (optionally recursive).
112+
113+
Keyword arguments:
114+
client -- the http client to send requests to
115+
args -- the arguments to the HTTP client's request
116+
f -- a file object, a filename, an iterable of filenames, an
117+
iterable of file objects, or a heterogeneous iterable of file
118+
objects and filenames
119+
kwargs -- additional arguments (include 'recursive' if recursively
120+
copying a directory)
42121
"""
43122
if kwargs.pop('recursive', False):
44123
return self.directory(client, args, f, recursive=True, **kwargs)
@@ -47,29 +126,67 @@ def request(self, client, args, f, **kwargs):
47126
else:
48127
return self.files(client, args, f, **kwargs)
49128

50-
def files(self, client, args, files, chunk_size=default_chunk_size, **kwargs):
51-
"""
52-
Adds file-like objects as a multipart request to IPFS.
129+
def files(self, client, args, files,
130+
chunk_size=default_chunk_size, **kwargs):
131+
"""Adds file-like objects as a multipart request to IPFS.
132+
133+
Keyword arguments:
134+
client -- the http client to send requests to
135+
args -- the arguments to the HTTP client's request
136+
files -- the files being requested
137+
chunk_size -- the size of the chunks to break the files into
138+
kwargs -- additional arguments to HTTP client's request
53139
"""
54140
body, headers = multipart.stream_files(files,
55141
chunk_size=chunk_size)
56-
return client.request(self.path, args=args, data=body, headers=headers, **kwargs)
142+
return client.request(self.path, args=args, data=body,
143+
headers=headers, **kwargs)
57144

58145
def directory(self, client, args, dirname,
59146
match='*', recursive=False,
60147
chunk_size=default_chunk_size, **kwargs):
61-
"""
62-
Loads a directory recursively into IPFS, files are matched against the
63-
given pattern.
148+
"""Loads a directory recursively into IPFS.
149+
150+
Files are matched against the given pattern.
151+
152+
Keyword arguments:
153+
client -- the http client to send requests to
154+
args -- the arguments to the HTTP client's request
155+
dirname -- the name of the directory being requested
156+
match -- a pattern to match the files against
157+
recursive -- boolean for whether to load contents recursively
158+
chunk_size -- the size of the chunks to break the files into
159+
kwargs -- additional arguments to HTTP client's request
64160
"""
65161
body, headers = multipart.stream_directory(dirname,
66162
fnpattern=match,
67163
recursive=recursive,
68164
chunk_size=chunk_size)
69-
return client.request(self.path, args=args, data=body, headers=headers, **kwargs)
165+
return client.request(self.path, args=args, data=body,
166+
headers=headers, **kwargs)
70167

71168

72169
class DownloadCommand(Command):
170+
"""Downloads requested files.
171+
172+
Subclass of Command
173+
174+
Public methods:
175+
request -- make a request to this DownloadCommand's path to download a
176+
given file
177+
178+
Instance variables:
179+
path -- the url path to send requests to
180+
"""
73181

74182
def request(self, client, *args, **kwargs):
183+
"""Requests a download from the HTTP Client.
184+
185+
See the HTTP client's doc for details of what to pass in.
186+
187+
Keyword arguments:
188+
client -- the http client to send requests to
189+
args -- the arguments to the HTTP client
190+
kwargs -- additional arguments to the HTTP client
191+
"""
75192
return client.download(self.path, args=args, **kwargs)

ipfsApi/encoding.py

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,15 @@
1+
"""Defines encoding related classes.
2+
3+
Classes:
4+
Encoding - An abstract based for a data parser/encoder interface.
5+
Json - A subclass of Encoding that handles JSON parsing and encoding.
6+
Protobuf - A subclass of Encoding to handle Protobuf parsing/encoding. TO DO
7+
Xml - A subclass of Encoding to handle Xml parsing and encoding. TO DO
8+
9+
Functions:
10+
get_encoding(name) - Retrieves the Encoder object for the named encoding.
11+
"""
12+
113
from __future__ import absolute_import
214

315
import json
@@ -6,34 +18,54 @@
618

719

820
class Encoding(object):
9-
"""
10-
Abstract base for a data parser/encoder interface interface
21+
"""Abstract base for a data parser/encoder interface.
22+
23+
Public methods:
24+
parse -- parses string into corresponding encoding
25+
encode - serialize a raw object into corresponding encoding
1126
"""
1227

1328
def parse(self, string):
29+
"""Parses string into corresponding encoding.
30+
31+
Keyword arguments:
32+
string - string to be parsed
33+
"""
1434
raise NotImplemented
1535

1636
def encode(self, obj):
37+
"""Serialize a raw object into corresponding encoding.
38+
39+
Keyword arguments:
40+
obj - object to be encoded.
41+
"""
1742
raise NotImplemented
1843

1944

2045
class Json(Encoding):
21-
"""
22-
JSON parser/encoder that handles concatenated JSON
46+
"""JSON parser/encoder that handles concatenated JSON.
47+
48+
Public methods:
49+
__init__ -- creates a Json encoder/decoder
50+
parse -- returns a Python object decoded from JSON object(s) in raw
51+
encode -- returns obj serialized as JSON formatted string
2352
"""
2453
name = 'json'
2554

2655
def __init__(self):
56+
"""Creates a JSON encoder/decoder"""
2757
self.encoder = json.JSONEncoder()
2858
self.decoder = json.JSONDecoder()
2959

3060
def parse(self, raw):
31-
"""
32-
Returns a Python object decoded from JSON object(s) in raw
61+
"""Returns a Python object decoded from JSON object(s) in raw
3362
3463
Some responses from the IPFS api are a concatenated string of JSON
3564
objects, which crashes json.loads(), so we need to use this instead as
3665
a general approach.
66+
67+
Keyword arguments:
68+
raw -- raw JSON object
3769
"""
3870
json_string = raw.strip()
3971
results = []
@@ -54,16 +86,21 @@ def parse(self, raw):
5486

5587
def encode(self, obj):
5688
"""
57-
Returns obj encoded as JSON in a binary string
89+
Returns obj serialized as JSON formatted string
90+
91+
Keyword arguments:
92+
obj -- generic Python object
5893
"""
5994
return json.dumps(obj)
6095

6196

6297
class Protobuf(Encoding):
98+
"""Protobuf parser/encoder that handles protobuf."""
6399
name = 'protobuf'
64100

65101

66102
class Xml(Encoding):
103+
"""XML parser/encoder that handles XML."""
67104
name = 'xml'
68105

69106
# encodings supported by the IPFS api (default is json)
@@ -77,6 +114,9 @@ class Xml(Encoding):
77114
def get_encoding(name):
78115
"""
79116
Returns an Encoder object for the named encoding
117+
118+
Keyword arguments:
119+
name - named encoding. Supported options: Json, Protobuf, Xml
80120
"""
81121
try:
82122
return __encodings[name.lower()]()

ipfsApi/exceptions.py

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,40 @@
1+
"""Defines the skeleton for exceptions.
2+
3+
Classes:
4+
ipfsApiError - A base class for generic exceptions.
5+
InvalidCommand - An ipfsApiError subclass for invalid commands.
6+
InvalidArguments - An ipfsApiError subclass for invalid arguments.
7+
InvalidPath - An ipfsApiError subclass for invalid path.
8+
FileCommandException - An ipfsApiError subclass for file command exceptions.
9+
EncodingException - An ipfsApiError subclass for encoding exceptions.
10+
"""
11+
12+
113
class ipfsApiError(Exception):
14+
"""Base class for exceptions in this module."""
215
pass
316

417

518
class InvalidCommand(ipfsApiError):
19+
"""Exception raised for an invalid command."""
620
pass
721

822

923
class InvalidArguments(ipfsApiError):
24+
"""Exception raised for invalid arguments."""
1025
pass
1126

1227

1328
class InvalidPath(ipfsApiError):
29+
"""Exception raised for an invalid path."""
1430
pass
1531

1632

1733
class FileCommandException(ipfsApiError):
34+
"""Exception raised for file command exception."""
1835
pass
1936

2037

2138
class EncodingException(ipfsApiError):
39+
"""Exception raised for invalid encoding."""
2240
pass

0 commit comments

Comments
 (0)