emehrkay / Pypher

Python Cypher Querybuilder
MIT License
170 stars 29 forks source link

Pypher behaves strangely in Pycharm Debug mode #47

Open rock-it-with-asher opened 3 years ago

rock-it-with-asher commented 3 years ago

ran with python 3.7.0 on both windows and mac versions, here is an output example:


str(tmp)
'MATCH (yo:`label`) shape shape.`len` shape shape.`len`'
str(tmp)
'MATCH (yo:`label`) shape shape.`len` shape shape.`len` shape shape.`len` shape shape.`len`'
str(tmp)
'MATCH (yo:`label`) shape shape.`len` shape shape.`len` shape shape.`len` shape shape.`len` shape shape.`len` shape shape.`len`'```

Each call to `__str__` adds more of the garbage strings. it doesn't happen in a regular run mode
CisterMoke commented 3 years ago

This issue seems the be a result of the following if statement in Pypher.__getattr__ shown here . Looks like that was added to support the mathematical operations. Adding the definition of __len__ to the Pypher fixes the issue of the len spam. I haven't come across any shape spam though. Maybe that is the result of Pycharm's scientific mode?

CisterMoke commented 3 years ago

Upon further inspection I was unable to come up with a proper definition of __len__ that wouldn't break the tests. I also don't understand why __getattr__ is defined in such a way that 'p.property' would add a property to the Pypher instance. It feels very hacky and appears to go against the lower level python routines. Perhaps a different syntax could be used to for this functionality?

emehrkay commented 3 years ago

The reason why it is p.__property__ or p.property('property') is because p.property takes care of defining a Statement when a Statement is at the bottom of the chain it does double duty -- either being a statement or a function -- it can turn into a function when __call__ is called on the pypher instance

ie

p = Pypher()
p.RETURN # statement

# vs.

p.RETURN(*args) # statement, then __call__

There were a bunch of concessions and trade-offs made to get this magic to work. Maybe the underscore syntax should be dropped all together since it is causing issues with tooling.

A possible fix would be to add a __len__ method to Pypher (it would be O(N) but I we dont care about that really lol). Im guessing it would look something like

def __len__(self):
    len = len(self.next) if self.next is not None else 0
    return 1 + len
emehrkay commented 3 years ago

^^^ keeping the double underscore for property syntax, we'd have to define the behavior of every dunder method on the Pypher class. it may make more sense to drop it