Skip to content

Instantly share code, notes, and snippets.

@FrostyX
Last active February 15, 2018 21:07
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save FrostyX/46206d61b69033fdd04b4e953ec40b89 to your computer and use it in GitHub Desktop.
Save FrostyX/46206d61b69033fdd04b4e953ec40b89 to your computer and use it in GitHub Desktop.
Copr APIv3 samples
# Copr APIv3 - Option 1
# - instancing Resource
# - Resource methods return Response objects
from munch import Munch
class Client(object):
def __init__(self):
self.builds = BuildResource(None)
class BuildResource(object):
def __init__(self, config):
pass
def get(self, build_id):
request = Request(endpoint="/build/{}".format(build_id))
# request.get() / .send() to get the Response
return Response(data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
})
class Request(object):
# This should be a replacement of the _fetch method from APIv1
def __init__(self, endpoint, data=None):
pass
# With no descendants like BuildResponse
class Response(object):
def __init__(self, headers=None, data=None):
self.headers = headers
self.data = Munch(data)
client = Client()
response = client.builds.get(5)
assert response.data.id == 5
# Or we can use Response only internally and return just Munch to the user,
# which is basically option 4. It could be done by response.to_munch() and
# it could additionally put headers to the munch (keys starting with _ or something
# Copr APIv3 - Option 2
# https://pagure.io/copr/copr/issue/218#comment-492758
# How else we could hande config for static class?
# from ... import config
class Client(object):
def __init__(self):
# As @clime suggested
self.Build = Build
# But I like this much better
self.build = Build
class Build(object):
def __init__(self, data):
self.data = data
def __getattr__(self, attr):
return self.data[attr]
@classmethod
def get(cls, build_id):
# ...
data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
}
return cls(data)
# It can't have a same name as the instance method
@classmethod
def cancel_by_id(cls, build_id):
pass
def cancel(self):
return Build.cancel_by_id(self.id)
client = Client()
build = client.Build.get(5)
assert build.id == 5
build.cancel()
# Copr APIv3 - Option 3
# - Basically same approach as option 2, but with separated class methods to BuildResource,
# which is now instanceable
class Client(object):
def __init__(self):
self.builds = BuildResource(None)
class Entity(object):
@classmethod
def from_dict(cls, data):
entity = Entity()
entity.data = data
return entity
def __getattr__(self, attr):
return self.data[attr]
class Build(Entity):
# Now we can have same method name
def cancel(self):
pass
class BuildResource(object):
def __init__(self, config=None):
pass
def get(self, build_id):
data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
}
return Build.from_dict(data)
def cancel(self, build_id):
pass
client = Client()
build = client.builds.get(5)
assert build.id == 5
# Copr APIv3 - Option 4
# https://pagure.io/copr/copr/issue/218#comment-492808 (second part of the comment)
from munch import Munch
from copr_apiv3_option1 import Request
class Client(object):
def __init__(self):
self.builds = BuildResource(None)
class BuildResource(object):
def __init__(self, config):
pass
def get(self, build_id):
request = Request(endpoint="/build/{}".format(build_id))
# request.get() / .send() to get the data
data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
}
return Munch(data)
client = Client()
build = client.builds.get(5)
assert build.id == 5
# Copr APIv3 - Option 5
# - No namespacing, no client, and functions spread among multiple files
# - https://pagure.io/copr/copr/issue/218#comment-492808 (first part of the comment)
from munch import Munch
from copr_apiv3_option1 import Request
# Read the ~/.config/copr
DEFAULT_CONFIG = {"login": "foo", "username": "frostyx",
"token": "bar", "copr_url": "http://frontend/"}
# How should this class name? `Build` seems to be representing a one particular build,
# maybe it should rather be `BuildResource`. Same issue comes with naming an instance
# of this class. User will work with it a lot, so the name should be short and sexy,
# not like `build_resource`, but also not just a `build` (already explained). The best
# that comes to my mind is `build_r`, `r_build` or `br`.
class Build(object):
def __init__(self, config=DEFAULT_CONFIG):
self.config = config
def get(self, build_id):
request = Request(endpoint="/build/{}".format(build_id))
# request.get() / .send() to get the data
data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
}
return Munch(data)
# When using default configuration,
# user doesn't have to care about specifying it in argument
build_r1 = Build()
build1 = build_r1.get(5)
assert build1.id == 5
assert build_r1.config["username"] == "frostyx"
# Using an alternative configuration
config = {"login": "baz", "username": "someone",
"token": "qux", "copr_url": "http://frontend/"}
build_r2 = Build(config=config)
build2 = build_r2.get(10)
assert build2.id == 10
assert build_r2.config["username"] == "someone"
# Copr APIv3 - Option 6
# - No namespacing, but functions spread among multiple files
from copr_apiv3_option6_init import Client
client = Client()
build = client.get_build(5)
assert build.id == 5
from munch import Munch
from copr_apiv3_option1 import Request
from copr_apiv3_option6_client import client_method
@client_method
def get_build(self, build_id):
request = Request(endpoint="/build/{}".format(build_id))
# request.get() / .send() to get the data
data={
"id": build_id,
"owner": "foo",
"project": "bar",
"results": "..."
# ...
}
return Munch(data)
class Client(object):
def __init__(self):
pass
def client_method(fun):
# Could also modify the arguments, so we won't have to
# write `self` to the build.py functions
setattr(Client, fun.__name__, fun)
import copr_apiv3_option6_build
from copr_apiv3_option6_client import Client
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment