tsudoko / anki-sync-server Goto Github PK
View Code? Open in Web Editor NEWSelf-hosted Anki sync server
License: GNU Affero General Public License v3.0
Self-hosted Anki sync server
License: GNU Affero General Public License v3.0
Sometimes anki-server may encounter some accidental bug causing no connection, and I need to restart it, but there is no command to stop the server. So I can only kill it or reboot the Linux. Is there a python command can stop or restart the server?
I actually do want the REST api and it looks (from the name!) like you have a branch that has been updated to 2.1 (upstream doesn't appear to be, and isn't merging useful patches...), and still contains the REST api. @tsudoko can you comment on this branch? It appears to have been updated until late last year. Is it worth starting from that to get 2.1 compatibility and the REST api? Thanks!
Hello! I am a beginner, but I would like to setup Anki Server. Is it possible to set up an Anki like website? And will the addons be still available from the main source at the Anki webpage? thank you! andreas
ankidroid is no problem when upload or down load from anki-sync-server. but when i want to uplaod or download data from anki-sync-server, then windows anki always pop up the tooltip 'the password is not correct'. I have no idea about this.
it is more instresting that , if the acount is registed on the anki web, there are no problem to sync data. but the data was backup on the anki web, even though you have created the same acount by the command './ankisyncctl.py username'.
however, if the acount is build by command './ankisyncctl.py adduser username' and is not registed on the anki web, when you sync data , it will pop up the tooltip 'the password is not correct'. I am sure the password is correct, if not i can't sync data for ankidroid.
please give me a hand, thank you. @tsudoko .
Split from #27:
the first issue is about the account. If I delete the user in server without deauthorizing the account in the client, the client will still be able to use this deleted account to sync.
I followed the instruction of this bolg, and install all the dependencies, But still come out of this error when I want to create a new user. How can I fix this?
sudo python3 ./ankisyncctl.py adduser test
Enter password for test:
Traceback (most recent call last):
File "./ankisyncctl.py", line 82, in <module>
main()
File "./ankisyncctl.py", line 74, in main
cmds[c](arg)
File "./ankisyncctl.py", line 25, in adduser
user_manager.add_user(username, password)
File "/home/junyu/anki-sync-server/ankisyncd/users.py", line 108, in add_user
self._add_user_to_auth_db(username, password)
File "/home/junyu/anki-sync-server/ankisyncd/users.py", line 125, in _add_user_to_auth_db
(username, pass_hash))
sqlite3.OperationalError: no such table: auth
I'm back again :-). Thanks again for your amazing work on keeping things compatible with the clients! The nasty hacks I talked about in #7 for exposing some user data in a rest-y way turned out to not even scale to one person - I need to totally hammer the API for periods - performance was slow, and the wsgiref started resetting connections after I put it in a container with even moderate load for one user.
That got me thinking - I don't really want to have the hassle of thinking about API performance when all I really want is access to the data. So I decided to implement support for Postgres, meaning the endpoints where performance is critical I can just access the data directly, and all the rest can stay the same.
You mentioned you would be happy to look at some reorganisation PRs to make that easier. What would you say to moving out the SessionManagers (like the UserManagers) into separate modules, adding a PersistenceManager (for managing sqlite3 upload/download) and the creating factory methods for each that will mirror the same behaviour as now but also also potentially dynamically load child classes specified in the config file?
That would mean I could just plop an extra module or two in, add a few lines to the config file and it will Just Work.
If you're interested in Postgres support we could also discuss that, but I'm only half way through and there are already some pretty nasty hacks I need to do to override anki stuff so don't expect anything particularly beautiful :-).
Thanks again for your awesome work on this!
The readme.md sounds like one only needs to place the displayed __init__.py
in one folder. The code apparently has a bug anki.sync.SYNC_BASE = "%s" + addr
%s will be the string %s and not formatted.
But then why does the "anki-sync-server/addon/" folder exist? Are there supposed to be two folders? Why are they not integrated in one addon?
client version: Anki Version 2.1.12 (on Ubuntu 18.04), AnkiDroid (on the android phone)
Issue: error 404 while sync media files.
I find the HTTP request URL is a mistake for the media files sync. Such as POST /msync//begin HTTP/1.1
, there is an excrescent slash in the URL.
In ./ankisyncd/sync_app.py
, I changed the media sync URL
url = req.path[len(self.base_media_url):]
url = req.path[len(self.base_media_url):].replace('/','')
Then it worked. Should I pull request for this?
192.168.31.190 - - [16/May/2019 12:19:12] "POST /sync/sanityCheck2 HTTP/1.1" 200 16
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running finish(*[], **{})
192.168.31.190 - - [16/May/2019 12:19:12] "POST /sync/finish HTTP/1.1" 200 13
192.168.31.190 - - [16/May/2019 12:19:31] "POST /msync//begin HTTP/1.1" 404 52
INFO:root:Monitor is closing collection on inactive CollectionThread[/app/data/collections/kunlocal/collection.anki2]
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running _close(*[], **{})
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running meta(*[], **{})
192.168.31.190 - - [16/May/2019 12:46:20] "POST /sync/meta HTTP/1.1" 200 110
192.168.31.190 - - [16/May/2019 12:46:20] "POST /msync//begin HTTP/1.1" 404 52
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running meta(*[], **{})
192.168.31.190 - - [16/May/2019 12:46:22] "POST /sync/meta HTTP/1.1" 200 110
192.168.31.190 - - [16/May/2019 12:46:22] "POST /msync//begin HTTP/1.1" 404 52
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running meta(*[], **{})
192.168.31.190 - - [16/May/2019 12:46:43] "POST /sync/meta HTTP/1.1" 200 110
192.168.31.190 - - [16/May/2019 12:46:43] "POST /msync//begin HTTP/1.1" 404 52
INFO:root:Monitor is closing collection on inactive CollectionThread[/app/data/collections/kunlocal/collection.anki2]
INFO:root:CollectionThread[/app/data/collections/kunlocal/collection.anki2]: Running _close(*[], **{})
as a complete novice of Linux, really want build my own anki sync server, but just can't get a clue on building one that really works. I have searched tons of internet instructions, tried thousands of ways, spent days of hard working, still can get it done!
Would anyone bother to write an instruction for absolute dummies like me? Please!
OS: Ubuntu 16.04
when I upload data by ankidroid, then windows server throw the bellow error:
Traceback (most recent call last):
File "C:\Python37\lib\wsgiref\handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "C:\Python37\lib\site-packages\webob\dec.py", line 129, in __call__
resp = self.call_func(req, *args, **kw)
File "C:\Python37\lib\site-packages\webob\dec.py", line 193, in call_func
return self.func(req, *args, **kwargs)
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\sync_app.py", line 572, in __call__
result = thread.execute(self.operation_upload, [data['data'], session])
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\thread.py", line 79, in execute
raise ret
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\thread.py", line 98, in _run
ret = self.wrapper.execute(func, args, kw, return_queue)
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\collection.py", line 44, in execute
ret = func(*args, **kw)
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\sync_app.py", line 488, in operation_upload
return self.full_sync_manager.upload(col, data, session)
File "C:\Users\hqzxj\Documents\work\anki-sync-server\ankisyncd\full_sync.py", line 28, in upload
os.rename(temp_db_path, session.get_collection_path())
FileExistsError: [WinError 183] Cannot create a file when that file already exists: 'C:\\Users\\hqzxj\\Documents\\work\\anki-sync-server\\srv\\anki\\ankisyncd\\hqzxjczx\\collection.anki2.tmp' -> 'C:\\Users\\hqzxj\\Documents\\work\\anki-sync-server\\srv\\anki\\ankisyncd\\hqzxjczx\\collection.anki2'
ankidroid version is 2.8.4
anki-sync-server is the master version
windows anki is 2.1.11
@tsudoko
I was testing ankisyncd
against version 2.1.0 to actually use the version mentioned in README.md. Meanwhile it works fine on Android (2.9.1), on AnkiDesktop (2.1.19) I get this message on the second sync (after I have confirmed the "Download form AnkiWeb" message):
"Syncing failed:
AnkiWeb encountered an error. Please try again in a few minutes, and if the problem persists, please file a bug report."
Between the two synchronizations I reviewed exactly one card on the desktop side.
anki-sync-server_1 | [2020-02-04 17:38:52,250]:INFO:ankisyncd.http:172.20.0.1 "POST /sync/start HTTP/1.1" 500 59
anki-sync-server_1 | [2020-02-04 17:39:35,575]:INFO:ankisyncd.CollectionThread[en]:Running meta(*[], **{'v': 9, 'cv': 'ankidesktop,2.1.19 (3c8690ae),lin:arch:rolling'})
anki-sync-server_1 | [2020-02-04 17:39:35,576]:INFO:ankisyncd.http:172.20.0.1 "POST /sync/meta HTTP/1.1" 200 110
anki-sync-server_1 | [2020-02-04 17:39:35,584]:INFO:ankisyncd.CollectionThread[en]:Running start(*[], **{'minUsn': 100, 'lnewer': True, 'offset': None})
anki-sync-server_1 | [2020-02-04 17:39:35,585]:ERROR:ankisyncd.CollectionThread[en]:Unable to start(*[], **{'minUsn': 100, 'lnewer': True, 'offset': None}): start() got an unexpected keyword argument 'offset'
anki-sync-server_1 | Traceback (most recent call last):
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/thread.py", line 98, in _run
anki-sync-server_1 | ret = self.wrapper.execute(func, args, kw, return_queue)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/collection.py", line 44, in execute
anki-sync-server_1 | ret = func(*args, **kw)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/sync_app.py", line 626, in run_func
anki-sync-server_1 | res = handler_method(**keyword_args)
anki-sync-server_1 | TypeError: start() got an unexpected keyword argument 'offset'
anki-sync-server_1 | Traceback (most recent call last):
anki-sync-server_1 | File "/usr/local/lib/python3.7/wsgiref/handlers.py", line 137, in run
anki-sync-server_1 | self.result = application(self.environ, self.start_response)
anki-sync-server_1 | File "/usr/local/lib/python3.7/site-packages/webob/dec.py", line 129, in __call__
anki-sync-server_1 | resp = self.call_func(req, *args, **kw)
anki-sync-server_1 | File "/usr/local/lib/python3.7/site-packages/webob/dec.py", line 193, in call_func
anki-sync-server_1 | return self.func(req, *args, **kwargs)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/sync_app.py", line 558, in __call__
anki-sync-server_1 | result = self._execute_handler_method_in_thread(url, data, session)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/sync_app.py", line 635, in _execute_handler_method_in_thread
anki-sync-server_1 | result = thread.execute(run_func, kw=keyword_args)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/thread.py", line 79, in execute
anki-sync-server_1 | raise ret
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/thread.py", line 98, in _run
anki-sync-server_1 | ret = self.wrapper.execute(func, args, kw, return_queue)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/collection.py", line 44, in execute
anki-sync-server_1 | ret = func(*args, **kw)
anki-sync-server_1 | File "/app/anki-sync-server/ankisyncd/sync_app.py", line 626, in run_func
anki-sync-server_1 | res = handler_method(**keyword_args)
anki-sync-server_1 | TypeError: start() got an unexpected keyword argument 'offset'
anki-sync-server_1 | [2020-02-04 17:39:35,586]:INFO:ankisyncd.http:172.20.0.1 "POST /sync/start HTTP/1.1" 500 59
I am running latest anki-sync-server and latest (2.1.12) windows app.
I am not the only one encountering this issue:
dsnopek/anki-sync-server#78
Edit: I no longer get this error (see below)
Is anyone running a public intance of this?
If not, would it not be a good idea to have one, for those who do not want to spend the time setting everything up? It could be for paid accounts only, something like 1eur/month or something.
I want to sync my anki from desktop<->android but I am not comfortable using closed source software (ankiweb) nor can I setup this server..
With the latest beta (beta 26), Anki will ignore mysyncserver.py if you leave it in the addons21 folder.
https://apps.ankiweb.net/docs/addons21.html
I followed the instructions and got it working:
__init__.py
__init__.py
, enter the following lines:import anki.sync
anki.sync.SYNC_BASE = 'http://127.0.0.1:27701/'
anki.sync.SYNC_MEDIA_BASE = 'http://127.0.0.1:27701/msync/'
After doing this, I'm able to sync.
There are still some issues though. Anki wants to keep doing full syncs and oftentimes says that the database is in an inconsistent state.
C:\Python34\Scripts>python ankiserverctl.py start
Traceback (most recent call last):
File "ankiserverctl.py", line 165, in
main()
File "ankiserverctl.py", line 145, in main
startsrv(sys.argv[2], False)
File "ankiserverctl.py", line 50, in startsrv
with open(PIDPATH, "w") as pidfile:
FileNotFoundError: [Errno 2] No such file or directory: '/tmp/ankiserver.pid'
Only one client per session at a time should be able to sync. Starting a sync from multiple clients at the same time is generally a bad idea, it's not clear what state both clients will end up in after syncing.
Hi, i installed syn server and i was success to run it from console and sync with linux's and android's anki. But i want to serve it behind uWSGI (and latter via nginx due TLS), and deploy it in public net (to have more robust solution as python's simple server), but i encounter a problem, which i am not able to solve.
I prepared simple file for uWSGI (with some "debug" prints):
import os
from pathlib import Path
import sys
import uwsgi
import ankisyncd.config
from ankisyncd.sync_app import SyncApp
from ankisyncd.thread import shutdown
print(sys.path)
# Replace with your app's method of configuration
cfgfile = os.environ.get('ANKI_CONFIG', Path(__file__).parent.resolve() / "ankisyncd.conf")
print("Loading config from %s" % cfgfile)
config = ankisyncd.config.load(cfgfile)
print(config)
# uWSGI will look for this variable
print("Initialize application...")
application = SyncApp(config)
def do_shutdown():
print("Doing shutdown...")
shutdown()
# will be invoked after uWSGI reload or shutdown
uwsgi.atexit = do_shutdown
Then i run uWSGI simple instance from anksi-sync-server's directory:
uwsgi --plugin python3,http --http :27701 --master --enable-threads --wsgi-file uwsgi.py
It basically loads application
object from uwsgi.py
file, which is SyncApp()
object and serves it via HTTP. Apps starts nicely:
*** Starting uWSGI 2.0.18-debian (64bit) on [Sun May 12 09:57:31 2019] ***
compiled with version: 8.2.0 on 10 February 2019 02:42:46
os: Linux-4.19.0-4-amd64 #1 SMP Debian 4.19.28-2 (2019-03-15)
nodename: debmail
machine: x86_64
clock source: unix
pcre jit disabled
detected number of CPU cores: 1
current working directory: /home/slavko/anki-sync-server
detected binary path: /usr/bin/uwsgi-core
your processes number limit is 1818
your memory page size is 4096 bytes
detected max file descriptor number: 1024
lock engine: pthread robust mutexes
thunder lock: disabled (you can enable it with --thunder-lock)
uWSGI http bound on :27701 fd 4
uwsgi socket 0 bound to TCP address 127.0.0.1:40809 (port auto-assigned) fd 3
Python version: 3.7.3rc1 (default, Mar 13 2019, 11:01:15) [GCC 8.3.0]
Python main interpreter initialized at 0x55f67b1314d0
python threads support enabled
your server socket listen backlog is limited to 100 connections
your mercy for graceful operations on workers is 60 seconds
mapped 145840 bytes (142 KB) for 1 cores
*** Operational MODE: single process ***
['./anki-bundled', '/usr/share/anki', '.', '', '/usr/lib/python37.zip', '/usr/lib/python3.7', '/usr/lib/python3.7/lib-dynload', '/usr/local/lib/python3.7/dist-packages', '/usr/lib/python3/dist-packages']
Loading config from /home/slavko/anki-sync-server/ankisyncd.conf
<Section: sync_app>
Initialize application...
WSGI app 0 (mountpoint='') ready in 1 seconds on interpreter 0x55f67b1314d0 pid: 2748 (default app)
*** uWSGI is running in multiple interpreter mode ***
spawned uWSGI master process (pid: 2748)
spawned uWSGI worker 1 (pid: 2751, cores: 1)
spawned uWSGI http 1 (pid: 2752)
Here you can see print's output (after "Operational MODE: single process" line), that paths are added into sys.path, config is loaded, and app initialized. I am able to connect to it, then it basically works:
wget -qO- --server-response http://debmail.skk:27701/
HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Content-Length: 16
Anki Sync Server
But when i try to sync with it, i got error about missing module anki.sched
:
--- Logging error ---
Traceback (most recent call last):
File "./ankisyncd/thread.py", line 98, in _run
File "./ankisyncd/collection.py", line 42, in execute
File "./ankisyncd/collection.py", line 72, in open
File "./ankisyncd/collection.py", line 66, in _get_collection
File "./anki-bundled/anki/storage.py", line 40, in Collection
File "./anki-bundled/anki/collection.py", line 75, in __init__
File "./anki-bundled/anki/collection.py", line 100, in _loadScheduler
ModuleNotFoundError: No module named 'anki.sched'
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/usr/lib/python3.7/logging/__init__.py", line 1034, in emit
msg = self.format(record)
File "/usr/lib/python3.7/logging/__init__.py", line 880, in format
return fmt.format(record)
File "/usr/lib/python3.7/logging/__init__.py", line 619, in format
record.message = record.getMessage()
File "/usr/lib/python3.7/logging/__init__.py", line 380, in getMessage
msg = msg % self.args
TypeError: not all arguments converted during string formatting
Call stack:
File "/usr/lib/python3.7/threading.py", line 885, in _bootstrap
self._bootstrap_inner()
File "/usr/lib/python3.7/threading.py", line 917, in _bootstrap_inner
self.run()
File "/usr/lib/python3.7/threading.py", line 865, in run
self._target(*self._args, **self._kwargs)
File "./ankisyncd/thread.py", line 101, in _run
Message: 'Unable to %s(*%s, **%s): %s'
Arguments: ('/home/slavko/anki-sync-server/collections/slavko/collection.anki2', 'meta', '[]', "{'v': 9, 'cv': 'ankidesktop,2.1.8,lin:debian:buster/sid'}", ModuleNotFoundError("No module named 'anki.sched'"))
Traceback (most recent call last):
File "/usr/lib/python3/dist-packages/webob/dec.py", line 129, in __call__
resp = self.call_func(req, *args, **kw)
File "/usr/lib/python3/dist-packages/webob/dec.py", line 193, in call_func
return self.func(req, *args, **kwargs)
File "./ankisyncd/sync_app.py", line 557, in __call__
File "./ankisyncd/sync_app.py", line 634, in _execute_handler_method_in_thread
File "./ankisyncd/thread.py", line 79, in execute
File "./ankisyncd/thread.py", line 98, in _run
File "./ankisyncd/collection.py", line 42, in execute
File "./ankisyncd/collection.py", line 72, in open
File "./ankisyncd/collection.py", line 66, in _get_collection
File "./anki-bundled/anki/storage.py", line 40, in Collection
File "./anki-bundled/anki/collection.py", line 75, in __init__
File "./anki-bundled/anki/collection.py", line 100, in _loadScheduler
ModuleNotFoundError: No module named 'anki.sched'
[pid: 2751|app: 0|req: 2/2] 192.168.10.1 () {36 vars in 465 bytes} [Sun May 12 10:00:04 2019] POST /sync/meta => generated 0 bytes in 221 msecs (HTTP/1.1 500) 0 headers in 0 bytes (0 switches on core 0)
When i run the same instance directly, all works:
python3 -m ankisyncd
[2019-05-12 10:13:55,609]:INFO:ankisyncd:Loaded config from /home/slavko/anki-sync-server/ankisyncd.conf
[2019-05-12 10:13:55,610]:INFO:ankisyncd.users:Found auth_db_path in config, using SqliteUserManager for auth
[2019-05-12 10:13:55,611]:INFO:ankisyncd.sessions:Found session_db_path in config, using SqliteSessionManager for auth
[2019-05-12 10:13:55,612]:INFO:ankisyncd:Serving HTTP on 0.0.0.0 port 27701...
[2019-05-12 10:14:01,516]:INFO:ankisyncd.CollectionThread[slavko]:Starting...
[2019-05-12 10:14:01,517]:INFO:ankisyncd.CollectionThread[slavko]:Running meta(*[], **{'v': 9, 'cv': 'ankidesktop,2.1.8,lin:debian:buster/sid'})
[2019-05-12 10:14:01,524]:INFO:ankisyncd.http:192.168.10.1 "POST /sync/meta HTTP/1.1" 200 108
[2019-05-12 10:14:41,099]:INFO:ankisyncd.CollectionThread[slavko]:Running meta(*[], **{'v': 9, 'cv': 'ankidesktop,2.1.8,lin:debian:buster/sid'})
[2019-05-12 10:14:41,100]:INFO:ankisyncd.http:192.168.10.1 "POST /sync/meta HTTP/1.1" 200 108
I really don't know, what is missing, can you please give me some tips, where to go?
it may be a long passage if I write it down. In order to visualize it, I recorded it to a video, and the test collection file is also attached within the zip package.
the first issue is about the account. If I delete the user in server without deauthorizing the account in the client, the client will still be able to use this deleted account to sync.
the second issue, my friend gave me a large collection pkg, it's a little bit big, which includes about 7000 media files , when I import the pkg, and then sync, even if I checked the database, the sync would probably fail and causing jam in the server, which will block other clients' connection to the anki-sync-server.
https://send.firefox.com/download/6526c14ca6/#vWJu0mvCc-Cp78FbdfLwog
(This link will not funtion after 24 hours)
2.1.9 just updated, and the custom-server add-on went out a problem, which prompted a error says ankiweb encountered a network problem. When I over-write it with 2.1.8, the problem solved.
We can update anki-bundled to 2.1.16 without modify any other code.
I've tried on windows 2.1.19, 2.1.20beta9 and ankidroid 2.9.2 and they are all working good.
Server runs on Ubuntu 19.10.
The OS was Debian 10 Buster
The python version was python3
The anki-sync-server server can be installed as the instruction as this git document description.
Android Phone: AnkiDroid version 2.9.2
Linux Laptop: Anki Version 2.1.15 (442df9d6) Qt 5.12.1 PyQt 5.11.3
'''''''''''''''''''''
result:
The anki-sync-server running as normal. And the media attachment can not be used.
The AnkiDroid v2.92 can sync with anki-sync-server as normal. except that "Sync error: Syncing error, type: 404, message: Not Found"
The linux version Anki2.1.15 can sync with anki-sync-server as normal.
'''''''''''''''''''''''''''
anki-sync-server system log:
...
INFO:ankisyncd.http:xxx.xxx.xxx.xxx "POST /sync/finish HTTP/1.1" 200 13
...
INFO:ankisyncd.http:xxx.xxx.xxx.xxx "POST /msync//begin HTTP/1.1" 404 52
'''''''''
What's your opinion on this topic?
Could you please give any idea?
Thanks!
I set up a private anki server follow below link. I can sync data from windows 10 anki client. But when I try to sync from android mobile phone. It always pop-up incorrect username or password. Any one can help me. Thanks.
Hi everyone.
Iam trying to reimplement the RESTapi which was included in the original Anki-sync-server by dsnopek.
My programming is quite noobish, so i will proably fail. Therefore if any of you guys wants to help out please say so. Would be great to get that API up and running again.
I hope there is a supercoder out there with a little time of his/hers hands. :) :D
Cheers!!
I use AnkiDroid 2.8.5beta1
and get code 400, message Bad request version ('À')
on the sync server console output log. So I configured my client correctly (it reaches the server).
Hello,
I've been testing this out with Anki 2.1.0 beta 4. Whenever I make a change to my deck that requires a full sync upload, like changing a note type, I get the following error:
Syncing failed:
Traceback (most recent call last):
File "aqt/sync.py", line 340, in run
File "aqt/sync.py", line 396, in _sync
File "aqt/sync.py", line 425, in _fullSync
File "anki/sync.py", line 680, in upload
File "anki/sync.py", line 565, in req
File "anki/sync.py", line 510, in assertOk
Exception: Unknown response code: 400
Full sync downloads work okay for me.
Thanks
Don't work on anki 2.1.20. When I go back 2.1.15, it gets back normal.
I just installed the latest anki-sync-server, but the jam problem still exixts.
When the user have a big amount of media files, the sync will not succeed, and the other user will not be able to use the sync server any more, unless I restart the server manually.
The demonstration video file is attached below (within the zip file, there is a 7z file, the video is in the 7z file. sorry the video is 30MB, so I have to double zip it, so it can be uploaded):
you can also download the mp4 file directly here
I've setup anki-sync-server, opened the port 27701 on my router, manage to sync my laptop Anki to the server using the internet ip.
I can also access the server from my android's browser and see the message "Anki Sync Server"
But when I try syncing from the phone, it failed with the following error:
From the readme:
AnkiDroid
Advanced → Custom sync serverUnless you have set up a reverse proxy to handle encrypted connections, use http as the protocol. The port will be either the default, 27701, or whatever you have specified in ankisyncd.conf (or, if using a reverse proxy, whatever port you configured to accept the front-end connection).
Do not use trailing slashes.
It looks like http isn't supported by default on android
https://better-coding.com/solved-android-cannot-send-data-to-the-server-cleartext-communication-to-not-permitted-by-network-security-policy/
I have no idea how many things I've done right and how many wrong. I'm definitely an amatour.
What is not working here?
PS C:\Users\xxx\Desktop\Anki_sync\anki-sync-server> python -m ankisyncd
Traceback (most recent call last):
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 193, in _run_module_as_main return _run_code(code, main_globals, None,
File "C:\Users\xxx\AppData\Local\Programs\Python\Python38\lib\runpy.py", line 86, in _run_code exec(code, run_globals)
File "C:\Users\xxx\Desktop\Anki_sync\anki-sync-server\ankisyncd\__main__.py", line 8, in <module> import ankisyncd.sync_app
File "C:\Users\xxx\Desktop\Anki_sync\anki-sync-server\ankisyncd\sync_app.py", line 37, in <module> import anki.db ModuleNotFoundError: No module named 'anki.db'
Also feel free to change the title as I'm not sure what I should've put there.
Thanks for you work,I configured server work fine.
But when I sync from anki desktop to server,It dumps
Traceback (most recent call last):
File "aqt\sync.py", line 382, in _sync
File "aqt\sync.py", line 362, in abortingSync
File "anki\sync.py", line 41, in sync
File "anki\sync.py", line 593, in meta
File "json_init.py", line 354, in loads
File "json\decoder.py", line 339, in decode
File "json\decoder.py", line 357, in raw_decode
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
============
anki desktop:
version 2.1.5
platform windows 10
I've been use anki-sync-server for couple of years for sync between pc and mobile.
after upgrade anki to 2.1, I noticed I have to login server again, but unfortunately I didn't remember the username and password of it. I should note them in my password log, but I didn't.
how can I reset them?
I am a novice of linux stuff, would very appreciate if you can let me know more step by step way. thanks.
I am operating on 3b8fe9e
I encountered an AssertionError while attempting to push some media changes from Anki (2.1.15 and 2.1.19) on Ubuntu. As part of that process, ankisyncd is being requested to delete some media files which do not currently exist in the collection.media
directory. This triggers the AssertionError on assert self.col.media.lastUsn() == oldUsn + processed_count
To help debug, I added some print statements to the immediately-preceding code:
# We count all files we are to remove, even if we don't have them in
# our media directory and our db doesn't know about them.
processed_count = len(media_to_remove) + len(media_to_add)
assert len(meta) == processed_count # sanity check
print(f'==== POINT A :: usn={usn}, oldUsn={oldUsn}, len(meta)==processed_count=={processed_count}', file=sys.stderr)
if media_to_remove:
print(f'==== Removing media: {repr(media_to_remove)}', file=sys.stderr)
self._remove_media_files(media_to_remove)
if media_to_add:
print(f'==== Adding media: {repr(media_to_add)}', file=sys.stderr)
self.col.media.db.executemany(
"INSERT OR REPLACE INTO media VALUES (?,?,?)", media_to_add)
self.col.media.db.commit()
print(f'==== POINT B :: lastUsn()={self.col.media.lastUsn()}, oldUsn={oldUsn}, processed_count={processed_count}', file=sys.stderr)
assert self.col.media.lastUsn() == oldUsn + processed_count # TODO: move to some unit test
return processed_count
The output is as follows:
[2020-01-22 16:48:18,298]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Starting...
[2020-01-22 16:48:18,299]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Running meta(*[], **{'v': 9, 'cv': 'ankidesktop,2.1.15 (442df9d6),lin:ubuntu:18.04'})
[2020-01-22 16:48:18,312]:INFO:ankisyncd.http:127.0.0.1 "POST /sync/meta HTTP/1.0" 200 112
[2020-01-22 16:48:20,560]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Running operation_upload(*[b'SQLite format 3\x00\x10\x00\x01\x01\x00@ \x00\x00\x00\xc4\x00\x00\x00\x81\x00\x00\x00\x0f\x00\x00\x00\x01\x00\x00\x00\x18\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00...', <__main__.SyncUserSession object at 0x7ff9be98deb8>], **{})
[2020-01-22 16:48:20,573]:INFO:ankisyncd.http:127.0.0.1 "POST /sync/upload HTTP/1.0" 200 2
[2020-01-22 16:48:20,630]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Running begin(*[], **{'skey': '7ca4d999'})
[2020-01-22 16:48:20,631]:INFO:ankisyncd.http:127.0.0.1 "POST /msync/begin HTTP/1.0" 200 52
[2020-01-22 16:48:20,682]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Running mediaChanges(*[], **{'lastUsn': 1347})
[2020-01-22 16:48:20,683]:INFO:ankisyncd.http:127.0.0.1 "POST /msync/mediaChanges HTTP/1.0" 200 23
[2020-01-22 16:48:20,742]:INFO:ankisyncd.CollectionThread[yq-class-Z1]:Running uploadChanges(*[], **{'data': b'PK\x03\x04\x14\x00\x00\x00\x08\x00\n\x866P\xec[G\xf9\r\x01\x00\x00R\x03\x00\x00\x05\x00\x00\x00_metauR\xcbj\xc3@\x0c\xfc\x95\xe0s\x08\x92f\xa4]}K\x08:\x06\n\x85\xfc\xff\xa9\xb2K\xa1\xe0\xf5Y\xc3<\xf5|n&:T\xc5U\x14\x82R...'})
==== POINT A :: usn=1347, oldUsn=1347, len(meta)==processed_count==25
==== Removing media: ['20171105101303_14010.jpg', '20180302112534_42967.mp3', '20180301160604_88997.mp3', '20180302133019_27990.mp3', '20180416092356_40344.jpg', '20171030214910_26553.jpg', '20180302092239_46576.mp3', '20180227113121_59562.mp3', '20180302101241_19948.mp3', '20180227115011_64478.mp3', '20171110165954_33939.jpg', '20180604115213_14556.mp3', '20180227141910_86300.mp3', '20180302112109_54634.mp3', '20171104220557_42406.jpg', '20180227165103_57636.mp3', '20180301150503_63690.mp3', '20180301155325_64802.mp3', '20180227094943_28410.mp3', '20171121221705_63044.jpg', '20180227113240_97547.mp3', '20180227145848_50959.mp3', '20180227133215_10335.mp3', '20171105113357_96684.jpg', '20180301142836_52352.mp3']
==== POINT B :: lastUsn()=1347, oldUsn=1347, processed_count=25
[2020-01-22 16:48:20,746]:ERROR:ankisyncd.CollectionThread[yq-class-Z1]:Unable to uploadChanges(*[], **{'data': b"PK\x03\x04\x14\x00\x00\x00\x08\x00\n\x866P\xec[G\xf9\r\x01\x00\x00R\x03\x00\x00\x05\x00\x00\x00_metauR\xcbj\xc3@\x0c\xfc\x95\xe0s\x08\x92f\xa4]}K\x08:\x06\n\x85\xfc\xff\xa9\xb2K\xa1\xe0\xf5Y\xc3<\xf5|n&:T\xc5U\x14\x82R\x8a\xca\xe3\xeb\xf3\xde\xee\xb7m{\xddo\x07b\n\xc4T\xcd\xc1\xa2e\x8c\xc7\xf7\x07'\x84jH\x08k\xce\xcc5\xc2\x14\r\xcb\xb2\x91)\x0b\x04\x9b!\r\x1eE\x01y\xf21\xf4 a\xaa\x94\x85;\xd6N\x9b\xc3\x90\xc5\xf0\x11\x0b\x15\xb3N\x0c5-O\x0f\xbbp*j\xd4\xd2L\xce+\x0e\xef\xc8\x15\xe48#\xfa\xda\x0c\xd1\x02, \x91\x0b\xa7\xddUst'\xdd\xba\xfb\x95S\xea\x9ev\x06d\xd5\xd8\xef.*Y\xce\x00W>\x84f\xe2>z9J,|\xec*\xd1\x0f\x80\xea\xbe\xb0\xf2\xb1o\xeb\xe2\x8d\xe8\xfbr\xb9\x03\xe10\xef>\x9aq\x9dE\x92I\x94M\xea\x99c\xec9\xcctHs@\x16\xeb\xff-\xd71*\x87s\xf5cGc>9\xcb%=/\x10\x80\xa9W'\x86/\x1b\xf3VA7\x96\x11s\xe5cOK\x9b\x88\xf2\xfe\xd6\x7fi_?PK\x01\x02\x14\x03\x14\x00\x00\x00\x08\x00\n\x866P\xec[G\xf9\r\x01\x00\x00R\x03\x00\x00\x05\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x80\x01\x00\x00\x00\x00_metaPK\x05\x06\x00\x00\x00\x00\x01\x00\x01\x003\x00\x00\x000\x01\x00\x00\x00\x00"}):
Traceback (most recent call last):
File "/home/anki/src/anki-sync-server/ankisyncd/thread.py", line 98, in _run
ret = self.wrapper.execute(func, args, kw, return_queue)
File "/home/anki/src/anki-sync-server/ankisyncd/collection.py", line 46, in execute
ret = func(*args, **kw)
File "ankisyncd/sync_app.py", line 622, in run_func
res = handler_method(**keyword_args)
File "ankisyncd/sync_app.py", line 197, in uploadChanges
processed_count = self._adopt_media_changes_from_zip(z)
File "ankisyncd/sync_app.py", line 272, in _adopt_media_changes_from_zip
assert self.col.media.lastUsn() == oldUsn + processed_count # TODO: move to some unit test
AssertionError
Traceback (most recent call last):
File "/usr/lib/python3.6/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/home/anki/.local/lib/python3.6/site-packages/webob/dec.py", line 129, in __call__
resp = self.call_func(req, *args, **kw)
File "/home/anki/.local/lib/python3.6/site-packages/webob/dec.py", line 193, in call_func
return self.func(req, *args, **kwargs)
File "ankisyncd/sync_app.py", line 599, in __call__
result = self._execute_handler_method_in_thread(url, data, session)
File "ankisyncd/sync_app.py", line 631, in _execute_handler_method_in_thread
result = thread.execute(run_func, kw=keyword_args)
File "/home/anki/src/anki-sync-server/ankisyncd/thread.py", line 79, in execute
raise ret
File "/home/anki/src/anki-sync-server/ankisyncd/thread.py", line 98, in _run
ret = self.wrapper.execute(func, args, kw, return_queue)
File "/home/anki/src/anki-sync-server/ankisyncd/collection.py", line 46, in execute
ret = func(*args, **kw)
File "ankisyncd/sync_app.py", line 622, in run_func
res = handler_method(**keyword_args)
File "ankisyncd/sync_app.py", line 197, in uploadChanges
processed_count = self._adopt_media_changes_from_zip(z)
File "ankisyncd/sync_app.py", line 272, in _adopt_media_changes_from_zip
assert self.col.media.lastUsn() == oldUsn + processed_count # TODO: move to some unit test
AssertionError
[2020-01-22 16:48:20,752]:INFO:ankisyncd.http:127.0.0.1 "POST /msync/uploadChanges HTTP/1.0" 500 59
The actual collection.media
directory contains exactly the 1347 files which it would be expected to contain after a successful sync. The media_to_remove
(such as 20180301160604_88997.mp3
) do exist under other users but not this user (yq-class-Z1
).
Note that I've reproduced this every time that I try to sync, but the first time it failed there were not yet any debug print statements, so I don't have debug output from the first time it occurred.
Interestingly, I also see the same error when attempting to pull (force a download sync) from the server.
I am happy to help debug this if there's anything I can do to assist. anki-sync-server
is a core piece of our infrastructure and I really appreciate your work on it.
Is anyone noticing a long sync time for media changes, for those of you who have a large collection? It's 15 minutes on my end. Sometimes it fails, so I have to resync and wait another 15 min, etc.
To reproduce the issue, simply have a large media collection (I have 40k files), make some media changes, and then sync.
I'm not sure if the issue is on the side of AnkiDroid or ankisyncd, just my observations.
I upload my data normally until it reachs 6500kb. Whether it is anki2.0 or anki2.1.8, it always fails to upload when the data has already uploaded 6500kb.
server: centos 7 python3.6
Version 2.1.18 (fb9d59fe)
Python 3.8.0 Qt 5.14.0 PyQt 5.13.2
I got this error and cannot sync the changes made on my android device to my windows computer. After struggling for a while I realized that the server responded a 500. By examining the output (btw I use the docker version and a docker attach
):
ERROR:root:CollectionThread[/app/data/collections/gzz/collection.anki2]: Unable to start(*[], **{}): start() got an unexpected keyword argument 'offset'
Traceback (most recent call last):
File "/app/anki-sync-server/ankisyncd/thread.py", line 71, in _run
ret = self.wrapper.execute(func, args, kw, return_queue)
File "/app/anki-sync-server/ankisyncd/collection.py", line 39, in execute
ret = func(*args, **kw)
File "/app/anki-sync-server/ankisyncd/sync_app.py", line 673, in run_func
res = handler_method(**keyword_args)
TypeError: start() got an unexpected keyword argument 'offset'
Traceback (most recent call last):
File "/usr/local/lib/python3.7/wsgiref/handlers.py", line 137, in run
self.result = application(self.environ, self.start_response)
File "/usr/local/lib/python3.7/site-packages/webob/dec.py", line 129, in __call__
resp = self.call_func(req, *args, **kw)
File "/usr/local/lib/python3.7/site-packages/webob/dec.py", line 193, in call_func
return self.func(req, *args, **kwargs)
File "/app/anki-sync-server/ankisyncd/sync_app.py", line 605, in __call__
result = self._execute_handler_method_in_thread(url, data, session)
File "/app/anki-sync-server/ankisyncd/sync_app.py", line 682, in _execute_handler_method_in_thread
result = thread.execute(run_func)
File "/app/anki-sync-server/ankisyncd/thread.py", line 52, in execute
raise ret
File "/app/anki-sync-server/ankisyncd/thread.py", line 71, in _run
ret = self.wrapper.execute(func, args, kw, return_queue)
File "/app/anki-sync-server/ankisyncd/collection.py", line 39, in execute
ret = func(*args, **kw)
File "/app/anki-sync-server/ankisyncd/sync_app.py", line 673, in run_func
res = handler_method(**keyword_args)
TypeError: start() got an unexpected keyword argument 'offset'
It seems that it is a new offset
argument passed to SyncCollectionHandler.start
causes the trouble. I found that it's always a None
in my case so I just added it and ignored it, it just works.
def start(self, minUsn, lnewer, graves={"cards": [], "notes": [], "decks": []}, offset=None):
Please check if you also have this problem with Anki 2.1.18. If it's the right thing to do I can make a pull request on this one-line patch.
After deleting the PC version of Anki data, sync the private server again, it shows that the synchronization is correct, but the private server data is not cleared
Environmental description:
os: Windows7
PC anki version: 2.1.20
Python version :3.6
It's been 3 years since the last release, and I would prefer to use release versions when packaging ankisyncd. Any chance you could bump the release version to incorporate the changes in the past few years sometime soon?
Thanks!
Hey tsudoku,
I am not sure if I should this report to you or directly to the developers of Anki Desktop, but I have encountered an interesting behavior that can break syncing, while I was about to update the image to support the latest version of Anki.
Anki Desktop version: 2.1.14
ankisyncd
version: 7ef3d4f on master
Reproduction:
Set up ankisyncd
and point an Anki Desktop instance to it
Create a deck and some cards, maybe manipulate them
Synchronize making sure it works at this point
Ensure that you have at least one completely fresh, unreviewed card
It should look as follows in the browser:
Synchronize again - it should still work
BREAK IT: Hit Check datatabase...
A message similar to this one should appear:
Found 1 new cards with a due number >= 1,000,000 - consider repositioning them in the Browse screen.
Database rebuilt and optimized.
The server output does not seem to contain too much useful information at the very moment this message appears on the client side:
[2019-07-08 12:31:20,928]:INFO:ankisyncd.CollectionThread[sajat_anki]:Running meta(*[], **{'v': 9, 'cv': 'ankidesktop,2.1.14 (7b93e985),lin:arch:rolling'})
[2019-07-08 12:31:20,930]:INFO:ankisyncd.http:172.17.0.1 "POST /sync/meta HTTP/1.1" 200 112
What do you think, is it related to ankisyncd
or should I forward this bug to the developers of Anki Desktop?
Best regards,
István
Hi!
I'm trying to get this working with python3 (adduser function won't work with python2) but I got stuck on last step while running python3 ankisyncd/sync_app.py ankisyncd.conf
(i'm using master branch):
File "ankisyncd/sync_app.py", line 116
print(f"applyGraves chunk: {chunk}")
^
SyntaxError: invalid syntax
With python2 I get the same error.
I tried to comment out that line or removing that f
after print(
(I don't know about python at all, so I did it just to try) and I got this:
Traceback (most recent call last):
File "ankisyncd/sync_app.py", line 36, in <module>
import anki.db
ImportError: No module named 'anki'
Thanks a lot!
Anki Desktop 2.1.14
AnkiDroid 2.8.4
I am using anki sync server behind a NGINX reverse proxy.
My setup works with the Anki desktop client with the SyncRedirector Add-on and the following URLs defined:
{
"msyncUrl": "http://ankisync.my-domain.org/msync/",
"syncUrl": "http://ankisync.my-domain.org/sync/"
}
It also works via local network with the IP configured directly:
{
"msyncUrl": "http://192.168.0.x:27701/msync/",
"syncUrl": "http://192.168.0.x/sync/"
}
However, I tried both variants with and without a trailing slash at the end of the URL and get the following error with all configurations:
Syncing error, type: 404, message: Not Found
Accessing http://ankisync.my-domain.org/ via mobile web browser displays Anki Sync Server
correctly.
I'd be grateful for hints on how to debug this issue further.
Instead of
conn = self._conn()
cursor = conn.cursor()
cursor.execute(<some sql>)
conn.commit()
we can do:
conn = self._conn()
with conn:
conn.execute(<some sql>)
which also handles rollbacks. Would you accept a PR to this effect?
I am trying to synchronize with anki-sync-server for the first time, the collections have been synchronized with AnkiWeb before.
I get Error syncing media data
org.json.JSONException: Value Anki of type java.lang.String cannot be converted to JSONObject
.
It would be great for the addon to be able to be installed directly from within Anki, without having to go into hidden directories, copy, unzip. As it now does everything from config, is there a reason why it hasn't been uploaded? I had a quick look and from what I can tell there is already one existing custom sync addon there, though it is a little sneaky in that the description is not in English.
I didn't see anything in the terms that suggests setting an alternative sync server is against the T&C, and it would be very handy for me to have this.
I can take on the responsibility for keeping it up to date and supporting it, if you prefer not to take that on.
when I run this commandpip3 install -r requirements.txt
, it shows the following error:
Ignoring psutil: markers 'sys_platform == "win32"' don't match your environment
Requirement already satisfied: beautifulsoup4 in /usr/local/lib/python3.6/site-packages (from -r requirements.txt (line 1)) (4.7.1)
Requirement already satisfied: send2trash in /usr/local/lib64/python3.6/site-packages (from -r requirements.txt (line 2)) (1.5.0)
Collecting pyaudio (from -r requirements.txt (line 3))
Using cached https://files.pythonhosted.org/packages/ab/42/b4f04721c5c5bfc196ce156b3c768998ef8c0ae3654ed29ea5020c749a6b/PyAudio-0.2.11.tar.gz
Collecting requests (from -r requirements.txt (line 4))
Using cached https://files.pythonhosted.org/packages/7d/e3/20f3d364d6c8e5d2353c72a67778eb189176f08e873c9900e10c0287b84b/requests-2.21.0-py2.py3-none-any.whl
Collecting decorator (from -r requirements.txt (line 5))
Using cached https://files.pythonhosted.org/packages/f1/cd/7c8240007e9716b14679bc217a1baefa4432aa30394f7e2ec40a52b1a708/decorator-4.3.2-py2.py3-none-any.whl
Collecting markdown (from -r requirements.txt (line 6))
Using cached https://files.pythonhosted.org/packages/7a/6b/5600647404ba15545ec37d2f7f58844d690baf2f81f3a60b862e48f29287/Markdown-3.0.1-py2.py3-none-any.whl
Collecting distro (from -r requirements.txt (line 8))
Using cached https://files.pythonhosted.org/packages/ea/35/82f79b92fa4d937146c660a6482cee4f3dfa1f97ff3d2a6f3ecba33e712e/distro-1.4.0-py2.py3-none-any.whl
Requirement already satisfied: soupsieve>=1.2 in /usr/local/lib/python3.6/site-packages (from beautifulsoup4->-r requirements.txt (line 1)) (1.8)
Collecting chardet<3.1.0,>=3.0.2 (from requests->-r requirements.txt (line 4))
Using cached https://files.pythonhosted.org/packages/bc/a9/01ffebfb562e4274b6487b4bb1ddec7ca55ec7510b22e4c51f14098443b8/chardet-3.0.4-py2.py3-none-any.whl
Collecting certifi>=2017.4.17 (from requests->-r requirements.txt (line 4))
Using cached https://files.pythonhosted.org/packages/60/75/f692a584e85b7eaba0e03827b3d51f45f571c2e793dd731e598828d380aa/certifi-2019.3.9-py2.py3-none-any.whl
Collecting urllib3<1.25,>=1.21.1 (from requests->-r requirements.txt (line 4))
Using cached https://files.pythonhosted.org/packages/62/00/ee1d7de624db8ba7090d1226aebefab96a2c71cd5cfa7629d6ad3f61b79e/urllib3-1.24.1-py2.py3-none-any.whl
Collecting idna<2.9,>=2.5 (from requests->-r requirements.txt (line 4))
Using cached https://files.pythonhosted.org/packages/14/2c/cd551d81dbe15200be1cf41cd03869a46fe7226e7450af7a6545bfc474c9/idna-2.8-py2.py3-none-any.whl
Building wheels for collected packages: pyaudio
Building wheel for pyaudio (setup.py) ... error
Complete output from command /bin/python36 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-fwzy1qst/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" bdist_wheel -d /tmp/pip-wheel-k1o3i0sh --python-tag cp36:
running bdist_wheel
running build
running build_py
creating build
creating build/lib.linux-x86_64-3.6
copying src/pyaudio.py -> build/lib.linux-x86_64-3.6
running build_ext
building '_portaudio' extension
creating build/temp.linux-x86_64-3.6
creating build/temp.linux-x86_64-3.6/src
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python3.6m -c src/_portaudiomodule.c -o build/temp.linux-x86_64-3.6/src/_portaudiomodule.o
src/_portaudiomodule.c:28:20: fatal error: Python.h: No such file or directory
#include "Python.h"
^
compilation terminated.
error: command 'gcc' failed with exit status 1
----------------------------------------
Failed building wheel for pyaudio
Running setup.py clean for pyaudio
Failed to build pyaudio
Installing collected packages: pyaudio, chardet, certifi, urllib3, idna, requests, decorator, markdown, distro
Running setup.py install for pyaudio ... error
Complete output from command /bin/python36 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-fwzy1qst/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-tt74n3z_/install-record.txt --single-version-externally-managed --compile:
running install
running build
running build_py
creating build
creating build/lib.linux-x86_64-3.6
copying src/pyaudio.py -> build/lib.linux-x86_64-3.6
running build_ext
building '_portaudio' extension
creating build/temp.linux-x86_64-3.6
creating build/temp.linux-x86_64-3.6/src
gcc -pthread -Wno-unused-result -Wsign-compare -DDYNAMIC_ANNOTATIONS_ENABLED=1 -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python3.6m -c src/_portaudiomodule.c -o build/temp.linux-x86_64-3.6/src/_portaudiomodule.o
src/_portaudiomodule.c:28:20: fatal error: Python.h: No such file or directory
#include "Python.h"
^
compilation terminated.
error: command 'gcc' failed with exit status 1
----------------------------------------
Command "/bin/python36 -u -c "import setuptools, tokenize;__file__='/tmp/pip-install-fwzy1qst/pyaudio/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /tmp/pip-record-tt74n3z_/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /tmp/pip-install-fwzy1qst/pyaudio/
my installation step:
git clone https://github.com/tsudoko/anki-sync-server.git /usr/local/anki-sync-server
cd /usr/local/anki-sync-server
git submodule update --init
cd anki-bundled
yum install portaudio-devel
pip3 install -r requirements.txt
Would it be possible to create a setup file (setuptools) to make installing this easier?
I'm looking at the README and the instructions seem to skip a few steps. How can one run $ python -m ankisyncd
if those files are still in the local directory? Should I manually copy it into my Python site-packages directory? Where should I put the ankisyncctl.py
and ankisyncd.conf
files?
I have created a Docker image based on your work sometime before and I am curious if it could be merged or linked to your repository to centralise our efforts as one of your contributors suggested:
kuklinistvan/docker-anki-sync-server#2
Also, I'd like to say thank you to you for maintaining ankisyncd as well as to all the contributors!
For my usecase it would be great for users to be able to sync with the custom server for only a subset of their profiles. That way they can continue syncing with ankiweb for some of their profiles, and with the custom server for the others. By default the behaviour stays as it is now (sync all with the custom server if it's activated).
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.