<commit_before>#!/usr/bin/python
# @Author: Eddie Ruano
# @Date:   2017-05-01 05:14:54
# @Last Modified by:   Eddie Ruano
# @Last Modified time: 2017-06-08 21:04:57
#
"""
    MissionControl.py is a debugging tool for DESI_Sentinel
"""
################################## IMPORTS ###################################
import sys
import os.path
import signal
import time
#
import collections
import pyaudio
import wave
from math import floor
# Customs Mods #
import RPi.GPIO as GPIO
import Sentinel as Sentinel
# Local Modules #
################################### PATHS #####################################
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import drivers.VoyagerHCSR04 as VoyagerHCSR04
import DESIConfig as DESIConfig
import drivers.MPR121 as MPR121
#import trigger.snowboydetect as snowboydetect
############################ INITIALIZE CLASSES ###############################
DESI = DESIConfig.DESI()
Voyager1 = VoyagerHCSR04.Voyager("Voyager1", DESI.PROX1_TRIG, DESI.PROX1_ECHO)
Voyager2 = VoyagerHCSR04.Voyager("Voyager2", DESI.PROX2_TRIG, DESI.PROX2_ECHO)
TouchSense = MPR121.MPR121()
Sentinel = Sentinel.Sentinel()
################################## PATHS ######################################

def main():
    # Variables/Flags
    flagRailWarning = False
    flagSelectorWarning = False
    flagProximityWarning = False
    # Initialize DESI States
    DESI.initDESI()
    # Initialize Voyager Proximity Sensors
    DESI.initProximity(Voyager1, Voyager2)
    try:
        if not TouchSense.begin():  # Init TouchSense Capacitive Sensor Array
            print("TSense Error")
            sys.exit(1)
    except OSError as e:
        print(e)
        print("Sensor Error.")
        sys.exit(1)
    Sentinel.getStateKnob(DESI)
    Sentinel.setStateKnob()
    Sentinel.updateActiveLock(TouchSense)
    # Add the triggers
    GPIO.add_event_detect(DESI.IN_START, GPIO.FALLING, callback=StartHandler, bouncetime=Sentinel.CONST_BOUNCE)
    GPIO.add_event_detect(DESI.IN_PAUSE, GPIO.FALLING, callback=PauseHandler, bouncetime=Sentinel.CONST_BOUNCE)
    try:
        DESI.DESISendResponse("audio/wav_lets_start.wav")
        print("Listening")
        localKnobState = Sentinel.StateKnob
        while True:
            # Update the ActiveLock
            Sentinel.updateActiveLock(TouchSense)
            # Query the knob states
            Sentinel.getStateKnob(DESI)
            # Set the Knob State according to the recent get
            Sentinel.setStateKnob()
            speed = getSpeed()
            # Check if the knob changed position
            if ((Sentinel.StateKnob * 1.0) != localKnobState):
                localKnobState = Sentinel.StateKnob
                DESI.DESISend(speed)
                print("in")
            # Set the Speed if the knob doesn't match up
            if ((Sentinel.StateKnob * 1.0) != Sentinel.StateSpeed):
                DESI.DESISend(Sentinel.StateKnob * 1.0)
                Sentinel.StateSpeed = (speed)
            #Start Query for Distances
            Sentinel.Proximity = queryDistance()
            # Check to see if the Distance is above the threshold
            if (Sentinel.Proximity > 12.0):
                #if (flagProximityWarning == False):
                #    DESI.DESISendResponse(DESI.RespondProx)
                #    flagProximityWarning = True
                print("Yellow")
                # Start the coundown here
                Sentinel.ProxCountdown -= 1
                # Here we trigger finally
                if(Sentinel.ProxCountdown == 0):
                    i = 0
                    while i < Sentinel.Redux:
                        DESI.DESISend("SendDown")
                        i += 1
                    # Update the new speed and redux
                    Sentinel.setSpeed(Sentinel.StateSpeed - Sentinel.Redux)
                    # Restart the counter
                    Sentinel.ProxCountdown = Sentinel.PROXCOUNT
            else: # Else, we're back in the green
                Sentinel.ProxCountdown = Sentinel.PROXCOUNT
                Sentinel.setSpeed(Sentinel.StateKnob * 1.0)
            # Here we check for contact
            if not Sentinel.ActiveLock:
                # Start the countdown to regain contact
                if ((flagRailWarning == False) and Sentinel.CapCountdown == (Sentinel.CapCountdown/ 2)):
                    DESI.DESISendResponse(DESI.RespondRails)
                    flagRailWarning = True
                if Sentinel.CapCountdown == 0 and (DESI.State_Main != "Pause"):
                    saved_state = DESI.State_Main
                    DESI.DESISend("Pause")
                    #print("la")
                    #DESI.State_Main = "Pause"
                    print(DESI.State_Main)
                    Sentinel.ActiveLock = True
                else:
                    # Continue to countdown
                    Sentinel.CapCountdown -= 1
            elif DESI.State_Main == "Pause":
                DESI.DESISend("Pause")
                DESI.DESISend("Send01")
                #print("ra")
                # Any contact will reset the counter because it's sensitive
                Sentinel.CapCountdown = Sentinel.CAPCOUNT
                Sentinel.ActiveLock = False
                Sentinel.setSpeed(Sentinel.StateKnob * 1.0)
            time.sleep(Sentinel.RunningLoopSpeed)
    except KeyboardInterrupt:
        GPIO.cleanup()
        DESI.DESICleanup()
        print("Shutdown Mission.")
        #Detector.terminate()

### END OF MAIN ###
"""Helper Functions"""
def activateAlexa():
    GPIO.output(DESI.OUT_ALEXA, GPIO.LOW)
    time.sleep(2)
    GPIO.output(DESI.OUT_ALEXA, GPIO.HIGH)
def queryDistance():
    distv1 = Voyager1.get_distance()
    distv2 = Voyager2.get_distance()
    # Sanitize
    distv1 = sanitizeDistance(Voyager1, distv1)
    distv2 = sanitizeDistance(Voyager2, distv2)
    # Subtract 3.5 to get 0
    distv1 = abs(distv1 - 3.5)
    distv2 = abs(distv2 - 3.5)
    if distv1 == -1.0 and distv2 != -1.0:
        print("Check Sensor 1")
        return distv2
    elif distv2 == -1.0 and distv1 != -1.0:
        print("Check Sensor 2")
        return distv1
    else:
        ave = (distv1 + distv2) / 2
    return ave
def sanitizeDistance(voy, inDist):
    tries = 0
    while inDist == -1.0 and tries < Sentinel.ProximityRetries:
        inDist = Voyager1.get_distance()
    return inDist
def StartHandler(channel):
    print("Starting")
    DESI.DESISend("Start")
def getSpeed():
    if Sentinel.StateKnob == 0:
        return "Send00"
    elif Sentinel.StateKnob == 1:
        return "Send01"
    elif Sentinel.StateKnob == 2:
        return "Send02"
    elif Sentinel.StateKnob == 3:
        return "Send03"
    elif Sentinel.StateKnob == 4:
        return "Send04"
    else:
        return "Send00"
def PauseHandler(channel):
    if (Sentinel.StateKnob == 0):
        DESI.DESISend("Shutdown")
        time.sleep(30)
        GPIO.cleanup()
        print("Shutdown")
        sys.exit(0)
    else:
        print("pause")
        DESI.DESISend("Pause")
#def signal_handler(signal, frame):
#    global HotwordInterrupt
#    HotwordInterrupt = True
#def interrupt_callback():
#    global HotwordInterrupt
#    return HotwordInterrupt
### MAIN CALL ###
if __name__ == "__main__":
    main()<commit_msg>Script<commit_after>#!/usr/bin/python
# @Author: Eddie Ruano
# @Date:   2017-05-01 05:14:54
# @Last Modified by:   Eddie Ruano
# @Last Modified time: 2017-06-08 21:08:17
#
"""
    MissionControl.py is a debugging tool for DESI_Sentinel
"""
################################## IMPORTS ###################################
import sys
import os.path
import signal
import time
#
import collections
import pyaudio
import wave
from math import floor
# Customs Mods #
import RPi.GPIO as GPIO
import Sentinel as Sentinel
# Local Modules #
################################### PATHS #####################################
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import drivers.VoyagerHCSR04 as VoyagerHCSR04
import DESIConfig as DESIConfig
import drivers.MPR121 as MPR121
#import trigger.snowboydetect as snowboydetect
############################ INITIALIZE CLASSES ###############################
DESI = DESIConfig.DESI()
Voyager1 = VoyagerHCSR04.Voyager("Voyager1", DESI.PROX1_TRIG, DESI.PROX1_ECHO)
Voyager2 = VoyagerHCSR04.Voyager("Voyager2", DESI.PROX2_TRIG, DESI.PROX2_ECHO)
TouchSense = MPR121.MPR121()
Sentinel = Sentinel.Sentinel()
################################## PATHS ######################################

