RESTful API echo server using Python bottles
The code looks a bit incomplete, e.g. shouldn't there be a main method
somewhere?

I added the following to get it to run for now:

if __name__ == "__main__":
    run()


It's good practice to have the __name__ check in there instead of just
executing, because then you're still able to import the file elsewhere
without it automatically executing code.



Okay, so with that out of the way, there's commented out code that
should be there:  Either it's correct, then it should replace the
uncommented code, or it's not, then it should be deleted.  To me,
reading that just confuses me what the purpose is, or was.

And then there's two functions, which are identical ... why is that?  I
suppose that's a feature of the framework that allows you to have both
functions because of the annotations, but generally do not do that and
give them separate names, at least something like
data_get/data_post.

The specification is pretty vague, what are you supposed to echo, the
POST body, or the URL parameters?  Because then I don't get what the
GET one is supposed to be doing.  With that in mind I'd delete it.

So, then, trying it out:

&gt; curl -d '{"data": 1}' -H "Content-Type: application/json" -v http://localhost:8080/data
{"method": "POST", "data": {"data": 1}}%


Seems to work.

(Also, since there's a single endpoint that echoes data ... there's
little REST here.  I'm not sure what other best practices are meant to
be followed for this exercise.)

I've no idea how you'd get an exception in there, but in any case,
raise ValueError isn't super helpful, it says exactly nothing about
what went wrong.  Consider adding some information like raise
ValueError("Couldn't format data.").  Note that in this particular
situation there's little that adds information, maybe don't catch the
exception then.

At that point it might look like this:

@post("/data")
def data():
    response.content_type = "application/json"
    return dumps({"method": request.method, "data": request.json})




However, then I was thinking, maybe this framework does the JSON
formatting for us.  And it does:

@post("/data")
def data():
    return {"method": request.method, "data": request.json}


Probably can't get it much smaller than that actually.  And then you can
delete a lot of imports too:

from bottle import run, request, post
from json import dumps




Hope that helps.  In general it's good to let readers know all you can,
like "which dependencies do I need" and "how do I run this", including
example invocations.