gpkgstatus.gpkgstatus

The gpkgstatus module searches package and prints its update info.

The gpkgstatus module that searches the package from selected url or cached file and prints the update info to terminal.

  1"""The gpkgstatus module searches package and prints its update info.
  2
  3The gpkgstatus module that searches the package from selected url or
  4cached file and prints the update info to terminal.
  5
  6"""
  7import argparse
  8import logging
  9from random import randint
 10import sys
 11
 12from typing import Optional
 13
 14from termcolor import colored
 15
 16from gpkgstatus.utils.config import Config
 17from gpkgstatus.utils.json_file_reader import FileNotFoundException, JSONFileReader
 18from gpkgstatus.utils.url_reader import URLReader
 19from gpkgstatus import __version__
 20
 21
 22def select_url(name: Optional[str], version: str):
 23    """Selects url based on name based on corresponding release \
 24        version if specified or else globally.
 25
 26    Selects url based on first character of version from a dictionary of
 27    urls. If url is not present in urls, then program halts with exit
 28    status 1 and immediately states that given version/Linux distribution
 29    release is invalid.
 30
 31    Args:
 32        name (Optional[str]): Name of the package. Defaults to None if none \
 33            is given in command-line arguments.
 34        version (str): If version is given, then package will be searched \
 35            in specific release; or else the package will be searched globally. \
 36                Defaults to None.
 37
 38    Returns:
 39        str : Complete URL containing parameters based on given arguments that searches \
 40            a package with given name in corresponding release version if specified.
 41    """
 42    first_letter = version[0]
 43    urls = {
 44        "f": "https://bodhi.fedoraproject.org/updates/?",
 45    }
 46
 47    if first_letter in urls:
 48        url = urls[first_letter]
 49        logging.info("Given version is in list")
 50    else:
 51        print(colored("Error: Invalid Distribution Release. Format: f{version}", "red"))
 52        logging.debug("Invalid Version: %s", version)
 53
 54        sys.exit(1)
 55
 56    if name:
 57        url += f"&search={name}"
 58
 59    if len(version) > 1:
 60        url += f"&releases={version}"
 61
 62    logging.info("URL Selected: %s", url)
 63
 64    return url
 65
 66
 67def print_update_info(update: dict, status_color: str = None, more_info=False):
 68    """Prints colored update info to terminal.
 69
 70    The color is selected based on current status of package
 71    from a colors dictionary with keys as status and colors
 72    as values. If status is not present in colors, then
 73    default color is blue.
 74
 75    If terminal does not support ASCII colors, then normal text
 76    is printed.
 77
 78    Args:
 79        update (dict): Dictionary of Updates containing metadata.
 80        status_color (str): ASCII Color if explicitly given.
 81    """
 82    colors = {"stable": "green", "testing": "yellow", "pending": "red"}
 83
 84    if update["status"].lower() in colors:
 85        status_color = colors[update["status"]]
 86    else:
 87        status_color = "blue"
 88
 89    print(colored(f"Update ID: {update['updateid']}", status_color))
 90    print(colored(f"Package Name: {update['title']}", status_color))
 91    print(colored(f"Status: {update['status']}", status_color))
 92    if more_info:
 93        print(colored(f"Alias: {update['alias']}", status_color))
 94        print(colored(f"Date Submitted: {update['date_submitted']}", status_color))
 95        print(colored(f"Severity: {update['severity']}", status_color))
 96        print(colored(f"Version Hash: {update['version_hash']}", status_color))
 97        print(colored(f"URL: {update['url']}", status_color))
 98        print(colored(f"Notes: {update['notes']}", status_color))
 99