def main():
    # Variables/Flags
    flagRailWarning = False
    flagSelectorWarning = False
    flagProximityWarning = False
    # Initialize DESI States
    DESI.initDESI()
    # Initialize Voyager Proximity Sensors
    DESI.initProximity(Voyager1, Voyager2)
    try:
        if not TouchSense.begin():  # Init TouchSense Capacitive Sensor Array
            print("TSense Error")
            sys.exit(1)
    except OSError as e:
        print(e)
        print("Sensor Error.")
        sys.exit(1)
    Sentinel.getStateKnob(DESI)
    Sentinel.setStateKnob()
    Sentinel.updateActiveLock(TouchSense)
    # Add the triggers
    GPIO.add_event_detect(DESI.IN_START, GPIO.FALLING, callback=StartHandler, bouncetime=Sentinel.CONST_BOUNCE)
    GPIO.add_event_detect(DESI.IN_PAUSE, GPIO.FALLING, callback=PauseHandler, bouncetime=Sentinel.CONST_BOUNCE)
    try:
        DESI.DESISendResponse("audio/wav_lets_start.wav")
        print("Listening")
        localKnobState = Sentinel.StateKnob
        while True:
            # Update the ActiveLock
            Sentinel.updateActiveLock(TouchSense)
            # Query the knob states
            Sentinel.getStateKnob(DESI)
            # Set the Knob State according to the recent get
            Sentinel.setStateKnob()
            speed = getSpeed()
            # Check if the knob changed position
            if ((Sentinel.StateKnob * 1.0) != localKnobState):
                localKnobState = Sentinel.StateKnob
                DESI.DESISend(speed)
                print("in")
            # Set the Speed if the knob doesn't match up
            if ((Sentinel.StateKnob * 1.0) != Sentinel.StateSpeed):
                DESI.DESISend(Sentinel.StateKnob * 1.0)
                Sentinel.StateSpeed = (speed)
            #Start Query for Distances
            Sentinel.Proximity = queryDistance()
            # Check to see if the Distance is above the threshold
            if (Sentinel.Proximity > 12.0):
                #if (flagProximityWarning == False):
                #    DESI.DESISendResponse(DESI.RespondProx)
                #    flagProximityWarning = True
                print("Yellow")
                # Start the coundown here
                Sentinel.ProxCountdown -= 1
                # Here we trigger finally
                if(Sentinel.ProxCountdown == 0):
                    i = 0
                    while i < Sentinel.Redux:
                        DESI.DESISend("SendDown")
                        i += 1
                    # Update the new speed and redux
                    Sentinel.setSpeed(Sentinel.StateSpeed - Sentinel.Redux)
                    # Restart the counter
                    Sentinel.ProxCountdown = Sentinel.PROXCOUNT
            else: # Else, we're back in the green
                Sentinel.ProxCountdown = Sentinel.PROXCOUNT
                Sentinel.setSpeed(Sentinel.StateKnob * 1.0)
            # Here we check for contact
            if not Sentinel.ActiveLock:
                # Start the countdown to regain contact
                if ((flagRailWarning == False) and Sentinel.CapCountdown == (Sentinel.CapCountdown/ 2)):
                    DESI.DESISendResponse(DESI.RespondRails)
                    flagRailWarning = True
                if Sentinel.CapCountdown == 0 and (DESI.State_Main != "Pause"):
                    saved_state = DESI.State_Main
                    DESI.DESISend("Pause")
                    #print("la")
                    #DESI.State_Main = "Pause"
                    print(DESI.State_Main)
                    Sentinel.ActiveLock = True
                else:
                    # Continue to countdown
                    Sentinel.CapCountdown -= 1
            elif DESI.State_Main == "Pause":
                DESI.DESISend("Pause")
                DESI.DESISend("Send01")
                #print("ra")
                # Any contact will reset the counter because it's sensitive
                Sentinel.CapCountdown = Sentinel.CAPCOUNT
                Sentinel.ActiveLock = False
                Sentinel.setSpeed(Sentinel.StateKnob * 1.0)
            time.sleep(Sentinel.RunningLoopSpeed)
    except KeyboardInterrupt:
        GPIO.cleanup()
        DESI.DESICleanup()
        print("Shutdown Mission.")
        #Detector.terminate()

### END OF MAIN ###
"""Helper Functions"""
def activateAlexa():
    GPIO.output(DESI.OUT_ALEXA, GPIO.LOW)
    time.sleep(2)
    GPIO.output(DESI.OUT_ALEXA, GPIO.HIGH)
def queryDistance():
    distv1 = Voyager1.get_distance()
    distv2 = Voyager2.get_distance()
    # Sanitize
    distv1 = sanitizeDistance(Voyager1, distv1)
    distv2 = sanitizeDistance(Voyager2, distv2)
    # Subtract 3.5 to get 0
    distv1 = abs(distv1 - 3.5)
    distv2 = abs(distv2 - 3.5)
    if distv1 == -1.0 and distv2 != -1.0:
        print("Check Sensor 1")
        return distv2
    elif distv2 == -1.0 and distv1 != -1.0:
        print("Check Sensor 2")
        return distv1
    else:
        ave = (distv1 + distv2) / 2
    return ave
def sanitizeDistance(voy, inDist):
    tries = 0
    while inDist == -1.0 and tries < Sentinel.ProximityRetries:
        inDist = Voyager1.get_distance()
    return inDist
def StartHandler(channel):
    print("Starting")
    DESI.DESISend("Start")
def getSpeed():
    if Sentinel.StateKnob == 0:
        return "Send00"
    elif Sentinel.StateKnob == 1:
        return "Send01"
    elif Sentinel.StateKnob == 2:
        return "Send02"
    elif Sentinel.StateKnob == 3:
        return "Send03"
    elif Sentinel.StateKnob == 4:
        return "Send04"
    else:
        return "Send00"
def PauseHandler(channel):
    if (Sentinel.StateKnob == 0):
        DESI.DESISend("Shutdown")
        time.sleep(30)
        GPIO.cleanup()
        print("Shutdown")
        sys.exit(0)
    else:
        print("pause")
        DESI.DESISend("Pause")
#def signal_handler(signal, frame):
#    global HotwordInterrupt
#    HotwordInterrupt = True
#def interrupt_callback():
#    global HotwordInterrupt
#    return HotwordInterrupt
### MAIN CALL ###
if __name__ == "__main__":
    main()<|endoftext|>


<commit_before>#!/usr/bin/python
# @Author: Eddie Ruano
# @Date:   2017-05-01 05:14:54
# @Last Modified by:   Eddie Ruano
# @Last Modified time: 2017-06-03 22:09:08
#
"""
    MissionControl.py is a debugging tool for DESI_Sentinel
"""
### IMPORT MODULES ###
import sys
import os.path
import signal
import time
# Customs Mods #
import Adafruit_MPR121.MPR121 as MPR121
import RPi.GPIO as GPIO
# Local Modules #
### Set path ###
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import drivers.VoyagerHCSR04 as VoyagerHCSR04
import drivers.DESIConfig as DESIConfig
### Global Variables ###
DESI = DESIConfig.DESI()
#Voyager1 = VoyagerHCSR04.Voyager("Voyager1", DESI.PROX1_TRIG, DESI.PROX1_ECHO)
#Voyager2 = VoyagerHCSR04.Voyager("Voyager2", DESI.PROX2_TRIG, DESI.PROX2_ECHO)
TouchSense = MPR121.MPR121()

def main():
    # Variables
    proxError = 0.0
    distv1 = 0.0
    distv2 = 0.0
    slack = 0.0
    contact = False
    # Initialize DESI States
    DESI.initDESI()
    # Initialize Voyager Proximity Sensors
    #DESI.initProximity(Voyager1, Voyager2)
    if not TouchSense.begin():  # Init TouchSense Capacitive Sensor Array
        print("TSense")
        sys.exit(1)
    try:
        print("Listening")
        GPIO.add_event_detect(DESI.IN_START, GPIO.FALLING, DESI.performStart, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_PAUSE, GPIO.FALLING, DESI.performPause, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED0, GPIO.FALLING, DESI.performS0, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED1, GPIO.FALLING, DESI.performS1, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED2, GPIO.FALLING, DESI.performS2, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED3, GPIO.FALLING, DESI.performS3, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED4, GPIO.FALLING, DESI.performS4, DESI.bounceTime)
        #DESI.DESIListen()
        activeFlag = True
        while activeFlag == True:
            activeFlag = True
            command = input("Enter a command: ")
            if command == "start":
                DESI.DESISend("Start")
            elif command == "shutdown":
                DESI.DESISend("Shutdown")
            elif command == "pause":
                DESI.DESISend("Pause")
            elif command == "unpause":
                DESI.DESISend("Pause")
            elif command == "enter":
                DESI.DESISend("Enter")
            elif command == "0":
                DESI.DESISend("Send00")
            elif command == "1":
                DESI.DESISend("Send01")
            elif command == "2":
                DESI.DESISend("Send02")
            elif command == "3":
                DESI.DESISend("Send03")
            elif command == "4":
                DESI.DESISend("Send04")
            elif command == "alexa":
                DESI.DESISend("SendAlexa")
            else:
                print("Invalid Command")
            # Query for the proximity of Megan #
            #distv1 = Voyager1.get_distance()
            #time.sleep(0.3)
            #distv2 = Voyager2.get_distance()
            #distAverage = (distv1 + distv2) / 2
            #proxError = distv1 - distv2
            #contact = checkContact()
            #state = checkState(distAverage)
            #if state == "Red":
            #    print("Red!")
            #    past_state = state
            #    DESI.send("Pause")
            #    time.sleep(5)
            #    DESI.send(past_state)
            #elif state == "Yellow":
            #    DESI.send("Down")
            #    time.sleep(0.4)
            #    DESI.send("Down")
            #    time.sleep(0.4)
            #    DESI.send("Down")
            #else:
            #    print("Green!")
            #    slack = 30 - distAverage
            #    redux = ((distAverage - 10) / 2) * 10
            #    redux = int(redux)
#
#           time.sleep(1)
    # Catch Ctrl+C
    except KeyboardInterrupt:
        GPIO.cleanup()
        print("Shutdown Mission.")
        #Detector.terminate()

### END OF MAIN ###
"""Helper Functions"""
def activateAlexa():
    GPIO.output(DESI.OUT_ALEXA, GPIO.LOW)
    time.sleep(2)
    GPIO.output(DESI.OUT_ALEXA, GPIO.HIGH)
#def signal_handler(signal, frame):
#    global HotwordInterrupt
#    HotwordInterrupt = True
#def interrupt_callback():
#    global HotwordInterrupt
#    return HotwordInterrupt
### MAIN CALL ###
if __name__ == "__main__":
    main()<commit_msg>Script<commit_after>#!/usr/bin/python
# @Author: Eddie Ruano
# @Date:   2017-05-01 05:14:54
# @Last Modified by:   Eddie Ruano
# @Last Modified time: 2017-06-03 22:13:44
#
"""
    MissionControl.py is a debugging tool for DESI_Sentinel
"""
### IMPORT MODULES ###
import sys
import os.path
import signal
import time
# Customs Mods #
import Adafruit_MPR121.MPR121 as MPR121
import RPi.GPIO as GPIO
# Local Modules #
### Set path ###
sys.path.append(os.path.join(os.path.dirname(__file__), '..'))
import drivers.VoyagerHCSR04 as VoyagerHCSR04
import drivers.DESIConfig as DESIConfig
### Global Variables ###
DESI = DESIConfig.DESI()
#Voyager1 = VoyagerHCSR04.Voyager("Voyager1", DESI.PROX1_TRIG, DESI.PROX1_ECHO)
#Voyager2 = VoyagerHCSR04.Voyager("Voyager2", DESI.PROX2_TRIG, DESI.PROX2_ECHO)
TouchSense = MPR121.MPR121()

