Giter VIP home page Giter VIP logo

unsonic's Introduction

Unsonic, the un-Subsonic music server.

Status

PyPi Latest Version Project Status License Supported Python Versions

Builds Build Status Coverage Status Updates

About

Unsonic is a free drop in replacement for the Subsonic music server. It follows the Subsonic API and is usable with existing Subsonic clients without requiring any adjustment to them.

Unsonic strives to be better at handling music files tags, playing of those songs and use less system resources.

Supported Clients

These are the clients that are known to work well:

  • DSub (Android)
  • JamStash (web)

These clients sort of work with isues:

  • Clementine (Linux desktop)

Installation

Unsonic requires Python 3.6 or greater to work.

Install Unsonic as a system service via pip

  • pip3 install unsonic
  • sudo unsonic install
  • <Edit /etc/unsonic.ini and update database and music libraries>
  • su unsonic -c 'unsonic sync'
  • su unsonic -c 'unsonic adduser '
  • systemctl start unsonic

Running Unsonic from source

  • make build
  • make run

Installing a Web Client

[unsonic]
ui = ../Jamstash/dist
  • With Unsonic running, point your browser at the url printed out, normally something like http://localhost:6543 and your will be redirected to the load Jamstash.
  • Jamstash is very picky about the server URL in it's configuration. Make sure there is no trailing '/' character otherwise Jamstash will not be able to build the path correctly.

Docker Installation

Docker files are located in the ./docker directory. The Makefile contains some convenience targets but the specific docker and/or docker-compose cmmands are also shown.

To build the Unsonic Docker image:

$ docker build ./docker

Or using docker-compose:

$ docker-compose -f ./docker/docker-compose.yml build

The docker-compose file defines 3 containers, each is geared toward a development/test setup; a production Docker should only use these as a reference. The containers defined are of PostgreSQL, and an Unsonic serve based on PostgreSQL and SQLite. The Unsonic containers requires a music directory to volume mount so one must be specified.

$ MUSIC_DIR=~/music/ docker-compose -f ./docker/docker-compose.yml create
$ MUSIC_DIR=~/music/ docker-compose -f ./docker/docker-compose.yml up Unsonic-postgres

Or using the Makefile to simplify all of the above.

$ make MUSIC_DIR=~/music/ docker-sqlite

See docker/Dockerfile for details about the unsonic image. The container details are defined docker/docker-compose.yml. The files docker/config.ini and docker/unsonic-init can be used to tweak the Unsonic process itself.

Adjusting the configuration

The main configuration settings are the location of the database

[mishmash]
sqlalchemy.url = sqlite:///%(here)s/build/development.sqlite

and the location of the music libraries

[library:Music]
paths = ~/music
sync = true

[library:More Music]
paths = /data/music
sync = true

Adjust them to fit your deployment needs. The mishmash.paths can have multiple music directories, one per line. %(here)s refers to the location of the configuration file itself.

Setting up LastFM

Unsonic includes support for querying LastFM for artist/album information out of the box. In addition, you can configure Unsonic with your LastFM account to enable scrobbling.

$ unsonic config -s "lastfm.user=lastfm-user" unsonic-user
$ unsonic config -s "lastfm.password=lastfm-password" unsonic-user

Running with TLS

Unsonic itself doesn't handle TLS, but can easily be run behind a reverse proxy that does. The following example shows how to configure nginx to reverse proxy to a local Unsonic instance. Replace example.com with your domain name/IP. You may change the path portion of the url from "unsonic" to whatever you wish, or remove it completely.

This would go into your /etc/nginx/nginx.conf or its own file in /etc/nginx/sites-available depending on how your distro is setup.

server {
    listen       80;
    server_name  example.com;
    return 301 https://$host$request_uri;
}

