Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Python 3 Upgrade (minimal) #577

Merged
merged 23 commits into from
Oct 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
9979bc6
feat: initial py2 to 3 work
JacobCoffee Jul 22, 2024
bc58d1c
feat: upgrade sanitze,feedparser
JacobCoffee Jul 22, 2024
7d43518
style(optional): apply basic ruff linting and formatting
JacobCoffee Jul 22, 2024
46dfdf0
feat: pyupgrade against latest
JacobCoffee Jul 22, 2024
d03851f
style(optional): apply ruff against latest
JacobCoffee Jul 22, 2024
a8484cf
style(optional): apply ruff against latest
JacobCoffee Jul 22, 2024
7e5539e
feat: upgrade docker config
JacobCoffee Jul 31, 2024
d0a199e
feat: working-ish app
JacobCoffee Jul 31, 2024
ada79c1
push along
ewdurbin Aug 7, 2024
4be16d9
explicitly check for times when setting to CachedInfo
ewdurbin Aug 8, 2024
cddaff0
Drop the vendored dependencies
offbyone Oct 5, 2024
b023876
Move the top level project into the root
offbyone Oct 6, 2024
44a8595
Convert the test templates to jinja2
offbyone Oct 6, 2024
a1b9e4e
Make the test config use relative paths
offbyone Oct 6, 2024
29e2ea5
Delete replaceable dependencies
offbyone Oct 6, 2024
86e31f9
WIP: upgrade to 3 in truth
offbyone Oct 6, 2024
7419397
Convert the main templates to jinja2
offbyone Oct 6, 2024
4579636
Correctly identify cache keys from the current item
offbyone Oct 6, 2024
1241a86
Various small fixes for 2 to 3
offbyone Oct 7, 2024
aedc01f
Merge remote-tracking branch 'upstream/master' into py2-to-3
offbyone Oct 7, 2024
0998580
Actually add some minimal tests
offbyone Oct 9, 2024
89f8fc5
Update the planet-cache.py admin utility
offbyone Oct 10, 2024
aa13325
Work around a DB consistency bug on macOS
offbyone Oct 10, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
/_cache
/_output
/.venv
/data
10 changes: 5 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
FROM ubuntu:bionic
FROM ubuntu:noble

RUN apt-get update \
&& apt-get install -y --no-install-recommends \
python-pip python-setuptools python-wheel \
python3-pip python3-setuptools python3-wheel \
locales tzdata \
ca-certificates \
strace gdb lsof locate net-tools htop iputils-ping dnsutils \
python2.7-dbg python2.7 libpython2.7 python-dbg libpython-dbg \
python3-dbg libpython3-dbg \
curl nano vim tree less telnet patch \
graphviz sqlite3 \
dumb-init \
Expand All @@ -25,9 +25,9 @@ WORKDIR /planet
ENTRYPOINT ["dumb-init"]

RUN echo "#!/bin/bash -eux \n\
python2.7 code/planet.py config/config.ini \n\
python3.12 code/planet.py config/config.ini \n\
cd /srv/planetpython.org/ \n\
python2.7 -mSimpleHTTPServer 8080 \n\
python3.12 -m http.server 8080 \n\
"> /start.sh
RUN chmod +x /start.sh
EXPOSE 8080
Expand Down
Empty file added README.md
Empty file.
268 changes: 151 additions & 117 deletions code/planet-cache.py
Original file line number Diff line number Diff line change
@@ -1,194 +1,228 @@
#!/usr/bin/env python
# -*- coding: UTF-8 -*-
"""Planet cache tool.
#!/usr/bin/env python3
"""Planet cache tool."""

"""

__authors__ = [ "Scott James Remnant <[email protected]>",
"Jeff Waugh <[email protected]>" ]
__authors__ = [
"Scott James Remnant <[email protected]>",
"Jeff Waugh <[email protected]>",
]
__license__ = "Python"


import argparse
import configparser
import os
import shelve
import sys
import time
import dbhash
import ConfigParser

import planet