def main():
    # Variables
    proxError = 0.0
    distv1 = 0.0
    distv2 = 0.0
    slack = 0.0
    contact = False
    # Initialize DESI States
    DESI.initDESI()
    # Initialize Voyager Proximity Sensors
    #DESI.initProximity(Voyager1, Voyager2)
    if not TouchSense.begin():  # Init TouchSense Capacitive Sensor Array
        print("TSense")
        sys.exit(1)
    try:
        print("Listening")
        GPIO.add_event_detect(DESI.IN_START, GPIO.FALLING, DESI.performStart, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_PAUSE, GPIO.FALLING, DESI.performPause, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED0, GPIO.FALLING, DESI.performS0, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED1, GPIO.FALLING, DESI.performS1, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED2, GPIO.FALLING, DESI.performS2, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED3, GPIO.FALLING, DESI.performS3, DESI.bounceTime)
        GPIO.add_event_detect(DESI.IN_SPEED4, GPIO.FALLING, DESI.performS4, DESI.bounceTime)
        #DESI.DESIListen()
        activeFlag = True
        while activeFlag == True:
            activeFlag = True
            command = input("Enter a command: ")
            if command == "start":
                DESI.DESISend("Start")
            elif command == "shutdown":
                DESI.DESISend("Shutdown")
            elif command == "pause":
                DESI.DESISend("Pause")
            elif command == "unpause":
                DESI.DESISend("Pause")
            elif command == "enter":
                DESI.DESISend("Enter")
            elif command == "0":
                DESI.DESISend("Send00")
            elif command == "1":
                DESI.DESISend("Send01")
            elif command == "2":
                DESI.DESISend("Send02")
            elif command == "3":
                DESI.DESISend("Send03")
            elif command == "4":
                DESI.DESISend("Send04")
            elif command == "alexa":
                DESI.DESISend("SendAlexa")
            else:
                print("Invalid Command")
            print(DESI.StateMain)
            # Query for the proximity of Megan #
            #distv1 = Voyager1.get_distance()
            #time.sleep(0.3)
            #distv2 = Voyager2.get_distance()
            #distAverage = (distv1 + distv2) / 2
            #proxError = distv1 - distv2
            #contact = checkContact()
            #state = checkState(distAverage)
            #if state == "Red":
            #    print("Red!")
            #    past_state = state
            #    DESI.send("Pause")
            #    time.sleep(5)
            #    DESI.send(past_state)
            #elif state == "Yellow":
            #    DESI.send("Down")
            #    time.sleep(0.4)
            #    DESI.send("Down")
            #    time.sleep(0.4)
            #    DESI.send("Down")
            #else:
            #    print("Green!")
            #    slack = 30 - distAverage
            #    redux = ((distAverage - 10) / 2) * 10
            #    redux = int(redux)
#
#           time.sleep(1)
    # Catch Ctrl+C
    except KeyboardInterrupt:
        GPIO.cleanup()
        print("Shutdown Mission.")
        #Detector.terminate()

### END OF MAIN ###
"""Helper Functions"""
def activateAlexa():
    GPIO.output(DESI.OUT_ALEXA, GPIO.LOW)
    time.sleep(2)
    GPIO.output(DESI.OUT_ALEXA, GPIO.HIGH)
#def signal_handler(signal, frame):
#    global HotwordInterrupt
#    HotwordInterrupt = True
#def interrupt_callback():
#    global HotwordInterrupt
#    return HotwordInterrupt
### MAIN CALL ###
if __name__ == "__main__":
    main()<|endoftext|>


<commit_before>"""MessageProperty -- a property storing ProtoRPC Message objects.

Basic usage:

Let's assume you have a protorpc.Message subclass, like this:

  from protorpc import messages

  class Note(messages.Message):
    text = messages.StringField(1, required=True)
    when = messages.IntegerField(2)

Now suppose you'd like to store Notes in the datastore.  Create a
model class to hold your notes, as follows:

  from google.appengine.ext import ndb
  from google.appengine.ext.ndb import msgprop

  class NoteStore(ndb.Model):
    note = msgprop.MessageProperty(Note)
    name = ndb.StringProperty()

(The class name, 'NoteStore', and the property name, 'note', are yours
to choose.)

To store, a Note message, create a NoteStore entity and write it:

  ns = NoteStore(note=my_note, name='foo')
  key = ns.put()

To later retrieve the Note, read the NoteStore entity back:

  ns = key.get()
  my_note = ns.note

The MessageProperty class has many of the usual Property options:
  - name: optional datastore name
  - repeated: if True, stores a list of message values
  - required: if True, the message value cannot be None
  - default: optional default message value to store
  - choices: optional list of allowed choices (must all be messages)
  - validator: optional function to validate message values
  - verbose_name: optional long name for the property

However, MessageProperty does not support the 'indexed' option.
Instead, you can specify a list of field names that will be indexed,
like this:

  class MyStore(ndb.Model):
    author = ndb.StringProperty()
    note = msgprop.MessageProperty(Note, indexed_fields=['text', 'when'])

Now you can query for field values, like this:

  stores = MyStore.query(MyStore.note.when >= 123).fetch()

Note the similarity with StructuredProperty -- in fact,
MessageProperty inherits from StructuredProperty.  The main difference
is that StructuredProperty takes an Model subclass instead of a
protorpc.messages.Message subclass; and StructuredProperty doesn't
index any fields by default.

It works for nested messages (using MessageField) as well:

  class Notes(messages.Message):
    notes = messages.MessageField(Note, 1, repeated=True)

  class MyNotesStore(ndb.Model):
    author = ndb.StringProperty()
    foo = msgprop.MessageProperty(Notes,
                                 indexed_fields=['notes.text, 'notes.when'])

And given this value for indexed_fields, in this example you can also
query for subfields:

  stores = MyNoteStore.query(MyNoteStore.foo.notes.when < 123).fetch()

A final option for MessageProperty is 'protocol'.  This lets you
specify how the message object is serialized to the datastore.  The
values are protocol names as used by protorpc.remote.Protocols class.
Supported protocol names are 'protobuf' and 'protojson'; the default
is 'protobuf'.  (In the future this will use the global protocols
registry that is being added to protorpc; then any registered protocol
name will be acceptable.)

There is also an EnumProperty, which can be used to store a
messages.Enum value without wrapping it in a Message object.  Example:

  class Color(messages.Enum):
    RED = 620
    GREEN = 495
    BLUE = 450

  class Part(ndb.Model):
    name = ndb.StringProperty()
    color = msgprop.EnumProperty(Color, required=True)

  p1 = Part(name='foo', color=Color.RED)
  key1 = p1.put()
  ...
  p2 = key1.get()
  print p2.name, p2.color  # prints "foo RED"

The EnumProperty stores the value as an integer; in fact, EnumProperty
is a subclass of IntegerProperty.  This is handy to know, since it
implies that you can rename your enum values without having to modify
already-stored entities, but you cannot renumber them.

The EnumProperty supports the following standard options:
  - name
  - indexed
  - repeated
  - required
  - default
  - choices
  - validator
  - verbose_name
"""

from protorpc import messages
from protorpc import remote

from . import model
from . import utils

__all__ = ['MessageProperty', 'EnumProperty']

# TODO: Use ProtoRPC's global Protocols instance once it is in the SDK.
_protocols_registry = remote.Protocols.new_default()
_default_protocol = 'protobuf'

class EnumProperty(model.IntegerProperty):
  """Enums are represented in the datastore as integers.

  While this is less user-friendly in the Datastore viewer, it matches
  the representation of enums in the protobuf serialization (although
  not in JSON), and it allows renaming enum values without requiring
  changes to values already stored in the Datastore.
  """

  _enum_type = None

  # Insert enum_type as an initial positional argument.
  _attributes = ['_enum_type'] + model.IntegerProperty._attributes
  _positional = 1 + model.IntegerProperty._positional

  @utils.positional(1 + _positional)
  def __init__(self, enum_type, name=None, default=None, choices=None, **kwds):
    """Constructor.

    Args:
      enum_type: A subclass of protorpc.messages.Enum.
      name: Optional datastore name (defaults to the property name).

    Additional keywords arguments specify the same options as
    supported by IntegerProperty.
    """
    self._enum_type = enum_type
    if default is not None:
      self._validate(default)
    if choices is not None:
      map(self._validate, choices)
    super(EnumProperty, self).__init__(name, default=default,
                                       choices=choices, **kwds)

  def _validate(self, value):
    """Validate an Enum value.

    Raises:
      TypeError if the value is not an instance of self._enum_type.
    """
    if not isinstance(value, self._enum_type):
      raise TypeError('Expected a %s instance, got %r instead' %
                      (self._enum_type.__name__, value))

  def _to_base_type(self, enum):
    """Convert an Enum value to a base type (integer) value."""
    return enum.number

  def _from_base_type(self, val):
    """Convert a base type (integer) value to an Enum value."""
    return self._enum_type(val)

def _analyze_indexed_fields(indexed_fields):
  """Internal helper to check a list of indexed fields.

  Args:
    indexed_fields: A list of names, possibly dotted names.

  (A dotted name is a string containing names separated by dots,
  e.g. 'foo.bar.baz'.  An undotted name is a string containing no
  dots, e.g. 'foo'.)

  Returns:
    A dict whose keys are undotted names.  For each undotted name in
    the argument, the dict contains that undotted name as a key with
    None as a value.  For each dotted name in the argument, the dict
    contains the first component as a key with a list of remainders as
    values.

  Example:
    If the argument is ['foo.bar.baz', 'bar', 'foo.bletch'], the return
    value is {'foo': ['bar.baz', 'bletch'], 'bar': None}.

  Raises:
    TypeError if an argument is not a string.
    ValueError for duplicate arguments and for conflicting arguments
      (when an undotted name also appears as the first component of
      a dotted name).
  """
  result = {}
  for field_name in indexed_fields:
    if not isinstance(field_name, basestring):
      raise TypeError('Field names must be strings; got %r' % (field_name,))
    if '.' not in field_name:
      if field_name in result:
        raise ValueError('Duplicate field name %s' % field_name)
      result[field_name] = None
    else:
      head, tail = field_name.split('.', 1)
      if head not in result:
        result[head] = [tail]
      elif result[head] is None:
        raise ValueError('Field name %s conflicts with ancestor %s' %
                         (field_name, head))
      else:
        result[head].append(tail)
  return result

