Secure your code as it's written. Use Snyk Code to scan source code in minutes - no build needed - and fix issues immediately.
Defn('curse', 'mythic-dungeon-tools', strategy),
Defn('curse', 'classiccastbars', strategy),
Defn('curse', 'elkbuffbars', strategy),
]
)
separate, retail_only, classic_only, flavour_explosion = results.values()
assert isinstance(separate, Pkg)
if manager.config.is_classic:
if strategy is Strategies.any_flavour:
assert 'classic' not in separate.version
assert isinstance(retail_only, Pkg)
else:
assert 'classic' in separate.version
assert (
isinstance(retail_only, E.PkgFileUnavailable)
and retail_only.message
== f"no files compatible with classic using '{strategy.name}' strategy"
)
assert isinstance(classic_only, Pkg)
else:
assert 'classic' not in separate.version
assert isinstance(retail_only, Pkg)
if strategy is Strategies.any_flavour:
assert isinstance(classic_only, Pkg)
else:
assert (
isinstance(classic_only, E.PkgFileUnavailable)
and classic_only.message
== f"no files compatible with retail using '{strategy.name}' strategy"
)
else:
assert 'classic' in separate.version
assert (
isinstance(retail_only, E.PkgFileUnavailable)
and retail_only.message
== f"no files compatible with classic using '{strategy.name}' strategy"
)
assert isinstance(classic_only, Pkg)
else:
assert 'classic' not in separate.version
assert isinstance(retail_only, Pkg)
if strategy is Strategies.any_flavour:
assert isinstance(classic_only, Pkg)
else:
assert (
isinstance(classic_only, E.PkgFileUnavailable)
and classic_only.message
== f"no files compatible with retail using '{strategy.name}' strategy"
)
versions = {*request.config.cache.get('flavour_explosion', ()), flavour_explosion.version}
assert len(versions) == 1
request.config.cache.set('flavour_explosion', tuple(versions))
def rollback(ctx: click.Context, addon: Defn, undo: bool):
"Roll an add-on back to an older version."
from .prompts import Choice, select
manager: CliManager = ctx.obj.m
limit = 10
pkg = manager.get_pkg(addon)
if not pkg:
Report([(addon, E.PkgNotInstalled())]).generate_and_exit()
return # noop
resolver = manager.resolvers[pkg.source]
if not resolver.supports_rollback:
Report(
[(addon, E.PkgFileUnavailable('source does not support rollback'))]
).generate_and_exit()
if undo:
Report(
chain(
manager.run(manager.remove([addon])).items(),
manager.run(manager.install([addon], replace=False)).items(),
)
).generate_and_exit()
versions: List[models.PkgVersionLog] = (
manager.db_session.query(models.PkgVersionLog)
.filter(
models.PkgVersionLog.pkg_source == pkg.source, models.PkgVersionLog.pkg_id == pkg.id
)
.order_by(models.PkgVersionLog.install_time.desc())
manager.run(manager.remove([addon])).items(),
manager.run(manager.install([addon], replace=False)).items(),
)
).generate_and_exit()
versions: List[models.PkgVersionLog] = (
manager.db_session.query(models.PkgVersionLog)
.filter(
models.PkgVersionLog.pkg_source == pkg.source, models.PkgVersionLog.pkg_id == pkg.id
)
.order_by(models.PkgVersionLog.install_time.desc())
.limit(limit)
.all()
)
if len(versions) <= 1:
Report([(addon, E.PkgFileUnavailable('cannot find older versions'))]).generate_and_exit()
reconstructed_defn = Defn.from_pkg(pkg)
choices = [
Choice(
[('', v.version)], # type: ignore
disabled='installed version' if v.version == pkg.version else None,
)
for v in versions
]
selection = select(
f'Select version of {reconstructed_defn} for rollback', choices
).unsafe_ask()
Report(
chain(
manager.run(manager.remove([reconstructed_defn])).items(),
manager.run(
repo_url = self.repos_api_url / defn.name
try:
project_metadata = await cache_json_response(self.manager, repo_url, 3600)
except ClientResponseError as error:
if error.status == 404:
raise E.PkgNonexistent
raise
if defn.strategy is Strategies.version:
release_url = repo_url / 'releases/tags' / defn.strategy_vals[0]
else:
release_url = repo_url / 'releases/latest'
async with self.web_client.get(release_url) as response:
if response.status == 404:
raise E.PkgFileUnavailable('release not found')
release_metadata = await response.json()
try:
def is_valid_asset(asset: JsonDict):
return (
# There is something of a convention that Classic archives
# end in '-classic' and lib-less archives end in '-nolib'.
# Archives produced by packager follow this convention
not asset['name'].endswith(('-nolib.zip', '-nolib-classic.zip'))
and asset['content_type']
in {'application/zip', 'application/x-zip-compressed'}
# A failed upload has a state value of 'starter'
and asset['state'] == 'uploaded'
)
def is_of_specified_quality(f: JsonDict):
return f['releaseType'] == 3
else:
def is_of_specified_quality(f: JsonDict):
return f['releaseType'] == 1
def is_compatible(f: JsonDict):
return (
is_not_libless(f) and supports_game_version(f) and is_of_specified_quality(f)
)
if not files:
raise E.PkgFileUnavailable('no files available for download')
try:
file = max(
filter(is_compatible, files),
# The ``id`` is just a counter so we don't have to go digging around dates
key=lambda f: f['id'],
)
except ValueError:
raise E.PkgFileUnavailable(
f'no files compatible with {self.config.game_flavour} '
f'using {defn.strategy.name!r} strategy'
)
# 1 = embedded library
# 2 = optional dependency
# 3 = required dependency
# 4 = tool
async def resolve_one(self, defn: Defn, metadata: Any = None) -> m.Pkg:
try:
id_, slug = next(p for p in self._addons if defn.name in p)
except StopIteration:
raise E.PkgNonexistent
from .wa_updater import BuilderConfig, WaCompanionBuilder
sentinel = '__sentinel__'
builder = WaCompanionBuilder(self.manager, BuilderConfig(account=sentinel))
if id_ == '1':
if builder.builder_config.account == sentinel:
raise E.PkgFileUnavailable('account name not provided')
await builder.build()
checksum = await t(builder.checksum)()
return m.Pkg(
source=self.source,
id=id_,
slug=slug,
name='WeakAuras Companion',
description='A WeakAuras Companion clone.',
url='https://github.com/layday/instawow',
download_url=builder.addon_file.as_uri(),
date_published=datetime.now(),
version=checksum[:7],
options=m.PkgOptions(strategy=defn.strategy.name),
)