Skip to content

Commit

Permalink
Transparent constructor argument for Documenter class via the Given f…
Browse files Browse the repository at this point in the history
…unction
  • Loading branch information
pylover committed Aug 25, 2024
1 parent 276b75e commit e312768
Show file tree
Hide file tree
Showing 9 changed files with 44 additions and 74 deletions.
21 changes: 4 additions & 17 deletions bddrest/authoring/given.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,23 @@
from .story import Story


# TODO: add autodoc_format argumnet


class Given(Story, Context):
"""
:param application: A WSGI Application to examine.
:param autodump: A file-like object to write dumped story.
Default is `None`, means autodump is disabled by default.
:param autodoc: A file-like object to write documentation.
Default is `None`, meana autodoc is disabled by default.
:param autodoc_format: Either ``markdown`` or ``html``. default is
``markdown``.
:param fieldinfo: A callable(resource, verb, fieldname) to provide the
field's metadata.
:param autodoc: A dictionary to pass to :class:`Documenter` and enable
auto documentary.
See :class:`Story` for other arguments.
"""

def __init__(self, application, *args, autodump=None, autodoc=None,
autodoc_format='markdown', fieldinfo=None, **kwargs):
**kwargs):
self.application = application
self.autodump = autodump
self.autodoc = autodoc
self.autodoc_format = autodoc_format
self.fieldinfo = fieldinfo
base_call = FirstCall(*args, **kwargs)
base_call.conclude(application)
super().__init__(base_call)
Expand Down Expand Up @@ -71,11 +62,7 @@ def __exit__(self, exc_type, exc_value, traceback):
self.dump(self.autodump)

if self.autodoc:
self.document(
self.autodoc,
format_=self.autodoc_format,
fieldinfo=self.fieldinfo
)
self.document(**self.autodoc)

@property
def response(self):
Expand Down
6 changes: 3 additions & 3 deletions bddrest/authoring/story.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,9 @@ def validate(self):
for call in self.calls:
call.validate()

def document(self, outfile, format_='markdown', **kw):
documenter = Documenter(format_, **kw)
documenter.document(self, outfile)
def document(self, file, **kwargs):
documenter = Documenter(**kwargs)
documenter.document(self, file)

@property
def title(self):
Expand Down
3 changes: 2 additions & 1 deletion bddrest/documentary/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,5 +21,6 @@ def __call__(self, args):

def convert_file(self, source, outfile, format_):
from ..authoring import Story

story = Story.load(source)
story.document(outfile, format_=format_)
story.document(outfile, format=format_)
37 changes: 17 additions & 20 deletions bddrest/documentary/documenter.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@


class Documenter:
def __init__(self, format_, fieldinfo=None):
self.format_ = format_
self.fieldinfo = fieldinfo
def __init__(self, format='markdown', oncall=None, onfield=None):
self.format = format
self.oncall = oncall
self.onfield = onfield

def write_response(self, formatter, response):
formatter.write_header(f'Response: {response.status}', 3)
Expand Down Expand Up @@ -35,6 +36,9 @@ def write_curl(self, formatter, content):

def write_call(self, basecall, call, formatter):

if self.oncall:
self.oncall(call)

formatter.write_header(f'{call.verb} {call.url}', 3)

if call.description:
Expand Down Expand Up @@ -66,61 +70,54 @@ def write_call(self, basecall, call, formatter):
formatter.write_header('Form', 3)
rows = []
for k, value in call.form.items():
info = self.fieldinfo(call.url, call.verb, k) \
if self.fieldinfo else None
info = self.onfield(call, k) if self.onfield else {}
if info is None:
info = {}

for v in value:
info = info or {}
needed = info.get('required')
notnone = info.get('not_none')
type_ = info.get('type')
rows.append((
k,
'?' if needed is None else needed and 'Yes' or 'No',
'?' if notnone is None else notnone and 'No' or 'Yes',
'?' if type_ is None else type_,
v
))

formatter.write_table(
rows,
headers=('Name', 'Required', 'Nullable', 'Type', 'Example')
headers=('Name', 'Required', 'Type', 'Example')
)

if call.multipart \
and (basecall is None or call.multipart != basecall.multipart):
formatter.write_header('Multipart', 3)
rows = []
for k, v in call.multipart.items():
info = self.fieldinfo(call.url, call.verb, k) \
if self.fieldinfo else None
info = self.onfield(call, k) if self.onfield else {}
if info is None:
info = {}

info = info or {}
required = info.get('required')
not_none = info.get('not_none')
type_ = info.get('type')
rows.append((
k,
'?' if required is None else required and 'Yes' or 'No',
'?' if not_none is None else not_none and 'No' or 'Yes',
'?' if type_ is None else type_,
v if not isinstance(v, io.BytesIO) else '<File>',
))

