Graphene: What are the Difference between serializer, parse_literal and parse_value staticmethods on Custom Scalar? [duplicate] - python

Looking through the GraphQL documentation for custom scalar types (I'm trying to create my own date type) I'm not sure what the difference between parseValue and parseLiteral are.
http://graphql.org/graphql-js/type/#graphqlscalartype
The documentation doesn't seem to include any descriptions of what the functions are supposed to do.
Can someone let me know what the requirements are? I'm assuming that serialize must serialize the scalar to a string. Is that correct? I'm assuming that parseLiteral is a deserialization of that string to the type? In my case a Date type. However, in the examples - serialize and parseValue are the same function - which suggests it's not a simple deserialization method.

The serialize method would be called when the value of the type is going to be sent to the client as a response. Since the values on the output is in the form of JSON, the return value of serialize could be anything. Could be string, number, array, object ...
The other two methods (parseValue and parseLiteral) are to read input.
In GraphQL there are two ways of reading input from client, one is inline in the query, like:
query {
allUsers(first:10) {
id
}
}
where 10 is the inline value for first argument. Since the input language for GraphQL is not exactly JSON, the value (here 10) is being parsed and converted to AST (Abstract Syntax Tree). In this case, parseLiteral comes to play. It inputs the AST and returns the parsed value of the type. Types could be as complex as JSON and parseLiteral could traverse the AST and return JSON.
The other way of reading input from clients is through variables:
query ($howMany: YourCustomType) {
users(first: $howMany) {
id
}
}
variables:
{
"howMany": {
"thisMany": 10
}
}
Since the variables are pure JSON, you don't need AST here, you already have JSON. That's where parseValue comes to play. It gets the input as JSON and returns whatever the query resolver should use.
function parseValue(value) {
let first = value.thisMany;
return first;
}
So, you could have different presentation when you read from variables than when you read values inline, but conceptually, they should be the same in terms of presentation. However since the "type" of input is different (inline is GraphQL and variable is JSON), the parsing algorithm could be different. That's why if you define it as input type, you need to provide two separate methods to read them.

Related

JSON-serialization of complex Pandas types to store them into DynamoDB

We're trying to store data parsed from a PDF into a DynamoDB table.
Some of the "entities" that we extract from the text have a corresponding type builtin into DynamoDB, e.g. float, boolean, string...
However, there are some entities which can not be represented in terms of builtin types.
For example, we're extracting some time offsets defined in terms of business days, which we decided to represent as pandas.tseries.offsets
from pandas.tseries import offsets
offsets.BusinessDay(2)
>>> <2 * BusinessDays>
This cannot be saved directly into DynamoDB, so we thought of serializing it into JSON beforehand
{
"type": "offsets.BusinessDay",
"value": 2
}
and to write some conversion functions to get the original object back with the right type whenever we need to use it to do some computations.
The problem is that this is hard to generalize to different complex types, as the parameter(s) used to define the object (in this case "2", the number of business days) change.
We would like to find a generalized way to serialize a complex type to a JSON representation so that something like this
var = complexType(param1=2, param2='a')
would be automatically translated into something like this
varJSON = {
"type": "complexType",
"param1": 2,
"param2": 'a'
}
which can then hopefully be converted back to the original type by doing something like (in pseudo-code, I don't know whether it makes sense!)
var = varJSON["type"](**params)
Is this stupid? :) Any way to do this?

Is there something like a reverse eval() function?

Imagine the following problem: you have a dictionary of some content in python and want to generate python code that would create this dict. (which is like eval but in reverse)
Is there something that can do this?
Scenario:
I am working with a remote python interpreter. I can give source files to it but no input. So I am now looking for a way to encode my input data into a python source file.
Example:
d = {'a': [1,4,7]}
str_d = reverse_eval(d)
# "{'a': [1, 4, 7]}"
eval(str_d) == d
repr(thing)
will output text that when executed will (in most cases) reproduce the dictionary.
Actually, it's important for which types of data do you want this reverse function to exist. If you're talking about built-in/standard classes, usually their .__repr__() method returns the code you want to access. But if your goal is to save something in a human-readable format, but to use an eval-like function to use this data in python, there is a json library.
It's better to use json for this reason because using eval is not safe.
Json's problem is that it can't save any type of data, it can save only standard objects, but if we're talking about not built-in types of data, you never know, what is at their .__repr__(), so there's no way to use repr-eval with this kind of data
So, there is no reverse function for all types of data, you can use repr-eval for built-in, but for built-in data the json library is better at least because it's safe

Python JSON module not throwing exception for invalid JSON

So, valid JSON must be an Object or Array, correct? I was expecting the following code to throw an exception but it is not:
>>> import json
>>> json.loads("245235")
245235
That's not invalid JSON*. Number is a valid JSON type, just like object. http://en.wikipedia.org/wiki/JSON#Data_types.2C_syntax_and_example any of these types could appear on its own, albeit that object and array are probably the most common top level types.
*according to the python implementation
EDIT:
As pointed out in a deleted (not sure why) answer, the python docs suggest that the JSON RFC does require the top level object to be of array or object type, but that the json module doesn't enforce this. Since a lot of what I know about JSON has come from working with the python json module, I don't know how portable this behavior is.
As requested, this is noted at http://docs.python.org/2/library/json.html#standard-compliance:
This module does not comply with the RFC in a strict fashion,
implementing some extensions that are valid JavaScript but not valid
JSON. In particular:
Top-level non-object, non-array values are accepted and output;
Infinite and NaN number values are accepted and output;
Repeated names within an object are accepted, and only the value of the last name-value pair is used.
JSON data can have a wide range of types including strings, numbers and booleans

Why does CouchDb-python (or do I) confuse strings and dictionaries?

I'm trying to use the Python wrapper for CouchDB to update a database. The file is structured as a nested dictionary as follows.
doc = { ...,
'RLSoo': {'RT_freq': 2, 'tweet': "They're going to play monopoly now.
This makes me feel like an excellent mother. #Sandy #NYC"},
'GiltCityNYC': {},
....}
I would like to put each entry of the larger dicitionary, for example RLSoo into its own document. However, I get an error message when I try the following code.
for key in doc:
db.update(doc[key],all_or_nothing=True)
Error Message
TypeError: expected dict, got <type 'str'>
I don't understand why CouchDB won't accept the dictionary.
According Database.update() method realization and his documentation, first argument should be list of document objects (e.g. list of dicts). Since you doc variable has dict type, direct iteration over it actually iterates over all his keys which are string typed. If I understood your case right, probably your doc contains nested documents as values. So, try just:
db.update(doc.values(), all_or_nothing=True)
And it all first level values are dicts, it should works!

Sort lexicographically?

I am working on integrating with the Photobucket API and I came across this in their api docs:
"Sort the parameters by name
lexographically [sic] (byte ordering, the
standard sorting, not natural or case
insensitive). If the parameters have
the same name, then sort by the value."
What does that mean? How do I sort something lexicographically? byte ordering?
The rest of their docs have been ok so far, but (to me) it seems like this line bears further explanation. Unfortunately there was none to be had.
Anyway, I'm writing the application in Python (it'll eventually become a Django app) in case you want to recommend specific modules that will handle such sorting for me ^_^
I think that here lexicographic is a "alias" for ascii sort?
Lexicographic Natural
z1.doc z1.doc
z10.doc z2.doc
z100.doc z3.doc
z101.doc z4.doc
z102.doc z5.doc
z11.doc z6.doc
z12.doc z7.doc
z13.doc z8.doc
z14.doc z9.doc
z15.doc z10.doc
z16.doc z11.doc
z17.doc z12.doc
z18.doc z13.doc
z19.doc z14.doc
z2.doc z15.doc
z20.doc z16.doc
z3.doc z17.doc
z4.doc z18.doc
z5.doc z19.doc
z6.doc z20.doc
z7.doc z100.doc
z8.doc z101.doc
z9.doc z102.doc
The word should be "lexicographic"
http://www.thefreedictionary.com/Lexicographic
Dictionary order. Using the letters as they appear in the strings.
As they suggest, don't fold upper- and lower-case together. Just use the Python built-in list.sort() method.
This is similar to the Facebook API — the query string needs to be normalized before generating the signature hash.
You probably have a dictionary of parameters like:
params = {
'consumer_key': "....",
'consumer_secret': "....",
'timestamp': ...,
...
}
Create the query string like so:
urllib.urlencode(sorted(params.items()))
params.items() returns the keys and values of the dictionary as a list tuples, sorted() sorts the list, and urllib.urlencode() concatenates them into a single string while escaping.
Quote a bit more from the section:
2 Generate the Base String:
Normalize the parameters:
Add the OAuth specific parameters for this request to the input parameters, including:
oauth_consumer_key = <consumer_key>
oauth_timestamp = <timestamp>
oauth_nonce = <nonce>
oauth_version = <version>
oauth_signature_method = <signature_method>
Sort the parameters by name lexographically [sic] (byte ordering, the standard sorting, not natural or case insensitive). If the parameters have the same name, then sort by the value.
Encode the parameter values as in RFC3986 Section 2 (i.e., urlencode).
Create parameter string (). This is the same format as HTTP 'postdata' or 'querystring', that is, each parameter represented as name=value separated by &. For example, a=1&b=2&c=hello%20there&c=something%20else
I think that they are saying that the parameters must appear in the sorted order - oauth_consumer_key before oauth_nonce before ...

Categories

Resources