Anki 2.1.28 Beta

Did the requirements on how to expose resources on the internal server change? Because scripts, css files and the like, registered with setWebExports, do not work anymore with beta2.
A look at the console shows the following for all resources:
Failed to load resource: the server responded with a status of 500 (INTERNAL SERVER ERROR)

Not intentionally. Can you suggest an add-on to use to easily reproduce this?

@addons_zz ping

1 Like this one uses a lot of css and js files, it works on beta1.
Edit: But I could possibly spin up a more isolated example.

the card cound chart doesn’t seem to be accurate (new and young have the same length on the chart while young cards are 800 and new are 300)

and as @addons_zz said, it would be nice to have some kind of background for the charts.
when there is data, they look good even without background, but when there’s no data the numbers on the sides look kinda bad. (some background with high transparency that just makes the chart area stand out a bit is what i’m thinking would look good)

and i think the placement for the scope/time selector were better on old stats.

the chart sizes are really good now, and it’s cool that now “Ctrl+scroll” scales up/down the charts too.

I noticed that revlog rows in card info (ctrl+shift+I) are now descending order i.e. from the first to the most recent review. Perhaps the 1st beta was doing the same, I did not noticed it.

Graph bars are now always the same size but fall partly outside of the cards added graph. I cropped at the start and at the end.

b1 b2

1 Like

Here is a pretty minimal example, when using this, and then opening e.g. the Add Cards dialog, the abovementioned error appears in the web inspector. The URL that is built seems to be correct though.

from aqt import mw
import aqt

# assuming add-on folder is named "test"
# and assuming a 'test.js' is in the same folder
addon_id = "test"
port = mw.mediaServer.getPort()
mw.addonManager.setWebExports(addon_id, ".*\\.js$")

aqt.editor._html += f"""
        var script = document.createElement('script');
        script.type = 'text/javascript';
        script.src = '{port}/_addons/{addon_id}/test.js';

1 Like

Thanks for the minimal example. It was very helpful allowing to fix this quite fast. I fixed this and submitted a pull-request fixing it: Fix _addons/ URL prefix not being removed on Windows systems

The error on the server was an extra _addons being appended to the path:

Caught HTTP server exception,
Traceback (most recent call last):
  File "F:\anki\qt\aqt\", line 145, in allroutes
    return flask.send_file(fullpath, mimetype=mimetype, conditional=True)
  File "F:\anki\pyenv\lib\site-packages\flask\", line 629, in send_file
    file = open(filename, "rb")
FileNotFoundError: [Errno 2] No such file or directory: 'D:\\User\\Documents\\Anki2\\addons21\\_addons\\someaddon\\test.js'

I don’t know if it is sth in my machine (Windows), but since the first beta I noticed that Alt Gr does not work (to make ª and º and ², for example). When I run the stable version (2.1.26) or any other software it works normally.

This no data thing is not much good than an empty graph:

At least remove the extra height:


Not having a limit on the graph width helps showing graphs with long periods: (highly dense data)

1 Like

Beta 3 is now available with fixes for some of the above issues.

Changing the height (or hiding the graph completely) means that the page height will change as you alter the search criteria, making it difficult to see how a graph changes, as it may jump up or down.

They’re aligned to the ticks, not the start or end of the bars, as it’s simpler to implement.

I experimented with it, but it didn’t look great. I’ve added a faint line along the axis instead in beta 3 - any better?

1 Like

I’ve added a faint line along the axis instead in beta 3 - any better?

yes, they’re awesome. :smiley:

About Reviews graph, either count or time, even thou it is already fantastic, I think it would be nice if, besides the “Running Total”, there were a Total for the period. It could be placed before the Running Total or, even better, after the period description above. Eg. “Yesterday: 200 reviews” or “0-5 Days ago: 7.1 hours”. That’s because, otherwise, you would have to sum the totals for each category to obtains this information (or just have an approximate info by looking to the graph; but as there is the precise info for each category, it would make sense to have the precise info of the total of the day/period).

And as far as I can see, Alt Gr is still not working in beta 3.


The Reviews graph does not show today’s value (only up to yesterday):

1 Like

@addons_zz @dae Thanks for fixing the media server issue that fast!

1 Like

The manual, in the section “Searching -> Card State”, says:

is:learn is:review
cards that have lapsed and are awaiting relearning

-is:learn is:review
review cards, not including lapsed cards

But it seems to me that “is:learn” is not matching lapsed cards anymore. The first mentioned search always results in no cards being found (even if there are lapsed cards still awaiting relearning). And the second mentioned search matches the same number of cards of the search “is: review”.

That is the case for the beta version and also for the stable version 2.1.26.

Will look into it, thanks. Re AltGR, please see above.

@addons_zz @dae:

It looks like the changes introduced in 1e6fa5 break exposing web resources in add-ons that are symlinked to the add-ons folder. This is a usage pattern that’s pretty common in testing add-ons where the current source is symlinked to the Anki test folder rather than copying the add-on over after each source change.

(Though I assume that there are other use cases for symlinks as well, e.g. advanced users that reuse the same set of add-ons among multiple Anki configurations)

It would be great if we could somehow fix this as this currently breaks all of my test configs.

I’m not super familiar with path traversal attacks, but based on the docs here, I would assume that resolving symlinks as we do here is not essential. os.path.abspath should do the job, but I might be missing something.

1 Like

I think that just replacing:

fullpath = os.path.realpath(os.path.join(directory, path))
# -->
fullpath = os.path.abspath(os.path.join(directory, path))

Should fix the problem of external symlinks as it stops resolving the path part of the resource. Then, if it is a symlink it should not be resolved and the security check should not fail.

@glutanimate, can you change the code and see if it works?


@addons_zz Yep, been using

fullpath = os.path.abspath(os.path.join(directory, path))

for my test runs today and it works perfectly. If it’s equal from a security standpoint I’d say let’s go ahead and change it.

1 Like