Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Consumer Methods to Reduce Boilerplate #159

Merged
merged 5 commits into from
Apr 23, 2019
Merged

Conversation

prkumar
Copy link
Owner

@prkumar prkumar commented Apr 23, 2019

Fixes #151

Consumer methods are methods decorated with Uplink's HTTP method decorators,
such as @get or @post (see
here for more background).

Consumer methods can be used as decorators to minimize duplication across similar
consumer method definitions.

For example, you can define consumer method templates like so:

from uplink import Consumer, get, json

@returns.json
@json
@get
def get_json():
     """Template for GET request that consumes and produces JSON."""

class GitHub(Consumer):
    @get_json("/users/{user}")
    def get_user(self, user):
        """Fetches a specific GitHub user."""

Further, you can use this technique to remove duplication across definitions
of similar consumer methods, whether or not the methods are defined in the same
class:

from uplink import Consumer, get, params, timeout

class GitHub(Consumer):
    @timeout(10)
    @get("/users/{user}/repos")
    def get_user_repos(self, user):
        """Retrieves the repos that the user owns."""

    # Extends the above method to define a variant:
    @params(type="member")
    @get_user_repos
    def get_team_repos_for_user(self, user):
        """
        Retrieves the repos that are owned by teams
        that the user holds membership in.
        """

class EnhancedGitHub(Github):
    # Updates the return type of an inherited method.
    @GitHub.get_user_repos
    def get_user_repos(self, user) -> List[Repo]:
        """Retrieves the repos that the user owns."""

CC: @liiight

@prkumar prkumar added this to the v0.9.0 milestone Apr 23, 2019
@codecov
Copy link

codecov bot commented Apr 23, 2019

Codecov Report

Merging #159 into master will not change coverage.
The diff coverage is 100%.

Impacted file tree graph

@@          Coverage Diff          @@
##           master   #159   +/-   ##
=====================================
  Coverage     100%   100%           
=====================================
  Files          41     41           
  Lines        2149   2164   +15     
  Branches      172    173    +1     
=====================================
+ Hits         2149   2164   +15
Impacted Files Coverage Δ
uplink/decorators.py 100% <100%> (ø) ⬆️
uplink/commands.py 100% <100%> (ø) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 0d29483...527e8e4. Read the comment docs.

@prkumar
Copy link
Owner Author

prkumar commented Apr 23, 2019

TODO: Found an issue when this is used in conjunction with @returns.* decorators:

    from uplink import Consumer, get, json, returns

    @returns.json
    @json
    @get
    def get_json():
        """Template for GET request that consumes and produces JSON."""

    class GitHub(Consumer):
        @get_json("/users/{user}")
        def get_user(self, user):
             """Fetches a specific GitHub user."""

Get the following traceback:

Traceback (most recent call last):
  File "/Users/prkumar/Library/Preferences/PyCharm2018.3/scratches/scratch_12.py", line 17, in <module>
    print(github.get_user("prkumar"))
  File "/Users/prkumar/Developer/uplink/uplink/builder.py", line 99, in __call__
    self._request_definition.define_request(request_builder, args, kwargs)
  File "/Users/prkumar/Developer/uplink/uplink/commands.py", line 326, in define_request
    self._method_handler.handle_builder(request_builder)
  File "/Users/prkumar/Developer/uplink/uplink/decorators.py", line 62, in handle_builder
    annotation.modify_request(request_builder)
  File "/Users/prkumar/Developer/uplink/uplink/returns.py", line 61, in modify_request
    if not return_type.is_applicable(self):
AttributeError: 'NoneType' object has no attribute 'is_applicable'

@prkumar prkumar merged commit 8483dcc into master Apr 23, 2019
@prkumar prkumar mentioned this pull request Jun 5, 2019
@prkumar prkumar deleted the v0.9.0/extend-method branch June 7, 2019 01:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Support extending a consumer method using the definition of another
1 participant