formatter.write_table(
rows,
headers=('Name', 'Required', 'Nullable', 'Type', 'Example')
headers=('Name', 'Required', 'Type', 'Example')
)

if call.json and not isinstance(call.json, list) \
and (basecall is None or call.json != basecall.json):
formatter.write_header('Form', 3)
rows = []
for k, v in call.json.items():
info = self.fieldinfo(call.url, call.verb, k) \
if self.fieldinfo else None

info = info or {}
info = self.onfield(call, k) if self.onfield else {}
required = info.get('required')
not_none = info.get('not_none')
type_ = info.get('type')
Expand Down Expand Up @@ -149,7 +146,7 @@ def write_call(self, basecall, call, formatter):

def document(self, story, outfile):
basecall = story.base_call
formatter = createformatter(self.format_, outfile)
formatter = createformatter(self.format, outfile)
formatter.write_header(basecall.title.capitalize(), 2)
self.write_call(None, basecall, formatter)

Expand Down
2 changes: 1 addition & 1 deletion tests/test_autodocumentation.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def test_autodoc_file_object():
wsgi_application,
title='Testing auto documentation',
url='/apiv1/devices/name: SM-12345678',
autodoc=file,
autodoc=dict(file=file),
):
assert response.status == 200

Expand Down
6 changes: 3 additions & 3 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,9 +68,9 @@ def test_help():
### Form
Name | Required | Nullable | Type | Example
--- | --- | --- | --- | ---
name | ? | ? | ? | BDD Book
Name | Required | Type | Example
--- | --- | --- | ---
name | ? | ? | BDD Book
### CURL
Expand Down
19 changes: 2 additions & 17 deletions tests/test_documentary_html.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

def test_html():

def get_field_info(resource, verb, name):
def get_field_info(call, name):
return dict(
f1=dict(required=True, not_none=True, type='str'),
).get(name)

story = Story.loads(provided_story)
outfile = io.StringIO()
story.document(outfile, fieldinfo=get_field_info, format_='html')
story.document(outfile, onfield=get_field_info, format='html')
outputstring = outfile.getvalue()
assert expected_html == outputstring

Expand Down Expand Up @@ -131,9 +131,6 @@ def get_field_info(resource, verb, name):
Required
</th>
<th>
Nullable
</th>
<th>
Type
</th>
<th>
Expand All @@ -148,9 +145,6 @@ def get_field_info(resource, verb, name):
Yes
</td>
<td>
No
</td>
<td>
str
</td>
<td>
Expand All @@ -168,9 +162,6 @@ def get_field_info(resource, verb, name):
?
</td>
<td>
?
</td>
<td>
123
</td>
</tr>
Expand Down Expand Up @@ -277,9 +268,6 @@ def get_field_info(resource, verb, name):
Required
</th>
<th>
Nullable
</th>
<th>
Type
</th>
<th>
Expand All @@ -294,9 +282,6 @@ def get_field_info(resource, verb, name):
Yes
</td>
<td>
No
</td>
<td>
str
</td>
<td>
Expand Down
18 changes: 9 additions & 9 deletions tests/test_documentary_markdown.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,14 @@

def test_markdown():

def get_field_info(resource, verb, name):
def get_field_info(call, name):
return dict(
f1=dict(required=True, not_none=True, type='str'),
).get(name)

story = Story.loads(provided_story)
outfile = io.StringIO()
story.document(outfile, fieldinfo=get_field_info)
story.document(outfile, onfield=get_field_info)
outputstring = outfile.getvalue()
assert expected_markdown == outputstring

Expand Down Expand Up @@ -81,10 +81,10 @@ def get_field_info(resource, verb, name):
### Form
Name | Required | Nullable | Type | Example
--- | --- | --- | --- | ---
f1 | Yes | No | str | abc
f2 | ? | ? | ? | 123
Name | Required | Type | Example
--- | --- | --- | ---
f1 | Yes | str | abc
f2 | ? | ? | 123
### Request Headers
Expand Down Expand Up @@ -129,9 +129,9 @@ def get_field_info(resource, verb, name):
### Form
Name | Required | Nullable | Type | Example
--- | --- | --- | --- | ---
f1 | Yes | No | str | cba
Name | Required | Type | Example
--- | --- | --- | ---
f1 | Yes | str | cba
### Request Headers
Expand Down
6 changes: 3 additions & 3 deletions tests/test_multipart_form.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,9 +36,9 @@ def wsgi_application(environ, start_response):
### Multipart
Name | Required | Nullable | Type | Example
--- | --- | --- | --- | ---
a | ? | ? | ? | <File>
Name | Required | Type | Example
--- | --- | --- | ---
a | ? | ? | <File>
### CURL
Expand Down

0 comments on commit e312768

Please sign in to comment.