server {
    listen       443 ssl http2;
    server_name  example.com;

    ssl config...

    # Your Unsonic is located on https://example.com/
    location / {
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_buffers 16 4k;
        proxy_buffer_size 2k;
        proxy_pass http://localhost:6543;
        proxy_read_timeout 90;
    }

Developing Unsonic

Running tests requires docker.

Development build

  • make devel
  • make devel-run

Tests

  • make tests

Running

  • ./bin/unsonic -c <config.ini> sync
  • ./bin/unsonic -c <config.ini> adduser name pass
  • ./bin/unsonic -c <config.ini> serve [--reload]

Manual Testing

  • ./test/bin/tester getArtists

New DB Version

  • ... Edit schema classes
  • make devel-clean
  • make devel-db
  • ./venv/bin/alembic -c unsonic/alembic/alembic.ini revision --autogenerate -m "comment"
  • ... DB schema should still be the older version
  • bin/unsonic -c unsonic/etc/development.ini listusers
  • ... Check DB schema matches new revision
  • ... Check in new revision file

License

Unsonic is licensed under the GPL v2 license. See the COPYING file for details or http://www.gnu.org/licenses/gpl-2.0.html#SEC1

unsonic's People

Contributors

nicfit avatar pyup-bot avatar redshodan avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

unsonic's Issues

Add DBUS support

I'm sure I can come up with uses... But for now, backlog the place holder

last.fm API support

  • Add last.fm API support
  • Store credentials in the DB
  • have a command to manage the creds #27
  • Implement the subsonic calls that need it
  • this allows for #8

README updates

General outline:

  • general use. Tags based.
  • pip install
  • config
  • syncing
  • running server
  • TLS nginx
  • Dev howto

Doc stuff:

  • Filter README.md for:
  • man page
  • html
  • setup.py README

Support Subsonic API 1.15

The 1.15 API only adds two calls for music scanning. Implement those interfaces and scanning in the web server process in a different thread.

Make the config code sane

The unsonic the config, web, and models modules do bad things to the configuration. Between the needs of Pyramid, the test framework and mishmash, that code has gotten very ugly. It needs to be fixed up into a single interface that works for everything.

  • Generic (totally not unosnic-only) Config class derived from base ConfigParser. Follow the ConfigParser API as much as possible for compat with other things.
  • Configured the Config class to know about:
    • default .ini config file to read in first
    • database table to key/pairs to read from
    • environment variables, named after key name with app prefix
    • user ~/. config.ini
    • system /etc/*/config.ini

Package up Jamstash

  • Create a pip package for jamstash that works with unsonic
  • Use the static assets in pyramid to serve it up from installed source
  • Make it optional so it doesn't break anything if not installed
  • Make sure the Jamstash license is kosher
  • Pre-populate the cfg bits for Jamstash
  • don't land on the settings page once it's pre-populated

Scrobble

  • Watch for stupid clients pushing the same scrobble multiple times too fast.

Option to show artist vs album_artist

  • Have a server side config option to choose how artists are sorted: via artist or album_artist.
  • If possible, add some way to toggle that via the client. Most likely require an extension to the protocol and client mods.

Handle offline scrobbles by scrobbling them

When coming online Dsub...

2018-03-26 22:02:17,505 INFO  [wsgi][waitress] [email protected] [26/Mar/2018:22:02:17 -0600] "GET /rest/search2.view?u=nicfit&&v=1.2.0&c=DSub&query=artist%3A%22The+Freeze%22+AND+title%3A%22Bloodlights%22&artistCount=0&albumCount=0&songCount=1 HTTP/1.1" 200 174 "-" "DSub"

One per song played while offline.

duplicate insert in scrobble

unsonic.nicfit.net    | 2017-05-04 01:02:36,794 INFO  [unsonic.views.rest.scrobble][waitress] Scrobbling Oh
unsonic.nicfit.net    | 2017-05-04 01:02:37,394 INFO  [wsgi][waitress] 74.220.34.132 - - [04/May/2017:01:02:37 +0000] "GET /rest/stream.view?u=nicfit&s=h6km5imj47943sg2392qm8aap5&t=81d52df812f89b1cfceac5cfade91790&v=1.2.0&c=DSub&id=tr-12788&maxBitRate=196 HTTP/1.1" 200 6371328 "-" "DSub"
PostgreSQL-unsonic.nicfit.net | ERROR:  duplicate key value violates unique constraint "pk_un_playcounts"
PostgreSQL-unsonic.nicfit.net | DETAIL:  Key (track_id, user_id)=(12787, 2) already exists.
PostgreSQL-unsonic.nicfit.net | STATEMENT:  INSERT INTO un_playcounts (track_id, user_id, count) VALUES (12787, 2, 1)
unsonic.nicfit.net    | 2017-05-04 01:02:37,830 INFO  [wsgi][waitress] 74.220.34.132 - - [04/May/2017:01:02:35 +0000] "GET /rest/scrobble.view?u=nicfit&s=h6km5imj47943sg2392qm8aap5&t=81d52df812f89b1cfceac5cfade91790&v=1.2.0&c=DSub&id=tr-12787&submission=false HTTP/1.1" 200 139 "-" "DSub"
unsonic.nicfit.net    | 2017-05-04 01:02:39,556 INFO  [wsgi][waitress] 74.220.34.132 - - [04/May/2017:01:02:39 +0000] "GET /rest/savePlayQueue.view?u=nicfit&s=h6km5imj47943sg2392qm8aap5&t=81d52df812f89b1cfceac5cfade91790&v=1.2.0&c=DSub&id=tr-12781&id=tr-12782&id=tr-12783&id=tr-12784&id=tr-12785&id=tr-12786&id=tr-12787&id=tr-12788&id=tr-12789&id=tr-12790&id=tr-32976&current=tr-12788&position=0 HTTP/1.1" 200 139 "-" "DSub"

Language support

Add support for multiple languages. Yes, I know this should be done sooner than later, but..

  • intl protocol strings
  • select lastfm language

Packaging issues

My commit was to fix this, it doesn't.
Although the files are included in the dist now.

Unsonic-sqlite      | General error:
Unsonic-sqlite      | Traceback (most recent call last):
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/mishmash/__main__.py", line 46, in main
Unsonic-sqlite      |     retval = args.command_func(args, args.config) or 0
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/mishmash/core.py", line 16, in run
Unsonic-sqlite      |     retval = super().run(args)
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/nicfit/command.py", line 49, in run
Unsonic-sqlite      |     return self._run()
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/unsonic/commands/sync.py", line 13, in newrun
Unsonic-sqlite      |     initAlembic()
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/unsonic/models.py", line 313, in initAlembic
Unsonic-sqlite      |     command.upgrade(alembic_cfg, "head")
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/alembic/command.py", line 254, in upgrade
Unsonic-sqlite      |     script.run_env()
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/alembic/script/base.py", line 416, in run_env
Unsonic-sqlite      |     util.load_python_file(self.dir, 'env.py')
Unsonic-sqlite      |   File "/unsonic/lib/python3.6/site-packages/alembic/util/pyfiles.py", line 99, in load_python_file
Unsonic-sqlite      |     raise ImportError("Can't find Python file %s" % path)
Unsonic-sqlite      | ImportError: Can't find Python file /unsonic/lib/python3.6/site-packages/unsonic/alembic/env.py

deluser traceback

Traceback (most recent call last):
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
    context)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
    cursor.execute(statement, parameters)
psycopg2.IntegrityError: update or delete on table "un_users" violates foreign key constraint "fk_un_playcounts_user_id_un_users" on table "un_playcounts"
DETAIL:  Key (id)=(2) is still referenced from table "un_playcounts".


The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "/unsonic/lib/python3.6/site-packages/mishmash/__main__.py", line 53, in main
    retval = args.command_func(args, args.config) or 0
  File "/unsonic/lib/python3.6/site-packages/mishmash/core.py", line 17, in run
    retval = super().run(args)
  File "/unsonic/lib/python3.6/site-packages/nicfit/command.py", line 55, in run
    return self._run()
  File "/unsonic/lib/python3.6/site-packages/unsonic/commands/deluser.py", line 22, in _run
    res.delete()
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/orm/query.py", line 3188, in delete
    delete_op.exec_()
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 1179, in exec_
    self._do_exec()
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/orm/persistence.py", line 1363, in _do_exec
    mapper=self.mapper)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/orm/session.py", line 1107, in execute
    bind, close_with_result=True).execute(clause, params or {})
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 945, in execute
    return meth(self, multiparams, params)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/sql/elements.py", line 263, in _execute_on_connection
    return connection._execute_clauseelement(self, multiparams, params)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1053, in _execute_clauseelement
    compiled_sql, distilled_params
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1189, in _execute_context
    context)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1393, in _handle_dbapi_exception
    exc_info
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 203, in raise_from_cause
    reraise(type(exception), exception, tb=exc_tb, cause=cause)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/util/compat.py", line 186, in reraise
    raise value.with_traceback(tb)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
    context)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
    cursor.execute(statement, parameters)
sqlalchemy.exc.IntegrityError: (psycopg2.IntegrityError) update or delete on table "un_users" violates foreign key constraint "fk_un_playcounts_user_id_un_users" on table "un_playcounts"
DETAIL:  Key (id)=(2) is still referenced from table "un_playcounts".
 [SQL: 'DELETE FROM un_users WHERE un_users.name = %(name_1)s'] [parameters: {'name_1': 'nicfit'}]
Traceback (most recent call last):
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/base.py", line 1182, in _execute_context
    context)
  File "/unsonic/lib/python3.6/site-packages/sqlalchemy/engine/default.py", line 470, in do_execute
    cursor.execute(statement, parameters)
psycopg2.IntegrityError: update or delete on table "un_users" violates foreign key constraint "fk_un_playcounts_user_id_un_users" on table "un_playcounts"
DETAIL:  Key (id)=(2) is still referenced from table "un_playcounts".

getRandomSongs exception traceback

'''
unsonic.nicfit.net | 2019-05-22 07:38:11,019 DEBUG [txn.139753145244392][waitress] new transaction
unsonic.nicfit.net | Traceback (most recent call last):
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/unsonic/views/rest/init.py", line 80, in call
unsonic.nicfit.net | return self.handleReq(session)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/unsonic/views/rest/getrandomsongs.py", line 48, in handleReq
unsonic.nicfit.net | join(Album).filter(Album.release_date >= fy and
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 3054, in bool
unsonic.nicfit.net | raise TypeError("Boolean value of this clause is not defined")
unsonic.nicfit.net | TypeError: Boolean value of this clause is not defined
unsonic.nicfit.net | 2019-05-22 07:38:11,025 DEBUG [txn.139753145244392][waitress] abort
unsonic.nicfit.net | 2019-05-22 07:38:11,028 ERROR [waitress][waitress] Exception when serving /rest/getRandomSongs.view
unsonic.nicfit.net | Traceback (most recent call last):
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/tweens.py", line 13, in error_handler
unsonic.nicfit.net | response = request.invoke_exception_view(exc_info)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/view.py", line 769, in invoke_exception_view
unsonic.nicfit.net | raise HTTPNotFound
unsonic.nicfit.net | pyramid.httpexceptions.HTTPNotFound: The resource could not be found.
unsonic.nicfit.net |
unsonic.nicfit.net | During handling of the above exception, another exception occurred:
unsonic.nicfit.net |
unsonic.nicfit.net | Traceback (most recent call last):
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/waitress/channel.py", line 336, in service
unsonic.nicfit.net | task.service()
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/waitress/task.py", line 175, in service
unsonic.nicfit.net | self.execute()
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/waitress/task.py", line 452, in execute
unsonic.nicfit.net | app_iter = self.channel.server.application(env, start_response)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/paste/translogger.py", line 69, in call
unsonic.nicfit.net | return self.application(environ, replacement_start_response)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/router.py", line 270, in call
unsonic.nicfit.net | response = self.execution_policy(environ, self)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/router.py", line 279, in default_execution_policy
unsonic.nicfit.net | return request.invoke_exception_view(reraise=True)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/view.py", line 768, in invoke_exception_view
unsonic.nicfit.net | reraise
(*exc_info)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/compat.py", line 179, in reraise
unsonic.nicfit.net | raise value
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/router.py", line 277, in default_execution_policy
unsonic.nicfit.net | return router.invoke_request(request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/router.py", line 249, in invoke_request
unsonic.nicfit.net | response = handle_request(request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid_tm/init.py", line 171, in tm_tween
unsonic.nicfit.net | reraise(*exc_info)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid_tm/compat.py", line 36, in reraise
unsonic.nicfit.net | raise value
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid_tm/init.py", line 136, in tm_tween
unsonic.nicfit.net | response = handler(request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/tweens.py", line 43, in excview_tween
unsonic.nicfit.net | response = _error_handler(request, exc)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/tweens.py", line 17, in _error_handler
unsonic.nicfit.net | reraise(*exc_info)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/compat.py", line 179, in reraise
unsonic.nicfit.net | raise value
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/tweens.py", line 41, in excview_tween
unsonic.nicfit.net | response = handler(request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/router.py", line 148, in handle_request
unsonic.nicfit.net | registry, request, context, context_iface, view_name
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/view.py", line 657, in _call_view
unsonic.nicfit.net | response = view_callable(context, request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/viewderivers.py", line 325, in secured_view
unsonic.nicfit.net | return view(context, request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/viewderivers.py", line 401, in viewresult_to_response
unsonic.nicfit.net | result = view(context, request)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/pyramid/viewderivers.py", line 130, in _class_view
unsonic.nicfit.net | response = inst()
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/unsonic/views/rest/init.py", line 80, in call
unsonic.nicfit.net | return self.handleReq(session)
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/unsonic/views/rest/getrandomsongs.py", line 48, in handleReq
unsonic.nicfit.net | join(Album).filter(Album.release_date >= fy and
unsonic.nicfit.net | File "/usr/local/lib/python3.7/site-packages/sqlalchemy/sql/elements.py", line 3054, in bool
unsonic.nicfit.net | raise TypeError("Boolean value of this clause is not defined")
unsonic.nicfit.net | TypeError: Boolean value of this clause is not defined
unsonic.nicfit.net | 2019-05-22 07:38:11,033 DEBUG [txn.139753147366120][waitress] new transaction

'''

404 returned for artist bio info request.

Click on artist in the library and dsub makes a request for artist bio info and shows an error dialog
"resource not found". The request:

unsonic.nicfit.net | 2017-03-28 01:31:17,388 INFO [wsgi][waitress] 192.168.1.114 - - [28/Mar/2017:01:31:17 +0000] "GET /rest/getArtistInfo2.view?u=nicfit&s=XXXXXXXXXXXXX&t=XXXXXXXXXXXXXX&v=1.2.0&c=DSub&id=ar-9&includeNotPresent=true HTTP/1.1" 404 77 "-" "DSub"

Option to encrypt secrets in db

Have a startup password to (de)-encrypt the secrets in the database, like credentials for lastfm. Ask for the password on startup, keep decrypted data in memory only.

Implement search auto suggestions

2018-11-30 19:47:43,483 DEBUG [txn.139913930069760][waitress] commit
2018-11-30 19:47:43,483 INFO  [wsgi][waitress] [email protected] [30/Nov/2018:19:47:43 -0600] "GET /rest/search3.view?u=nicfit&s=j7566d7aqn5kdaqts13v2o2o6v&t=369acc6b20d2ff2e237ae5b7472ce5c8&v=1.2.0&c=DSub&query=and+y*&artistCount=5&albumCount=10&songCount=10 HTTP/1.1" 200 174 "-" "DSub"
2018-11-30 19:47:44,142 DEBUG [txn.139913921677056][waitress] new transaction
2018-11-30 19:47:44,178 INFO  [unsonic][waitress] Response(search3.view): <?xml version="1.0" encoding="UTF-8"?><subsonic-response status="ok" unsonic="0.1" version="1.16.0" xmlns="http://subsonic.org/restapi"><searchResult3 /></subsonic-response>

Make unsonic easier to run out of the box

  • If no config file on the cmdline, look: /etc/unsonic.ini, INSTALL/etc/unsonic.ini
  • Package up production.ini as unsonic/etc/unsonic.ini.in
  • Add systemd file: #23
  • Install script that can be run to fully setup unsonic

Installation fails due to conflicting pastedeploy version

Hi, users are unable to run Unsonic due to dependency conflict with pastedeploy package. As shown in the following full dependency graph of Unsonic, Unsonic requires pastedeploy==1.5.2,while plaster-pastedeploy * requires pastedeploy>=2.0.

According to pip’s “first found wins” installation strategy, pastedeploy 1.5.2 is the actually installed version. However, pastedeploy 1.5.2 does not satisfy pastedeploy>=2.0.

Dependency tree-----------

unsonic - 0.1.3
| +- alembic(install version:0.9.7 version range:==0.9.7)
| | +- mako(install version:1.1.2 version range:*)
| | | +- MarkupSafe(install version:2.0.0a1 version range:>=0.9.2)
| | +- python-dateutil(install version:2.8.1 version range:*)
| | +- python-editor(install version:1.0.4 version range:>=0.3)
| | +- sqlalchemy(install version:1.2.2 version range:>=0.7.6)
| +- mishmash(install version:0.3b5 version range:==0.3b5)
| +- paste(install version:2.0.3 version range:==2.0.3)
| | +- six(install version:1.14.0 version range:>=1.4.0)
| +- pastedeploy(install version:1.5.2 version range:==1.5.2)
| +- psycopg2(install version:2.7.3.2 version range:==2.7.3.2)
| +- pyramid(install version:1.9.1 version range:==1.9.1)
| +- pyramid-debugtoolbar(install version:4.3 version range:==4.3)
| | +- pygments(install version:2.6.1 version range:*)
| | +- pyramid(install version:1.9.1 version range:>=1.4)
| | +- pyramid-mako(install version:1.1.0 version range:>=0.3.1)
| | | +- Mako(install version:1.1.2 version range:>=1.1.0)
| | | | +- MarkupSafe(install version:2.0.0a1 version range:>=0.9.2)
| | | +- pyramid(install version:1.9.1 version range:*)
| | +- repoze-lru(install version:0.7 version range:*)
| +- pyramid-tm(install version:2.2 version range:==2.2)
| | +- pyramid (install version:1.10.4 version range:>=1.5)
| | | +- hupper(install version:1.10.2 version range:>=1.5)
| | | +- plaster(install version:1.0 version range:*)
| | | | +- setuptools(install version:46.1.3 version range:*)
| | | +- plaster-pastedeploy(install version:0.7 version range:*)
| | | | +- pastedeploy(install version:2.1.0 version range:>=2.0)
| | | | +- plaster(install version:1.0 version range:>=0.5)
| | | +- setuptools(install version:46.1.3 version range:*)
| | | +- translationstring(install version:1.3 version range:>=0.4)
| | | +- venusian(install version:3.0.0 version range:>=1.0)
| | | +- webob(install version:1.8.6 version range:>=1.8.3)
| | | +- zope-deprecation(install version:4.4.0 version range:>=3.5.0)
| | | | +- setuptools(install version:46.1.3 version range:*)
| | | +- zope-interface(install version:5.1.0 version range:>=3.8.0)
| | +- transaction (install version:3.0.0 version range:>=2.0)
| | | +- zope.interface(install version:5.1.0 version range:*)
| +- recommonmark(install version:0.4.0 version range:==0.4.0)
| | +- commonmark(install version:0.5.4 version range:<=0.5.4)
| | +- docutils(install version:0.16 version range:>=0.11)
| +- sphinx(install version:1.6.6 version range:==1.6.6)
| +- sqlalchemy(install version:1.2.2 version range:==1.2.2)
| +- transaction(install version:2.1.2 version range:==2.1.2)
| | +- zope-interface(install version:5.1.0 version range:*)
| +- waitress(install version:1.1.0 version range:==1.1.0)
| +- xmltodict(install version:0.11.0 version range:==0.11.0)
| +- zope-sqlalchemy(install version:0.7.7 version range:==0.7.7)
| | +- setuptools(install version:46.1.3 version range:*)
| | +- sqlalchemy(install version:1.2.2 version range:>=0.5.1)
| | +- transaction(install version:2.1.2 version range:*)
| | | +- zope-interface(install version:5.1.0 version range:*)
| | +- zope-interface(install version:5.1.0 version range:>=3.6.0)

Thanks for your help.
Best,
Neolith

Traceback during `unsonic config`

└> unsonic --version
unsonic (0.1.2, protocol: 0.1, subsonic protocol: 1.15.0) mishmash (0.3b5)

└> unsonic config
2018-01-27 19:02:41,878 DEBUG [unsonic][MainThread] Application._main: Namespace(VALUE=None, app=<unsonic.__main__.Unsonic object at 0x7fb074cd9dd8>, applyLoggingOpts=<function applyLoggingOpts at 0x7fb074014ae8>, command='config', command_func=<bound method Command.run of <unsonic.commands.config.Config object at 0x7fb06a4846d8>>, config=<unsonic.config.HereConfig object at 0x7fb06a499898>, config_show_default=False, db_url=None, debug_pdb=False, list=False, log_files=[], log_levels=[], set=None)
2018-01-27 19:02:41,878 DEBUG [mishmash.database][MainThread] Checking for database 'sqlite:////home/travis/devel/unsonic/venv/development.sqlite'
2018-01-27 19:02:41,881 INFO  [mishmash.database][MainThread] Creating database 'sqlite:////home/travis/devel/unsonic/venv/development.sqlite'
2018-01-27 19:02:41,882 ERROR [mishmash][MainThread] [Errno 2] No such file or directory: '/home/travis/devel/unsonic/venv/development.sqlite'
Traceback (most recent call last):
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/__main__.py", line 49, in main
    retval = args.command_func(args, args.config) or 0
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/core.py", line 22, in run
    self.db_conn) = database.init(self.config.db_url)
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/database.py", line 41, in init
    create_database(db_url, template="template0")
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/sqlalchemy_utils/functions/database.py", line 565, in create_database
    open(database, 'w').close()
FileNotFoundError: [Errno 2] No such file or directory: '/home/travis/devel/unsonic/venv/development.sqlite'
General error:
Traceback (most recent call last):
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/__main__.py", line 49, in main
    retval = args.command_func(args, args.config) or 0
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/core.py", line 22, in run
    self.db_conn) = database.init(self.config.db_url)
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/mishmash/database.py", line 41, in init
    create_database(db_url, template="template0")
  File "/home/travis/.virtualenvs/unsonic-0.1.x/lib/python3.6/site-packages/sqlalchemy_utils/functions/database.py", line 565, in create_database
    open(database, 'w').close()
FileNotFoundError: [Errno 2] No such file or directory: '/home/travis/devel/unsonic/venv/development.sqlite'

Update for 1.16 version of Subsonic API

The 1.16 version added RadioStations. Looks like just 4 new endpoints were added.

  • getInternetRadioStations
  • createInternetRadioStation
  • updateInternetRadioStation
  • deleteInternetRadioStation

Can't serve with v0.1.1

Expected behavior

$ unsonic -c ... serve 

Runs the Unsonic API server.

Actual behavior

Fails with exception:

$ bin/unsonic -c docker/config.ini serve
2018-01-23 12:52:30,396 ERROR [mishmash][MainThread] 'Serve' object has no attribute 'config'
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/mishmash/__main__.py", line 49, in main
    retval = args.command_func(args, args.config) or 0
  File "/Users/bschumac/src/repos/unsonic/unsonic/commands/serve.py", line 26, in run
    super()._run(args)
  File "/Users/bschumac/src/repos/unsonic/unsonic/commands/__init__.py", line 21, in _run
    initAlembic(self.config.get("mishmash", "sqlalchemy.url"))
AttributeError: 'Serve' object has no attribute 'config'
General error:
Traceback (most recent call last):
  File "/usr/local/lib/python3.6/site-packages/mishmash/__main__.py", line 49, in main
    retval = args.command_func(args, args.config) or 0
  File "/Users/bschumac/src/repos/unsonic/unsonic/commands/serve.py", line 26, in run
    super()._run(args)
  File "/Users/bschumac/src/repos/unsonic/unsonic/commands/__init__.py", line 21, in _run
    initAlembic(self.config.get("mishmash", "sqlalchemy.url"))
AttributeError: 'Serve' object has no attribute 'config'
2018-01-23 12:52:30,397 DEBUG [unsonic][MainThread] Application._atexit

This appears to be related to change ef3680a.

Steps to reproduce the behavior

Start Unsonic with serve.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.