Store custom data.

        Store arbitrary user data as JSON.
        
        Arbitrary JSON data can be stored for a User.
        A typical scenario would be an external site/service that registers users in Canvas
        and wants to capture additional info about them.  The part of the URL that follows
        +/custom_data/+ defines the scope of the request, and it reflects the structure of
        the JSON data to be stored or retrieved.
        
        The value +self+ may be used for +user_id+ to store data associated with the calling user.
        In order to access another user's custom data, you must be an account administrator with
        permission to manage users.
        
        A namespace parameter, +ns+, is used to prevent custom_data collisions between
        different apps.  This parameter is required for all custom_data requests.
        
        A request with Content-Type multipart/form-data or Content-Type
        application/x-www-form-urlencoded can only be used to store strings.
        
        Example PUT with multipart/form-data data:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/telephone' \
            -X PUT \
            -F 'ns=com.my-organization.canvas-app' \
            -F 'data=555-1234' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "555-1234"
          }
        
        Subscopes (or, generated scopes) can also be specified by passing values to
        +data+[+subscope+].
        
        Example PUT specifying subscopes:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/body/measurements' \
            -X PUT \
            -F 'ns=com.my-organization.canvas-app' \
            -F 'data[waist]=32in' \
            -F 'data[inseam]=34in' \
            -F 'data[chest]=40in' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": {
              "chest": "40in",
              "waist": "32in",
              "inseam": "34in"
            }
          }
        
        Following such a request, subsets of the stored data to be retrieved directly from a subscope.
        
        Example {api:UsersController#get_custom_data GET} from a generated scope
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/body/measurements/chest' \
            -X GET \
            -F 'ns=com.my-organization.canvas-app' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "40in"
          }
        
        If you want to store more than just strings (i.e. numbers, arrays, hashes, true, false,
        and/or null), you must make a request with Content-Type application/json as in the following
        example.
        
        Example PUT with JSON data:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data' \
            -H 'Content-Type: application/json' \
            -X PUT \
            -d '{
                  "ns": "com.my-organization.canvas-app",
                  "data": {
                    "a-number": 6.02e23,
                    "a-bool": true,
                    "a-string": "true",
                    "a-hash": {"a": {"b": "ohai"}},
                    "an-array": [1, "two", null, false]
                  }
                }' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": {
              "a-number": 6.02e+23,
              "a-bool": true,
              "a-string": "true",
              "a-hash": {
                "a": {
                  "b": "ohai"
                }
              },
              "an-array": [1, "two", null, false]
            }
          }
        
        If the data is an Object (as it is in the above example), then subsets of the data can
        be accessed by including the object's (possibly nested) keys in the scope of a GET request.
        
        Example {api:UsersController#get_custom_data GET} with a generated scope:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/a-hash/a/b' \
            -X GET \
            -F 'ns=com.my-organization.canvas-app' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "ohai"
          }
        
        
        On success, this endpoint returns an object containing the data that was stored.
        
        Responds with status code 200 if the scope already contained data, and it was overwritten
        by the data specified in the request.
        
        Responds with status code 201 if the scope was previously empty, and the data specified
        in the request was successfully stored there.
        
        Responds with status code 400 if the namespace parameter, +ns+, is missing or invalid, or if
        the +data+ parameter is missing.
        
        Responds with status code 409 if the requested scope caused a conflict and data was not stored.
        This happens when storing data at the requested scope would cause data at an outer scope
        to be lost.  e.g., if +/custom_data+ was +{"fashion_app": {"hair": "blonde"}}+, but
        you tried to +`PUT /custom_data/fashion_app/hair/style -F data=buzz`+, then for the request
        to succeed,the value of +/custom_data/fashion_app/hair+ would have to become a hash, and its
        old string value would be lost.  In this situation, an error object is returned with the
        following format:
        
          !!!javascript
          {
            "message": "write conflict for custom_data hash",
            "conflict_scope": "fashion_app/hair",
            "type_at_conflict": "String",
            "value_at_conflict": "blonde"
          }