def _make_model_class(message_type, indexed_fields, **props):
  """Construct a Model subclass corresponding to a Message subclass.

  Args:
    message_type: A Message subclass.
    indexed_fields: A list of dotted and undotted field names.
    **props: Additional properties with which to seed the class.

  Returns:
    A Model subclass whose properties correspond to those fields of
    message_type whose field name is listed in indexed_fields, plus
    the properties specified by the **props arguments.  For dotted
    field names, a StructuredProperty is generated using a Model
    subclass created by a recursive call.

  Raises:
    Whatever _analyze_indexed_fields() raises.
    ValueError if a field name conflicts with a name in **props.
    ValueError if a field name is not valid field of message_type.
    ValueError if an undotted field name designates a MessageField.
  """
  analyzed = _analyze_indexed_fields(indexed_fields)
  for field_name, sub_fields in analyzed.iteritems():
    if field_name in props:
      # TODO: Solve this without reserving 'blob_'.
      raise ValueError('field name %s is reserved' % field_name)
    try:
      field = message_type.field_by_name(field_name)
    except KeyError:
      raise ValueError('Message type %s has no field named %s' %
                       (message_type.__name__, field_name))
    if isinstance(field, messages.MessageField):
      if not sub_fields:
        raise ValueError(
          'MessageField %s cannot be indexed, only sub-fields' % field_name)
      sub_model_class = _make_model_class(field.type, sub_fields)
      prop = model.StructuredProperty(sub_model_class, field_name,
                                      repeated=field.repeated)
    else:
      if sub_fields is not None:
        raise ValueError(
          'Unstructured field %s cannot have indexed sub-fields' % field_name)
      if isinstance(field, messages.EnumField):
        prop = EnumProperty(field.type, field_name, repeated=field.repeated)
      elif isinstance(field, messages.BytesField):
        prop = model.BlobProperty(field_name,
                                  repeated=field.repeated, indexed=True)
      else:
        # IntegerField, FloatField, BooleanField, StringField.
        prop = model.GenericProperty(field_name, repeated=field.repeated)
    props[field_name] = prop
  return model.MetaModel('_%s__Model' % message_type.__name__,
                         (model.Model,), props)

class MessageProperty(model.StructuredProperty):
  """Messages are represented in the datastore as structured properties.

  By default, the structured property has a single subproperty
  containing the serialized message.  This property is named 'blob_'
  in Python but __<protocol>__ in the Datastore, where <protocol> is
  the value of the protocol argument (default 'protobuf').
  """

  _message_type = None
  _indexed_fields = ()
  _protocol = _default_protocol
  _protocol_impl = None

  # *Replace* first positional argument with _message_type, since the
  # _modelclass attribute is synthetic.
  _attributes = (['_message_type'] + model.StructuredProperty._attributes[1:] +
                 ['_indexed_fields', '_protocol'])

  @utils.positional(1 + model.StructuredProperty._positional)
  def __init__(self, message_type, name=None,
               indexed_fields=None, protocol=None, **kwds):
    """Constructor.

    Args:
      message_tyoe: A subclass of protorpc.messages.Message.
      name: Optional datastore name (defaults to the property name).
      indexed_fields: Optional list of dotted and undotted field names.
      protocol: Optional protocol name default 'protobuf'.

    Additional keywords arguments specify the same options as
    supported by StructuredProperty, except 'indexed'.
    """
    if not (isinstance(message_type, type) and
            issubclass(message_type, messages.Message)):
      raise TypeError('MessageProperty argument must be a Message subclass')
    self._message_type = message_type
    if indexed_fields is not None:
      # TODO: Check they are all strings naming fields.
      self._indexed_fields = tuple(indexed_fields)
    # NOTE: Otherwise the class default i.e. (), prevails.
    if protocol is None:
      protocol = _default_protocol
    self._protocol = protocol
    self._protocol_impl = _protocols_registry.lookup_by_name(protocol)
    blob_prop = model.BlobProperty('__%s__' % self._protocol)
    message_class = _make_model_class(message_type, self._indexed_fields,
                                      blob_=blob_prop)
    super(MessageProperty, self).__init__(message_class, name, **kwds)

  def _validate(self, msg):
    """Validate an Enum value.

    Raises:
      TypeError if the value is not an instance of self._message_type.
    """
    if not isinstance(msg, self._message_type):
      raise TypeError('Expected a %s instance for %s property',
                      self._message_type.__name__,
                      self._code_name or self._name)

  def _to_base_type(self, msg):
    """Convert a Message value to a Model instance (entity)."""
    ent = _message_to_entity(msg, self._modelclass)
    ent.blob_ = self._protocol_impl.encode_message(msg)
    return ent

  def _from_base_type(self, ent):
    """Convert a Model instance (entity) to a Message value."""
    if ent._projection:
      # Projection query result.  Reconstitute the message from the fields.
      return _projected_entity_to_message(ent, self._message_type)

    blob = ent.blob_
    if blob is not None:
      protocol = self._protocol_impl
    else:
      # Perhaps it was written using a different protocol.
      protocol = None
      for name in _protocols_registry.names:
        key = '__%s__' % name
        if key in ent._values:
          blob = ent._values[key]
          if isinstance(blob, model._BaseValue):
            blob = blob.b_val
          protocol = _protocols_registry.lookup_by_name(name)
          break
    if blob is None or protocol is None:
      return None  # This will reveal the underlying dummy model.
    msg = protocol.decode_message(self._message_type, blob)
    return msg

def _message_to_entity(msg, modelclass):
  """Recursive helper for _to_base_type() to convert a message to an entity.

  Args:
    msg: A Message instance.
    modelclass: A Model subclass.

  Returns:
    An instance of modelclass.
  """
  ent = modelclass()
  for prop_name, prop in modelclass._properties.iteritems():
    if prop._code_name == 'blob_':  # TODO: Devise a cleaner test.
      continue  # That's taken care of later.
    value = getattr(msg, prop_name)
    if value is not None and isinstance(prop, model.StructuredProperty):
      if prop._repeated:
        value = [_message_to_entity(v, prop._modelclass) for v in value]
      else:
        value = _message_to_entity(value, prop._modelclass)
    setattr(ent, prop_name, value)
  return ent

def _projected_entity_to_message(ent, message_type):
  """Recursive helper for _from_base_type() to convert an entity to a message.

  Args:
    ent: A Model instance.
    message_type: A Message subclass.

  Returns:
    An instance of message_type.
  """
  msg = message_type()
  analyzed = _analyze_indexed_fields(ent._projection)
  for name, sublist in analyzed.iteritems():
    prop = ent._properties[name]
    val = prop._get_value(ent)
    assert isinstance(prop, model.StructuredProperty) == bool(sublist)
    if sublist:
      field = message_type.field_by_name(name)
      assert isinstance(field, messages.MessageField)
      assert prop._repeated == field.repeated
      if prop._repeated:
        assert isinstance(val, list)
        val = [_projected_entity_to_message(v, field.type) for v in val]
      else:
        assert isinstance(val, prop._modelclass)
        val = _projected_entity_to_message(val, field.type)
    setattr(msg, name, val)
  return msg
<commit_msg>Reviewed: MessageProperty as it will appear in the next SDK.<commit_after>"""MessageProperty -- a property storing ProtoRPC Message objects.

Basic usage:

Let's assume you have a protorpc.Message subclass, like this:

  from protorpc import messages

  class Note(messages.Message):
    text = messages.StringField(1, required=True)
    when = messages.IntegerField(2)

Now suppose you'd like to store Notes in the datastore.  Create a
model class to hold your notes, as follows:

  from google.appengine.ext import ndb
  from google.appengine.ext.ndb import msgprop

  class NoteStore(ndb.Model):
    note = msgprop.MessageProperty(Note)
    name = ndb.StringProperty()

(The class name, 'NoteStore', and the property name, 'note', are yours
to choose.)

To store, a Note message, create a NoteStore entity and write it:

  ns = NoteStore(note=my_note, name='foo')
  key = ns.put()

To later retrieve the Note, read the NoteStore entity back:

  ns = key.get()
  my_note = ns.note

The MessageProperty class has many of the usual Property options:
  - name: optional datastore name
  - repeated: if True, stores a list of message values
  - required: if True, the message value cannot be None
  - default: optional default message value to store
  - choices: optional list of allowed choices (must all be messages)
  - validator: optional function to validate message values
  - verbose_name: optional long name for the property

However, MessageProperty does not support the 'indexed' option.
Instead, you can specify a list of field names that will be indexed,
like this:

  class MyStore(ndb.Model):
    author = ndb.StringProperty()
    note = msgprop.MessageProperty(Note, indexed_fields=['text', 'when'])

Now you can query for field values, like this:

  stores = MyStore.query(MyStore.note.when >= 123).fetch()

Note the similarity with StructuredProperty -- in fact,
MessageProperty inherits from StructuredProperty.  The main difference
is that StructuredProperty takes an Model subclass instead of a
protorpc.messages.Message subclass; and StructuredProperty doesn't
index any fields by default.

It works for nested messages (using MessageField) as well:

  class Notes(messages.Message):
    notes = messages.MessageField(Note, 1, repeated=True)

  class MyNotesStore(ndb.Model):
    author = ndb.StringProperty()
    foo = msgprop.MessageProperty(Notes,
                                  indexed_fields=['notes.text, 'notes.when'])

And given this value for indexed_fields, in this example you can also
query for subfields:

  stores = MyNoteStore.query(MyNoteStore.foo.notes.when < 123).fetch()

A final option for MessageProperty is 'protocol'.  This lets you
specify how the message object is serialized to the datastore.  The
values are protocol names as used by protorpc.remote.Protocols class.
Supported protocol names are 'protobuf' and 'protojson'; the default
is 'protobuf'.  (In the future this will use the global protocols
registry that is being added to protorpc; then any registered protocol
name will be acceptable.)

There is also an EnumProperty, which can be used to store a
messages.Enum value without wrapping it in a Message object.  Example:

  class Color(messages.Enum):
    RED = 620
    GREEN = 495
    BLUE = 450

  class Part(ndb.Model):
    name = ndb.StringProperty()
    color = msgprop.EnumProperty(Color, required=True)

  p1 = Part(name='foo', color=Color.RED)
  key1 = p1.put()
  ...
  p2 = key1.get()
  print p2.name, p2.color  # prints "foo RED"

The EnumProperty stores the value as an integer; in fact, EnumProperty
is a subclass of IntegerProperty.  This is handy to know, since it
implies that you can rename your enum values without having to modify
already-stored entities, but you cannot renumber them.

The EnumProperty supports the following standard options:
  - name
  - indexed
  - repeated
  - required
  - default
  - choices
  - validator
  - verbose_name
"""

from protorpc import messages
from protorpc import remote

from . import model
from . import utils

__all__ = ['MessageProperty', 'EnumProperty']

# TODO: Use ProtoRPC's global Protocols instance once it is in the SDK.
_protocols_registry = remote.Protocols.new_default()
_default_protocol = 'protobuf'

