Added in more documentation, cleaned up use of postproc in HttpRequest and refreshed docs
This commit is contained in:
@@ -20,6 +20,9 @@ based APIs.
|
||||
|
||||
__author__ = 'jcgregorio@google.com (Joe Gregorio)'
|
||||
|
||||
__all__ = [
|
||||
'build', 'build_from_document'
|
||||
]
|
||||
|
||||
import httplib2
|
||||
import logging
|
||||
@@ -67,6 +70,28 @@ def build(serviceName, version,
|
||||
developerKey=None,
|
||||
model=JsonModel(),
|
||||
requestBuilder=HttpRequest):
|
||||
"""Construct a Resource for interacting with an API.
|
||||
|
||||
Construct a Resource object for interacting with
|
||||
an API. The serviceName and version are the
|
||||
names from the Discovery service.
|
||||
|
||||
Args:
|
||||
serviceName: string, name of the service
|
||||
version: string, the version of the service
|
||||
discoveryServiceUrl: string, a URI Template that points to
|
||||
the location of the discovery service. It should have two
|
||||
parameters {api} and {apiVersion} that when filled in
|
||||
produce an absolute URI to the discovery document for
|
||||
that service.
|
||||
developerKey: string, key obtained from https://code.google.com/apis/console
|
||||
model: apiclient.Model, converts to and from the wire format
|
||||
requestBuilder: apiclient.http.HttpRequest, encapsulator for an HTTP request
|
||||
|
||||
Returns:
|
||||
A Resource object with methods for interacting with
|
||||
the service.
|
||||
"""
|
||||
params = {
|
||||
'api': serviceName,
|
||||
'apiVersion': version
|
||||
@@ -100,7 +125,12 @@ def build_from_document(
|
||||
developerKey=None,
|
||||
model=JsonModel(),
|
||||
requestBuilder=HttpRequest):
|
||||
"""
|
||||
"""Create a Resource for interacting with an API.
|
||||
|
||||
Same as `build()`, but constructs the Resource object
|
||||
from a discovery document that is it given, as opposed to
|
||||
retrieving one over HTTP.
|
||||
|
||||
Args:
|
||||
service: string, discovery document
|
||||
base: string, base URI for all HTTP requests, usually the discovery URI
|
||||
@@ -113,6 +143,10 @@ def build_from_document(
|
||||
model: Model class instance that serializes and
|
||||
de-serializes requests and responses.
|
||||
requestBuilder: Takes an http request and packages it up to be executed.
|
||||
|
||||
Returns:
|
||||
A Resource object with methods for interacting with
|
||||
the service.
|
||||
"""
|
||||
|
||||
service = simplejson.loads(service)
|
||||
@@ -229,10 +263,12 @@ def createResource(http, baseUrl, model, requestBuilder,
|
||||
url_result.path + expanded_url + query)
|
||||
|
||||
logging.info('URL being requested: %s' % url)
|
||||
return self._requestBuilder(self._http, url,
|
||||
method=httpMethod, body=body,
|
||||
return self._requestBuilder(self._http,
|
||||
self._model.response,
|
||||
url,
|
||||
method=httpMethod,
|
||||
body=body,
|
||||
headers=headers,
|
||||
postproc=self._model.response,
|
||||
methodId=methodId)
|
||||
|
||||
docs = ['A description of how to use this function\n\n']
|
||||
@@ -281,9 +317,11 @@ def createResource(http, baseUrl, model, requestBuilder,
|
||||
logging.info('URL being requested: %s' % url)
|
||||
resp, content = self._http.request(url, method='GET', headers=headers)
|
||||
|
||||
return self._requestBuilder(self._http, url, method='GET',
|
||||
return self._requestBuilder(self._http,
|
||||
self._model.response,
|
||||
url,
|
||||
method='GET',
|
||||
headers=headers,
|
||||
postproc=self._model.response,
|
||||
methodId=methodId)
|
||||
|
||||
setattr(theclass, methodName, method)
|
||||
|
@@ -20,21 +20,19 @@ class HttpRequest(object):
|
||||
"""Encapsulates a single HTTP request.
|
||||
"""
|
||||
|
||||
def __init__(self, http, uri, method="GET", body=None, headers=None,
|
||||
postproc=None, methodId=None):
|
||||
def __init__(self, http, postproc, uri, method="GET", body=None, headers=None,
|
||||
methodId=None):
|
||||
"""Constructor for an HttpRequest.
|
||||
|
||||
Only http and uri are required.
|
||||
|
||||
Args:
|
||||
http: httplib2.Http, the transport object to use to make a request
|
||||
postproc: callable, called on the HTTP response and content to transform
|
||||
it into a data object before returning, or raising an exception
|
||||
on an error.
|
||||
uri: string, the absolute URI to send the request to
|
||||
method: string, the HTTP method to use
|
||||
body: string, the request body of the HTTP request
|
||||
headers: dict, the HTTP request headers
|
||||
postproc: callable, called on the HTTP response and content to transform
|
||||
it into a data object before returning, or raising an exception
|
||||
on an error.
|
||||
methodId: string, a unique identifier for the API method being called.
|
||||
"""
|
||||
self.uri = uri
|
||||
@@ -136,8 +134,8 @@ class RequestMockBuilder(object):
|
||||
"""
|
||||
self.responses = responses
|
||||
|
||||
def __call__(self, http, uri, method="GET", body=None, headers=None,
|
||||
postproc=None, methodId=None):
|
||||
def __call__(self, http, postproc, uri, method="GET", body=None,
|
||||
headers=None, methodId=None):
|
||||
"""Implements the callable interface that discovery.build() expects
|
||||
of requestBuilder, which is to build an object compatible with
|
||||
HttpRequest.execute(). See that method for the description of the
|
||||
|
@@ -18,8 +18,54 @@ import urllib
|
||||
from anyjson import simplejson
|
||||
from errors import HttpError
|
||||
|
||||
def _abstract():
|
||||
raise NotImplementedError('You need to override this function')
|
||||
|
||||
class JsonModel(object):
|
||||
|
||||
class Model(object):
|
||||
"""Model base class.
|
||||
|
||||
All Model classes should implement this interface.
|
||||
The Model serializes and de-serializes between a wire
|
||||
format such as JSON and a Python object representation.
|
||||
"""
|
||||
|
||||
def request(self, headers, path_params, query_params, body_value):
|
||||
"""Updates outgoing requests with a deserialized body.
|
||||
|
||||
Args:
|
||||
headers: dict, request headers
|
||||
path_params: dict, parameters that appear in the request path
|
||||
query_params: dict, parameters that appear in the query
|
||||
body_value: object, the request body as a Python object, which must be
|
||||
serializable.
|
||||
Returns:
|
||||
A tuple of (headers, path_params, query, body)
|
||||
|
||||
headers: dict, request headers
|
||||
path_params: dict, parameters that appear in the request path
|
||||
query: string, query part of the request URI
|
||||
body: string, the body serialized in the desired wire format.
|
||||
"""
|
||||
_abstract()
|
||||
|
||||
def response(self, resp, content):
|
||||
"""Convert the response wire format into a Python object.
|
||||
|
||||
Args:
|
||||
resp: httplib2.Response, the HTTP response headers and status
|
||||
content: string, the body of the HTTP response
|
||||
|
||||
Returns:
|
||||
The body de-serialized as a Python object.
|
||||
|
||||
Raises:
|
||||
apiclient.errors.HttpError if a non 2xx response is received.
|
||||
"""
|
||||
_abstract()
|
||||
|
||||
|
||||
class JsonModel(Model):
|
||||
"""Model class for JSON.
|
||||
|
||||
Serializes and de-serializes between JSON and the Python
|
||||
|
@@ -35,8 +35,34 @@ based APIs.</tt></p>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Functions</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#eeaa77"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><dl><dt><a name="-build"><strong>build</strong></a>(serviceName, version, http<font color="#909090">=None</font>, discoveryServiceUrl<font color="#909090">='https://www.googleapis.com/discovery/v0.2beta1/describe/{api}/{apiVersion}'</font>, developerKey<font color="#909090">=None</font>, model<font color="#909090">=<apiclient.model.JsonModel object></font>, requestBuilder<font color="#909090">=<class 'apiclient.http.HttpRequest'></font>)</dt></dl>
|
||||
<dl><dt><a name="-build_from_document"><strong>build_from_document</strong></a>(service, base, future<font color="#909090">=None</font>, http<font color="#909090">=None</font>, developerKey<font color="#909090">=None</font>, model<font color="#909090">=<apiclient.model.JsonModel object></font>, requestBuilder<font color="#909090">=<class 'apiclient.http.HttpRequest'></font>)</dt><dd><tt>Args:<br>
|
||||
<td width="100%"><dl><dt><a name="-build"><strong>build</strong></a>(serviceName, version, http<font color="#909090">=None</font>, discoveryServiceUrl<font color="#909090">='https://www.googleapis.com/discovery/v0.2beta1/describe/{api}/{apiVersion}'</font>, developerKey<font color="#909090">=None</font>, model<font color="#909090">=<apiclient.model.JsonModel object></font>, requestBuilder<font color="#909090">=<class 'apiclient.http.HttpRequest'></font>)</dt><dd><tt>Construct a Resource for interacting with an API.<br>
|
||||
<br>
|
||||
Construct a Resource object for interacting with<br>
|
||||
an API. The serviceName and version are the<br>
|
||||
names from the Discovery service.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
serviceName: string, name of the service<br>
|
||||
version: string, the version of the service<br>
|
||||
discoveryServiceUrl: string, a URI Template that points to<br>
|
||||
the location of the discovery service. It should have two<br>
|
||||
parameters {api} and {apiVersion} that when filled in<br>
|
||||
produce an absolute URI to the discovery document for<br>
|
||||
that service.<br>
|
||||
developerKey: string, key obtained from https://code.google.com/apis/console<br>
|
||||
model: apiclient.Model, converts to and from the wire format<br>
|
||||
requestBuilder: apiclient.http.HttpRequest, encapsulator for an HTTP request<br>
|
||||
<br>
|
||||
Returns:<br>
|
||||
A Resource object with methods for interacting with<br>
|
||||
the service.</tt></dd></dl>
|
||||
<dl><dt><a name="-build_from_document"><strong>build_from_document</strong></a>(service, base, future<font color="#909090">=None</font>, http<font color="#909090">=None</font>, developerKey<font color="#909090">=None</font>, model<font color="#909090">=<apiclient.model.JsonModel object></font>, requestBuilder<font color="#909090">=<class 'apiclient.http.HttpRequest'></font>)</dt><dd><tt>Create a Resource for interacting with an API.<br>
|
||||
<br>
|
||||
Same as `<a href="#-build">build</a>()`, but constructs the Resource object<br>
|
||||
from a discovery document that is it given, as opposed to<br>
|
||||
retrieving one over HTTP.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
service: string, discovery document<br>
|
||||
base: string, base URI for all HTTP requests, usually the discovery URI<br>
|
||||
future: string, discovery document with future capabilities<br>
|
||||
@@ -47,9 +73,11 @@ based APIs.</tt></p>
|
||||
from the API Console.<br>
|
||||
model: Model class instance that serializes and<br>
|
||||
de-serializes requests and responses.<br>
|
||||
requestBuilder: Takes an http request and packages it up to be executed.</tt></dd></dl>
|
||||
<dl><dt><a name="-createResource"><strong>createResource</strong></a>(http, baseUrl, model, requestBuilder, developerKey, resourceDesc, futureDesc)</dt></dl>
|
||||
<dl><dt><a name="-key2param"><strong>key2param</strong></a>(key)</dt><dd><tt>max-results -> max_results</tt></dd></dl>
|
||||
requestBuilder: Takes an http request and packages it up to be executed.<br>
|
||||
<br>
|
||||
Returns:<br>
|
||||
A Resource object with methods for interacting with<br>
|
||||
the service.</tt></dd></dl>
|
||||
</td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#55aa55">
|
||||
@@ -57,9 +85,7 @@ based APIs.</tt></p>
|
||||
<font color="#ffffff" face="helvetica, arial"><big><strong>Data</strong></big></font></td></tr>
|
||||
|
||||
<tr><td bgcolor="#55aa55"><tt> </tt></td><td> </td>
|
||||
<td width="100%"><strong>DISCOVERY_URI</strong> = 'https://www.googleapis.com/discovery/v0.2beta1/describe/{api}/{apiVersion}'<br>
|
||||
<strong>URITEMPLATE</strong> = <_sre.SRE_Pattern object><br>
|
||||
<strong>VARNAME</strong> = <_sre.SRE_Pattern object><br>
|
||||
<td width="100%"><strong>__all__</strong> = ['build', 'build_from_document']<br>
|
||||
<strong>__author__</strong> = 'jcgregorio@google.com (Joe Gregorio)'</td></tr></table><p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#7799ee">
|
||||
|
@@ -8,7 +8,7 @@
|
||||
<td valign=bottom> <br>
|
||||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.<a href="apiclient.ext.html"><font color="#ffffff">ext</font></a>.django_orm</strong></big></big></font></td
|
||||
><td align=right valign=bottom
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/django_orm.py">/usr/local/google/home/jcgregorio/projects/apiclient/apiclient/ext/django_orm.py</a></font></td></tr></table>
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/ext/django_orm.py">/home/jcgregorio/projects/apiary/apiclient/ext/django_orm.py</a></font></td></tr></table>
|
||||
<p></p>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
|
@@ -48,19 +48,17 @@ actuall HTTP request.</tt></p>
|
||||
<td colspan=2><tt>Encapsulates a single HTTP request.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<dl><dt><a name="HttpRequest-__init__"><strong>__init__</strong></a>(self, http, uri, method<font color="#909090">='GET'</font>, body<font color="#909090">=None</font>, headers<font color="#909090">=None</font>, postproc<font color="#909090">=None</font>, methodId<font color="#909090">=None</font>)</dt><dd><tt>Constructor for an <a href="#HttpRequest">HttpRequest</a>.<br>
|
||||
<br>
|
||||
Only http and uri are required.<br>
|
||||
<dl><dt><a name="HttpRequest-__init__"><strong>__init__</strong></a>(self, http, postproc, uri, method<font color="#909090">='GET'</font>, body<font color="#909090">=None</font>, headers<font color="#909090">=None</font>, methodId<font color="#909090">=None</font>)</dt><dd><tt>Constructor for an <a href="#HttpRequest">HttpRequest</a>.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
http: httplib2.Http, the transport <a href="__builtin__.html#object">object</a> to use to make a request<br>
|
||||
postproc: callable, called on the HTTP response and content to transform<br>
|
||||
it into a data <a href="__builtin__.html#object">object</a> before returning, or raising an exception<br>
|
||||
on an error.<br>
|
||||
uri: string, the absolute URI to send the request to<br>
|
||||
method: string, the HTTP method to use<br>
|
||||
body: string, the request body of the HTTP request<br>
|
||||
headers: dict, the HTTP request headers<br>
|
||||
postproc: callable, called on the HTTP response and content to transform<br>
|
||||
it into a data <a href="__builtin__.html#object">object</a> before returning, or raising an exception<br>
|
||||
on an error.<br>
|
||||
methodId: string, a unique identifier for the API method being called.</tt></dd></dl>
|
||||
|
||||
<dl><dt><a name="HttpRequest-execute"><strong>execute</strong></a>(self, http<font color="#909090">=None</font>)</dt><dd><tt>Execute the request.<br>
|
||||
@@ -115,7 +113,7 @@ is taken from the rpcName in the discovery&nb
|
||||
For more details see the project wiki.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<dl><dt><a name="RequestMockBuilder-__call__"><strong>__call__</strong></a>(self, http, uri, method<font color="#909090">='GET'</font>, body<font color="#909090">=None</font>, headers<font color="#909090">=None</font>, postproc<font color="#909090">=None</font>, methodId<font color="#909090">=None</font>)</dt><dd><tt>Implements the callable interface that discovery.build() expects<br>
|
||||
<dl><dt><a name="RequestMockBuilder-__call__"><strong>__call__</strong></a>(self, http, postproc, uri, method<font color="#909090">='GET'</font>, body<font color="#909090">=None</font>, headers<font color="#909090">=None</font>, methodId<font color="#909090">=None</font>)</dt><dd><tt>Implements the callable interface that discovery.build() expects<br>
|
||||
of requestBuilder, which is to build an <a href="__builtin__.html#object">object</a> compatible with<br>
|
||||
<a href="#HttpRequest">HttpRequest</a>.execute(). See that method for the description of the<br>
|
||||
parameters and the expected response.</tt></dd></dl>
|
||||
|
@@ -9,7 +9,7 @@
|
||||
<font color="#ffffff" face="helvetica, arial"> <br><big><big><strong><a href="apiclient.html"><font color="#ffffff">apiclient</font></a>.model</strong></big></big></font></td
|
||||
><td align=right valign=bottom
|
||||
><font color="#ffffff" face="helvetica, arial"><a href=".">index</a><br><a href="file:/home/jcgregorio/projects/apiary/apiclient/model.py">/home/jcgregorio/projects/apiary/apiclient/model.py</a></font></td></tr></table>
|
||||
<p><tt>Model objects for requests and responses<br>
|
||||
<p><tt><a href="#Model">Model</a> objects for requests and responses<br>
|
||||
<br>
|
||||
Each API may support one or more serializations, such<br>
|
||||
as JSON, Atom, etc. The model classes are responsible<br>
|
||||
@@ -36,23 +36,34 @@ for converting between the wire format and th
|
||||
<dt><font face="helvetica, arial"><a href="__builtin__.html#object">__builtin__.object</a>
|
||||
</font></dt><dd>
|
||||
<dl>
|
||||
<dt><font face="helvetica, arial"><a href="apiclient.model.html#Model">Model</a>
|
||||
</font></dt><dd>
|
||||
<dl>
|
||||
<dt><font face="helvetica, arial"><a href="apiclient.model.html#JsonModel">JsonModel</a>
|
||||
</font></dt></dl>
|
||||
</dd>
|
||||
</dl>
|
||||
</dd>
|
||||
</dl>
|
||||
<p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#000000" face="helvetica, arial"><a name="JsonModel">class <strong>JsonModel</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
|
||||
<font color="#000000" face="helvetica, arial"><a name="JsonModel">class <strong>JsonModel</strong></a>(<a href="apiclient.model.html#Model">Model</a>)</font></td></tr>
|
||||
|
||||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
|
||||
<td colspan=2><tt>Model class for JSON.<br>
|
||||
<td colspan=2><tt><a href="#Model">Model</a> class for JSON.<br>
|
||||
<br>
|
||||
Serializes and de-serializes between JSON and the Python<br>
|
||||
<a href="__builtin__.html#object">object</a> representation of HTTP request and response bodies.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<td width="100%"><dl><dt>Method resolution order:</dt>
|
||||
<dd><a href="apiclient.model.html#JsonModel">JsonModel</a></dd>
|
||||
<dd><a href="apiclient.model.html#Model">Model</a></dd>
|
||||
<dd><a href="__builtin__.html#object">__builtin__.object</a></dd>
|
||||
</dl>
|
||||
<hr>
|
||||
Methods defined here:<br>
|
||||
<dl><dt><a name="JsonModel-request"><strong>request</strong></a>(self, headers, path_params, query_params, body_value)</dt><dd><tt>Updates outgoing requests with JSON bodies.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
@@ -81,6 +92,56 @@ Returns:<br>
|
||||
Raises:<br>
|
||||
apiclient.errors.HttpError if a non 2xx response is received.</tt></dd></dl>
|
||||
|
||||
<hr>
|
||||
Data descriptors inherited from <a href="apiclient.model.html#Model">Model</a>:<br>
|
||||
<dl><dt><strong>__dict__</strong></dt>
|
||||
<dd><tt>dictionary for instance variables (if defined)</tt></dd>
|
||||
</dl>
|
||||
<dl><dt><strong>__weakref__</strong></dt>
|
||||
<dd><tt>list of weak references to the object (if defined)</tt></dd>
|
||||
</dl>
|
||||
</td></tr></table> <p>
|
||||
<table width="100%" cellspacing=0 cellpadding=2 border=0 summary="section">
|
||||
<tr bgcolor="#ffc8d8">
|
||||
<td colspan=3 valign=bottom> <br>
|
||||
<font color="#000000" face="helvetica, arial"><a name="Model">class <strong>Model</strong></a>(<a href="__builtin__.html#object">__builtin__.object</a>)</font></td></tr>
|
||||
|
||||
<tr bgcolor="#ffc8d8"><td rowspan=2><tt> </tt></td>
|
||||
<td colspan=2><tt><a href="#Model">Model</a> base class.<br>
|
||||
<br>
|
||||
All <a href="#Model">Model</a> classes should implement this interface.<br>
|
||||
The <a href="#Model">Model</a> serializes and de-serializes between a wire<br>
|
||||
format such as JSON and a Python <a href="__builtin__.html#object">object</a> representation.<br> </tt></td></tr>
|
||||
<tr><td> </td>
|
||||
<td width="100%">Methods defined here:<br>
|
||||
<dl><dt><a name="Model-request"><strong>request</strong></a>(self, headers, path_params, query_params, body_value)</dt><dd><tt>Updates outgoing requests with a deserialized body.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
headers: dict, request headers<br>
|
||||
path_params: dict, parameters that appear in the request path<br>
|
||||
query_params: dict, parameters that appear in the query<br>
|
||||
body_value: <a href="__builtin__.html#object">object</a>, the request body as a Python <a href="__builtin__.html#object">object</a>, which must be<br>
|
||||
serializable.<br>
|
||||
Returns:<br>
|
||||
A tuple of (headers, path_params, query, body)<br>
|
||||
<br>
|
||||
headers: dict, request headers<br>
|
||||
path_params: dict, parameters that appear in the request path<br>
|
||||
query: string, query part of the request URI<br>
|
||||
body: string, the body serialized in the desired wire format.</tt></dd></dl>
|
||||
|
||||
<dl><dt><a name="Model-response"><strong>response</strong></a>(self, resp, content)</dt><dd><tt>Convert the response wire format into a Python <a href="__builtin__.html#object">object</a>.<br>
|
||||
<br>
|
||||
Args:<br>
|
||||
resp: httplib2.Response, the HTTP response headers and status<br>
|
||||
content: string, the body of the HTTP response<br>
|
||||
<br>
|
||||
Returns:<br>
|
||||
The body de-serialized as a Python <a href="__builtin__.html#object">object</a>.<br>
|
||||
<br>
|
||||
Raises:<br>
|
||||
apiclient.errors.HttpError if a non 2xx response is received.</tt></dd></dl>
|
||||
|
||||
<hr>
|
||||
Data descriptors defined here:<br>
|
||||
<dl><dt><strong>__dict__</strong></dt>
|
||||
|
Reference in New Issue
Block a user