Skip to content

Conversation

@sandeepsajan0
Copy link
Contributor

Now it loads only the API structure from the API doc like classendpoints, collectionendpoints, entrypoints and some of these properties and operations, not loads the data from the endpoint. Please suggest any changes.

@xadahiya
Copy link
Member

@sandeepsajan0 The whole agent is supposed to work as a single thing. Why are you rewriting the code? You're supposed to refactor the code you wrote earlier to fit our needs not rewrite the entire thing.

@sandeepsajan0
Copy link
Contributor Author

Now, only the graph loads in Redis but after the first query data will be load in Redis in a way like for collection_endpoints, we will give endpoint_id to load_from_sever function and it will load the data for this particular endpoint to the Redis and all based on user's query. The code may be updated after the querying mechanism.


def load_from_server(
self,
class_endpoint_id,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All you need to fetch data from server is url or the endpoint. Refactor the code and create simple functions

@sandeepsajan0
Copy link
Contributor Author

The latest commit I have done for the update of querying mechanism and I am still working on it. So, review it later when I will update it next time. Now, I am working on the modification of graph and also on querying mechanism. So, I'll update it soon.


def final_file(url):
""" Open the given url and read and load the Json data."""
response = urllib.request.urlopen(url)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

try-except block needed here. Every I/O call has to be safely written into an exception block, same for the JSON serialization below.

map_string = map(str.strip,string.split(','))
property_list = list(map_string)
check = property_list.pop()
property_list.append(check.replace("\x00",""))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How it happens that this character "\x00" ends up here?

Copy link
Contributor Author

@sandeepsajan0 sandeepsajan0 Jun 23, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"\x00" is null character and In C it works also as a string terminator character. Here is something related to this.

print (property_list)

def endpoints_query(query):
r = redis.StrictRedis(host='localhost', port=6379, db=0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should factorized this at application run-time, and make the connection available through a proxy class or function like:

class RedisProxy:
    def __init__(self):
        self.connection = redis.StrictRedis...
    def get_connection(self):
        return self.connectoin

@Mec-iS
Copy link
Contributor

Mec-iS commented Jun 23, 2018

See annotations in the code.

Other annotations:

  • I don't see any comment explaining the procedures
  • try to apply basic patterns like Proxy or Facade, I know it seems hard in the beginning but you should try to give a better design to the codebase since the beginning, refactoring has to speed up, you can write better scripts since the beginning if the code is more ordered
  • in general, work should go on faster, with more iterations

@sandeepsajan0
Copy link
Contributor Author

Thanks @Mec-iS , Actually I am still working on it and I will update it soon with all these things you have mentioned.

if __name__ == "__main__":
def main(new_url,api_doc):
redis_con = redis.Redis(host='localhost', port=6379)
global redis_graph
Copy link
Member

@xadahiya xadahiya Jun 24, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of creating a global variable for the graph you should pass the graph as a function argument whenever required.

Global variables should be used very carefully. You should avoid using them unless it's absolutely necessary.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, we need to import redis_graph attribute in querying_mechanism. So, I am using this as a global variable.

count = 2

for objects in reply:
count+=1
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is count? How does it work?
Add DOCStrings and proper comments

global url
url =input("url>>>")
apidoc = final_file(url + "/vocab")
global api_doc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, avoid using global variables

'apidoc','MATCH (p:classes)' 'RETURN p')
count = 0

if query == "collectionEndpoint":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try to write small and separate functions for different types of queries. It'll make the code more readable and easier to maintain.

@sandeepsajan0
Copy link
Contributor Author

Querying mechanism is working now but I am still working on some of its issues like:

  • faceted index for every node properties.
  • error handling.
  • add more features.
  • Add new data in Redis memory #24
    @Mec-iS I have a point that it needs to indexing for every node's properties? If yes please elaborate a bit for me. As I think about it, it can partially resolve the Add new data in Redis memory #24 because if we use faceted indexing then we can show the data to the user with help of indexing. So, we don't need to access the graph for data and user will not get the problem of multiple data. Am I right? Please explain more.

@Mec-iS
Copy link
Contributor

Mec-iS commented Jun 29, 2018

  • Faceted indexes work because they index only few properties of an object. Indexing the full object means storing the object twice. For now we need only to index the unique id of an object, that's why I asked to work on a globally unique id for every entity.

Once we have unique ids, we can talk about synchronization and querying.

The idea is to store only predicates that relates objects ids. So:

unique_id -> some_prop -> unique_id

Again, that is why we need global ids in place.

Copy link
Member

@xadahiya xadahiya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sandeepsajan0 You should use Docstrings as vaibhav is using here HTTP-APIs/hydrus#228

endpoint][
"class"].supportedProperty:
if (endpoint != support_property.title and
support_property.title not in self.class_endpoints):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments explaining what you're doing here.