class EnumProperty(model.IntegerProperty):
  """Enums are represented in the datastore as integers.

  While this is less user-friendly in the Datastore viewer, it matches
  the representation of enums in the protobuf serialization (although
  not in JSON), and it allows renaming enum values without requiring
  changes to values already stored in the Datastore.
  """

  _enum_type = None

  # Insert enum_type as an initial positional argument.
  _attributes = ['_enum_type'] + model.IntegerProperty._attributes
  _positional = 1 + model.IntegerProperty._positional

  @utils.positional(1 + _positional)
  def __init__(self, enum_type, name=None, default=None, choices=None, **kwds):
    """Constructor.

    Args:
      enum_type: A subclass of protorpc.messages.Enum.
      name: Optional datastore name (defaults to the property name).

    Additional keywords arguments specify the same options as
    supported by IntegerProperty.
    """
    self._enum_type = enum_type
    if default is not None:
      self._validate(default)
    if choices is not None:
      map(self._validate, choices)
    super(EnumProperty, self).__init__(name, default=default,
                                       choices=choices, **kwds)

  def _validate(self, value):
    """Validate an Enum value.

    Raises:
      TypeError if the value is not an instance of self._enum_type.
    """
    if not isinstance(value, self._enum_type):
      raise TypeError('Expected a %s instance, got %r instead' %
                      (self._enum_type.__name__, value))

  def _to_base_type(self, enum):
    """Convert an Enum value to a base type (integer) value."""
    return enum.number

  def _from_base_type(self, val):
    """Convert a base type (integer) value to an Enum value."""
    return self._enum_type(val)

def _analyze_indexed_fields(indexed_fields):
  """Internal helper to check a list of indexed fields.

  Args:
    indexed_fields: A list of names, possibly dotted names.

  (A dotted name is a string containing names separated by dots,
  e.g. 'foo.bar.baz'.  An undotted name is a string containing no
  dots, e.g. 'foo'.)

  Returns:
    A dict whose keys are undotted names.  For each undotted name in
    the argument, the dict contains that undotted name as a key with
    None as a value.  For each dotted name in the argument, the dict
    contains the first component as a key with a list of remainders as
    values.

  Example:
    If the argument is ['foo.bar.baz', 'bar', 'foo.bletch'], the return
    value is {'foo': ['bar.baz', 'bletch'], 'bar': None}.

  Raises:
    TypeError if an argument is not a string.
    ValueError for duplicate arguments and for conflicting arguments
      (when an undotted name also appears as the first component of
      a dotted name).
  """
  result = {}
  for field_name in indexed_fields:
    if not isinstance(field_name, basestring):
      raise TypeError('Field names must be strings; got %r' % (field_name,))
    if '.' not in field_name:
      if field_name in result:
        raise ValueError('Duplicate field name %s' % field_name)
      result[field_name] = None
    else:
      head, tail = field_name.split('.', 1)
      if head not in result:
        result[head] = [tail]
      elif result[head] is None:
        raise ValueError('Field name %s conflicts with ancestor %s' %
                         (field_name, head))
      else:
        result[head].append(tail)
  return result

def _make_model_class(message_type, indexed_fields, **props):
  """Construct a Model subclass corresponding to a Message subclass.

  Args:
    message_type: A Message subclass.
    indexed_fields: A list of dotted and undotted field names.
    **props: Additional properties with which to seed the class.

  Returns:
    A Model subclass whose properties correspond to those fields of
    message_type whose field name is listed in indexed_fields, plus
    the properties specified by the **props arguments.  For dotted
    field names, a StructuredProperty is generated using a Model
    subclass created by a recursive call.

  Raises:
    Whatever _analyze_indexed_fields() raises.
    ValueError if a field name conflicts with a name in **props.
    ValueError if a field name is not valid field of message_type.
    ValueError if an undotted field name designates a MessageField.
  """
  analyzed = _analyze_indexed_fields(indexed_fields)
  for field_name, sub_fields in analyzed.iteritems():
    if field_name in props:
      raise ValueError('field name %s is reserved' % field_name)
    try:
      field = message_type.field_by_name(field_name)
    except KeyError:
      raise ValueError('Message type %s has no field named %s' %
                       (message_type.__name__, field_name))
    if isinstance(field, messages.MessageField):
      if not sub_fields:
        raise ValueError(
          'MessageField %s cannot be indexed, only sub-fields' % field_name)
      sub_model_class = _make_model_class(field.type, sub_fields)
      prop = model.StructuredProperty(sub_model_class, field_name,
                                      repeated=field.repeated)
    else:
      if sub_fields is not None:
        raise ValueError(
          'Unstructured field %s cannot have indexed sub-fields' % field_name)
      if isinstance(field, messages.EnumField):
        prop = EnumProperty(field.type, field_name, repeated=field.repeated)
      elif isinstance(field, messages.BytesField):
        prop = model.BlobProperty(field_name,
                                  repeated=field.repeated, indexed=True)
      else:
        # IntegerField, FloatField, BooleanField, StringField.
        prop = model.GenericProperty(field_name, repeated=field.repeated)
    props[field_name] = prop
  return model.MetaModel('_%s__Model' % message_type.__name__,
                         (model.Model,), props)

class MessageProperty(model.StructuredProperty):
  """Messages are represented in the datastore as structured properties.

  By default, the structured property has a single subproperty
  containing the serialized message.  This property is named 'blob_'
  in Python but __<protocol>__ in the Datastore, where <protocol> is
  the value of the protocol argument (default 'protobuf').
  """

  _message_type = None
  _indexed_fields = ()
  _protocol = _default_protocol
  _protocol_impl = None

  # *Replace* first positional argument with _message_type, since the
  # _modelclass attribute is synthetic.
  _attributes = (['_message_type'] + model.StructuredProperty._attributes[1:] +
                 ['_indexed_fields', '_protocol'])

  @utils.positional(1 + model.StructuredProperty._positional)
  def __init__(self, message_type, name=None,
               indexed_fields=None, protocol=None, **kwds):
    """Constructor.

    Args:
      message_tyoe: A subclass of protorpc.messages.Message.
      name: Optional datastore name (defaults to the property name).
      indexed_fields: Optional list of dotted and undotted field names.
      protocol: Optional protocol name default 'protobuf'.

    Additional keywords arguments specify the same options as
    supported by StructuredProperty, except 'indexed'.
    """
    if not (isinstance(message_type, type) and
            issubclass(message_type, messages.Message)):
      raise TypeError('MessageProperty argument must be a Message subclass')
    self._message_type = message_type
    if indexed_fields is not None:
      # TODO: Check they are all strings naming fields.
      self._indexed_fields = tuple(indexed_fields)
    # NOTE: Otherwise the class default i.e. (), prevails.
    if protocol is None:
      protocol = _default_protocol
    self._protocol = protocol
    self._protocol_impl = _protocols_registry.lookup_by_name(protocol)
    blob_prop = model.BlobProperty('__%s__' % self._protocol)
    # TODO: Solve this without reserving 'blob_'.
    message_class = _make_model_class(message_type, self._indexed_fields,
                                      blob_=blob_prop)
    super(MessageProperty, self).__init__(message_class, name, **kwds)

  def _validate(self, msg):
    """Validate an Enum value.

    Raises:
      TypeError if the value is not an instance of self._message_type.
    """
    if not isinstance(msg, self._message_type):
      raise TypeError('Expected a %s instance for %s property',
                      self._message_type.__name__,
                      self._code_name or self._name)

  def _to_base_type(self, msg):
    """Convert a Message value to a Model instance (entity)."""
    ent = _message_to_entity(msg, self._modelclass)
    ent.blob_ = self._protocol_impl.encode_message(msg)
    return ent

  def _from_base_type(self, ent):
    """Convert a Model instance (entity) to a Message value."""
    if ent._projection:
      # Projection query result.  Reconstitute the message from the fields.
      return _projected_entity_to_message(ent, self._message_type)

    blob = ent.blob_
    if blob is not None:
      protocol = self._protocol_impl
    else:
      # Perhaps it was written using a different protocol.
      protocol = None
      for name in _protocols_registry.names:
        key = '__%s__' % name
        if key in ent._values:
          blob = ent._values[key]
          if isinstance(blob, model._BaseValue):
            blob = blob.b_val
          protocol = _protocols_registry.lookup_by_name(name)
          break
    if blob is None or protocol is None:
      return None  # This will reveal the underlying dummy model.
    msg = protocol.decode_message(self._message_type, blob)
    return msg

def _message_to_entity(msg, modelclass):
  """Recursive helper for _to_base_type() to convert a message to an entity.

  Args:
    msg: A Message instance.
    modelclass: A Model subclass.

  Returns:
    An instance of modelclass.
  """
  ent = modelclass()
  for prop_name, prop in modelclass._properties.iteritems():
    if prop._code_name == 'blob_':  # TODO: Devise a cleaner test.
      continue  # That's taken care of later.
    value = getattr(msg, prop_name)
    if value is not None and isinstance(prop, model.StructuredProperty):
      if prop._repeated:
        value = [_message_to_entity(v, prop._modelclass) for v in value]
      else:
        value = _message_to_entity(value, prop._modelclass)
    setattr(ent, prop_name, value)
  return ent

def _projected_entity_to_message(ent, message_type):
  """Recursive helper for _from_base_type() to convert an entity to a message.

  Args:
    ent: A Model instance.
    message_type: A Message subclass.

  Returns:
    An instance of message_type.
  """
  msg = message_type()
  analyzed = _analyze_indexed_fields(ent._projection)
  for name, sublist in analyzed.iteritems():
    prop = ent._properties[name]
    val = prop._get_value(ent)
    assert isinstance(prop, model.StructuredProperty) == bool(sublist)
    if sublist:
      field = message_type.field_by_name(name)
      assert isinstance(field, messages.MessageField)
      assert prop._repeated == field.repeated
      if prop._repeated:
        assert isinstance(val, list)
        val = [_projected_entity_to_message(v, field.type) for v in val]
      else:
        assert isinstance(val, prop._modelclass)
        val = _projected_entity_to_message(val, field.type)
    setattr(msg, name, val)
  return msg
<|endoftext|>


<commit_before>version = '0.12.0.dev0'
<commit_msg>update version number<commit_after>version = '0.11.1'
<|endoftext|>


<commit_before>from neo4j.v1 import GraphDatabase, basic_auth
import datetime
import time

# Drop all data
def drop(session):
    session.run("MATCH (n) DETACH DELETE n")

# Print all data
def print_all(session):
    print('The program have inserted the following nodes:')
    for item in session.run('MATCH (n) RETURN n'):
        print(item)

# Create a part node with parameters specified
def create_part(session, identifier, partkey, mfgr, type, size):
    session.run("CREATE (" + identifier + ":Part {partkey:'" + partkey +
                "', mfgr:'" + mfgr + "', type: '" + type + "', size: " + size + "})")

# Create a supplier node with parameters specified
def create_supplier(session, identifier, suppkey, name, accbal, adress, phone, comment, n_name, r_name):
    session.run("CREATE (" + identifier + ":Supplier {suppkey: '" + suppkey +
                "', name: '" + name + "', accbal: " + accbal + ", adress: '" + adress +
                "', phone: '" + phone + "', comment: '" + comment +
                "', n_name: '" + n_name + "', r_name: '" + r_name + "'})")

# Create an order node with parameters specified
def create_order(session, identifier, orderkey, orderdate, shippriority, c_marketsegment, n_name):
    session.run("CREATE (" + identifier + ":Order {orderkey: '" + orderkey + "', orderdate: {date}, shippriority:'" +
                shippriority + "', c_marketsegment: '" + c_marketsegment + "', n_name: '" + n_name + "'})",
                {"date": orderdate})

# Create a line item node with parameters specified
def create_lineitem(session, identifier, orderkey, suppkey, returnflag, quantity,
                    extendedPrice, discount, tax, shipdate, linestatus):
    session.run("CREATE (" + identifier + ":LineItem {orderkey: '" + orderkey +
                "', suppkey: '" + suppkey + "', returnflag: '" + returnflag + "', quantity: " + quantity +
                ", extendedPrice: " + extendedPrice + ", discount: " + discount + ", tax: " + tax +
                ", shipdate: {date2}, linestatus: '" + linestatus + "'})", {"date2": shipdate})

# Create a edge between supplier and part nodes specified in parameters
def create_edge_supplier_part(session, supplier, suppkey, part, partkey, supplycost):
    session.run(
        "MATCH (" + supplier + ":Supplier {suppkey: '" + suppkey + "'}), (" + part + ":Part {partkey: '" + partkey +
        "'}) CREATE (" + supplier + ")-[:ps {supplycost: {suppcost} }]->(" + part + ")",
        {"suppcost": supplycost})

# Create a edge between order and line item nodes specified in parameters
def create_edge_order_lineitem(session, order, orderkey, lineitem):
    session.run("MATCH (" + order + ":Order {orderkey: '" + orderkey + "'}), (" + lineitem +
                ":LineItem {orderkey: '" + orderkey + "'}) CREATE (" + order + ")-[:has]->(" + lineitem + ")")

# Create a edge between line item and supplier nodes specified in parameters
def create_edge_lineitem_supplier(session, lineitem, supplier, suppkey):
    session.run("MATCH (" + lineitem + ":LineItem {suppkey: '" + suppkey + "'}), (" + supplier +
                ":Supplier {suppkey: '" + suppkey + "'}) CREATE (" + lineitem + ")-[:isFrom]->(" + supplier + ")")

# Insert some data in database
def inserts(db):
    print('Starting inserts...')
    session = db.session()

    date = datetime.datetime(2016, 11, 24)
    date2 = datetime.datetime(2016, 11, 25)
    timestamp = time.mktime(date.timetuple())
    timestamp2 = time.mktime(date2.timetuple())

    drop(session)
    create_part(session, 'p1', '1', 'aaaa', 'A', '10')
    create_part(session, 'p2', '2', 'bbbb', 'B', '15')
    create_part(session, 'p3', '3', 'cccc', 'C', '5')
    create_part(session, 'p4', '4', 'dddd', 'D', '2')
    create_supplier(session, 's1', 's1', 'supp1', '1.00', 'Main Street', '111111', 'nothing', 'Spain', 'Barcelona')
    create_supplier(session, 's2', 's2', 'supp2', '2.00', 'Main Street 2', '2222222 ', 'nothing 2', 'Spain',
                    'Barcelona')
    create_order(session, 'o1', 'o1', timestamp, '1', 'MKT1', 'Spain')
    create_order(session, 'o2', 'o2', timestamp, '2', 'MKT1', 'Spain')
    create_lineitem(session, 'l1', 'o1', 's1', 'a', '10', '10.0', '0.1', '2.0', timestamp2, 'a')
    create_lineitem(session, 'l2', 'o1', 's1', 'a', '5', '18.0', '0.5', '3.0', timestamp2, 'a')
    create_lineitem(session, 'l3', 'o1', 's1', 'a', '5', '5.0', '0.05', '1.0', timestamp2, 'a')
    create_lineitem(session, 'l4', 'o2', 's2', 'b', '10', '20.0', '0.3', '3.0', timestamp2, 'b')
    create_lineitem(session, 'l5', 'o2', 's2', 'b', '20', '40.0', '0.5', '1.0', timestamp2, 'b')
    create_lineitem(session, 'l6', 'o2', 's2', 'b', '5', '10.0', '0.2', '2.0', timestamp2, 'b')

    create_edge_supplier_part(session, 's1', 's1', 'p1', '1', 10)
    create_edge_supplier_part(session, 's1', 's1', 'p2', '2', 20)
    create_edge_supplier_part(session, 's1', 's1', 'p3', '3', 30)
    create_edge_supplier_part(session, 's1', 's1', 'p4', '4', 40)
    create_edge_supplier_part(session, 's2', 's2', 'p1', '1', 5)
    create_edge_supplier_part(session, 's2', 's2', 'p2', '2', 10)
    create_edge_supplier_part(session, 's2', 's2', 'p3', '3', 15)
    create_edge_supplier_part(session, 's2', 's2', 'p4', '4', 20)
    create_edge_order_lineitem(session, 'o1', 'o1', 'l1')
    create_edge_order_lineitem(session, 'o2', 'o2', 'l4')
    create_edge_lineitem_supplier(session, 'l1', 's1', 's1')
    create_edge_lineitem_supplier(session, 'l2', 's2', 's2')

    print_all(session)
    print('Finish inserts!\n')

    session.close()
    return db

# Create the neo4j database
def create():
    print('Create and connect with Database')

    db = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "neo4j"))
    return inserts(db)

# Query 1 code
def query1(db, date):
    print('Query 1 starting...')
    result = \
        db.session().run(" MATCH " +
                         "      ( li:LineItem ) " +
                         " WHERE " +
                         "      li.shipdate <= {date} " +
                         " WITH " +
                         "      li.returnflag                                    AS l_returnflag, " +
                         "      li.linestatus                                    AS l_linestatus, " +
                         "      SUM(li.quantity)                                 AS sum_qty, " +
                         "      SUM(li.extendedPrice)                            AS sum_base_price, " +
                         "      SUM(li.extendedPrice*(1-li.discount))            AS sum_disc_price, " +
                         "      SUM(li.extendedPrice*(1-li.discount)*(1+li.tax)) AS sum_charge, " +
                         "      AVG(li.quantity)                                 AS avg_qty, " +
                         "      AVG(li.extendedPrice)                            AS avg_price, " +
                         "      AVG(li.discount)                                 AS avg_disc, " +
                         "      COUNT(*)                                         AS count_order " +
                         " RETURN " +
                         "      l_returnflag, " +
                         "      l_linestatus, " +
                         "      sum_qty, " +
                         "      sum_base_price, " +
                         "      sum_disc_price, " +
                         "      sum_charge, " +
                         "      avg_qty, " +
                         "      avg_price, " +
                         "      avg_disc, " +
                         "      count_order " +
                         " ORDER BY " +
                         "      l_returnflag       ASC, " +
                         "      l_linestatus       ASC ",
                         {"date": time.mktime(date.timetuple())})

    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for first query")
    print()

# Query 2 code
def query2(db, region, type, size):
    print('Query 2 starting...')
    subquery_result = \
        db.session().run(" MATCH " +
                         "    (su: Supplier)-[res:ps]->() " +
                         " WHERE " +
                         "    su.r_name = {region} " +
                         " RETURN " +
                         "    MIN(res.supplycost) ",
                         {"region": region})

    global min_cost
    for item in subquery_result:
        min_cost = item['MIN(res.supplycost)']

    result = \
        db.session().run(" MATCH " +
                         "     (su: Supplier)-[res:ps]->(p1: Part) " +
                         " WHERE " +
                         "     p1.size = {size}                 AND " +
                         "     p1.type = {type}                 AND " +
                         "     res.supplycost = {suppcost} " +
                         " RETURN " +
                         "     su.accbal   AS s_accbal, " +
                         "     su.name     AS s_name, " +
                         "     su.n_name   AS n_name, " +
                         "     p1.partkey  AS p_partkey, " +
                         "     p1.mfgr     AS p_mfgr, " +
                         "     su.adress   AS s_adress, " +
                         "     su.phone    AS s_phone, " +
                         "     su.comment  AS s_comment " +
                         " ORDER BY " +
                         "     su.accbal   DESC, " +
                         "     su.n_name   ASC, " +
                         "     p1.partkey  ASC ",
                         {"size": size,
                          "type": type,
                          "suppcost": min_cost})
    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for second query")

    print()

# Query 3 code
def query3(db, date1, date2, segment):
    print('Query 3 starting...')
    result = \
        db.session().run(" MATCH " +
                         "     (o1:Order)-[:has]->(l1:LineItem) " +
                         " WHERE " +
                         "     l1.shipdate > {date2}            AND " +
                         "     o1.orderdate < {date1}           AND " +
                         "     o1.c_marketsegment = {segment}   AND " +
                         "     o1.orderkey = l1.orderkey "
                         " WITH " +
                         "      l1.orderkey                                   AS l_orderkey, " +
                         "      o1.orderdate                                  AS o_orderdate, " +
                         "      o1.shippriority                               As o_shippriority, " +
                         "      SUM(l1.extendedPrice*(1-l1.discount))         AS revenue " +
                         " RETURN " +
                         "      l_orderkey, " +
                         "      o_orderdate, " +
                         "      o_shippriority, " +
                         "      revenue " +
                         " ORDER BY " +
                         "      revenue        DESC, " +
                         "      o_orderdate    ASC ",
                         {"date1": time.mktime(date1.timetuple()),
                          "date2": time.mktime(date2.timetuple()),
                          "segment": segment})

    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for third query")
    print()

# Query 4 code
def query4(db, region, date):
    print('Query 4 starting...')

    result = \
        db.session().run(" MATCH " +
                         "      (o:Order)-[:has]->(li:LineItem)-[:isFrom]->(s:Supplier)" +
                         " WHERE " +
                         "      s.r_name = {region}             AND " +
                         "      s.n_name = o.n_name             AND " +
                         "      o.orderdate >= {date}           AND " +
                         "      o.orderdate < {date_year} "
                         " RETURN " +
                         "      o.n_name                                    AS n_name, " +
                         "      SUM(li.extendedPrice*(1-li.discount))       AS revenue " +
                         " ORDER BY " +
                         "      revenue     DESC ",
                         {"date": time.mktime(date.timetuple()),
                          "date_year": time.mktime(date.replace(year=date.year + 1).timetuple()),
                          "region": region})
    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for fourth query")

    print()

# Main function
def run():
    print('Neo4J Laboratory\n')
    db = create()
    query1(db, date=datetime.datetime(2016, 11, 28))
    query2(db, region='Barcelona', type='A', size=10)
    query3(db, date1=datetime.datetime(2016, 11, 28), date2=datetime.datetime(2016, 11, 20), segment='MKT1')
    query4(db, region="Barcelona", date=datetime.datetime(2016, 11, 20))
    print('THE END')

if __name__ == '__main__':
    run()<commit_msg>indexes created and finalize practice<commit_after>from neo4j.v1 import GraphDatabase, basic_auth
import datetime
import time

# Drop all data
def drop(session):
    session.run("MATCH (n) DETACH DELETE n")

# Print all data
def print_all(session):
    print('The program have inserted the following nodes:')
    for item in session.run('MATCH (n) RETURN n'):
        print(item)

# Create a part node with parameters specified
def create_part(session, identifier, partkey, mfgr, type, size):
    session.run("CREATE (" + identifier + ":Part {partkey:'" + partkey +
                "', mfgr:'" + mfgr + "', type: '" + type + "', size: " + size + "})")

# Create a supplier node with parameters specified
def create_supplier(session, identifier, suppkey, name, accbal, adress, phone, comment, n_name, r_name):
    session.run("CREATE (" + identifier + ":Supplier {suppkey: '" + suppkey +
                "', name: '" + name + "', accbal: " + accbal + ", adress: '" + adress +
                "', phone: '" + phone + "', comment: '" + comment +
                "', n_name: '" + n_name + "', r_name: '" + r_name + "'})")

# Create an order node with parameters specified
def create_order(session, identifier, orderkey, orderdate, shippriority, c_marketsegment, n_name):
    session.run("CREATE (" + identifier + ":Order {orderkey: '" + orderkey + "', orderdate: {date}, shippriority:'" +
                shippriority + "', c_marketsegment: '" + c_marketsegment + "', n_name: '" + n_name + "'})",
                {"date": orderdate})

# Create a line item node with parameters specified
def create_lineitem(session, identifier, orderkey, suppkey, returnflag, quantity,
                    extendedPrice, discount, tax, shipdate, linestatus):
    session.run("CREATE (" + identifier + ":LineItem {orderkey: '" + orderkey +
                "', suppkey: '" + suppkey + "', returnflag: '" + returnflag + "', quantity: " + quantity +
                ", extendedPrice: " + extendedPrice + ", discount: " + discount + ", tax: " + tax +
                ", shipdate: {date2}, linestatus: '" + linestatus + "'})", {"date2": shipdate})

# Create a edge between supplier and part nodes specified in parameters
def create_edge_supplier_part(session, supplier, suppkey, part, partkey, supplycost):
    session.run(
        "MATCH (" + supplier + ":Supplier {suppkey: '" + suppkey + "'}), (" + part + ":Part {partkey: '" + partkey +
        "'}) CREATE (" + supplier + ")-[:ps {supplycost: {suppcost} }]->(" + part + ")",
        {"suppcost": supplycost})

# Create a edge between order and line item nodes specified in parameters
def create_edge_order_lineitem(session, order, orderkey, lineitem):
    session.run("MATCH (" + order + ":Order {orderkey: '" + orderkey + "'}), (" + lineitem +
                ":LineItem {orderkey: '" + orderkey + "'}) CREATE (" + order + ")-[:has]->(" + lineitem + ")")

# Create a edge between line item and supplier nodes specified in parameters
def create_edge_lineitem_supplier(session, lineitem, supplier, suppkey):
    session.run("MATCH (" + lineitem + ":LineItem {suppkey: '" + suppkey + "'}), (" + supplier +
                ":Supplier {suppkey: '" + suppkey + "'}) CREATE (" + lineitem + ")-[:isFrom]->(" + supplier + ")")

# Insert some data in database
def inserts(db):
    print('Starting inserts...')
    session = db.session()

    date = datetime.datetime(2016, 11, 24)
    date2 = datetime.datetime(2016, 11, 25)
    timestamp = time.mktime(date.timetuple())
    timestamp2 = time.mktime(date2.timetuple())

    drop(session)
    create_part(session, 'p1', '1', 'aaaa', 'A', '10')
    create_part(session, 'p2', '2', 'bbbb', 'B', '15')
    create_part(session, 'p3', '3', 'cccc', 'C', '5')
    create_part(session, 'p4', '4', 'dddd', 'D', '2')
    create_supplier(session, 's1', 's1', 'supp1', '1.00', 'Main Street', '111111', 'nothing', 'Spain', 'Barcelona')
    create_supplier(session, 's2', 's2', 'supp2', '2.00', 'Main Street 2', '2222222 ', 'nothing 2', 'Spain',
                    'Barcelona')
    create_order(session, 'o1', 'o1', timestamp, '1', 'MKT1', 'Spain')
    create_order(session, 'o2', 'o2', timestamp, '2', 'MKT1', 'Spain')
    create_lineitem(session, 'l1', 'o1', 's1', 'a', '10', '10.0', '0.1', '2.0', timestamp2, 'a')
    create_lineitem(session, 'l2', 'o1', 's1', 'a', '5', '18.0', '0.5', '3.0', timestamp2, 'a')
    create_lineitem(session, 'l3', 'o1', 's1', 'a', '5', '5.0', '0.05', '1.0', timestamp2, 'a')
    create_lineitem(session, 'l4', 'o2', 's2', 'b', '10', '20.0', '0.3', '3.0', timestamp2, 'b')
    create_lineitem(session, 'l5', 'o2', 's2', 'b', '20', '40.0', '0.5', '1.0', timestamp2, 'b')
    create_lineitem(session, 'l6', 'o2', 's2', 'b', '5', '10.0', '0.2', '2.0', timestamp2, 'b')

    create_edge_supplier_part(session, 's1', 's1', 'p1', '1', 10)
    create_edge_supplier_part(session, 's1', 's1', 'p2', '2', 20)
    create_edge_supplier_part(session, 's1', 's1', 'p3', '3', 30)
    create_edge_supplier_part(session, 's1', 's1', 'p4', '4', 40)
    create_edge_supplier_part(session, 's2', 's2', 'p1', '1', 5)
    create_edge_supplier_part(session, 's2', 's2', 'p2', '2', 10)
    create_edge_supplier_part(session, 's2', 's2', 'p3', '3', 15)
    create_edge_supplier_part(session, 's2', 's2', 'p4', '4', 20)
    create_edge_order_lineitem(session, 'o1', 'o1', 'l1')
    create_edge_order_lineitem(session, 'o2', 'o2', 'l4')
    create_edge_lineitem_supplier(session, 'l1', 's1', 's1')
    create_edge_lineitem_supplier(session, 'l2', 's2', 's2')

    print_all(session)
    print('Finish inserts!\n')

    session.close()
    return db

# Create the neo4j database
def create():
    print('Create and connect with Database')

    db = GraphDatabase.driver("bolt://localhost", auth=basic_auth("neo4j", "neo4j"))
    return inserts(db)

# Create indexes
def indexes(db):
    print('Creating indexes...')
    session = db.session()

    session.run("CREATE INDEX ON :LineItem(shipdate)")
    session.run("CREATE INDEX ON :Order(orderdate)")

    print('Indexes created!')
    session.close()

    print()

# Query 1 code
def query1(db, date):
    print('Query 1 starting...')
    result = \
        db.session().run(" MATCH " +
                         "      ( li:LineItem ) " +
                         " WHERE " +
                         "      li.shipdate <= {date} " +
                         " WITH " +
                         "      li.returnflag                                    AS l_returnflag, " +
                         "      li.linestatus                                    AS l_linestatus, " +
                         "      SUM(li.quantity)                                 AS sum_qty, " +
                         "      SUM(li.extendedPrice)                            AS sum_base_price, " +
                         "      SUM(li.extendedPrice*(1-li.discount))            AS sum_disc_price, " +
                         "      SUM(li.extendedPrice*(1-li.discount)*(1+li.tax)) AS sum_charge, " +
                         "      AVG(li.quantity)                                 AS avg_qty, " +
                         "      AVG(li.extendedPrice)                            AS avg_price, " +
                         "      AVG(li.discount)                                 AS avg_disc, " +
                         "      COUNT(*)                                         AS count_order " +
                         " RETURN " +
                         "      l_returnflag, " +
                         "      l_linestatus, " +
                         "      sum_qty, " +
                         "      sum_base_price, " +
                         "      sum_disc_price, " +
                         "      sum_charge, " +
                         "      avg_qty, " +
                         "      avg_price, " +
                         "      avg_disc, " +
                         "      count_order " +
                         " ORDER BY " +
                         "      l_returnflag       ASC, " +
                         "      l_linestatus       ASC ",
                         {"date": time.mktime(date.timetuple())})

    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for first query")
    print()

# Query 2 code
def query2(db, region, type, size):
    print('Query 2 starting...')
    subquery_result = \
        db.session().run(" MATCH " +
                         "    (su: Supplier)-[res:ps]->() " +
                         " WHERE " +
                         "    su.r_name = {region} " +
                         " RETURN " +
                         "    MIN(res.supplycost) ",
                         {"region": region})

    global min_cost
    for item in subquery_result:
        min_cost = item['MIN(res.supplycost)']

    result = \
        db.session().run(" MATCH " +
                         "     (su: Supplier)-[res:ps]->(p1: Part) " +
                         " WHERE " +
                         "     p1.size = {size}                 AND " +
                         "     p1.type = {type}                 AND " +
                         "     res.supplycost = {suppcost} " +
                         " RETURN " +
                         "     su.accbal   AS s_accbal, " +
                         "     su.name     AS s_name, " +
                         "     su.n_name   AS n_name, " +
                         "     p1.partkey  AS p_partkey, " +
                         "     p1.mfgr     AS p_mfgr, " +
                         "     su.adress   AS s_adress, " +
                         "     su.phone    AS s_phone, " +
                         "     su.comment  AS s_comment " +
                         " ORDER BY " +
                         "     su.accbal   DESC, " +
                         "     su.n_name   ASC, " +
                         "     p1.partkey  ASC ",
                         {"size": size,
                          "type": type,
                          "suppcost": min_cost})
    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for second query")

    print()

