Example #1
0
def execute_commit(qlist):
    global client, polity_query_name, polity_query
    global total_assertions, total_inserts, total_deletes, total_commit_failures
    msg = f"Committing data for {polity_query_name}"
    try:
        q = WOQLQuery().woql_and(*qlist)
        execute_start_time = time.time()
        result = q.execute(client, commit_msg=msg)
        # Makes no difference to timing: client.squash(msg) # per Kevin: flatten the 'journal'
        execute_elapsed_s = "%.2fs" % (time.time() - execute_start_time)
        total_assertions += 1
        if type(result) is dict:
            inserts = result['inserts']
            deletes = result['deletes']
            total_inserts += inserts
            total_deletes += deletes
            print(f"{msg} i:{inserts} d:{deletes} {execute_elapsed_s}")
        else:
            # Sometimes we get a <Response> object that is not subscriptable?
            # result.status_code is the HTTP status code, 200 is successful but we don't have bindings?
            print(f"{msg} {execute_elapsed_s}")
        if dump_results:
            pprint.pprint(result, indent=4)
    except Exception as exception:  # API error or whatever
        execute_elapsed_s = "%.2fs" % (time.time() - execute_start_time)
        print(
            f"Execution ERROR while {msg} after {execute_elapsed_s} -- skipped"
        )
        print(f"{exception.msg}")
        total_commit_failures += 1
def create_schema(client, commit_msg):
    """The query which creates the schema
        Parameters - it uses variables rather than the fluent style as an example
        ==========
        client : a WOQLClient() connection

    """
    station_dt = WOQLQuery().doctype(
        "Station",
        label="Bike Station",
        description="A station where bikes are deposited")
    bicycle_dt = WOQLQuery().doctype("Bicycle", label="Bicycle")
    journey_dt = (WOQLQuery().doctype("Journey", label="Journey").property(
        "start_station", "Station", label="Start Station").property(
            "end_station", "Station",
            label="End Station").property("duration",
                                          "integer",
                                          label="Journey Duration").property(
                                              "start_time",
                                              "dateTime",
                                              label="Time Started").property(
                                                  "end_time",
                                                  "dateTime",
                                                  label="Time Ended").property(
                                                      "journey_bicycle",
                                                      "Bicycle",
                                                      label="Bicycle Used"))
    schema = station_dt + bicycle_dt + journey_dt
    return schema.execute(client, commit_msg)
Example #3
0
def generateMatchClause(code, type, i):
    """ Bug in python string conversion < 0.0.19 - fixed thereafter 
    """
    match = WOQLQuery().woql_and(
        WOQLQuery().idgen("doc:" + type, [code], "v:ID_" + str(i)),
        WOQLQuery().cast(code, "xsd:string", "v:Label_" + str(i))
        #WOQLQuery().idgen("doc:" + type, [{"@value": code, "@type": "xsd:string"}], "v:ID_"+str(i)),
        #WOQLQuery().cast({"@value": code, "@type": "xsd:string"}, "xsd:string", "v:Label_"+ str(i))
    )
    return match
Example #4
0
def generateMultiInsertQuery(codes, type):
    matches = []
    inserts = []
    index = 0
    for code in codes:
        matches.append(generateMatchClause(code, type, index))
        inserts.append(generateInsertClause(code, type, index))
        index = index + 1
    return WOQLQuery().when(WOQLQuery().woql_and(*matches),
                            WOQLQuery().woql_and(*inserts))
def load_csvs(client, csvlist, wrangl, insert):
    """Load the CSVs as input
       Parameters
       ==========
       client : a WOQLClient() connection
       csvs : a dict of all csvs to be input
    """
    for url in csvlist:
        csv = get_csv_variables(url)
        inputs = WOQLQuery().woql_and(csv, *wrangl)
        answer = WOQLQuery().when(inputs, insert)
        answer.execute(client, f"loading {url} into the graph")
Example #6
0
def build_schema(client):
    spacy_doc = WOQLQuery().doctype("SpaCyDoc",
                                    label="SpaCy Document",
                                    description="The Document object in SpaCy")
    token_dt = (WOQLQuery().doctype(
        "SpaCyToken",
        label="SpaCy Tokens").property("lemma", "string").property(
            "pos", "string").property("tag", "string").property(
                "dep", "string").property("shape", "string").property(
                    "is_alpha",
                    "boolean").property("is_stop", "boolean").property(
                        "head", "SpaCyToken").property("doc", "SpaCyDoc"))
    schema = spacy_doc + token_dt
    return schema.execute(client, "Create a schema for SpaCy Tokens")