member[support_property.title] = str(
new_file[support_property.title].replace(" ", ""))
else:
no_endpoint_property = new_file[support_property.title]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments to explain this as well.

endpoint_property]:
for nodes in self.redis_graph.nodes.values():
if endpoints == nodes.alias:
self.addEdge(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the point of using break in line 182?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we got the endpoint once in redis_graph nodes then no need to go ahead in the redis_graph. So, I am using the break for that.

print("member alias and url+id",
member_alias.capitalize(),
base_url + member_id)
new_url1 = new_url + "/" + member_id
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rename this and use proper variables.

member[support_property.title] = str(
new_file1[support_property.title].replace(" ", ""))
new_file1[
support_property.title].replace(" ", ""))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add comments to explain what you're doing and why.


def get_classes_properties(self, query):
"""
Show the given type of property of given Class endpoint.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Explain what query is with example. In general, you should use the format vaibhav is using for docstrings.
See this HTTP-APIs/hydrus#228

faceted_list.append(self.faceted_key(key, value))
if len(query) > 0:
operation, query = query.split(" ", 1)
if operation == "or":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if there are multiple key:value pair and not all have or. Like what it two conditions have and and the rest have or and similar situations.
You should handle such scenarios as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, there are some issues like this. I am working on it.

url = input("url>>>")
handle_data = HandleData()
apidoc = handle_data.load_data(url + "/vocab")
while (1):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use while(True) instead. Also, you should display what errors occurred in APIDoc loading failed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay.
Yeah, we are displaying the error in HandleData (line 26-30).

facades.initialize()
global check_list
check_list = []
while(1):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should do something like this, it's much more elegant.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can also create a help() to return the help strings.

print("for collection properties:-",
"show <collection_endpoint> properties")
print("for classes properties:- show class<class_endpoint> properties")
print("for compare properties:-show <key> <value> and/or <key1> <value1>")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clear this, use the method I've suggested above.

@sandeepsajan0 sandeepsajan0 changed the title add lazyload graph Implement querying mechanism Jul 6, 2018

PARENT_DIR = path.dirname(path.dirname(path.abspath(__file__)))
sys.path.append(PARENT_DIR)
import querying_mechanism
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Use absolute imports everywhere not relative imports

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am trouble here, I have tried or read many things but I don't find any for that. Please help for that.

"""Test for all the endpoints class + collection endpoints"""
query = "show endpoints"
data = query_facades.user_query(query)
if len(data) == 11:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need to use assert statements in tests. Also, don't just compare the length you need to test data as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we don't need to test for all the endpoint because we have two different test for class endpoints and collection endpoints. So, These two can cover this endpoint test. And Yeah, I have change comparison of length to comparison of data. I'll push it early.

return False


class TestQueryingMechanism(unittest.TestCase):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should define tests here only. Why are you defining them outside?



class TestQueryingMechanism(unittest.TestCase):
query_test = Tests()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also, use teardown and setup methods for testing.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can not figure out, what should I put in setUp and tearDown function? I think there are the different things in every test because of the different query in every test nothing is similar to put in setUp function.

Copy link
Member

@xadahiya xadahiya left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You still haven't fixed all the things I pointed out earlier. Also, see the issues I've commented upon.

@sandeepsajan0
Copy link
Contributor Author

I think, only one major issue is remaining that user can input and and or both in one query.
I need some time for that. Can I open an issue for that and can discuss there if required?

self.assertEqual(data,check_data)


if __name__ == "__main__":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sandeep you're supposed to initialize the graph and everything in the setUp function. It is meant to do the same. Rest everything looks fine for now. Create an issue for the and or query part then we can merge this.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xadahiya If we initialize the graph every time for every test with setup method then there will be data stored multiple times in Redis server(because Redis server is running independently to the files). And It'll provide duplicate data for which we already have an issue #24 ( I am working on it). And due to duplicate data test cases will fail.

self.assertEqual(data,check_data)


if __name__ == "__main__":
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sandeepsajan0 You need to include all this in the setUp function, rest everything looks fine for now. Fix this then we can merge your PR.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just call unittest.main() here

@xadahiya xadahiya merged commit 5b9fa10 into HTTP-APIs:develop Jul 9, 2018
@sandeepsajan0 sandeepsajan0 deleted the sandeeppatch1 branch February 6, 2019 06:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants