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