Example #7
0
def create_schema(client):
    # creating objects doctype
    movie_obj = WOQLQuery().doctype("Movie", label="Movie Title", description="Movie short description")
    person_obj = WOQLQuery().doctype("Person", label="Name of the person")
    genre_obj = WOQLQuery().doctype("Genre", label="Genre of a movie")
    # adding property
    movie_obj = (movie_obj
                .property("Director", "Person", label="Dirctor of the movie")
                .property("Cast", "Person", label="Cast of the movie")
                .property("MovieGenre", "Genre", label="Genre of the movie")
                .property("Year", "xsd:integer", label="Year of release")
                .property("Runtime", "xsd:integer", label="Runtime", description="Runtime of the movie in mins")
                .property("Rating", "xsd:decimal", label="Rating of the movie", description="User rating for the movie 0-10")
                .property("Votes", "xsd:integer", label="Votes", description="Number of votes")
                )
    WOQLQuery().woql_and(movie_obj, genre_obj, person_obj).execute(client, "Building Schema for the movie graph")
Example #8
0
    def post(self, request, *args, **kwargs):


        WOQLQuery().insert("stu002", "scm:student") \
            .property("scm:name", request.data['name']) \
            .execute(client)

        # Generate response
        return Response({'message': 'ok'})
def get_csv_variables(url):
    """Extracting the data from a CSV and binding it to variables
       Parameters
       ==========
       client : a WOQLClient() connection
       url : string, the URL of the CSV
       """
    csv = WOQLQuery().get(
        WOQLQuery().woql_as("Start station", "v:Start_Station").woql_as(
            "End station",
            "v:End_Station").woql_as("Start date", "v:Start_Time").woql_as(
                "End date",
                "v:End_Time").woql_as("Duration", "v:Duration").woql_as(
                    "Start station number", "v:Start_ID").woql_as(
                        "End station number",
                        "v:End_ID").woql_as("Bike number", "v:Bike").woql_as(
                            "Member type", "v:Member_Type")).remote(url)
    return csv
def get_inserts():
    inserts = WOQLQuery().woql_and(
        WOQLQuery().insert("v:Journey_ID", "Journey",
            label="v:Journey_Label",
            description="v:Journey_Description").
            property("start_time", "v:Start_Time_Cast").
            property("end_time", "v:End_Time_Cast").
            property("duration", "v:Duration_Cast").
            property("start_station", "v:Start_Station_URL").
            property("end_station", "v:End_Station_URL").
            property("journey_bicycle", "v:Bike_URL"),
        WOQLQuery().insert("v:Start_Station_URL", "Station",
            label="v:Start_Station_Label"),
        WOQLQuery().insert("v:End_Station_URL", "Station",
            label="v:End_Station_Label"),
        WOQLQuery().insert("v:Bike_URL", "Bicycle",
            label="v:Bike_Label")
    )
    return inserts
Example #11
0
def loading_data(client, file_url):
    read_csv = WOQLQuery().get(
        WOQLQuery().woql_as("Rank", "v:rank_raw")
                   .woql_as("Title", "v:title_raw")
                   .woql_as("Genre", "v:genre_raw")
                   .woql_as("Description", "v:description_raw")
                   .woql_as("Director", "v:director_raw")
                   .woql_as("Actors", "v:actors_raw")
                   .woql_as("Year", "v:year_raw")
                   .woql_as("Runtime (Minutes)", "v:runtime_raw")
                   .woql_as("Rating", "v:rating_raw")
                   .woql_as("Votes", "v:votes_raw")
                   .woql_as("Revenue (Millions)", "v:rev_raw")
                   .woql_as("Metascore","v:metascore_raw")
    ).remote(file_url)

    prepare_genre_obj = WOQLQuery().split("v:genre_raw", ", ", "v:genre_list").member("v:one_genre", "v:genre_list").idgen("doc:Genre", ["v:one_genre"], "v:genre_objid")

    prepare_actor_obj = WOQLQuery().split("v:actors_raw", ", ", "v:actors_list").member("v:one_actor", "v:actors_list").idgen("doc:Person", ["v:one_actor"], "v:actors_objid")

    prepare_director_obj = WOQLQuery().split("v:director_raw", ", ", "v:director_list").member("v:one_director", "v:director_list").idgen("doc:Person", ["v:one_director"], "v:director_objid")


    wangles = (
    WOQLQuery().typecast("v:year_raw", "xsd:integer", "v:year_clean")
        .typecast("v:runtime_raw", "xsd:integer", "v:runtime_clean")
        .typecast("v:rating_raw", "xsd:decimal", "v:rating_clean")
        .typecast("v:votes_raw", "xsd:integer", "v:votes_clean")
        .idgen("doc:Movie",["v:title_raw", "v:director_raw"], "v:movie_id")
        )

    insert = (
    WOQLQuery().insert("v:genre_objid", "Genre", label="v:one_genre")
    .insert("v:actors_objid", "Person", label="v:one_actor")
    .insert("v:director_objid", "Person", label="v:one_director")
    .insert("v:movie_id", "Movie", label="v:title_raw", description="v:description_raw")
    .property("Director", "v:director_objid")
    .property("Cast", "v:actors_objid")
    .property("MovieGenre", "v:genre_objid")
    .property("Year", "v:year_clean")
    .property("Runtime", "v:runtime_clean")
    .property("Rating", "v:rating_clean")
    .property("Votes", "v:votes_clean")
    )

    data_prep = WOQLQuery().woql_and(read_csv, prepare_genre_obj, prepare_actor_obj, prepare_director_obj, wangles)

    return WOQLQuery().woql_and(data_prep, insert).execute(client, "Loading data for the movie graph")
