Fix detached instance error in game support

This commit is contained in:
rubenwardy 2022-06-25 02:39:36 +01:00
parent d9e65f7c3a
commit 4a82172e07
3 changed files with 24 additions and 50 deletions

@ -653,14 +653,15 @@ def game_support(package):
form.unsupported.data = ", ".join([x.game.name for x in manual_supported_games if not x.supports]) form.unsupported.data = ", ".join([x.game.name for x in manual_supported_games if not x.supports])
if form and form.validate_on_submit(): if form and form.validate_on_submit():
resolver = GameSupportResolver(db.session) if current_user not in package.maintainers:
resolver = GameSupportResolver(db.session)
game_is_supported = {} game_is_supported = {}
for game in get_games_from_csv(db.session, form.supported.data or ""): for game in get_games_from_csv(db.session, form.supported.data or ""):
game_is_supported[game.id] = True game_is_supported[game.id] = True
for game in get_games_from_csv(db.session, form.unsupported.data or ""): for game in get_games_from_csv(db.session, form.unsupported.data or ""):
game_is_supported[game.id] = False game_is_supported[game.id] = False
resolver.set_supported(package, game_is_supported, 8) resolver.set_supported(package, game_is_supported, 8)
next_url = package.getURL("packages.game_support") next_url = package.getURL("packages.game_support")

@ -55,44 +55,17 @@ mtg_mod_blacklist = {
} }
class PackageSet:
packages: Dict[str, Package]
def __init__(self, packages: Optional[Iterable[Package]] = None):
self.packages = {}
if packages:
self.update(packages)
def update(self, packages: Iterable[Package]):
for package in packages:
key = package.getId()
if key not in self.packages:
self.packages[key] = package
def intersection_update(self, other):
keys = set(self.packages.keys())
keys.difference_update(set(other.packages.keys()))
for key in keys:
del self.packages[key]
def __len__(self):
return len(self.packages)
def __iter__(self):
return self.packages.values().__iter__()
class GameSupportResolver: class GameSupportResolver:
session: sqlalchemy.orm.Session session: sqlalchemy.orm.Session
checked_packages = set() checked_packages = set()
checked_metapackages = set() checked_metapackages = set()
resolved_packages: Dict[str, PackageSet] = {} resolved_packages: Dict[int, set[int]] = {}
resolved_metapackages: Dict[str, PackageSet] = {} resolved_metapackages: Dict[int, set[int]] = {}
def __init__(self, session): def __init__(self, session):
self.session = session self.session = session
def resolve_for_meta_package(self, meta: MetaPackage, history: List[str]) -> PackageSet: def resolve_for_meta_package(self, meta: MetaPackage, history: List[str]) -> set[int]:
print(f"Resolving for {meta.name}", file=sys.stderr) print(f"Resolving for {meta.name}", file=sys.stderr)
key = meta.name key = meta.name
@ -101,11 +74,11 @@ class GameSupportResolver:
if key in self.checked_metapackages: if key in self.checked_metapackages:
print(f"Error, cycle found: {','.join(history)}", file=sys.stderr) print(f"Error, cycle found: {','.join(history)}", file=sys.stderr)
return PackageSet() return set()
self.checked_metapackages.add(key) self.checked_metapackages.add(key)
retval = PackageSet() retval = set()
for package in meta.packages: for package in meta.packages:
if package.state != PackageState.APPROVED: if package.state != PackageState.APPROVED:
@ -116,7 +89,7 @@ class GameSupportResolver:
ret = self.resolve(package, history) ret = self.resolve(package, history)
if len(ret) == 0: if len(ret) == 0:
retval = PackageSet() retval = set()
break break
retval.update(ret) retval.update(ret)
@ -124,29 +97,29 @@ class GameSupportResolver:
self.resolved_metapackages[key] = retval self.resolved_metapackages[key] = retval
return retval return retval
def resolve(self, package: Package, history: List[str]) -> PackageSet: def resolve(self, package: Package, history: List[str]) -> set[int]:
key = package.getId() key = package.id
print(f"Resolving for {key}", file=sys.stderr) print(f"Resolving for {key}", file=sys.stderr)
history = history.copy() history = history.copy()
history.append(key) history.append(key)
if package.type == PackageType.GAME: if package.type == PackageType.GAME:
return PackageSet([package]) return {package.id}
if key in self.resolved_packages: if key in self.resolved_packages:
return self.resolved_packages.get(key) return self.resolved_packages.get(key)
if key in self.checked_packages: if key in self.checked_packages:
print(f"Error, cycle found: {','.join(history)}", file=sys.stderr) print(f"Error, cycle found: {','.join(history)}", file=sys.stderr)
return PackageSet() return set()
self.checked_packages.add(key) self.checked_packages.add(key)
if package.type != PackageType.MOD: if package.type != PackageType.MOD:
raise LogicError(500, "Got non-mod") raise LogicError(500, "Got non-mod")
retval = PackageSet() retval = set()
for dep in package.dependencies.filter_by(optional=False).all(): for dep in package.dependencies.filter_by(optional=False).all():
ret = self.resolve_for_meta_package(dep.meta_package, history) ret = self.resolve_for_meta_package(dep.meta_package, history)
@ -165,7 +138,8 @@ class GameSupportResolver:
def update_all(self) -> None: def update_all(self) -> None:
for package in self.session.query(Package).filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all(): for package in self.session.query(Package).filter(Package.type == PackageType.MOD, Package.state != PackageState.DELETED).all():
retval = self.resolve(package, []) retval = self.resolve(package, [])
for game in retval: for game_id in retval:
game = self.session.query(Package).get(game_id)
support = PackageGameSupport(package, game, 1, True) support = PackageGameSupport(package, game, 1, True)
self.session.add(support) self.session.add(support)
@ -197,7 +171,7 @@ class GameSupportResolver:
game_is_supported = {} game_is_supported = {}
if package.enable_game_support_detection: if package.enable_game_support_detection:
retval = self.resolve(package, []) retval = self.resolve(package, [])
for game in retval: for game_id in retval:
game_is_supported[game.id] = True game_is_supported[game_id] = True
self.set_supported(package, game_is_supported, 1) self.set_supported(package, game_is_supported, 1)

@ -76,7 +76,6 @@ def getMeta(urlstr, author):
return result return result
@celery.task()
def releaseUpdateGameSupport(package_id: int, supported_games, unsupported_games): def releaseUpdateGameSupport(package_id: int, supported_games, unsupported_games):
with db.create_session({})() as session: with db.create_session({})() as session:
package = session.query(Package).get(package_id) package = session.query(Package).get(package_id)
@ -155,7 +154,7 @@ def postReleaseCheckUpdate(self, release: PackageRelease, path):
# Update game support # Update game support
if package.type == PackageType.MOD: if package.type == PackageType.MOD:
releaseUpdateGameSupport.delay(package.id, tree.meta.get("supported_games"), tree.meta.get("unsupported_games")) releaseUpdateGameSupport(package.id, tree.meta.get("supported_games"), tree.meta.get("unsupported_games"))
return tree return tree