Skip to content

Commit 47db350

Browse files
Merge branch 'release/2.0.2'
2 parents b3a9f61 + 3ead313 commit 47db350

File tree

11 files changed

+155
-145
lines changed

11 files changed

+155
-145
lines changed

.coveragerc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,4 +3,5 @@ include = hug/*.py
33
exclude_lines = def hug
44
def serve
55
sys.stdout.buffer.write
6+
class Socket
67

ACKNOWLEDGEMENTS.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ Documenters
3535
- Sven-Hendrik Haase (@svenstaro)
3636
- Matt Caldwell (@mattcaldwell)
3737
- berdario (@berdario)
38+
- Cory Taylor (@coryandrewtaylor)
3839

3940
--------------------------------------------
4041

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,10 @@ Ideally, within a virtual environment.
1212
Changelog
1313
=========
1414

15+
### 2.0.2
16+
- Work-around bug that was keeping hug from working on Windows machines
17+
- Introduced a delete method to the abstract hug store module
18+
1519
### 2.0.1
1620
- Add in-memory data / session store for testing
1721
- Default hug.use.HTTP to communicate over JSON body

documentation/DIRECTIVES.md

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,24 @@
11
hug directives (automatic argument injection)
22
===================
33

4-
Often times you'll find yourself needing something particular to an interface (say a header, a session, or content_type) but don't want to tie your function
5-
to a single interface. To support this: hug introduces the concept of `directives`. In hug directives are simply arguments that have been registered to automatically provide a parameter value based on knowledge known to the interface.
4+
Oftentimes you'll find yourself needing something particular to an interface (say a header, a session, or content_type), but don't want to tie your function
5+
to a single interface. To support this, hug introduces the concept of `directives`. In hug, directives are simply arguments that have been registered to automatically provide a parameter value based on knowledge known to the interface.
66

7-
For example - this is the built in session directive:
7+
For example, this is the built-in session directive:
88

99

1010
@hug.directive()
1111
def session(context_name='session', request=None, **kwargs):
1212
"""Returns the session associated with the current request"""
1313
return request and request.context.get(context_name, None) or None
1414

15-
Then when using this directive in your code, you can either specify the directive via type annotation:
15+
Then, when using this directive in your code, you can either specify the directive via type annotation:
1616

1717
@hug.get()
1818
def my_endpoint(session: hug.directives.session):
1919
session # is here automatically, without needing to be passed in
2020

21-
Or, prefixing the argument with `hug_`:
21+
Or by prefixing the argument with `hug_`:
2222

2323
@hug.get()
2424
def my_endpoint(hug_session):
@@ -35,22 +35,22 @@ Built-in directives
3535

3636
hug provides a handful of directives for commonly needed attributes:
3737

38-
- hug.directives.Timer (hug_timer=precision): Stores the time the interface was initially called, returns how much time has passed since the function was called if casted as a float. Automatically converts to a the time taken when returned as part of a JSON structure. The default value is used to specify the float precision desired when keeping track of the time passed
39-
- hug.directives.module (hug_module): Passes along the module that contains the API associated with this endpoint
40-
- hug.directives.api (hug_api): Passes along the hug API singleton associated with this endpoint
41-
- hug.directives.api_version (hug_api_version): Passes along the version of the API being called
42-
- hug.directives.documentation (hug_documentation): Generates and passes along the entire set of documentation for the API the endpoint is contained within
43-
- hug.directives.session (hug_session=context_name): Passes along the session associated with the current request. The default value is used to provide a different key where the value is stored on the request.context object.
44-
- hug.directives.user (hug_user): Passes along the user object associated with the request
45-
- hug.directives.CurrentAPI (hug_current_api): Passes along a smart version aware API caller, to enable calling other functions within your API with reissurence the correct function is being called for the version of the API being requested
38+
- hug.directives.Timer (hug_timer=precision): Stores the time the interface was initially called, returns how much time has passed since the function was called, if casted as a float. Automatically converts to the time taken when returned as part of a JSON structure. The default value specifies the float precision desired when keeping track of the time passed.
39+
- hug.directives.module (hug_module): Passes along the module that contains the API associated with this endpoint.
40+
- hug.directives.api (hug_api): Passes along the hug API singleton associated with this endpoint.
41+
- hug.directives.api_version (hug_api_version): Passes along the version of the API being called.
42+
- hug.directives.documentation (hug_documentation): Generates and passes along the entire set of documentation for the API that contains the endpoint.
43+
- hug.directives.session (hug_session=context_name): Passes along the session associated with the current request. The default value provides a different key whose value is stored on the request.context object.
44+
- hug.directives.user (hug_user): Passes along the user object associated with the request.
45+
- hug.directives.CurrentAPI (hug_current_api): Passes along a smart, version-aware API caller, to enable calling other functions within your API, with reassurance that the correct function is being called for the version of the API being requested.
4646

4747
Building custom directives
4848
===================
4949

50-
hug provides the `@hug.directive()` to enable creation of new directives. It takes one argument: apply_globally which defaults to False.
51-
If you set this parameter to True the hug directive will be automatically made available as a magic `hug_` argument on all endpoints outside of just your defined API. This is not a concern if your applying directives via type annotation.
50+
hug provides the `@hug.directive()` to enable creation of new directives. It takes one argument: apply_globally, which defaults to False.
51+
If you set this parameter to True, the hug directive will be automatically made available as a magic `hug_` argument on all endpoints outside of your defined API. This is not a concern if you're applying directives via type annotation.
5252

53-
The most basic directive will simply take an optional default value, and **kwargs:
53+
The most basic directive will take an optional default value, as well as **kwargs:
5454

5555
@hug.directive()
5656
def basic(default=False, **kwargs):
@@ -65,16 +65,16 @@ This directive could then be used like this:
6565

6666
assert endpoint() == 'hi there!'
6767

68-
It's important to always accept **kwargs for directive functions as each interface get's to decide it's own set of
69-
key word arguments to send to the directive, which can then be used to pull-in information for the directive.
68+
It's important to always accept **kwargs for directive functions, as each interface gets to decide its own set of
69+
keyword arguments to send to the directive, which can then be used to pull in information for the directive.
7070

7171
Common directive key word parameters
7272
===================
7373

74-
Independ of what interface a directive is being ran through, the following key word arguments will be passed to it:
74+
Independent of interface, the following key word arguments will be passed to the directive:
7575

76-
- `interface` - the interface that the directive is being ran through. Useful for conditionally injecting different data via the decorator depending on the interface it is being called through, as demonstrated at the bottom of this section
77-
- `api` - the API singleton associated with this endpoint
76+
- `interface` - The interface that the directive is being run through. Useful for conditionally injecting data (via the decorator) depending on the interface it is being called through, as demonstrated at the bottom of this section.
77+
- `api` - The API singleton associated with this endpoint.
7878

7979
Interface Example:
8080

@@ -92,15 +92,15 @@ Interface Example:
9292
HTTP directive key word parameters
9393
===================
9494

95-
Directives are passed the following additional keyword parameters when they are being ran through an HTTP interface:
95+
Directives are passed the following additional keyword parameters when they are being run through an HTTP interface:
9696

97-
- `response`: The HTTP response object that will be returned for this request
98-
- `request`: The HTTP request object that caused this interface to be called
99-
- `api_version`: The version of the endpoint being hit
97+
- `response`: The HTTP response object that will be returned for this request.
98+
- `request`: The HTTP request object that caused this interface to be called.
99+
- `api_version`: The version of the endpoint being hit.
100100

101101
CLI directive key word parameters
102102
===================
103103

104-
Directives get one additional argument when they are being ran through a command line interface:
104+
Directives get one additional argument when they are run through a command line interface:
105105

106-
- `argparse`: The argparse instance created to parse command line arguments
106+
- `argparse`: The argparse instance created to parse command line arguments.

documentation/OUTPUT_FORMATS.md

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
hug output formats
22
===================
33

4-
Every endpoint that is exposed via an external facing interface will need to output the data returned in a standard format that users of the interface will be able to understand.
4+
Every endpoint that is exposed through an externally facing interface will need to return data in a standard, easily understandable format.
55

6-
The default output format for all hug APIs is JSON unless you explicitly specify a different default output_format:
6+
The default output format for all hug APIs is JSON. However, you may explicitly specify a different default output_format:
77

88
hug.API(__name__).output_format = hug.output_format.html
99

@@ -13,13 +13,13 @@ or:
1313
def my_output_formatter(data, request, response):
1414
# Custom output formatting code
1515

16-
Or to specify an output_format for a specific endpoint, simply specify the output format within it's router:
16+
Or, to specify an output_format for a specific endpoint, simply specify the output format within its router:
1717

1818
@hug.get(output=hug.output_format.html)
1919
def my_endpoint():
2020
return # HTML generating code goes here
2121

22-
Remember that you can also always use route chaining to specify an output format for a group of endpoints within an API:
22+
You can use route chaining to specify an output format for a group of endpoints within an API:
2323

2424
html = hug.get(output=hug.output_format.html)
2525

@@ -31,7 +31,7 @@ Remember that you can also always use route chaining to specify an output format
3131
def root():
3232
return # HTML generating code goes here
3333

34-
Finally, it's perfectly valid for an output format to in essence be a collection of other output format's that get conditionally used. For example using the built in suffix output format:
34+
Finally, an output format may be a collection of different output formats that get used conditionally. For example, using the built-in suffix output format:
3535

3636
suffix_output = hug.output_format.suffix({'.js': hug.output_format.json,
3737
'.html':hug.output_format.html})
@@ -40,33 +40,33 @@ Finally, it's perfectly valid for an output format to in essence be a collection
4040
def my_endpoint():
4141
return ''
4242

43-
In this case if the endpoint is accesed via my_endpoint.js the output type will be JSON, however if it's accesed via .html the output type will be HTML.
43+
In this case, if the endpoint is accesed via my_endpoint.js, the output type will be JSON; however if it's accesed via my_endoint.html, the output type will be HTML.
4444

45-
Built in hug output formats
45+
Built-in hug output formats
4646
===================
4747

48-
hug provides a large catolog of built in output formats that can be used to build useful APIs right away:
48+
hug provides a large catalog of built-in output formats, which can be used to build useful APIs right away:
4949

50-
- `hug.output_format.json`: The default hug output formatter for all endpoints, outputs in Javascript Serialized Object Notation (JSON)
51-
- `hug.output_format.text`: Outputs in a plain text format
52-
- `hug.output_format.html`: Outputs Hyper Text Markup Language (HTML)
53-
- `hug.output_format.json_camelcase`: Outputs in the JSON format but first converts all keys to camelCase to better conform to Javascript coding standards.
54-
- `hug.output_format.pretty_json`: Outputs in the JSON format, with extra white-space to improve human readability
55-
- `hug.output_format.image(format)`: Outputs an image (of the specified format)
50+
- `hug.output_format.json`: The default hug output formatter for all endpoints; outputs in Javascript Serialized Object Notation (JSON).
51+
- `hug.output_format.text`: Outputs in a plain text format.
52+
- `hug.output_format.html`: Outputs Hyper Text Markup Language (HTML).
53+
- `hug.output_format.json_camelcase`: Outputs in the JSON format, but first converts all keys to camelCase to better conform to Javascript coding standards.
54+
- `hug.output_format.pretty_json`: Outputs in the JSON format, with extra whitespace to improve human readability.
55+
- `hug.output_format.image(format)`: Outputs an image (of the specified format).
5656
- There are convience calls in the form `hug.output_format.{FORMAT}_image for the following image types: 'png', 'jpg', 'bmp', 'eps', 'gif', 'im', 'jpeg', 'msp', 'pcx', 'ppm', 'spider', 'tiff', 'webp', 'xbm',
5757
'cur', 'dcx', 'fli', 'flc', 'gbr', 'gd', 'ico', 'icns', 'imt', 'iptc', 'naa', 'mcidas', 'mpo', 'pcd',
5858
'psd', 'sgi', 'tga', 'wal', 'xpm', and 'svg'.
59-
Automatically works on returned file names, streams, or objects that produce an image on read, save, or render
59+
Automatically works on returned file names, streams, or objects that produce an image on read, save, or render.
6060

61-
- `hug.output_format.video(video_type, video_mime, doc)`: Streams a video back to the user in the specified format
61+
- `hug.output_format.video(video_type, video_mime, doc)`: Streams a video back to the user in the specified format.
6262
- There are convience calls in the form `hug.output_format.{FORMAT}_video for the following video types: 'flv', 'mp4', 'm3u8', 'ts', '3gp', 'mov', 'avi', and 'wmv'.
63-
Automatically works on returned file names, streams, or objects that produce a video on read, save, or render
63+
Automatically works on returned file names, streams, or objects that produce a video on read, save, or render.
6464

65-
- `hug.output_format.file`: Will dynamically determine and stream a file based on its content. Automatically works on returned file names and streams
65+
- `hug.output_format.file`: Will dynamically determine and stream a file based on its content. Automatically works on returned file names and streams.
6666

67-
- `hug.output_format.on_content_type(handlers={content_type: output_format}, default=None)`: Dynamically changes the output format based on the request content type
68-
- `hug.output_format.suffix(handlers={suffix: output_format}, default=None)`: Dynamically changes the output format based on a suffix at the end of the requested path
69-
- `hug.output_format.prefix(handlers={suffix: output_format}, defualt=None)`: Dynamically changes the output format based on a prefix at the begining of the requested path
67+
- `hug.output_format.on_content_type(handlers={content_type: output_format}, default=None)`: Dynamically changes the output format based on the request content type.
68+
- `hug.output_format.suffix(handlers={suffix: output_format}, default=None)`: Dynamically changes the output format based on a suffix at the end of the requested path.
69+
- `hug.output_format.prefix(handlers={suffix: output_format}, defualt=None)`: Dynamically changes the output format based on a prefix at the begining of the requested path.
7070

7171
Creating a custom output format
7272
===================
@@ -77,7 +77,7 @@ An output format is simply a function with a content type attached that takes a
7777
def format_as_text(data, request=None, response=None):
7878
return str(content).encode('utf8')
7979

80-
A common pattern is to only apply the output format validation errors aren't passed in since it's hard to deal with this for several formats (such as images) and it may make more sense to simply return the error as JSON. hug makes this pattern simple as well with the `hug.output_format.on_valid` decorator:
80+
A common pattern is to only apply the output format. Validation errors aren't passed in, since it's hard to deal with this for several formats (such as images), and it may make more sense to simply return the error as JSON. hug makes this pattern simple, as well, with the `hug.output_format.on_valid` decorator:
8181

8282
@hug.output_format.on_valid('file/text')
8383
def format_as_text_when_valid(data, request=None, response=None):

hug/_version.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,4 @@
2121
"""
2222
from __future__ import absolute_import
2323

24-
current = "2.0.1"
24+
current = "2.0.2"

hug/store.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,8 @@ def exists(self, key):
4747
def set(self, key, data):
4848
"""Set data object for given store key."""
4949
self._data[key] = data
50+
51+
def delete(self, key):
52+
"""Delete data for given store key."""
53+
if key in self._data:
54+
del self._data[key]

0 commit comments

Comments
 (0)