# Query 3 code
def query3(db, date1, date2, segment):
    print('Query 3 starting...')
    result = \
        db.session().run(" MATCH " +
                         "     (o1:Order)-[:has]->(l1:LineItem) " +
                         " WHERE " +
                         "     l1.shipdate > {date2}            AND " +
                         "     o1.orderdate < {date1}           AND " +
                         "     o1.c_marketsegment = {segment}   AND " +
                         "     o1.orderkey = l1.orderkey "
                         " WITH " +
                         "      l1.orderkey                                   AS l_orderkey, " +
                         "      o1.orderdate                                  AS o_orderdate, " +
                         "      o1.shippriority                               As o_shippriority, " +
                         "      SUM(l1.extendedPrice*(1-l1.discount))         AS revenue " +
                         " RETURN " +
                         "      l_orderkey, " +
                         "      o_orderdate, " +
                         "      o_shippriority, " +
                         "      revenue " +
                         " ORDER BY " +
                         "      revenue        DESC, " +
                         "      o_orderdate    ASC ",
                         {"date1": time.mktime(date1.timetuple()),
                          "date2": time.mktime(date2.timetuple()),
                          "segment": segment})

    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for third query")
    print()

# Query 4 code
def query4(db, region, date):
    print('Query 4 starting...')

    result = \
        db.session().run(" MATCH " +
                         "      (o:Order)-[:has]->(li:LineItem)-[:isFrom]->(s:Supplier)" +
                         " WHERE " +
                         "      s.r_name = {region}             AND " +
                         "      s.n_name = o.n_name             AND " +
                         "      o.orderdate >= {date}           AND " +
                         "      o.orderdate < {date_year} "
                         " RETURN " +
                         "      o.n_name                                    AS n_name, " +
                         "      SUM(li.extendedPrice*(1-li.discount))       AS revenue " +
                         " ORDER BY " +
                         "      revenue     DESC ",
                         {"date": time.mktime(date.timetuple()),
                          "date_year": time.mktime(date.replace(year=date.year + 1).timetuple()),
                          "region": region})
    i = 0
    for item in result:
        i += 1
        print(item)

    if i == 0:
        print("No results for fourth query")

    print()

# Main function
def run():
    print('Neo4J Laboratory\n')
    db = create()
    indexes(db)
    query1(db, date=datetime.datetime(2016, 11, 28))
    query2(db, region='Barcelona', type='A', size=10)
    query3(db, date1=datetime.datetime(2016, 11, 28), date2=datetime.datetime(2016, 11, 20), segment='MKT1')
    query4(db, region="Barcelona", date=datetime.datetime(2016, 11, 20))
    print('THE END')

if __name__ == '__main__':
    run()
<|endoftext|>


<commit_before>"""
Django settings for Green_Roof_MapPy project.

Generated by 'django-admin startproject' using Django 1.10.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = '3rl&1v+d((&vh08lvks%7i*yfxhytkncc$lbdb&o@l2%v(csry'

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.gis',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'floppyforms',
    'warsaw',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'Green_Roof_MapPy.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Green_Roof_MapPy.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

try:
    from .settings_local import DATABASES
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

except ImportError:
    print('Error importing settings_local.py')

    DATABASES = {
        'default': {
            'ENGINE': 'django.contrib.gis.db.backends.postgis',
            'NAME': 'grm',
        }
    }

# DATABASES = {
#     'default': {
#         'ENGINE': 'django.db.backends.sqlite3',
#         'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
#     }
# }

# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = False

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'
<commit_msg>Hidden Secret Key<commit_after>"""
Django settings for Green_Roof_MapPy project.

Generated by 'django-admin startproject' using Django 1.10.6.

For more information on this file, see
https://docs.djangoproject.com/en/1.10/topics/settings/

For the full list of settings and their values, see
https://docs.djangoproject.com/en/1.10/ref/settings/
"""

import os

# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/1.10/howto/deployment/checklist/

# SECURITY WARNING: keep the secret key used in production secret!

try:
    from .settings_local import SECRET_KEY

except ImportError:
    print('Error importing SECRET_KEY')

# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True

ALLOWED_HOSTS = []

# Application definition

INSTALLED_APPS = [
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.gis',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'floppyforms',
    'warsaw',
]

MIDDLEWARE = [
    'django.middleware.security.SecurityMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

ROOT_URLCONF = 'Green_Roof_MapPy.urls'

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [],
        'APP_DIRS': True,
        'OPTIONS': {
            'context_processors': [
                'django.template.context_processors.debug',
                'django.template.context_processors.request',
                'django.contrib.auth.context_processors.auth',
                'django.contrib.messages.context_processors.messages',
            ],
        },
    },
]

WSGI_APPLICATION = 'Green_Roof_MapPy.wsgi.application'

# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

try:
    from .settings_local import DATABASES
# Database
# https://docs.djangoproject.com/en/1.10/ref/settings/#databases

except ImportError:
    print('Error importing settings_local.py')

    DATABASES = {
        'default': {
            'ENGINE': 'django.contrib.gis.db.backends.postgis',
            'NAME': 'grm',
        }
    }

# Password validation
# https://docs.djangoproject.com/en/1.10/ref/settings/#auth-password-validators

AUTH_PASSWORD_VALIDATORS = [
    {
        'NAME': 'django.contrib.auth.password_validation.UserAttributeSimilarityValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.MinimumLengthValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.CommonPasswordValidator',
    },
    {
        'NAME': 'django.contrib.auth.password_validation.NumericPasswordValidator',
    },
]

# Internationalization
# https://docs.djangoproject.com/en/1.10/topics/i18n/

LANGUAGE_CODE = 'en-us'

TIME_ZONE = 'UTC'

USE_I18N = True

USE_L10N = True

USE_TZ = False

# Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.10/howto/static-files/

STATIC_URL = '/static/'
<|endoftext|>


<commit_before>from pathlib import Path

from ..tools import HLINE, INDENT, printf_block, prompt
from ..types import AnyByStrDict, StrOrPath

__all__ = ("load_config_data", "query_user_data")

def load_toml_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    toml_path = Path(src_path) / "copier.toml"
    if not toml_path.exists():
        return {}

    import toml

    toml_src = toml_path.read_text()
    try:
        return dict(toml.loads(toml_src))
    except Exception as e:
        printf_block(e, "INVALID", msg=str(toml_path), quiet=quiet)
        return {}

def load_yaml_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    yaml_path = Path(src_path) / "copier.yml"
    if not yaml_path.exists():
        yaml_path = Path(src_path) / "copier.yaml"
        if not yaml_path.exists():
            return {}

    from ruamel.yaml import YAML

    yaml = YAML(typ="safe")

    try:
        return dict(yaml.load(yaml_path))
    except Exception as e:
        printf_block(e, "INVALID", msg=str(yaml_path), quiet=quiet)
        return {}

def load_json_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    json_path = Path(src_path) / "copier.json"
    if not json_path.exists():
        return {}

    import json

    json_src = json_path.read_text()
    try:
        return dict(json.loads(json_src))
    except ValueError as e:
        printf_block(e, "INVALID", msg=str(json_path), quiet=quiet)
        return {}

def load_config_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    """Try to load the content from a `copier.yml`, a `copier.toml`, a `copier.json`,
    or the deprecated `voodoo.json`, in that order.
    """
    loaders = (load_yaml_data, load_toml_data, load_json_data)
    for l in loaders:
        # The `_warning` argument is for easier testing
        data = l(src_path, quiet=quiet, _warning=_warning)
        if data:
            return data
    else:
        return {}

def query_user_data(default_user_data: AnyByStrDict) -> AnyByStrDict:  # pragma:no cover
    """Query to user about the data of the config file.
    """
    if not default_user_data:
        return {}
    print("")
    user_data = {}
    for key in default_user_data:
        default = default_user_data[key]
        user_data[key] = prompt(INDENT + f" {key}?", default)

    print(f"\n {INDENT} {HLINE}")
    return user_data
<commit_msg>Refactored exception handling in user_data.<commit_after>from pathlib import Path

from ..tools import HLINE, INDENT, printf_block, prompt
from ..types import AnyByStrDict, StrOrPath

__all__ = ("load_config_data", "query_user_data")

class InvalidConfigFile(ValueError):
    def __init__(self, msg: str, quiet: bool):
        printf_block(self, "INVALID", msg=msg, quiet=quiet)
        super().__init__(msg)

def load_toml_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    toml_path = Path(src_path) / "copier.toml"
    if not toml_path.exists():
        return {}

    import toml

    toml_src = toml_path.read_text()
    try:
        return dict(toml.loads(toml_src))
    except toml.TomlDecodeError as e:
        raise InvalidConfigFile(str(toml_path), quiet) from e

def load_yaml_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    yaml_path = Path(src_path) / "copier.yml"
    if not yaml_path.exists():
        yaml_path = Path(src_path) / "copier.yaml"
        if not yaml_path.exists():
            return {}

    from ruamel.yaml import YAML, YAMLError

    yaml = YAML(typ="safe")

    try:
        return dict(yaml.load(yaml_path))
    except YAMLError as e:
        raise InvalidConfigFile(str(yaml_path), quiet) from e

def load_json_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    json_path = Path(src_path) / "copier.json"
    if not json_path.exists():
        return {}

    import json

    json_src = json_path.read_text()
    try:
        return dict(json.loads(json_src))
    except json.JSONDecodeError as e:
        raise InvalidConfigFile(json_src, quiet) from e

def load_config_data(
    src_path: StrOrPath, quiet: bool = False, _warning: bool = True
) -> AnyByStrDict:
    """Try to load the content from a `copier.yml`, a `copier.toml`, a `copier.json`,
    or the deprecated `voodoo.json`, in that order.
    """
    loaders = (load_yaml_data, load_toml_data, load_json_data)
    for l in loaders:
        # The `_warning` argument is for easier testing
        data = l(src_path, quiet=quiet, _warning=_warning)
        if data:
            return data
    else:
        return {}

def query_user_data(default_user_data: AnyByStrDict) -> AnyByStrDict:  # pragma:no cover
    """Query to user about the data of the config file.
    """
    if not default_user_data:
        return {}
    print("")
    user_data = {}
    for key in default_user_data:
        default = default_user_data[key]
        user_data[key] = prompt(INDENT + f" {key}?", default)

    print(f"\n {INDENT} {HLINE}")
    return user_data
<|endoftext|>