def get_wrangles():
    wrangles = [
        WOQLQuery().idgen("doc:Journey", [
            "v:Start_ID", "v:Start_Time", "v:Bike"], "v:Journey_ID"),
        WOQLQuery().idgen("doc:Station", [
            "v:Start_ID"], "v:Start_Station_URL"),
        WOQLQuery().cast("v:Duration", "xsd:integer", "v:Duration_Cast"),
        WOQLQuery().cast("v:Bike", "xsd:string", "v:Bike_Label"),
        WOQLQuery().cast("v:Start_Time", "xsd:dateTime", "v:Start_Time_Cast"),
        WOQLQuery().cast("v:End_Time", "xsd:dateTime", "v:End_Time_Cast"),
        WOQLQuery().cast("v:Start_Station", "xsd:string", "v:Start_Station_Label"),
        WOQLQuery().cast("v:End_Station", "xsd:string", "v:End_Station_Label"),
        WOQLQuery().idgen("doc:Station", ["v:End_ID"], "v:End_Station_URL"),
        WOQLQuery().idgen("doc:Bicycle", ["v:Bike_Label"], "v:Bike_URL"),
        WOQLQuery().concat("Journey from v:Start_ID to v:End_ID at v:Start_Time", "v:Journey_Label"),
        WOQLQuery().concat("Bike v:Bike from v:Start_Station to v:End_Station at v:Start_Time until v:End_Time",
                           "v:Journey_Description")
    ]
    return wrangles