def store_custom_data(self, ns, data, user_id):
        """
        Store custom data.

        Store arbitrary user data as JSON.
        
        Arbitrary JSON data can be stored for a User.
        A typical scenario would be an external site/service that registers users in Canvas
        and wants to capture additional info about them.  The part of the URL that follows
        +/custom_data/+ defines the scope of the request, and it reflects the structure of
        the JSON data to be stored or retrieved.
        
        The value +self+ may be used for +user_id+ to store data associated with the calling user.
        In order to access another user's custom data, you must be an account administrator with
        permission to manage users.
        
        A namespace parameter, +ns+, is used to prevent custom_data collisions between
        different apps.  This parameter is required for all custom_data requests.
        
        A request with Content-Type multipart/form-data or Content-Type
        application/x-www-form-urlencoded can only be used to store strings.
        
        Example PUT with multipart/form-data data:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/telephone' \
            -X PUT \
            -F 'ns=com.my-organization.canvas-app' \
            -F 'data=555-1234' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "555-1234"
          }
        
        Subscopes (or, generated scopes) can also be specified by passing values to
        +data+[+subscope+].
        
        Example PUT specifying subscopes:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/body/measurements' \
            -X PUT \
            -F 'ns=com.my-organization.canvas-app' \
            -F 'data[waist]=32in' \
            -F 'data[inseam]=34in' \
            -F 'data[chest]=40in' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": {
              "chest": "40in",
              "waist": "32in",
              "inseam": "34in"
            }
          }
        
        Following such a request, subsets of the stored data to be retrieved directly from a subscope.
        
        Example {api:UsersController#get_custom_data GET} from a generated scope
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/body/measurements/chest' \
            -X GET \
            -F 'ns=com.my-organization.canvas-app' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "40in"
          }
        
        If you want to store more than just strings (i.e. numbers, arrays, hashes, true, false,
        and/or null), you must make a request with Content-Type application/json as in the following
        example.
        
        Example PUT with JSON data:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data' \
            -H 'Content-Type: application/json' \
            -X PUT \
            -d '{
                  "ns": "com.my-organization.canvas-app",
                  "data": {
                    "a-number": 6.02e23,
                    "a-bool": true,
                    "a-string": "true",
                    "a-hash": {"a": {"b": "ohai"}},
                    "an-array": [1, "two", null, false]
                  }
                }' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": {
              "a-number": 6.02e+23,
              "a-bool": true,
              "a-string": "true",
              "a-hash": {
                "a": {
                  "b": "ohai"
                }
              },
              "an-array": [1, "two", null, false]
            }
          }
        
        If the data is an Object (as it is in the above example), then subsets of the data can
        be accessed by including the object's (possibly nested) keys in the scope of a GET request.
        
        Example {api:UsersController#get_custom_data GET} with a generated scope:
          curl 'https://<canvas>/api/v1/users/<user_id>/custom_data/a-hash/a/b' \
            -X GET \
            -F 'ns=com.my-organization.canvas-app' \
            -H 'Authorization: Bearer <token>'
        
        Response:
          !!!javascript
          {
            "data": "ohai"
          }
        
        
        On success, this endpoint returns an object containing the data that was stored.
        
        Responds with status code 200 if the scope already contained data, and it was overwritten
        by the data specified in the request.
        
        Responds with status code 201 if the scope was previously empty, and the data specified
        in the request was successfully stored there.
        
        Responds with status code 400 if the namespace parameter, +ns+, is missing or invalid, or if
        the +data+ parameter is missing.
        
        Responds with status code 409 if the requested scope caused a conflict and data was not stored.
        This happens when storing data at the requested scope would cause data at an outer scope
        to be lost.  e.g., if +/custom_data+ was +{"fashion_app": {"hair": "blonde"}}+, but
        you tried to +`PUT /custom_data/fashion_app/hair/style -F data=buzz`+, then for the request
        to succeed,the value of +/custom_data/fashion_app/hair+ would have to become a hash, and its
        old string value would be lost.  In this situation, an error object is returned with the
        following format:
        
          !!!javascript
          {
            "message": "write conflict for custom_data hash",
            "conflict_scope": "fashion_app/hair",
            "type_at_conflict": "String",
            "value_at_conflict": "blonde"
          }
        """
        path = {}
        data = {}
        params = {}

        # REQUIRED - PATH - user_id
        """ID"""
        path["user_id"] = user_id

        # REQUIRED - ns
        """The namespace under which to store the data.  This should be something other
        Canvas API apps aren't likely to use, such as a reverse DNS for your organization."""
        data["ns"] = ns

        # REQUIRED - data
        """The data you want to store for the user, at the specified scope.  If the data is
        composed of (possibly nested) JSON objects, scopes will be generated for the (nested)
        keys (see examples)."""
        data["data"] = data

        self.logger.debug("PUT /api/v1/users/{user_id}/custom_data with query params: {params} and form data: {data}".format(params=params, data=data, **path))
        return self.generic_request("PUT", "/api/v1/users/{user_id}/custom_data".format(**path), data=data, params=params, no_data=True)