100    print("------------------------------")
101
102
103def search_pkg(args: dict):
104    """Search Package from cached file or given JSON url.
105
106    If --force argument is specified, url will be used for searching
107    irrespective of whether cached expired or not. After requesting the
108    url, the program stores the JSON response in a file named as
109    "name_release.json"; that has searched packages of corresponding release.
110    In case if --name argument is not specified, the file will be named
111    as "None_release.json".
112
113    If --noconfig argument is specified, config will be ignored and values of
114    cache_time and verbose will be set to default values.
115
116    Args:
117        args (dict): Command-Line arguments in the form of dictionary.
118    """
119    logger = logging.getLogger()
120    logger.addHandler(logging.StreamHandler(sys.stdout))
121
122    if not args["noconfig"]:
123        config = Config()
124        config.main()
125
126        if config.verbose or args["verbose"]:
127            logger.setLevel(logging.INFO)
128
129        cache_time = config.cache_time
130    else:
131        cache_time = randint(52, 65) * 60
132        if args["verbose"]:
133            logger.setLevel(logging.INFO)
134
135        logging.info("Forced to ignore config file")
136
137    logging.info(args)
138    logging.info("Cache Time: %d min", cache_time // 60)
139
140    release = args["release"][0]
141    name = args["name"][0] if args["name"] else None
142    more_info = args["moreinfo"]
143
144    try:
145        limit = int(args["limit"][0])
146    except ValueError:
147        print(colored("You must enter an integer value.", "red"))
148        sys.exit(1)
149
150    cache_file = f"{name}_{release}.json"
151    url = select_url(name, release.lower())
152
153    try:
154        file_reader = JSONFileReader(cache_file, "updates")
155
156        if args["force"]:
157            logging.info("Forced to update the cache")
158
159        if args["force"] or (file_reader.relative_time() > cache_time):
160            logging.info("File cache is outdated")
161
162            print(colored("Getting list of updates...", "green"))
163            url_reader = URLReader(url)
164            url_reader.save_as_file(cache_file)
165
166    except FileNotFoundException:
167        print(colored("Getting list of updates...", "green"))
168
169        url_reader = URLReader(url)
170        url_reader.save_as_file(cache_file)
171        file_reader = JSONFileReader(cache_file, "updates")
172
173    finally:
174        updates = file_reader.read(limit)
175
176        if not updates:
177            print(colored("No Updates Found. Check your arguments.", "red"))
178            sys.exit(0)
179
180        print("------------------------------")
181        for update in updates:
182            print_update_info(update, more_info=more_info)
183
184
185def cli():
186    """Command Line Interface of Program.
187
188    The CLI takes arguments from terminal ,parses it using ArgumentParser,
189    converts arguments into form of dictionary, and calls the search_pkg
190    function.
191    """
192    parser = argparse.ArgumentParser(
193        prog="gpkgstatus",
194        description="Get Current Package Status from Fedora Updates System",
195    )
196
197    parser.add_argument(
198        "-f",
199        "--force",
200        help="Sync cached info with Fedora Updates System",
201        action="store_true",
202    )
203
204    # limit = 5 (default)
205    parser.add_argument(
206        "-l",
207        "--limit",
208        help="Maximum limit on number of packages shown for package search",
209        default="5",
210        nargs=1,
211    )
212    parser.add_argument(
213        "--moreinfo",
214        help="Verbose (More Info) in Update Info",
215        action="store_true",
216    )
217    parser.add_argument(
218        "-n",
219        "--name",
220        help="Name of the package",
221        nargs=1,
222    )
223    parser.add_argument(
224        "--noconfig",
225        help="Do not check for config file",
226        action="store_true",
227    )
228    parser.add_argument(
229        "-r",
230        "--release",
231        help="Checks package status for corresponding Fedora release",
232        default="f",
233        nargs=1,
234    )
235    parser.add_argument(
236        "-v",
237        "--verbose",
238        help="Enable verbose output",
239        action="store_true",
240    )
241    parser.add_argument(
242        "--version",
243        help="gpkgstatus version",
244        action="version",
245        version=__version__,
246    )
247    args = parser.parse_args()
248
249    search_pkg(vars(args))
def select_url(name: Optional[str], version: str):
23def select_url(name: Optional[str], version: str):
24    """Selects url based on name based on corresponding release \
25        version if specified or else globally.
26
27    Selects url based on first character of version from a dictionary of
28    urls. If url is not present in urls, then program halts with exit
29    status 1 and immediately states that given version/Linux distribution
30    release is invalid.
31
32    Args:
33        name (Optional[str]): Name of the package. Defaults to None if none \
34            is given in command-line arguments.
35        version (str): If version is given, then package will be searched \
36            in specific release; or else the package will be searched globally. \
37                Defaults to None.
38
39    Returns:
40        str : Complete URL containing parameters based on given arguments that searches \
41            a package with given name in corresponding release version if specified.
42    """
43    first_letter = version[0]
44    urls = {
45        "f": "https://bodhi.fedoraproject.org/updates/?",
46    }
47
48    if first_letter in urls:
49        url = urls[first_letter]
50        logging.info("Given version is in list")
51    else:
52        print(colored("Error: Invalid Distribution Release. Format: f{version}", "red"))
53        logging.debug("Invalid Version: %s", version)
54
55        sys.exit(1)
56
57    if name:
58        url += f"&search={name}"
59
60    if len(version) > 1:
61        url += f"&releases={version}"
62
63    logging.info("URL Selected: %s", url)
64
65    return url

Selects url based on name based on corresponding release version if specified or else globally.

Selects url based on first character of version from a dictionary of urls. If url is not present in urls, then program halts with exit status 1 and immediately states that given version/Linux distribution release is invalid.

Arguments:
  • name (Optional[str]): Name of the package. Defaults to None if none is given in command-line arguments.
  • version (str): If version is given, then package will be searched in specific release; or else the package will be searched globally. Defaults to None.
Returns:

str : Complete URL containing parameters based on given arguments that searches a package with given name in corresponding release version if specified.

def search_pkg(args: dict):
104def search_pkg(args: dict):
105    """Search Package from cached file or given JSON url.
106
107    If --force argument is specified, url will be used for searching
108    irrespective of whether cached expired or not. After requesting the
109    url, the program stores the JSON response in a file named as
110    "name_release.json"; that has searched packages of corresponding release.
111    In case if --name argument is not specified, the file will be named
112    as "None_release.json".
113
114    If --noconfig argument is specified, config will be ignored and values of
115    cache_time and verbose will be set to default values.
116
117    Args:
118        args (dict): Command-Line arguments in the form of dictionary.
119    """
120    logger = logging.getLogger()
121    logger.addHandler(logging.StreamHandler(sys.stdout))
122
123    if not args["noconfig"]:
124        config = Config()
125        config.main()
126
127        if config.verbose or args["verbose"]:
128            logger.setLevel(logging.INFO)
129
130        cache_time = config.cache_time
131    else:
132        cache_time = randint(52, 65) * 60
133        if args["verbose"]:
134            logger.setLevel(logging.INFO)
135
136        logging.info("Forced to ignore config file")
137
138    logging.info(args)
139    logging.info("Cache Time: %d min", cache_time // 60)
140
141    release = args["release"][0]
142    name = args["name"][0] if args["name"] else None
143    more_info = args["moreinfo"]
144
145    try:
146        limit = int(args["limit"][0])
147    except ValueError:
148        print(colored("You must enter an integer value.", "red"))
149        sys.exit(1)
150
151    cache_file = f"{name}_{release}.json"
152    url = select_url(name, release.lower())
153
154    try:
155        file_reader = JSONFileReader(cache_file, "updates")
156
157        if args["force"]:
158            logging.info("Forced to update the cache")
159
160        if args["force"] or (file_reader.relative_time() > cache_time):
161            logging.info("File cache is outdated")
162
163            print(colored("Getting list of updates...", "green"))
164            url_reader = URLReader(url)
165            url_reader.save_as_file(cache_file)
166
167    except FileNotFoundException:
168        print(colored("Getting list of updates...", "green"))
169
170        url_reader = URLReader(url)
171        url_reader.save_as_file(cache_file)
172        file_reader = JSONFileReader(cache_file, "updates")
173
174    finally:
175        updates = file_reader.read(limit)
176
177        if not updates:
178            print(colored("No Updates Found. Check your arguments.", "red"))
179            sys.exit(0)
180
181        print("------------------------------")
182        for update in updates:
183            print_update_info(update, more_info=more_info)

Search Package from cached file or given JSON url.

If --force argument is specified, url will be used for searching irrespective of whether cached expired or not. After requesting the url, the program stores the JSON response in a file named as "name_release.json"; that has searched packages of corresponding release. In case if --name argument is not specified, the file will be named as "None_release.json".

If --noconfig argument is specified, config will be ignored and values of cache_time and verbose will be set to default values.

Arguments:
  • args (dict): Command-Line arguments in the form of dictionary.
def cli():
186def cli():
187    """Command Line Interface of Program.
188
189    The CLI takes arguments from terminal ,parses it using ArgumentParser,
190    converts arguments into form of dictionary, and calls the search_pkg
191    function.
192    """
193    parser = argparse.ArgumentParser(
194        prog="gpkgstatus",
195        description="Get Current Package Status from Fedora Updates System",
196    )
197
198    parser.add_argument(
199        "-f",
200        "--force",
201        help="Sync cached info with Fedora Updates System",
202        action="store_true",
203    )
204
205    # limit = 5 (default)
206    parser.add_argument(
207        "-l",
208        "--limit",
209        help="Maximum limit on number of packages shown for package search",
210        default="5",
211        nargs=1,
212    )
213    parser.add_argument(
214        "--moreinfo",
215        help="Verbose (More Info) in Update Info",
216        action="store_true",
217    )
218    parser.add_argument(
219        "-n",
220        "--name",
221        help="Name of the package",
222        nargs=1,
223    )
224    parser.add_argument(
225        "--noconfig",
226        help="Do not check for config file",
227        action="store_true",
228    )
229    parser.add_argument(
230        "-r",
231        "--release",
232        help="Checks package status for corresponding Fedora release",
233        default="f",
234        nargs=1,
235    )
236    parser.add_argument(
237        "-v",
238        "--verbose",
239        help="Enable verbose output",
240        action="store_true",
241    )
242    parser.add_argument(
243        "--version",
244        help="gpkgstatus version",
245        action="version",
246        version=__version__,
247    )
248    args = parser.parse_args()
249
250    search_pkg(vars(args))

Command Line Interface of Program.

The CLI takes arguments from terminal ,parses it using ArgumentParser, converts arguments into form of dictionary, and calls the search_pkg function.