def usage():
print "Usage: planet-cache [options] CACHEFILE [ITEMID]..."
print
print "Examine and modify information in the Planet cache."
print
print "Channel Commands:"
print " -C, --channel Display known information on the channel"
print " -L, --list List items in the channel"
print " -K, --keys List all keys found in channel items"
print
print "Item Commands (need ITEMID):"
print " -I, --item Display known information about the item(s)"
print " -H, --hide Mark the item(s) as hidden"
print " -U, --unhide Mark the item(s) as not hidden"
print
print "Other Options:"
print " -h, --help Display this help message and exit"
print("Usage: planet-cache [options] CACHEFILE [ITEMID]...")
print()
print("Examine and modify information in the Planet cache.")
print()
print("Channel Commands:")
print(" -C, --channel Display known information on the channel")
print(" -L, --list List items in the channel")
print(" -K, --keys List all keys found in channel items")
print()
print("Item Commands (need ITEMID):")
print(" -I, --item Display known information about the item(s)")
print(" -H, --hide Mark the item(s) as hidden")
print(" -U, --unhide Mark the item(s) as not hidden")
print()
print("Other Options:")
print(" -h, --help Display this help message and exit")
sys.exit(0)


def usage_error(msg, *args):
print >>sys.stderr, msg, " ".join(args)
print >>sys.stderr, "Perhaps you need --help ?"
print(msg, " ".join(args), file=sys.stderr)
print("Perhaps you need --help ?", file=sys.stderr)
sys.exit(1)


def print_keys(item, title):
keys = item.keys()
keys.sort()
key_len = max([ len(k) for k in keys ])
key_len = max([len(k) for k in sorted(keys)])

print title + ":"
for key in keys:
print(title + ":")
for key in sorted(keys):
if item.key_type(key) == item.DATE:
value = time.strftime(planet.TIMEFMT_ISO, item[key])
else:
value = str(item[key])
print " %-*s %s" % (key_len, key, fit_str(value, 74 - key_len))
print(" %-*s %s" % (key_len, key, fit_str(value, 74 - key_len)))


def fit_str(string, length):
if len(string) <= length:
return string
else:
return string[:length-4] + " ..."
return string[: length - 4] + " ..."


if __name__ == "__main__":
cache_file = None
want_ids = 0
ids = []

command = None

for arg in sys.argv[1:]:
if arg == "-h" or arg == "--help":
usage()
elif arg == "-C" or arg == "--channel":
if command is not None:
usage_error("Only one command option may be supplied")
command = "channel"
elif arg == "-L" or arg == "--list":
if command is not None:
usage_error("Only one command option may be supplied")
command = "list"
elif arg == "-K" or arg == "--keys":
if command is not None:
usage_error("Only one command option may be supplied")
command = "keys"
elif arg == "-I" or arg == "--item":
if command is not None:
usage_error("Only one command option may be supplied")
command = "item"
want_ids = 1
elif arg == "-H" or arg == "--hide":
if command is not None:
usage_error("Only one command option may be supplied")
command = "hide"
want_ids = 1
elif arg == "-U" or arg == "--unhide":
if command is not None:
usage_error("Only one command option may be supplied")
command = "unhide"
want_ids = 1
elif arg.startswith("-"):
usage_error("Unknown option:", arg)
else:
if cache_file is None:
cache_file = arg
elif want_ids:
ids.append(arg)
else:
usage_error("Unexpected extra argument:", arg)

if cache_file is None:
parser = argparse.ArgumentParser(
description="Examine and modify information in the Planet cache."
)
parser.add_argument(
"-C",
"--channel",
action="store_const",
const="channel",
dest="command",
help="Display known information on the channel",
)
parser.add_argument(
"-L",
"--list",
action="store_const",
const="list",
dest="command",
help="List items in the channel",
)
parser.add_argument(
"-K",
"--keys",
action="store_const",
const="keys",
dest="command",
help="List all keys found in channel items",
)
parser.add_argument(
"-I",
"--item",
action="store_const",
const="item",
dest="command",
help="Display known information about the item(s)",
)
parser.add_argument(
"-H",
"--hide",
action="store_const",
const="hide",
dest="command",
help="Mark the item(s) as hidden",
)
parser.add_argument(
"-U",
"--unhide",
action="store_const",
const="unhide",
dest="command",
help="Mark the item(s) as not hidden",
)
parser.add_argument("cache_file", help="Cache file to operate on")
parser.add_argument(
"item_ids",
nargs="*",
help="Item IDs to operate on when using item-related commands",
)