def create_seshat_schema(client):
    """The query which creates the schema
    Parameters - it uses variables rather than the fluent style as an example
    ==========
    client : a WOQLClient() connection
    """
    # presummably this goes into 'scm:' by default
    # what do I do if I wanted to name the schema to publish it (like bike_scm)?
    # presummably I would have to then dump it in rdf format and make it available on the web for parsing by other 3store apps right?
    # what do I use to load an external schema?

    # This controls 'debugging mode' True to incrementally execute, False to append and execute once
    execute_incrementally = False  # if False, flat defined in 7s; if True, 577s

    def process_q(q, message=None):
        if execute_incrementally:
            if message is not None:
                print(message)
            try:
                q.execute(client, commit_msg=message)
            except Exception as exception:  # API error or whatever
                print(f"Execution ERROR for: {message} -- skipped")
                print(f"{exception.msg}")

        return q

    # kevin.js: initial un-numbered q
    q = WOQLQuery().doctype(
        "Organization",
        label="Organization",
        description=
        "A human organization of any type - has the capacity to act as a unit, in some sense"
    ).abstract()
    all_q = process_q(q, "Organization")
    for class_defn in class_defns:
        if len(class_defn) == 4:
            name, label, description, parents = class_defn
        else:
            name, label, description = class_defn
            parents = []
        # name = normaliseID(name,'id')
        q = WOQLQuery().doctype(name, label=label, description=description)
        for parent in parents:
            # parent = normaliseID(parent,'id')
            q.parent(parent)
        all_q = all_q + process_q(q, name)

    # kevin.js: q2
    q = WOQLQuery().doctype(
        "Topic",
        label="Topic Class",
        description="A class that represents a topic").abstract()
    all_q = all_q + process_q(q, "Topic")
    for topic in topics:
        if len(topic) == 4:
            name, label, description, parents = topic
        else:
            name, label, description = topic
            parents = []
        # name = normaliseID(name,'id')
        q = WOQLQuery().doctype(name, label=label, description=description)
        for parent in parents:
            # parent = normaliseID(parent,'id')
            q.parent(parent)
        all_q = all_q + process_q(q, name)

    q = WOQLQuery().doctype("CitedWork", label="Cited Work").property(
        "remote_url", "xsd:anyURI")
    all_q = all_q + process_q(q, 'CitedWork')

    # This call defines the boxed datatypes we use, e.g., scm:IntegerRange whose 'type' is xdd:IntegerRange
    # kevin.js: q9
    if False:
        q = (WOQLQuery().add_class("scm:Box").label("Box Class").description(
            "A class that represents a boxed datatype").abstract())
        all_q = all_q + process_q(q, 'scm:Box')

    for bbt in boxed_basic_types:
        datatype, label, description = bbt
        raw_datatype = ensure_raw_type(
            datatype)  # how we are actually storing it
        Datatype = normaliseID(
            datatype, 'type'
        )  # get the scm: prefixed, upper-cased name, e.g., scm:GYear from xsd:gYear
        no_prefix_Datatype = Datatype.split(":")[1]
        type_info[no_prefix_Datatype] = (Datatype, datatype)
        if verbose:
            print(
                f"box type property: {Datatype} domain: {Datatype} type: {datatype} as {raw_datatype}"
            )

        qt = WOQLQuery().add_class(Datatype).label(label)
        if False:
            # no parent, e.g., scm:Box, needs to be added to qt so far (except it bundles all our types together)
            qt.parent('scm:Box')

        # scm:Integer is a class with a property scm:Integer that permits an xsd:integer
        # when when we mixin scm:Integer into a <prop>_Value class, and it has type xsd:integer
        qp = (WOQLQuery().add_property(Datatype, raw_datatype).domain(
            Datatype).label(label).description(description))
        q = WOQLQuery().woql_and(qt, qp)
        all_q = all_q + process_q(q, Datatype)

    # kevin.js: q5+q6
    # Is this class needed for generate_choice_list()?
    # JSB probably not.  it is like Box which just serves to organize the different types
    # q = WOQLQuery().doctype("Enumerated",label="Enumerated Type",description="A type that consists of a fixed set of choices")
    # all_q = all_q + process_q(q,"Enumerated")

    for etype in enumerations:
        Name, label, description, choices = etype
        Name = Name[0].upper() + Name[1:]  # ensure leading capitlized
        scm_Name = normaliseID(Name, 'id')  # e.g., scm:EpistemicState
        if False:  # DEBUG since fixed_generate_choice_list() uses prefix _:, which causes upset
            # choices = normaliseID(choices,'id')
            for choice in choices:
                choice[0] = normaliseID(choice[0], 'id')
            # q = WOQLQuery().generate_choice_list(name,clslabel=label,clsdesc=description,choices=choices)
            qus = fixed_generate_choice_list(cls=scm_name,
                                             clslabel=label,
                                             clsdesc=description,
                                             choices=choices)
            qsc = fixed_generate_choice_list(cls=scm_scoped_name,
                                             clslabel=label,
                                             clsdesc=description,
                                             choices=choices)
            q = WOQLQuery().woql_and(qus, qsc)
        else:
            # HACK define the class but not its structure
            # treat it like a Box type with a string
            raw_type = ensure_raw_type(scm_Name)
            if raw_type != 'xsd:string':
                print(f"Incorrect ensure_raw_type() entry for {scm_Name}")
                continue
            # class scm:EpistemicState with property EpistemicState of type xsd:string
            # class scm:Confidence with property scm:Confidence of type xsd:string # << this is used in property_Value confidence
            type_info[Name] = (scm_Name, scm_Name)
            if verbose:
                print(f"enumeration property: {scm_Name} domain: {scm_Name}")
            qt = WOQLQuery().add_class(scm_Name).label(label)
            qp = (WOQLQuery().add_property(scm_Name, raw_type).domain(
                scm_Name).label(label).description(description))
            q = WOQLQuery().woql_and(qt, qp)

        all_q = all_q + process_q(q, f"{scm_Name}")

    # define these after types and enumerations so we can refer to them
    # kevin.js: q7
    q = (WOQLQuery().add_class("Note").label("A Note on a value").description(
        "Editorial note on the value").property(
            "citation", "scm:CitedWork").label(
                "Citation").description("A link to a cited work").property(
                    "quotation", "xsd:string").label("Quotation").description(
                        "A quotation from a work"))
    all_q = all_q + process_q(q, 'Note')

    q = (
        WOQLQuery().add_class("ScopedValue").abstract()
        # These were xdd:integerRange
        # Don't we want these to be xsd:gYear and not a range?
        # Peter says we should always permit 'unknown' and 'suspected unknown' as a value
        # Thus we should add the following.  If it is NOT asserted, then lookup its usual typed value
        # Otherwise the string is 'unknown' (high confidence) or 'suspected unknown' (low confidence) (another enum) and remove it from EpistemicState
        # .property("unknown", 'xsd:string').label("Unknown").description("Whether the value is unknown")
        .property("start", raw_gYear_type).label("From").description(
            "The start of a time range").property("end", raw_gYear_type).
        label("To").description("The end of a time range").property(
            "confidence", "scm:Confidence").label("Confidence").description(
                "Qualifiers of the confidence of a variable value").property(
                    "notes", "scm:Note").label("Notes").description(
                        "Editorial notes on values"))
    all_q = all_q + process_q(q, 'ScopedValue')

    # kevin.js: q11
    for p in unscoped_properties:
        if len(p) == 5:
            npid, nptype, label, description, domain = p
        else:
            npid, nptype, label, description = p
            domain = "scm:PoliticalAuthority"
        # TODO no prefix nptype?
        variable_info[label] = (npid, False, nptype
                                )  # do this before adding scm: to npid!
        npid = normaliseID(npid, "id")  # add scm: if missing a prefix
        raw_nptype = ensure_raw_type(nptype)
        q = WOQLQuery().add_property(
            npid,
            raw_nptype).label(label).description(description).domain(domain)
        all_q = all_q + process_q(q, npid)

    # kevin.js: q15
    for p in scoped_properties:
        if len(p) == 6:
            npid, nptype, parents, label, description, domain = p
        else:
            npid, nptype, parents, label, description = p
            domain = "scm:PoliticalAuthority"
        parents = normaliseID(parents, "id")
        parents.append(
            "scm:ScopedValue"
        )  # these seshat polity properties always inherit from ScopedValue -- that is where datatypes and values are stored

        nptype = normaliseID(nptype,
                             "type")  # convert to our boxed types always
        # No need to lookup 'raw' type -- that was done up when we defined our boxed types
        no_prefix_nptype = nptype.split(":")[1]
        variable_info[label] = (npid, True, no_prefix_nptype
                                )  # before we add scm: to npid

        npid = normaliseID(npid, "id")
        parents.append(nptype)
        newclass = npid + "_Value"

        if verbose:
            print(
                f"property: {npid} domain: {domain} type: {newclass} parents: {parents}"
            )

        q = WOQLQuery().add_class(newclass).label(label).description(
            description)
        for parent in parents:
            q.parent(parent)
        all_q = all_q + process_q(q, newclass)

        q = WOQLQuery().add_property(
            npid, nptype).label(label).description(description).domain(domain)
        all_q = all_q + process_q(q, npid)

    if not execute_incrementally:
        execute_incrementally = True  # force execution
        process_q(all_q, "Defining the Seshat Schema")

    return True
