diff options
author | Matěj Cepl <mcepl@cepl.eu> | 2019-02-15 19:12:43 +0100 |
---|---|---|
committer | Matěj Cepl <mcepl@cepl.eu> | 2019-02-15 19:36:42 +0100 |
commit | ad1682ef2b087f8554af15937e35b516694eba13 (patch) | |
tree | 2c0e5e17ab382fcd4e84f59f44edce702eff5605 | |
parent | ee7d21fc755ab6a084312a656788441ea04dfb81 (diff) | |
download | dlp_check_version_PyPI-ad1682ef2b087f8554af15937e35b516694eba13.tar.gz |
First try of SQLite
-rw-r--r-- | .gitignore | 2 | ||||
-rwxr-xr-x | dlpcvp.py | 94 |
2 files changed, 79 insertions, 17 deletions
@@ -1,2 +1,4 @@ __pycache__/ *.log +dlpcvp-log*.txt +*.db @@ -7,10 +7,11 @@ import json import logging import os import os.path -# import sqlite3 +import sqlite3 import sys import tempfile import urllib.request +from distutils.version import LooseVersion from urllib.error import HTTPError from urllib.request import Request, urlopen from typing import Iterable, Optional, Tuple @@ -30,7 +31,7 @@ config = configparser.ConfigParser() config.read(ConfigRC) logging.basicConfig(format='%(levelname)s:%(funcName)s:%(message)s', - level=logging.DEBUG) + stream=sys.stdout, level=logging.DEBUG) log = logging.getLogger() # or HTTPPasswordMgrWithPriorAuth ? @@ -43,6 +44,15 @@ handler = urllib.request.HTTPBasicAuthHandler(password_mgr) opener = urllib.request.build_opener(handler) urllib.request.install_opener(opener) +TB_EXISTS = """SELECT name FROM sqlite_master + WHERE type='table' AND name='etags' + """ +TB_CREATE = """CREATE TABLE etags + (pkg text NOT NULL, + suse_name_etag text, suse_spec_etag text, pypi_etag text) + """ +TB_CREATE_IDX = "CREATE UNIQUE INDEX etags_names ON etags(pkg)" + def get_version_from_pypi(name: str, etag: str = None) -> Tuple[str, str, str]: """ @@ -61,6 +71,7 @@ def get_version_from_pypi(name: str, etag: str = None) -> Tuple[str, str, str]: except HTTPError as ex: if ex.getcode() == 404: log.error(f'Cannot find {name} on PyPI') + return None else: raise @@ -87,7 +98,7 @@ def suse_packages(proj: str) -> Iterable[str]: raise -def parse_spec_in_dev_null(spec, pkg, e_fn, e_spcf): +def parse_spec_in_dev_null(spec_file, pkg, e_fn, e_spcf): # rpm library generates awful lot of nonsensical goo on # stderr with open(os.devnull, 'wb') as nullf: @@ -96,12 +107,12 @@ def parse_spec_in_dev_null(spec, pkg, e_fn, e_spcf): sys.stderr = nullf sys.stdout = nullf try: - spc = rpm.spec(spec) + spc = rpm.spec(spec_file) except Exception: log.error("Cannot parse {}".format(pkg)) else: try: - return spc.packages[0].header['Version'].decode(), \ + return pkg, spc.packages[0].header['Version'].decode(), \ e_fn, e_spcf except IndexError: pass @@ -110,6 +121,27 @@ def parse_spec_in_dev_null(spec, pkg, e_fn, e_spcf): sys.stdout = old_stdout +def get_etags(con, pkg): + cur = con.execute("SELECT * FROM etags WHERE pkg=?", (pkg,)) + ret = cur.fetchone() + if ret is None: + return None, None, None, None + else: + return ret + + +def update_etags(con, pkg, e_suse_name, e_suse_spec, e_pypi): + if con.execute("SELECT * FROM etags WHERE pkg=?", (pkg,)).fetchone(): + con.execute('''UPDATE etags + SET suse_name_etag=?, suse_spec_etag=?, pypi_etag=? + WHERE pkg=?''', (e_suse_name, e_suse_spec, e_pypi, pkg)) + else: + con.execute('''INSERT INTO etags + (pkg, suse_name_etag, suse_spec_etag, pypi_etag) + VALUES (?, ?, ?, ?)''', (pkg, e_suse_name, e_suse_spec, e_pypi)) + con.commit() + + def package_version(proj: str, pkg_name: str, etag_fn: str = None, etag_spcf: str = None) \ -> Optional[Tuple[str, str, str]]: @@ -136,6 +168,7 @@ def package_version(proj: str, pkg_name: str, except HTTPError as ex: if ex.getcode() == 404: log.error(f'Cannot accquire version of {pkg_name} in {proj}') + return else: raise @@ -174,18 +207,45 @@ def package_version(proj: str, pkg_name: str, def main(prj): - for pkg in suse_packages(prj): - log.debug(f'pkg = {pkg}') - if pkg.startswith('python-'): - pypi_name = pkg[CUTCHARS:] - pypi_ver = get_version_from_pypi(pypi_name) - suse_ver = package_version(prj, pkg) - # FIXME We should somehow react to the situation, not just - # ignore it. - if suse_ver is not None: - print(f"{pkg} {suse_ver} {pypi_ver}") - else: - print(f'Is {pkg} on PyPI?') + db_name = os.path.split(os.path.basename(sys.argv[0]))[0] + ".db" + with sqlite3.connect(db_name) as conn: + if not conn.execute(TB_EXISTS).fetchone(): + conn.execute(TB_CREATE) + conn.execute(TB_CREATE_IDX) + + for pkg in suse_packages(prj): + log.debug(f'pkg = {pkg}') + if pkg.startswith('python-'): + pypi_name = pkg[CUTCHARS:] + _, et_suse_name, et_suse_spec, et_pypi = get_etags(conn, pkg) + + try: + suse_ver_tup = package_version(prj, pkg, + et_suse_name, et_suse_spec) + if suse_ver_tup is None: + raise RuntimeError('not in OBS') + + pypi_ver_tup = get_version_from_pypi(pypi_name, et_pypi) + if pypi_ver_tup is None: + raise RuntimeError('not in PyPI') + + update_etags(conn, pkg, + suse_ver_tup[1], suse_ver_tup[2], + pypi_ver_tup[2]) + except RuntimeError as ex: + log.warning(f'Package {pkg} cannot be found: {ex}') + continue + + log.debug(f"{pkg} {suse_ver_tup} {pypi_ver_tup}") + + pypi_ver = LooseVersion(pypi_ver_tup[1]) + suse_ver = LooseVersion(suse_ver_tup[1]) + + if pypi_ver > suse_ver: + print( + f'We need to upgrade {pkg} ({suse_ver} -> {pypi_ver})') + else: + print(f'Is {pkg} on PyPI?') if __name__ == '__main__': |