args = parser.parse_args()

# Check if more than one command option was supplied
if "command" not in args or args.command is None:
usage_error("One command option must be supplied.")
elif (
len(
{
key
for key, value in vars(args).items()
if key == "command" and value is not None
}
)
> 1
):
usage_error("Only one command option may be supplied")

# Handle missing cache_file
if not args.cache_file:
usage_error("Missing expected cache filename")
elif want_ids and not len(ids):

# Handle commands that require item IDs
if args.command in ["item", "hide", "unhide"] and not args.item_ids:
usage_error("Missing expected entry ids")

# Open the cache file directly to get the URL it represents
try:
db = dbhash.open(cache_file)
url = db["url"]
db.close()
except dbhash.bsddb._db.DBError, e:
print >>sys.stderr, cache_file + ":", e.args[1]
sys.exit(1)
with shelve.open(args.cache_file, "r") as db:
url = db["url"]
except KeyError:
print >>sys.stderr, cache_file + ": Probably not a cache file"
print(f"{args.cache_file}: Probably not a cache file", file=sys.stderr)
sys.exit(1)
except Exception as e:
print(f"{args.cache_file}: {e!s}", file=sys.stderr)
sys.exit(1)

# Now do it the right way :-)
my_planet = planet.Planet(ConfigParser.ConfigParser())
my_planet.cache_directory = os.path.dirname(cache_file)
my_planet = planet.Planet(configparser.ConfigParser())
my_planet.cache_directory = os.path.dirname(args.cache_file)
channel = planet.Channel(my_planet, url)

for item_id in ids:
for item_id in args.item_ids:
if not channel.has_item(item_id):
print >>sys.stderr, item_id + ": Not in channel"
print(item_id + ": Not in channel", file=sys.stderr)
sys.exit(1)

# Do the user's bidding
if command == "channel":
if args.command == "channel":
print_keys(channel, "Channel Keys")

elif command == "item":
for item_id in ids:
elif args.command == "item":
for item_id in args.item_ids:
item = channel.get_item(item_id)
print_keys(item, "Item Keys for %s" % item_id)

elif command == "list":
print "Items in Channel:"
for item in channel.items(hidden=1, sorted=1):
print " " + item.id
print " " + time.strftime(planet.TIMEFMT_ISO, item.date)
elif args.command == "list":
print("Items in Channel:")
for item in channel.items(hidden=True, sorted=True):
print(" " + item.id)
print(" " + time.strftime(planet.TIMEFMT_ISO, item.date))
if hasattr(item, "title"):
print " " + fit_str(item.title, 70)
print(" " + fit_str(item.title, 70))
if hasattr(item, "hidden"):
print " (hidden)"
print(" (hidden)")

elif command == "keys":
elif args.command == "keys":
keys = {}
for item in channel.items():
for key in item.keys():
for key in item:
keys[key] = 1

keys = keys.keys()
keys.sort()
keys = sorted(keys.keys())

print "Keys used in Channel:"
print("Keys used in Channel:")
for key in keys:
print " " + key
print
print(" " + key)
print()

print "Use --item to output values of particular items."
print("Use --item to output values of particular items.")

elif command == "hide":
for item_id in ids:
elif args.command == "hide":
for item_id in args.item_ids:
item = channel.get_item(item_id)
if hasattr(item, "hidden"):
print item_id + ": Already hidden."
print(item_id + ": Already hidden.")
else:
item.hidden = "yes"

channel.cache_write()
print "Done."
print("Done.")

elif command == "unhide":
for item_id in ids:
elif args.command == "unhide":
for item_id in args.item_ids:
item = channel.get_item(item_id)
if hasattr(item, "hidden"):
del(item.hidden)
del item.hidden
else:
print item_id + ": Not hidden."
print(item_id + ": Not hidden.")

channel.cache_write()
print "Done."
print("Done.")
Loading