When Python meets GraphQL: Managing contributors identities in your open source project
CC Attribution 2.0 Belgium:
You are free to use, adapt and copy, distribute and transmit the work or content in adapted or unchanged form for any legal purpose as long as the work is attributed to the author in the manner specified by the author or licensor.
Fernández, Miguel-Ángel
SortingHat is an open source Python tool that helps to manage the different contributor identities within an open source project. Under the hood SortingHat relies on a relational database, which can be queried via SQL, command line or directly via its Python interface. However, these ways of interacting with SortingHat hinder its integration with external tools, web interfaces and new web technologies (e.g., Django, REST services). To overcome these obstacles, we have evolved SortingHat's architecture using a GraphQL model based on the Graphene-Django implementation. This talk describes our experience in migrating to GraphQL, from adapting the SortingHat functionalities to refactoring the unit tests. Furthermore, we comment also on lesson learned, advantages and drawbacks of using this new approach SortingHat is one of the core tools of GrimoireLab, an open-source software analytics platform part of CHAOSS project (Community Health Analytics Open Source Software) under the umbrella of the Linux Foundation.
 Can you hear me? Now much better, right? Okay. Okay. Now it's working. Okay. Hi, everyone, again. Okay. So thank you for being here. My name is Miguel Angel Fernandez. I'm working at the DERGIA. My company does software development analytics. I'm part of the engineering team. I'm working as a software developer, and I'm also involved in stuff related with data and metrics. Okay. So first, to give you a glance of the talk, first I'm going to talk about the problem we are trying to solve, and then we are talking about GraphQL a little bit, and then we are going to see a little bit of how the implementation went and the process and so on. Okay. So we have people contributing to a software project, and people contributing to an open source project uses a lot of different tools, right? We have a huge variety of tools depending on the aspect you want to focus on. It could be code, it could be messaging, right? So you may want to ask some questions about the project. So first is how can you measure your project? That's the main question. First is how many contributors do we have? These are basic questions, right? Another question could be how many companies are contributing to my project? Okay. To ask, to answer these basic questions, you need to focus on identities, right? And to have all the contributors for your project properly identified, right? So this is an example. This is a guy contributing to a project. His name is Tom Bridell, and he's affiliated to his leadering. Okay. He's part of Hogwarts. And then we have another contributor. This guy over here is called Lord Voldemort. He's working as a freelance wizard now. But wait. He's the same person. So as a project manager, you may not have this information. So it's difficult to properly identify a contributor in your project. If you don't identify them properly, you may think that these are different contributors, but they are not. They are the same person, right? This is one of the problems. Another problem is that an open source project is a little bit more complex than that, right? First, this is our CEO, the CEO of my company, Marike. So he has made a lot of commits, git commits with different emails. He has his GitHub account. He has participated in several mailing lists with different emails. He has a fabricator account to do ticketing. He has a Slack with different channels. And he has worked in many companies, right? And we have also the dates where he started, when he ended, right? So it's a little bit more complex than the other case, right? Okay. So how do we solve this? The question you may ask is who is who, and who is going to ask this question? It could be anyone, but usually this is the project manager getting crazy about all these identities and how to identify everyone. And here comes sorting hat, which is the tool I'm talking about. It's the sorting hat for you, for those of you that you don't know Harry Potter. That this hat is the one that the students put in their head, and it tells you which house and how much you should be in, right? So sorting hat is using a relational model with all the entities that are related with identities. You can see their profiles. You can see enrollments, organizations, domain, and so on, right? Okay. So we had the guy from before. This is Lord Baltimore and Tom Riddle, right? We knew we know that he belonged to his littering, and we have a basic profile about him. So sorting hat can help us saying, okay, merge these two identities, affiliate these persons, and complete his profile with this information. Okay. Okay. So far, how can you interact with sorting hat? So you can interact with sorting hat via command line. You can use Hashtag, which is a web tool based on Django to communicate with sorting hat, and you can interact with sorting hat as a Python module. Okay. So the main idea here is to build a robust API for sorting hat, for making this easier, even easier to integrate it with other external applications. It has to be flexible and easy to adapt to new technologies and other technologies, and of course ensure consistency as we expect that many users are using sorting hat at the same time, right? And here comes GraphQL. How many of you know something about GraphQL? Okay. So probably most of you or those who raise your hand just giving a quick definition. GraphQL is a query language. It's typically served over HTTP protocol. It is also a specification for client server communication, right? But it doesn't tell you which language you use or how the data has to be stored or which client you have to support. It's only a specification, right? And it is based on graph theory. So it uses concepts from mathematical graph theory. For those of you just in case you don't know, if you see the GraphQL logo, the pink dots are the nodes, the lines between them are the edges, and the connections means the direction of those edges, okay? Okay. So let's compare traditional REST-based application versus GraphQL approach. REST traditional REST approach is the one used by HATSTYLE, which is the web interface we have right now. So imagine that you want a basic view of a profile of a person. So you have a unique identity, which is the main ID for that person. And you want his or her identities in all the data sources. You want also the profile with the name, maybe the gender, the country, okay? Also the enrollments. And for every enrollment, a main domain for that organization, okay? And this is what the query will look like in GraphQL, okay? So as you see, in one request, you are asking for all the things that you need for that view. And you can specify at the level of the field of every endpoint what you want to show. Okay. So I'm not going to be partial right now. I just wanted to point the strongest points, the worst points for the traditional approach and the best for GraphQL one. So as I said, REST is just a convention between the server and the client. It's not a specification. So you may have your own rules for that. You can have more data than you need or less data than you need. That's over or under fetching. The API documentation is not tied to development and we all know how hard it is to write the documentation to the things that we code. And as you have seen in the last slide, you have multiple requests per view, right? What about GraphQL? Is a strongly typed language? This means you define the abstract types you have and each field which type it should have. So the client defines what it receives as you saw in the other query. The client is telling how it wants to receive the information. The server only sends what the client needs and there is one single request per view. So summarizing, I think we get GraphQL as the winner. I'm talking about implementing process a little bit. So first, we are going to talk about the data model and schema. We are going to talk about how to implement basic queries and mutations which are basic entities together with the schema, basic entities of GraphQL. We added support for paginated results. We are now in the process of adding authentication. We are talking about how we are doing that and also some further steps. Okay. Okay, about implementation, GraphQL, as I said before, is not tied to any programming language. So you find implementation for different languages. Graphine is a library that provides tools to implement a GraphQL-based API. And Graphine Django is a library which is built on top of Graphine, right? So it provides some additional abstractions that you need. It may ease the process of implementing GraphQL functionality using Django objects. How many of you know Django and have worked with Django before? Okay. So most of you are familiar with Django. Perfect. Okay. So first, we have to do is to define the schema, right? Basically, GraphQL needs free basic entities. The schema is defined by types. Which types are we going to need for our model? On top of those types, we are going to define queries for obtaining the results, asking for those objects of those types. And mutations, which are request changing the objects we have in the database, right? And that as a whole makes the GraphQL schema. Okay. Okay. So what does this look like in Django? Okay. So as most of you know Django, but I think that goes for the rest of the people too. Instead of types, in Django, we define models, right? For the queries we are defining, we have to define resolvers, which are functions telling how to solve each query and how to return the results. And the mutations are operations creating things, reading things, updating or deleting any object in the database. Okay. And that's the Graph in Django schema. About the data model, it turns out it is already a graph. We saw before a picture. So it made sense to, to modelize this as a graph being the nodes, you see the nodes and the edges, right? So we will have nodes for identities, nodes for the profile, nodes for the domains, nodes for the stations and so on. Okay. Okay. So let's start sneaking something somehow into the implementation. So this is a basic recipe for building a query in GraphQL using the Graphin Django library. I don't know for those in the back. Please tell me if you can see the code. If not, remember that the slides are available in, in the website of this talk. You can see a link to the slides. Okay. So first you define a class in, in models script in Django creating an object. So we are defining here a, a simple one, which is an organization. It only has one field, which is the name, which is a chart field, right? This is Django syntax. And then in the script related to the schema, we are saying GraphQL. Okay, this is an organization type object and it's based on the model we have created there. Okay. And then we can define the different queries we want to, we want to have. So first is a query asking for organizations. It will go into return a list of organization type objects, right? And then we have the resolver, which gets the objects and they, it orders the, the results by name, right? And the good thing is documentation is already updated. If you check, I don't know if you, any of you have played with GraphQL before, but most of the implementations use a basic interface called GraphQL, where you can see that you can perform the queries and see their results. And there is a, there is a section for the automatic documentation that is created based on the schema. So you can see there, there is a query defined on which objects are this, is this query returning. It's an organization type object. It has an ID created at time and last modified. These fields are added by Django because it is inheriting from a very basic Django class and the name field we have added before. Okay. About building mutations. It's similar. We have to define in the schema how are we calling the mutation, which is in this case other organization. We want to add a new organization into the database with the field name. So we define that the field is an organization type field, which is the one we have defined before for the query. Okay. And then we have another class for defining all the mutations, like the one before for the queries. And you can, you can say here, this is a field. We are, we are, we are expecting a field, which is the name for having the organization. Okay. So if you, if you check on the function mutate, it, it calls to another function called other organization. Right. This is behind the scenes is calling. This is how we have defined this. A method in the API script, taking care of validating or controlling the errors that we may have, and also that API method calls a DB method that handles the interaction with the database itself. In this case, we are validating the field and checking for integrity errors to check that it's not duplicate or things like that. And again, the documentation is already updated. So this is a good thing. Okay. About pagination. There are many ways to implement pagination. Most of the methods proposed are based on first offset method, right? You can also use the idea of an object or you can use a cursor that you, is an object that you create for that. The question you may have is how are we getting the, this cursor in case we are, we are following any of these approaches. The thing is the cursor is not a property of the, of the object itself. You can store that in an organization object or identity object, right? It's a property of the connection. And that here comes the concept of edges and connections. So imagine that you have two nodes, one node is friend A, another node is friend B. So you have the forensic time and that, that value only makes sense in the connection. It's not a property of each of, it only makes sense about the connection, right? So this is information that is specific for the connection, for the edge, rather than the object themselves. There are specifications for, for building this in GraphQL, like Relive. But for this particular case, it's too complex because we will have to change the whole model we have defined before. And well, basically we wanted to take our own approach, but without reinventing the wheel, right? So in this case, we went for a hybrid approach using offset and limits, but using pagination Django objects, which, where it's already implemented, is well tested. We know it works well. So, and we also are benefiting from edges and connections. Okay, so I will talk about this in a moment. So it seems like we are complicating our lives, but it is not, it is not because we are using a well proven implementation of, of this. So this is what a query looks like. I don't know if I think I didn't show any query before. So you can see the query is split it in two parts. First in organization, I'm asking for organizations, right? We are setting the filters. I'm asking for the first page and I have, I want three results per page. And then we have two different parts. The entities section is the information about the nodes, the objects we are asking for. And the page info is the information, the information about the connection. In this case, the pagination fields. You can see on the left the result of this query. It gives you the list of organizations and it tells you, okay, this is the first page. Page size is three. This is the, the fields we have a specific value in the query. We have two pages. We have one next page, but we don't have any previous page. We start in one, ending in three, and we have five total results. So in this case, the client knows how to ask for the next results. This is bigger just in case for the people in the back. Okay. So this is how it is implemented behind the scenes. So basically we have to create an abstract type in top of the different types. So coming up, this is the Django objects, the paginator Django objects we are creating. This is the query results. This is the nodes information, the identities, the profiles, the organizations, et cetera. And this is the pagination info, the information that goes into the, into the connection side. And this is a constructor method. So now everyone, sorry, every time we want to add a new type, it has to inherit from that abstract type. So in this case, organization type is going to be organization paginated type, inheriting from that one. And then we have to modify our queries for, when we call the resolver, we have to construct a nested type to get the results as a result of the query. Okay. Okay. About authentication, we have follow-up approach of using JSON web tokens. I don't know if any of you is aware of, is familiar with this technology. The thing is, it's basically an existing user has to generate a token, which has to be included in the HTTP authorization, authorization, sorry, header with the HTTP request. So this token has to be generated by existing user using a mutation that gives you this, this token. Okay. And we are using a module called Graphene GW, GWT. Okay. And how to test this? This was a little bit difficult to test at first time until you set up everything. So first, you have to use an application which is capable of modifying the headers of the request. Otherwise, you are not going to be able to perform the request and get the result. And configuring the Django CSRF token, if any of you have played with Django, it's not trivial if you haven't seen it before. So I used an application calling Sonya. I don't know if any of you knows that. I recommend you to have a look at it. And you can see the token CSRF token there as a request cookie. And then the authorization header with the JSON GWT token is these three letters and then the long token after that. And about how to test in this, this also gave us some problems because we have to create some context in the connection to, in order to create the unit test and to make this work. I don't have, I think, time for more. I have one bonus slide in case you want to check how to do filtering. About future work, we have to implement a command line and web client for this server part we are developing. We have to limit nested queries, which is something, a problem in GraphQL because you can ask organizations and then domains and then organizations from all of the domains and so on. So you will have an infinite loop of queries. And of course, feedback is welcome. You have the link of the repository in the talk, the talk main page. And only saying that Shortening Hat is part of GreenWare Lab, which is a bigger platform to gather, to produce software development analytics. So please have a look. And thank you. Any questions? I think we've gone. Thank you.
 Can you hear me?  Now much better, right?  Okay.  Okay.  Now it's working.  Okay.  Hi, everyone, again.  Okay.  So thank you for being here.  My name is Miguel Angel Fernandez.  I'm working at the DERGIA.  My company does software development analytics.  I'm part of the engineering team.  I'm working as a software developer, and I'm also involved in stuff related with data and  metrics.  Okay.  So first, to give you a glance of the talk, first I'm going to talk about the problem  we are trying to solve, and then we are talking about GraphQL a little bit, and then we are  going to see a little bit of how the implementation went and the process and so on.  Okay.  So we have people contributing to a software project, and people contributing to an open  source project uses a lot of different tools, right?  We have a huge variety of tools depending on the aspect you want to focus on.  It could be code, it could be messaging, right?  So you may want to ask some questions about the project.  So first is how can you measure your project?  That's the main question.  First is how many contributors do we have?  These are basic questions, right?  Another question could be how many companies are contributing to my project?  Okay.  To ask, to answer these basic questions, you need to focus on identities, right?  And to have all the contributors for your project properly identified, right?  So this is an example.  This is a guy contributing to a project.  His name is Tom Bridell, and he's affiliated to his leadering.  Okay.  He's part of Hogwarts.  And then we have another contributor.  This guy over here is called Lord Voldemort.  He's working as a freelance wizard now.  But wait.  He's the same person.  So as a project manager, you may not have this information.  So it's difficult to properly identify a contributor in your project.  If you don't identify them properly, you may think that these are different contributors,  but they are not.  They are the same person, right?  This is one of the problems.  Another problem is that an open source project is a little bit more complex than that, right?  First, this is our CEO, the CEO of my company, Marike.  So he has made a lot of commits, git commits with different emails.  He has his GitHub account.  He has participated in several mailing lists with different emails.  He has a fabricator account to do ticketing.  He has a Slack with different channels.  And he has worked in many companies, right?  And we have also the dates where he started, when he ended, right?  So it's a little bit more complex than the other case, right?  Okay.  So how do we solve this?  The question you may ask is who is who, and who is going to ask this question?  It could be anyone, but usually this is the project manager getting crazy about all these  identities and how to identify everyone.  And here comes sorting hat, which is the tool I'm talking about.  It's the sorting hat for you, for those of you that you don't know Harry Potter.  That this hat is the one that the students put in their head, and it tells you which  house and how much you should be in, right?  So sorting hat is using a relational model with all the entities that are related with  identities.  You can see their profiles.  You can see enrollments, organizations, domain, and so on, right?  Okay.  So we had the guy from before.  This is Lord Baltimore and Tom Riddle, right?  We knew we know that he belonged to his littering, and we have a basic profile about him.  So sorting hat can help us saying, okay, merge these two identities, affiliate these  persons, and complete his profile with this information.  Okay.  Okay.  So far, how can you interact with sorting hat?  So you can interact with sorting hat via command line.  You can use Hashtag, which is a web tool based on Django to communicate with sorting hat,  and you can interact with sorting hat as a Python module.  Okay.  So the main idea here is to build a robust API for sorting hat, for making this easier,  even easier to integrate it with other external applications.  It has to be flexible and easy to adapt to new technologies and other technologies, and  of course ensure consistency as we expect that many users are using sorting hat at the  same time, right?  And here comes GraphQL.  How many of you know something about GraphQL?  Okay.  So probably most of you or those who raise your hand just giving a quick definition.  GraphQL is a query language.  It's typically served over HTTP protocol.  It is also a specification for client server communication, right?  But it doesn't tell you which language you use or how the data has to be stored or which  client you have to support.  It's only a specification, right?  And it is based on graph theory.  So it uses concepts from mathematical graph theory.  For those of you just in case you don't know, if you see the GraphQL logo, the pink dots  are the nodes, the lines between them are the edges, and the connections means the direction  of those edges, okay?  Okay.  So let's compare traditional REST-based application versus GraphQL approach.  REST traditional REST approach is the one used by HATSTYLE, which is the web interface  we have right now.  So imagine that you want a basic view of a profile of a person.  So you have a unique identity, which is the main ID for that person.  And you want his or her identities in all the data sources.  You want also the profile with the name, maybe the gender, the country, okay?  Also the enrollments.  And for every enrollment, a main domain for that organization, okay?  And this is what the query will look like in GraphQL, okay?  So as you see, in one request, you are asking for all the things that you need for that  view.  And you can specify at the level of the field of every endpoint what you want to show.  Okay.  So I'm not going to be partial right now.  I just wanted to point the strongest points, the worst points for the traditional approach  and the best for GraphQL one.  So as I said, REST is just a convention between the server and the client.  It's not a specification.  So you may have your own rules for that.  You can have more data than you need or less data than you need.  That's over or under fetching.  The API documentation is not tied to development and we all know how hard it is to write the  documentation to the things that we code.  And as you have seen in the last slide, you have multiple requests per view, right?  What about GraphQL?  Is a strongly typed language?  This means you define the abstract types you have and each field which type it should  have.  So the client defines what it receives as you saw in the other query.  The client is telling how it wants to receive the information.  The server only sends what the client needs and there is one single request per view.  So summarizing, I think we get GraphQL as the winner.  I'm talking about implementing process a little bit.  So first, we are going to talk about the data model and schema.  We are going to talk about how to implement basic queries and mutations which are basic  entities together with the schema, basic entities of GraphQL.  We added support for paginated results.  We are now in the process of adding authentication.  We are talking about how we are doing that and also some further steps.  Okay.  Okay, about implementation, GraphQL, as I said before, is not tied to any programming  language.  So you find implementation for different languages.  Graphine is a library that provides tools to implement a GraphQL-based API.  And Graphine Django is a library which is built on top of Graphine, right?  So it provides some additional abstractions that you need.  It may ease the process of implementing GraphQL functionality using Django objects.  How many of you know Django and have worked with Django before?  Okay.  So most of you are familiar with Django.  Perfect.  Okay.  So first, we have to do is to define the schema, right?  Basically, GraphQL needs free basic entities.  The schema is defined by types.  Which types are we going to need for our model?  On top of those types, we are going to define queries for obtaining the results, asking  for those objects of those types.  And mutations, which are request changing the objects we have in the database, right?  And that as a whole makes the GraphQL schema.  Okay.  Okay.  So what does this look like in Django?  Okay.  So as most of you know Django, but I think that goes for the rest of the people too.  Instead of types, in Django, we define models, right?  For the queries we are defining, we have to define resolvers, which are functions telling  how to solve each query and how to return the results.  And the mutations are operations creating things, reading things, updating or deleting  any object in the database.  Okay.  And that's the Graph in Django schema.  About the data model, it turns out it is already a graph.  We saw before a picture.  So it made sense to, to modelize this as a graph being the nodes, you see the nodes  and the edges, right?  So we will have nodes for identities, nodes for the profile, nodes for the domains, nodes  for the stations and so on.  Okay.  Okay.  So let's start sneaking something somehow into the implementation.  So this is a basic recipe for building a query in GraphQL using the Graphin Django library.  I don't know for those in the back.  Please tell me if you can see the code.  If not, remember that the slides are available in, in the website of this talk.  You can see a link to the slides.  Okay.  So first you define a class in, in models script in Django creating an object.  So we are defining here a, a simple one, which is an organization.  It only has one field, which is the name, which is a chart field, right?  This is Django syntax.  And then in the script related to the schema, we are saying GraphQL.  Okay, this is an organization type object and it's based on the model we have created  there.  Okay.  And then we can define the different queries we want to, we want to have.  So first is a query asking for organizations.  It will go into return a list of organization type objects, right?  And then we have the resolver, which gets the objects and they, it orders the, the results  by name, right?  And the good thing is documentation is already updated.  If you check, I don't know if you, any of you have played with GraphQL before, but most  of the implementations use a basic interface called GraphQL, where you can see that you  can perform the queries and see their results.  And there is a, there is a section for the automatic documentation that is created based  on the schema.  So you can see there, there is a query defined on which objects are this, is this query returning.  It's an organization type object.  It has an ID created at time and last modified.  These fields are added by Django because it is inheriting from a very basic Django class  and the name field we have added before.  Okay.  About building mutations.  It's similar.  We have to define in the schema how are we calling the mutation, which is in this case  other organization.  We want to add a new organization into the database with the field name.  So we define that the field is an organization type field, which is the one we have defined  before for the query.  Okay.  And then we have another class for defining all the mutations, like the one before for  the queries.  And you can, you can say here, this is a field.  We are, we are, we are expecting a field, which is the name for having the organization.  Okay.  So if you, if you check on the function mutate, it, it calls to another function called other  organization.  Right.  This is behind the scenes is calling.  This is how we have defined this.  A method in the API script, taking care of validating or controlling the errors that we  may have, and also that API method calls a DB method that handles the interaction with  the database itself.  In this case, we are validating the field and checking for integrity errors to check  that it's not duplicate or things like that.  And again, the documentation is already updated.  So this is a good thing.  Okay.  About pagination.  There are many ways to implement pagination.  Most of the methods proposed are based on first offset method, right?  You can also use the idea of an object or you can use a cursor that you, is an object  that you create for that.  The question you may have is how are we getting the, this cursor in case we are, we are following  any of these approaches.  The thing is the cursor is not a property of the, of the object itself.  You can store that in an organization object or identity object, right?  It's a property of the connection.  And that here comes the concept of edges and connections.  So imagine that you have two nodes, one node is friend A, another node is friend B. So you  have the forensic time and that, that value only makes sense in the connection.  It's not a property of each of, it only makes sense about the connection, right?  So this is information that is specific for the connection, for the edge, rather than  the object themselves.  There are specifications for, for building this in GraphQL, like Relive.  But for this particular case, it's too complex because we will have to change the whole model  we have defined before.  And well, basically we wanted to take our own approach, but without reinventing the wheel,  right?  So in this case, we went for a hybrid approach using offset and limits, but using pagination  Django objects, which, where it's already implemented, is well tested.  We know it works well.  So, and we also are benefiting from edges and connections.  Okay, so I will talk about this in a moment.  So it seems like we are complicating our lives, but it is not, it is not because we are using  a well proven implementation of, of this.  So this is what a query looks like.  I don't know if I think I didn't show any query before.  So you can see the query is split it in two parts.  First in organization, I'm asking for organizations, right?  We are setting the filters.  I'm asking for the first page and I have, I want three results per page.  And then we have two different parts.  The entities section is the information about the nodes, the objects we are asking for.  And the page info is the information, the information about the connection.  In this case, the pagination fields.  You can see on the left the result of this query.  It gives you the list of organizations and it tells you, okay, this is the first page.  Page size is three.  This is the, the fields we have a specific value in the query.  We have two pages.  We have one next page, but we don't have any previous page.  We start in one, ending in three, and we have five total results.  So in this case, the client knows how to ask for the next results.  This is bigger just in case for the people in the back.  Okay.  So this is how it is implemented behind the scenes.  So basically we have to create an abstract type in top of the different types.  So coming up, this is the Django objects, the paginator Django objects we are creating.  This is the query results.  This is the nodes information, the identities, the profiles, the organizations, et cetera.  And this is the pagination info, the information that goes into the, into the connection side.  And this is a constructor method.  So now everyone, sorry, every time we want to add a new type, it has to inherit from  that abstract type.  So in this case, organization type is going to be organization paginated type, inheriting  from that one.  And then we have to modify our queries for, when we call the resolver, we have to construct  a nested type to get the results as a result of the query.  Okay.  Okay.  About authentication, we have follow-up approach of using JSON web tokens.  I don't know if any of you is aware of, is familiar with this technology.  The thing is, it's basically an existing user has to generate a token, which has to be included  in the HTTP authorization, authorization, sorry, header with the HTTP request.  So this token has to be generated by existing user using a mutation that gives you this,  this token.  Okay.  And we are using a module called Graphene GW, GWT.  Okay.  And how to test this?  This was a little bit difficult to test at first time until you set up everything.  So first, you have to use an application which is capable of modifying the headers of the  request.  Otherwise, you are not going to be able to perform the request and get the result.  And configuring the Django CSRF token, if any of you have played with Django, it's not  trivial if you haven't seen it before.  So I used an application calling Sonya.  I don't know if any of you knows that.  I recommend you to have a look at it.  And you can see the token CSRF token there as a request cookie.  And then the authorization header with the JSON GWT token is these three letters and  then the long token after that.  And about how to test in this, this also gave us some problems because we have to create  some context in the connection to, in order to create the unit test and to make this work.  I don't have, I think, time for more.  I have one bonus slide in case you want to check how to do filtering.  About future work, we have to implement a command line and web client for this server  part we are developing.  We have to limit nested queries, which is something, a problem in GraphQL because you  can ask organizations and then domains and then organizations from all of the domains  and so on.  So you will have an infinite loop of queries.  And of course, feedback is welcome.  You have the link of the repository in the talk, the talk main page.  And only saying that Shortening Hat is part of GreenWare Lab, which is a bigger platform  to gather, to produce software development analytics.  So please have a look.  And thank you.  Any questions?  I think we've gone.  Thank you.
python2020_graphql_0_167.png python2020_graphql_168_875.png python2020_graphql_876_2003.png python2020_graphql_2004_3431.png python2020_graphql_3432_5219.png python2020_graphql_5220_5627.png python2020_graphql_5628_6491.png python2020_graphql_6492_7199.png python2020_graphql_7200_9875.png python2020_graphql_9876_11015.png python2020_graphql_11016_11531.png python2020_graphql_11532_13415.png python2020_graphql_13416_13559.png python2020_graphql_13560_14495.png python2020_graphql_14496_15587.png python2020_graphql_15588_15995.png python2020_graphql_15996_16667.png python2020_graphql_16668_16763.png python2020_graphql_16764_17543.png python2020_graphql_17544_18287.png python2020_graphql_18288_23687.png python2020_graphql_23688_26855.png python2020_graphql_26856_28439.png python2020_graphql_28440_28559.png python2020_graphql_28560_29339.png python2020_graphql_29340_30143.png python2020_graphql_30144_30983.png python2020_graphql_30984_31151.png python2020_graphql_31152_32831.png python2020_graphql_32832_32999.png python2020_graphql_33000_33719.png python2020_graphql_33720_34043.png python2020_graphql_34044_34583.png python2020_graphql_34584_34700.png