rpc.py 6.89 KB
Newer Older
1
2
from sqlalchemy import and_

3
4
import aurweb.config as config

5
6
from aurweb import db, models
from aurweb.models import dependency_type, relation_type
7
8
9

# Define dependency types.
DEP_TYPES = {
10
11
12
13
    dependency_type.DEPENDS_ID: "Depends",
    dependency_type.MAKEDEPENDS_ID: "MakeDepends",
    dependency_type.CHECKDEPENDS_ID: "CheckDepends",
    dependency_type.OPTDEPENDS_ID: "OptDepends"
14
15
16
17
}

# Define relationship types.
REL_TYPES = {
18
19
20
    relation_type.CONFLICTS_ID: "Conflicts",
    relation_type.PROVIDES_ID: "Provides",
    relation_type.REPLACES_ID: "Replaces"
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
}


# Define functions for request types.
def add_deps(current_array, db_dep):
    if db_dep.count() > 0:
        # Create lists for all dependency types.
        for i in DEP_TYPES.values():
            current_array[i] = []

        # Generate each dependency item in list.
        for i in db_dep.all():
            dep_string = i.DepName

            # Add relationship version restrictor (i.e. '<=5') if it exists.
            if i.DepCondition is not None:
                dep_string += i.DepCondition

            # Add item to list.
            current_deptype = DEP_TYPES.get(i.DepTypeID)
            current_array[current_deptype] += [dep_string]

        # Remove any dependency lists that are empty.
        for i in DEP_TYPES.values():
            if current_array[i] == []:
                current_array.pop(i)

    return current_array


def add_rels(current_array, db_rel):
    if db_rel.count() > 0:
        # Create lists for all relationship types.
        for i in REL_TYPES.values():
            current_array[i] = []

        # Generate each relationship item in list.
        for i in db_rel.all():
            rel_string = i.RelName

            # Add relationship version restrictor (i.e. '<=5') if it exists.
            if i.RelCondition is not None:
                rel_string += i.RelCondition

            # Add item to list.
            current_reltype = REL_TYPES.get(i.RelTypeID)
            current_array[current_reltype] += [rel_string]

        # Remove any relationship lists that are empty.
        for i in REL_TYPES.values():
            if current_array[i] == []:
                current_array.pop(i)

    return current_array


def run_info(returned_data, package_name, snapshot_uri):
    # Get package name.
79
80
81
    db_package = db.query(models.Package).filter(
        models.Package.Name == package_name
    )
82
83
84
85
86
87
88

    if db_package.count() == 0:
        return returned_data

    db_package = db_package.first()

    # Get name of package under PackageBaseID.
89
90
91
    db_package_baseid = db.query(models.PackageBase).filter(
        models.PackageBase.ID == db_package.PackageBaseID
    ).first()
92
93

    # Get maintainer info.
94
95
96
    db_package_maintainer = db.query(models.User).filter(
        models.User.ID == db_package_baseid.MaintainerUID
    ).first()
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126

    current_array = {}
    returned_data["resultcount"] = returned_data["resultcount"] + 1

    # Data from the Packages table.
    current_array["ID"] = db_package.ID
    current_array["Name"] = db_package.Name
    current_array["PackageBaseID"] = db_package.PackageBaseID
    current_array["Version"] = db_package.Version
    current_array["Description"] = db_package.Description
    current_array["URL"] = db_package.URL

    # PackageBase table.
    current_array["PackageBase"] = db_package_baseid.Name
    current_array["NumVotes"] = db_package_baseid.NumVotes
    current_array["Popularity"] = db_package_baseid.Popularity
    current_array["OutOfDate"] = db_package_baseid.OutOfDateTS
    current_array["FirstSubmitted"] = db_package_baseid.SubmittedTS
    current_array["LastModified"] = db_package_baseid.ModifiedTS

    # User table.
    try:
        current_array["Maintainer"] = db_package_maintainer.Username
    except AttributeError:
        current_array["Maintainer"] = None

    # Generate and add snapshot_uri.
    current_array["URLPath"] = snapshot_uri.replace("%s", package_name)

    # Add package votes.
127
    current_array["NumVotes"] = db.query(models.PackageVote).count()
128
129

    # Generate dependency listing.
130
131
    db_dep = db.query(models.PackageDependency).filter(
        models.PackageDependency.PackageID == db_package.ID)
132
133
134
    current_array = add_deps(current_array, db_dep)

    # Generate relationship listing.
135
136
    db_rel = db.query(models.PackageRelation).filter(
        models.PackageRelation.PackageID == db_package.ID)
137
138
139
140
141
    current_array = add_rels(current_array, db_rel)

    # License table.
    current_array["License"] = []

142
143
144
145
    licenses = db.query(models.PackageLicense).filter(
        models.PackageLicense.PackageID == db_package.ID)
    for i in licenses:
        current_array["License"] += [i.License.Name]
146
147
148
149

    # Keywords table.
    current_array["Keywords"] = []

150
151
152
    keywords = db.query(models.PackageKeyword).filter(
        models.PackageKeyword.PackageBaseID == db_package_baseid.ID)
    for i in keywords:
153
154
155
156
157
158
159
        current_array["Keywords"] += [i.Keyword]

    # Add current array to returned results.
    returned_data["results"] += [current_array]
    return returned_data


160
161
162
163
164
165
166
167
def run_suggest_pkgbase(returned_data, arg, snapshot_uri):
    results = db.query(models.PackageBase).filter(
        and_(models.PackageBase.PackagerUID.isnot(None),
             models.PackageBase.Name.like(f"%{arg}%"))
    ).order_by(models.PackageBase.Name.asc()).limit(20)
    return [result.Name for result in results]


168
169
170
171
def RPC(**function_args):
    # Get arguments.
    #
    # We'll use 'v' in the future when we add v6.
172
173
174
    # v = function_args.gea name used for an individual person, place, or
    # organization, spelled with initial capital letters, e.g., Larry,
    # Mexico, and Boston Red Sox.t("v")
175
176
177
178
179
180
181
182
183
    type = function_args.get("type")
    args = function_args.get("argument_list")
    returned_data = function_args.get("returned_data")

    # Get Snapshot URI
    snapshot_uri = config.get("options", "snapshot_uri")

    # Set request type to run.
    type_actions = {
184
        "info": run_info,
185
186
        "multiinfo": run_info,
        "suggest-pkgbase": run_suggest_pkgbase
187
188
189
190
191
192
    }

    # This if statement should always be executed, as we checked if the
    # specified type was valid in aurweb/routers/rpc.py.
    if type in type_actions:
        run_request = type_actions.get(type)
193
194
195
196
197
198
199
200
201
202
203

        # If type is 'info', overwrite type to 'multiinfo' to match the
        # behavior of the PHP implementation.
        if type == "info":
            returned_data["type"] = "multiinfo"

        # Remove duplicate arguments if type is 'multiinfo' so we don't
        # fetch results for a package multiple times.
        if returned_data["type"] == "multiinfo":
            args = set(args)

204
205
206
        for i in args:
            returned_data = run_request(returned_data, i, snapshot_uri)

207
208
209
210
211
212
213
214
    elif type is None:
        returned_data["type"] = "error"
        returned_data["error"] = "No request type/data specified."

    else:
        returned_data["type"] = "error"
        returned_data["error"] = "Incorrect request type specified."

215
    return returned_data