Example #14
0
else:
    client.db(db_id)
"""

# station_dt = WOQLQuery().doctype("doc_car",
#                     label="doc_car",
#                     description="A station where bikes are deposited")
# station_dt.execute(client, "creating schema")

# carInstance = WOQLQuery().insert(insert_id="OBJ123", insert_type="doc_car")
# carInstance.label("Porche 911")
# carInstance.property("car_make", "Porche")
# carInstance.property("car_model", "911")
# carInstance.execute(client)

WOQLQuery().doctype("scm:student").property("scm:name", "xsd:string").execute(client, "student schema created.")
WOQLQuery().insert("stu001", "scm:student").property("scm:name", "Alice").execute(client, "Adding Alice.")
WOQLQuery().insert("stu002", "scm:student").property("scm:name", "Bob").execute(client, "Adding Bob.")
client.query(WOQLQuery().star())
"""
station_dt = WOQLQuery().doctype("station",
                        label="Bike Station",
                        description="A station where bikes are deposited")
bicycle_dt = WOQLQuery().doctype("bike", label="Bicycle")
journey_dt = (
        WOQLQuery().doctype("journey", label="Journey").
        property("start_station", "Station", label="Start Station").
        property("end_station", "Station", label="End Station").
        property("duration", "integer", label="Journey Duration").
        property("start_time", "dateTime", label="Time Started").
        property("end_time", "dateTime", label="Time Ended").
Example #15
0
#!/usr/bin/python3

from terminusdb_client import WOQLClient
from terminusdb_client import WOQLQuery

server_url = "https://127.0.0.1:6363"
client = WOQLClient(server_url)
client.connect(user="******", account="admin", key="root", db="bike")

client.delete_database("bike")
client.create_database("bike","admin",label="Bikes", description="description")

query = WOQLQuery().get(
    WOQLQuery().woql_as("Start station","v:Start_Station")
        .woql_as("End station", "v:End_Station")
        .woql_as("Start date", "v:Start_Time")
        .woql_as("End date", "v:End_Time")
        .woql_as("Duration", "v:Duration")
        .woql_as("Start station number", "v:Start_ID")
        .woql_as("End station number", "v:End_ID")
        .woql_as("Bike number", "v:Bike")
        .woql_as("Member type", "v:Member_Type")
).post("bike_csv")
result = client.query(query,
                      "This is a commit string",
                      {'bike_csv' : '/home/gavin/tmp/bike_tutorial.csv'})
Example #16
0
def generateInsertClause(code, type, i):
    insert = WOQLQuery().woql_and(WOQLQuery().insert(
        "v:ID_" + str(i), type).label("v:Label_" + str(i)))
    return insert
Example #17
0
def assert_seshat_row(Polity, Variable, Value_From, Value_To, Date_From,
                      Date_To, Fact_Type, Value_Note):
    global client, flushed_values, polity_query_name, polity_query
    empty_value = ''  # Could be None

    def unique_var(prefix):
        uid = increment_unique_id()
        return f"{prefix}_{uid}"

    if polity_query_name != Polity:
        if polity_query is not None:
            execute_commit(polity_query)
        # fallthrough
        polity_query_name = Polity
        polity_query = [
        ]  # add individual queries to the list for a final woql_and in execute_commit()

    try:
        property_name, scoped, property_type = variable_info[Variable]
    except KeyError:
        print(f"WARNING: Unknown property {Variable} - skipping")
        return None

    if scoped:
        property_Value = property_name + '_Value'
        doc_property_Value = 'doc:' + property_Value
        scm_property_Value = 'scm:' + property_Value
        try:
            property_value_name, raw_type = type_info[property_type]
        except KeyError:
            print(
                f"WARNING: Unknown type {property_type} for {Variable} - skipping"
            )
            return None

    else:
        raw_type = property_type
    real_raw_type = ensure_raw_type(raw_type)

    lower_Polity = Polity.lower(
    )  # Make canonical;this was the previous encoding idea for ids
    where = f"{Polity}|{Variable}"
    # normally (like on the wiki or on another web interface) we would present all the Scoped values
    # for a variable and then reassert them enmass, deleting the prior versions
    # However, with a csv we don't know the order of the lines for all the multiple values
    # so we maintain a dict of what variables we've started to assert and if
    # this is a new variable we delete all the extant triples
    # this assumes, of course, that the csv contains, eventually, all the values for the property
    # and not just additions
    try:
        flushed_values[Polity]
        new_polity = False
    except KeyError:
        flushed_values[Polity] = [
        ]  # what variables have been flushed this session
        new_polity = True

    if new_polity:
        # TODO how do you bind all the instances of an scm:Polity to a variable?
        qp = WOQLQuery().woql_or(
            WOQLQuery().triple(
                'v:Polity_ID', 'original_PolID', Polity
            ),  # look up original if it exists under the lower_Polity name
            # Doesn't exist so create a Polity instance
            WOQLQuery().woql_and(
                WOQLQuery().idgen(
                    lower_Polity, [], 'v:Polity_ID'
                ),  # create an atom (why can't we use a raw string?)
                (
                    WOQLQuery().insert(
                        'v:Polity_ID', 'scm:Polity',
                        label=Polity).  # create in instance of scm:Polity
                    property('original_PolID', Polity)
                )))  # record the original 'spelling', e.g. AfHepht vs. afhepht
        polity_query.append(qp)

    # collect up all property queries for each Polity and when it changes, execute the collection once
    if Variable not in flushed_values[Polity]:
        # do this once, if at all for each property_name
        flushed_values[Polity].append(Variable)  # flushed done
        old_value_var = unique_var('v:Old_Values')
        # It is ok that this fails since it might be a new property
        # or a new class instance without any property at all
        qf = WOQLQuery()
        if scoped:
            qf.opt(WOQLQuery().woql_and(
                WOQLQuery().triple('v:Polity_ID', property_name,
                                   old_value_var),
                # TODO the Old_Values scoped value instances could have notes
                # and those instance need to be deleted as well
                # BUT NOT the CitedWork which might be shared
                # Do it before deleting the value object
                WOQLQuery().delete_triple('v:Polity_ID', property_name,
                                          old_value_var),
                WOQLQuery().delete_object(old_value_var)))
        else:
            # if unscoped just drop triples directly
            # but if the values happen to be instance themselves, .e.g, Politys, don't delete them
            qf.opt(WOQLQuery().woql_and(
                WOQLQuery().triple('v:Polity_ID', property_name,
                                   old_value_var),
                WOQLQuery().delete_triple('v:Polity_ID', property_name,
                                          old_value_var)))
        polity_query.append(qf)

    qv = WOQLQuery()  # updated/continued by side effect
    value = Value_From
    if 'Range' in raw_type:
        if Value_To != empty_value:
            value = Value_From + ':' + Value_To  # don't use - as separator
    value = precast_values(value, raw_type, where)

    dates = ''
    confidence = ''
    if scoped:
        # generate an instance of a scoped data value type
        pv_var = unique_var('v:propertyValue_ID')
        unique_id(
            qv, doc_property_Value, [lower_Polity], pv_var
        )  # will this generate a new id each time and ensure unique id
        qv.insert(
            pv_var,
            scm_property_Value)  # create an instance of the Value boxed class
        qv.add_triple('v:Polity_ID', property_name,
                      pv_var)  # assert the scoped property value

        # get type, if enumerated check that the given value is (lower) the allowed value
        # else cast to type
        # do dates handle CE and BCE and AD and BC?
        inferred = False
        if 'inferred' in value:
            # test scoped here; if not scoped we have a problem
            inferred = True
            value = value.split(' ')[1]
        val_var = unique_var('v:Value')
        qv.cast(value, real_raw_type, val_var)
        qv.add_triple(
            pv_var, property_value_name, val_var
        )  # store the cast value on the proper property name on the _value instance

        # NOTE: hard coded information about types under ScopedValue
        # if those types changes in the schema, this code must change as well
        if Date_From != empty_value:
            # Does gYear handle 450CE? NO
            # under ScopedValue why not dates as integerRange rather than start and end?
            Date_From = precast_values(Date_From, gYear_type,
                                       f"{where}_DateFrom")
            df_var = unique_var('v:Date_From')
            qv.cast(
                Date_From, raw_gYear_type, df_var
            )  # cast'ing to xsd:gYear fails to return anything and does not complain
            qv.add_triple(pv_var, 'start', df_var)
            dates = dates + f":{Date_From}"
            if Date_To != empty_value:
                Date_To = precast_values(Date_To, gYear_type,
                                         f"{where}_DateTo")
                dt_var = unique_var('v:Date_To')
                qv.cast(
                    Date_To, raw_gYear_type, dt_var
                )  # cast'ing to xsd:gYear fails to return anything and does not complain
                qv.add_triple(pv_var, 'end', dt_var)
                dates = f"[{Date_From},{Date_To}]"

        # TODO require scoped to deal with disputed else badly formed csv
        if scoped and Value_Note == 'disputed':
            # eventually we need to convert 'disputed' into the enumerated value in the class
            # name an instance of ScopedConfidence and assert property 'String'
            cd_var = unique_var('v:SVcd')
            unique_id(qv, 'doc:Confidence', [Polity, property_name], cd_var)
            qv.insert(cd_var, Confidence_type)  # make a Confidence instance
            cdv_var = unique_var('v:SVcdv')
            # Does cast deal w/ enums?
            qv.cast(
                Value_Note, raw_Confidence_type, cdv_var
            )  # eventually not 'disputed' but a variable bound to the right enum instance with disputed as 'label'
            qv.add_triple(cd_var, Confidence_type,
                          cdv_var)  # The property has the name as the class!
            # add the Confidence instance to the ScopedValue instance NOTE the cardinality of confidence must be > 1
            qv.add_triple(pv_var, 'confidence', cd_var)
            confidence = confidence + f" {Value_Note}"

        # Note we can have multiple 'confidence' assertions such as 'disputed' and 'inferred'? for the same 'value'?  Happens in the db, e.g.,
        # NGA|CnLrJin|Warfare variables|Military Technologies|Incendiaries|inferred present||||simple|disputed||
        # NGA|CnLrJin|Warfare variables|Military Technologies|Incendiaries|present||||simple|disputed||
        # TODO require scoped to deal with inferred else badly formed csv
        if scoped and inferred:
            ci_var = unique_var('v:SVci')
            unique_id(qv, 'doc:Confidence', [Polity, property_name], ci_var)
            qv.insert(ci_var, Confidence_type)  # make a Confidence instance
            civ_var = unique_var('v:SVciv')
            # Does cast deal w/ enums?
            qv.cast(
                'inferred', raw_Confidence_type, civ_var
            )  # eventually not 'inferred' but a variable bound to the right enum instance with disputed as 'label'
            qv.add_triple(ci_var, Confidence_type,
                          civ_var)  # The property has the name as the class!
            # add the Confidence instance to the ScopedValue instance NOTE the cardinality of confidence must be > 1
            qv.add_triple(pv_var, 'confidence', ci_var)
            confidence = confidence + " inferred"

        # TODO any Date_Note save as a Note instance (v:Note) and assert qv.property('notes','v:Note')
    else:  # unscoped
        qv.cast(value, real_raw_type, val_var)
        qv.add_triple('v:Polity_ID', property_name, val_var)
    polity_query.append(qv)
    if verbose_mode:
        print(f"Added {value}{dates}{confidence} for {Variable} on {Polity}")
    return
Example #18
0
def create_schema(client):
    """The query which creates the schema
        Parameters - it uses variables rather than the fluent style as an example
        ==========
        client : a WOQLClient() connection

    """
    base = WOQLQuery().doctype("EphemeralEntity").label(
        "Ephemeral Entity").description("An entity that has a lifespan")
    base.property("lifespan_start", "dateTime").label("Existed From")
    base.property("lifespan_end", "dateTime").label("Existed To")

    country = WOQLQuery().add_class("Country").label("Country").description(
        "A nation state").parent("EphemeralEntity")
    country.property("iso_code", "string").label("ISO Code")
    country.property("fip_code", "string").label("FIP Code")

    airline = WOQLQuery().add_class("Airline").label("Airline").description(
        "An operator of airplane flights").parent("EphemeralEntity")
    airline.property("registered_in", "Country").label("Registered In"),

    airport = WOQLQuery().add_class("Airport").label("Airport").description(
        "An airport where flights terminate").parent("EphemeralEntity")
    airport.property("situated_in", "Country").label("Situated In"),

    flight = WOQLQuery().add_class("Flight").label("Flight").description(
        "A flight between airports").parent("EphemeralEntity")
    flight.property("departs", "Airport").label("Departs")
    flight.property("arrives", "Airport").label("Arrives")
    flight.property("operated_by", "Airline").label("Operated By")

    schema = WOQLQuery().when(True).woql_and(base, country, airline, airport,
                                             flight)
    return schema.execute(client)
Example #19
0
import terminusdb_client as woql
from terminusdb_client import WOQLQuery
import sys

db_id = "student"
client = woql.WOQLClient(server_url = "https://127.0.0.1:6363", insecure=True)
client.connect(key="root", account="admin", user="******")


existing = client.get_database(db_id, "admin")
if existing is not None:
    client.delete_database(db_id)
client.create_database(db_id, accountid="admin", 
                        label = "Student", 
                        description = "Create a graph with student data")

WOQLQuery().doctype("scm:student").property("scm:name", "xsd:string").execute(client, "student schema created.")

WOQLQuery().insert("stu002", "scm:student") \
    .property("scm:name", "Bob") \
    .execute(client, "Adding Bob.")

from terminusdb_client import WOQLQuery as WOQL

# Connect to the server
server_url = "https://127.0.0.1:6363"
db = "dbpedia_1"
user = "******"
account = "admin"
key = "root"
client = WOQLClient(server_url)
client.connect(user=user, account=account, key=key, db=db)

# Example of a single hop
query = WOQL().limit(
    1,
    WOQL.woql_and(
        WOQL().path("doc:Whitesnake", "scm:bandMember", "v:Member",
                    "v:Path"), ))
result = client.query(query)
print(f"Band member: {result['bindings'][0]['Member']}")

query = WOQL().limit(
    1,
    WOQL.woql_and(
        WOQL().path("doc:Whitesnake", "scm:bandMember,scm:birthPlace",
                    "v:Place", "v:Path"), ))
result = client.query(query)
print(result['bindings'][0])

query = WOQL().limit(
    3,
    WOQL().select("v:P", "v:Result").woql_and(
Example #21
0
def insert_triple():
    subj = random_string_number()
    pred = random_string_number()
    value = random_string_number()
    WOQLQuery().using(f"admin/{db}").add_triple(subj, pred, value).execute(client)