ref!: various upgrades and fixes

Fixes #106

I'm not that versed in Python so I can't comment on a lot of this. I do however see code for the missing 'fs_uniquifier' columns as part of the upgrade() function. Hopefully this resolves the application errors you cited.

LGTM

@Diaoul I am trying to follow the Installation instructions for Development
I get an error when installing the dependencies with poetry:
Installing dependencies from lock file

Unable to read the lock file (Invalid statement (at line 428, column 1)).

indeed there are some git diff markers (like <<<<<<< HEAD) in the file

To fix the display of the Startable attribute, the definition of the startable field in the version table should be changed (add default=True) in models.py
    startable = db.Column(db.Boolean, default=True)

hey @Diaoul, I've been trying out the instructions in the new readme and I initially got stuck on the database table creation. I found a bug in the sequence for the migrations and corrected with https://github.com/SynoCommunity/spkrepo/pull/102/commits/b38660d6ff398c9ee0717d7720f4f4fca316f4ff. I'm now stuck at adding the admin account but I'm not sure how to fix. I see this:
$ flask users create username:admin<EMAIL_ADDRESS>--password adminadmin
/home/mreid/Documents/spkrepo/spkrepo/models.py:499: SAWarning: implicitly coercing SELECT object to scalar subquery; please use the .scalar_subquery() method to produce a scalar subquery.
  download_count = db.column_property(
/home/mreid/Documents/spkrepo/spkrepo/models.py:505: SAWarning: implicitly coercing SELECT object to scalar subquery; please use the .scalar_subquery() method to produce a scalar subquery.
  recent_download_count = db.column_property(
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.10/lib/python3.10/site-packages/flask_caching/__init__.py:119: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-30 08:56:21,543 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-30 08:56:21,543 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-30 08:56:21,544 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-30 08:56:21,544 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-30 08:56:21,544 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-30 08:56:21,544 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-30 08:56:21,545 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-30 08:56:21,549 INFO sqlalchemy.engine.Engine SELECT anon_1.user_id AS anon_1_user_id, anon_1.user_username AS anon_1_user_username, anon_1.user_email AS anon_1_user_email, anon_1.user_password AS anon_1_user_password, anon_1.user_api_key AS anon_1_user_api_key, anon_1.user_github_access_token AS anon_1_user_github_access_token, anon_1.user_fs_uniquifier AS anon_1_user_fs_uniquifier, anon_1.user_active AS anon_1_user_active, anon_1.user_confirmed_at AS anon_1_user_confirmed_at, role_1.id AS role_1_id, role_1.name AS role_1_name, role_1.description AS role_1_description
FROM (SELECT "user".id AS user_id, "user".username AS user_username, "user".email AS user_email, "user".password AS user_password, "user".api_key AS user_api_key, "user".github_access_token AS user_github_access_token, "user".fs_uniquifier AS user_fs_uniquifier, "user".active AS user_active, "user".confirmed_at AS user_confirmed_at
FROM "user"
WHERE lower("user".email) = lower(%(lower_1)s)
 LIMIT %(param_1)s) AS anon_1 LEFT OUTER JOIN (user_role AS user_role_1 JOIN role AS role_1 ON role_1.id = user_role_1.role_id) ON anon_1.user_id = user_role_1.user_id
2023-12-30 08:56:21,549 INFO sqlalchemy.engine.Engine [generated in 0.00013s] {'lower_1'<EMAIL_ADDRESS>'param_1': 1}
2023-12-30 08:56:21,551 INFO sqlalchemy.engine.Engine ROLLBACK
Usage: flask users create [OPTIONS] [ATTRIBUTES]...
Try 'flask users create --help' for help.

Error: Error creating user. {'username': ['This field is required.']}

As you can see it is complaining that the 'username' field is not determined even though it's in the command. I've been able to manually create a user with SQL and continue all the way to the login but I suspect this is an issue which may be contributing to other failures. Any thoughts on resolving?

As you can see it is complaining that the 'username' field is not determined even though it's in the command. I've been able to manually create a user with SQL and continue all the way to the login but I suspect this is an issue which may be contributing to other failures. Any thoughts on resolving?
P.S. I've also tried a number of variations of the command including the password option before the attributes but this had no effect.

I am facing the same issue.
Is solved it by creating the user with the following query:
insert into "user"(username, email, password, active, fs_uniquifier)
values ('admin'<EMAIL_ADDRESS>'adminadmin', true, 'ABC-1234');

I had to set the active and fs_uniquifier, since those fields are mandatory (not nullable).
With this, I was able to complete the installation with

Grant the created user with Administrator permissions flask roles add<EMAIL_ADDRESS>admin
Grant the created user with Package Administrator permissions flask roles add<EMAIL_ADDRESS>package_admin
Grant the created user with Developer permissions flask roles add<EMAIL_ADDRESS>developer

BTW: when I tried to create the user with flask users create and used --active paramerter and  fs_uniquifier:ABC-1234 I still got the  error: `Error: Error creating user. {'username': ['This field is required.']}
With this user, I am able to login into the admin pages.

The next error that pops up:
It is not possible to create an API Key:
it results in 500 (Internal Server Error)
From the logs of spkrepo I assume it is caused by a missing fs_uniquifier property.

I solved it by creating the user with the following query:
insert into "user"(username, email, password, active, fs_uniquifier)
values ('admin'<EMAIL_ADDRESS>'adminadmin', true, 'ABC-1234');

I had to set the active and fs_uniquifier, since those fields are mandatory (not nullable).

I also worked around the issue by simply registering the user at http://localhost:5000/register. Once the command was fired a user was created (along with the active and fs_uniquifier). Once that was done, I needed to manually update the email confirmation with:
update "user" set confirmed_at = current_timestamp where username = 'admin';

BTW: when I tried to create the user with flask users create and used --active paramerter and fs_uniquifier:ABC-1234 I still got the error: `Error: Error creating user. {'username': ['This field is required.']}
With this user, I am able to login into the admin pages.

I am also able to login to the admin pages but my raising this issue was more to address the root cause rather than document a workaround. I suspect something about the definition of how the app creates a user is not well defined and this is causing a problem with the flask command.

The next error that pops up:
It is not possible to create an API Key:
it results in 500 (Internal Server Error)

Fixed by including the additional required parameters for validate in https://github.com/SynoCommunity/spkrepo/pull/102/commits/d6ea8d603316cded1db65c3accde7de80475082f

rather than document a workaround.

I don't want to document a workaround too, but give hints on what might be wrong with the documented command to create the user with flask users create.

Based on my research, the flask users create will likely not work unless there is a definition for it. To quickly address this, I've re-implemented the create_user function which can be called similar to before:
flask spkrepo create_user -u admin -e<EMAIL_ADDRESS>-p adminadmin

Additionally, @hgy59, I've noted your concern in #106 and have rolled-back the changes to the frontend code in https://github.com/SynoCommunity/spkrepo/pull/102/commits/1aa2837e848f470eef7a22fc0494db0b210358f1.

Good work. Do you think we are able to fix some of the tests?
poetry run pytest -v

Good work. Do you think we are able to fix some of the tests?

Nah, the number of failed tests is currently:
spkrepo/tests/test_admin.py::IndexTestCase::test_admin FAILED            [  0%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous PASSED        [  1%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous_redirects_to_login FAILED [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_developer FAILED        [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_package_admin FAILED    [  3%]
spkrepo/tests/test_admin.py::IndexTestCase::test_user FAILED             [  4%]
[...]

This is the same outcome as before when I just started to work on this (https://github.com/SynoCommunity/spkrepo/pull/102/commits/f708234dcaf5ef874d31310f3eb30944b832d6e6):
spkrepo/tests/test_admin.py::IndexTestCase::test_admin FAILED            [  0%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous PASSED        [  1%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous_redirects_to_login FAILED [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_developer FAILED        [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_package_admin FAILED    [  3%]
spkrepo/tests/test_admin.py::IndexTestCase::test_user FAILED             [  4%]
[...]

What is interesting however is that the main branch has different results (https://github.com/SynoCommunity/spkrepo/commit/b3d6268fa9ad09672b63f51f5092289ff855e4dd):
spkrepo/tests/test_admin.py::IndexTestCase::test_admin PASSED            [  0%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous PASSED        [  1%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous_redirects_to_login FAILED [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_developer PASSED        [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_package_admin PASSED    [  3%]
spkrepo/tests/test_admin.py::IndexTestCase::test_user PASSED             [  4%]
[...]

As you see the tests with various logged in roles seem to have been successful before but not currently under this PR so I'm not sure what has changed.

I've removed some deprecation warnings, so you may want to pull changes and run poety install before making changes.

@publicarray all tests successful now. I think we need to update the version of the dependency pillow from 8.3.2 to 9.5.0 which is compatible with Python 3.11. I'm not familiar with updating these dependencies so I just manually did this in my test environment:
poetry add pillow==9.5

If you can assist with a commit for this it would be appreciated.

@publicarray all tests successful now. I think we need to update the version of the dependency pillow from 8.3.2 to 9.5.0 which is compatible with Python 3.11. I'm not familiar with updating these dependencies so I just manually did this in my test environment:
poetry add pillow==9.5

EDIT: I think I've updated it. However I think I broke something. On further checking it seems that the dependency for Werkzeug needs to be restricted to less than 3.0.0 as this version causes most of the api test post checks to fail.

@publicarray, I've rebuilt my environment and ran a number of tests which all look good. I didn't use docker as stated in the readme but the rest of it was pretty much the same. Below are my logs for reference:
Installation

Python Install
$ pyenv install 3.11
Downloading Python-3.11.7.tar.xz...
-> https://www.python.org/ftp/python/3.11.7/Python-3.11.7.tar.xz
Installing Python-3.11.7...
Installed Python-3.11.7 to /home/mreid/.pyenv/versions/3.11.7
$ pyenv local 3.11.7

Source repo install
$ git clone https://github.com/SynoCommunity/spkrepo
Cloning into 'spkrepo'...
remote: Enumerating objects: 880, done.
remote: Counting objects: 100% (339/339), done.
remote: Compressing objects: 100% (179/179), done.
remote: Total 880 (delta 206), reused 278 (delta 159), pack-reused 541
Receiving objects: 100% (880/880), 709.62 KiB | 2.42 MiB/s, done.
Resolving deltas: 100% (486/486), done.
$ cd spkrepo/
$ git pull origin pull/102/head
From https://github.com/SynoCommunity/spkrepo
 * branch            refs/pull/102/head -> FETCH_HEAD
Updating b3d6268..6d8df77
Fast-forward
 .flake8                                            |    2 +-
 .github/workflows/build.yml                        |   24 +-
 .github/workflows/publish.yml                      |   30 +-
 .pre-commit-config.yaml                            |   15 +-
 .python-version                                    |    1 -
 Dockerfile                                         |    2 +-
 README.md                                          |   54 +-
 docker-compose.yaml                                |   30 +-
 .../versions/76d559b4e873_add_fs_uniquifier.py     |   28 +
 .../d429595e8362_update_build_path_length.py       |    6 +-
 ...785f1fb2307_.py => d785f1fb2307_dsm6_fields.py} |    0
 ...a7_.py => dc7687894ba7_increase_field_sizes.py} |    2 +-
 poetry.lock                                        | 2417 ++++++++++----------
 pyproject.toml                                     |   48 +-
 requirements.txt                                   |  878 +++----
 spkrepo/app.py                                     |    8 +
 manage.py => spkrepo/cli.py                        |  111 +-
 spkrepo/config.py                                  |    3 +-
 spkrepo/models.py                                  |   20 +-
 spkrepo/templates/frontend/package.html            |    2 -
 spkrepo/tests/common.py                            |   29 +-
 spkrepo/tests/test_admin.py                        |   19 +-
 spkrepo/tests/test_api.py                          |   32 +-
 spkrepo/tests/test_frontend.py                     |   40 +-
 spkrepo/tests/test_nas.py                          |   34 +-
 spkrepo/views/api.py                               |   14 +-
 spkrepo/views/frontend.py                          |    6 +-
 27 files changed, 1880 insertions(+), 1975 deletions(-)
 delete mode 100644 .python-version
 create mode 100644 migrations/versions/76d559b4e873_add_fs_uniquifier.py
 rename migrations/versions/{d785f1fb2307_.py => d785f1fb2307_dsm6_fields.py} (100%)
 rename migrations/versions/{dc7687894ba7_.py => dc7687894ba7_increase_field_sizes.py} (98%)
 rename manage.py => spkrepo/cli.py (72%)

App environment setup
$ poetry env use 3.11.7
Creating virtualenv spkrepo-DHYObr5C-py3.11 in /home/mreid/.cache/pypoetry/virtualenvs
Using virtualenv: /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11
$ poetry install
Installing dependencies from lock file

Package operations: 80 installs, 1 update, 0 removals

  • Installing certifi (2023.11.17)
  • Installing charset-normalizer (3.3.2)
  • Installing idna (3.6)
  • Installing markupsafe (2.1.3)
  • Installing urllib3 (2.1.0)
  • Installing alabaster (0.7.13)
  • Installing babel (2.14.0)
  • Installing blinker (1.7.0)
  • Installing click (8.1.7)
  • Installing docutils (0.20.1)
  • Installing greenlet (3.0.3)
  • Installing imagesize (1.4.1)
  • Installing itsdangerous (2.1.2)
  • Installing jinja2 (3.1.2)
  • Installing packaging (23.2)
  • Installing pygments (2.17.2)
  • Installing requests (2.31.0)
  • Installing six (1.16.0)
  • Installing snowballstemmer (2.2.0)
  • Installing sphinxcontrib-applehelp (1.0.7)
  • Installing sphinxcontrib-devhelp (1.0.5)
  • Installing sphinxcontrib-htmlhelp (2.0.4)
  • Installing sphinxcontrib-jsmath (1.0.1)
  • Installing sphinxcontrib-qthelp (1.0.6)
  • Installing sphinxcontrib-serializinghtml (1.1.9)
  • Installing werkzeug (2.3.8)
  • Installing distlib (0.3.8)
  • Installing dnspython (2.4.2)
  • Installing filelock (3.13.1)
  • Installing flask (2.3.3)
  • Installing mako (1.3.0)
  • Installing platformdirs (4.1.0)
  • Installing python-dateutil (2.8.2)
  • Updating setuptools (69.0.2 -> 69.0.3)
  • Installing sphinx (7.2.6)
  • Installing sqlalchemy (1.4.50)
  • Installing typing-extensions (4.9.0)
  • Installing wtforms (3.1.1)
  • Installing alembic (1.13.1)
  • Installing aniso8601 (9.0.1)
  • Installing cachelib (0.9.0)
  • Installing cfgv (3.4.0)
  • Installing email-validator (2.1.0.post1)
  • Installing faker (15.3.4)
  • Installing flask-login (0.6.3)
  • Installing flask-principal (0.4.0)
  • Installing flask-sqlalchemy (3.0.5)
  • Installing flask-wtf (1.2.1)
  • Installing identify (2.5.33)
  • Installing importlib-resources (6.1.1)
  • Installing iniconfig (2.0.0)
  • Installing nodeenv (1.8.0)
  • Installing passlib (1.7.4)
  • Installing pluggy (1.3.0)
  • Installing pytz (2023.3.post1)
  • Installing pyyaml (6.0.1)
  • Installing sphinxcontrib-jquery (4.1)
  • Installing virtualenv (20.25.0)
  • Installing bcrypt (4.1.2)
  • Installing configparser (5.3.0)
  • Installing factory-boy (3.3.0)
  • Installing flask-admin (1.6.1)
  • Installing flask-babel (4.0.0)
  • Installing flask-caching (2.1.0)
  • Installing flask-debugtoolbar (0.14.1)
  • Installing flask-migrate (4.0.5)
  • Installing flask-restful (0.3.10)
  • Installing flask-mail (0.9.1)
  • Installing flask-security-too (5.3.3)
  • Installing flask-testing (0.8.1)
  • Installing ipaddress (1.0.23)
  • Installing lxml (4.9.4)
  • Installing mock (4.0.3)
  • Installing pillow (9.5.0)
  • Installing pre-commit (3.6.0)
  • Installing psycopg2 (2.9.9)
  • Installing pytest (7.4.4)
  • Installing python-gnupg (0.5.2)
  • Installing redis (4.6.0)
  • Installing sphinx-rtd-theme (2.0.0)
  • Installing text-unidecode (1.3)

Installing the current project: spkrepo (0.2.3)

App initial setup

Create database
$ poetry shell
$ flask db upgrade
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(

Populate database
$ flask spkrepo populate_db
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-31 15:03:37,077 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-31 15:03:37,077 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:37,077 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-31 15:03:37,078 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:37,078 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-31 15:03:37,078 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:37,078 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-31 15:03:37,079 INFO sqlalchemy.engine.Engine SELECT service.id AS service_id, service.code AS service_code
FROM service
2023-12-31 15:03:37,079 INFO sqlalchemy.engine.Engine [generated in 0.00012s] {}
2023-12-31 15:03:37,081 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,081 INFO sqlalchemy.engine.Engine [generated in 0.00017s] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,082 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,082 INFO sqlalchemy.engine.Engine [cached since 0.001285s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,114 INFO sqlalchemy.engine.Engine SELECT service.id AS service_id, service.code AS service_code
FROM service
2023-12-31 15:03:37,114 INFO sqlalchemy.engine.Engine [cached since 0.03463s ago] {}
2023-12-31 15:03:37,115 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,115 INFO sqlalchemy.engine.Engine [cached since 0.03407s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,116 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,116 INFO sqlalchemy.engine.Engine [cached since 0.03537s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,154 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,155 INFO sqlalchemy.engine.Engine [generated in 0.00052s] {}
2023-12-31 15:03:37,156 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,156 INFO sqlalchemy.engine.Engine [generated in 0.00022s] {'code_1': 'noarch'}
2023-12-31 15:03:37,208 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,208 INFO sqlalchemy.engine.Engine [cached since 0.0543s ago] {}
2023-12-31 15:03:37,209 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,209 INFO sqlalchemy.engine.Engine [cached since 0.05296s ago] {'code_1': 'noarch'}
2023-12-31 15:03:37,308 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,309 INFO sqlalchemy.engine.Engine [cached since 0.2277s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,309 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,309 INFO sqlalchemy.engine.Engine [cached since 0.2286s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,342 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,342 INFO sqlalchemy.engine.Engine [cached since 0.2613s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,343 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,343 INFO sqlalchemy.engine.Engine [cached since 0.2621s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,385 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,385 INFO sqlalchemy.engine.Engine [generated in 0.00047s] {'code_1': 'noarch', 'param_1': 1}
2023-12-31 15:03:37,386 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,386 INFO sqlalchemy.engine.Engine [cached since 0.2323s ago] {}
2023-12-31 15:03:37,415 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,415 INFO sqlalchemy.engine.Engine [cached since 0.03005s ago] {'code_1': 'noarch', 'param_1': 1}
2023-12-31 15:03:37,416 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,416 INFO sqlalchemy.engine.Engine [cached since 0.2619s ago] {}
2023-12-31 15:03:37,486 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,486 INFO sqlalchemy.engine.Engine [cached since 0.4055s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,487 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,487 INFO sqlalchemy.engine.Engine [cached since 0.4064s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,519 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,519 INFO sqlalchemy.engine.Engine [cached since 0.4387s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,520 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,520 INFO sqlalchemy.engine.Engine [cached since 0.4394s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,555 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,555 INFO sqlalchemy.engine.Engine [cached since 0.4011s ago] {}
2023-12-31 15:03:37,556 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,556 INFO sqlalchemy.engine.Engine [cached since 0.3999s ago] {'code_1': 'noarch'}
2023-12-31 15:03:37,638 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,638 INFO sqlalchemy.engine.Engine [cached since 0.4835s ago] {}
2023-12-31 15:03:37,638 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,638 INFO sqlalchemy.engine.Engine [cached since 0.482s ago] {'code_1': 'noarch'}
2023-12-31 15:03:37,761 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,761 INFO sqlalchemy.engine.Engine [cached since 0.6801s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,761 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,762 INFO sqlalchemy.engine.Engine [cached since 0.6807s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,787 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,787 INFO sqlalchemy.engine.Engine [cached since 0.7062s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,788 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,788 INFO sqlalchemy.engine.Engine [cached since 0.7071s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,828 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,828 INFO sqlalchemy.engine.Engine [cached since 0.7472s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,829 INFO sqlalchemy.engine.Engine SELECT language.id AS language_id, language.code AS language_code, language.name AS language_name
FROM language
WHERE language.code = %(code_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:37,829 INFO sqlalchemy.engine.Engine [cached since 0.7479s ago] {'code_1': 'enu', 'param_1': 1}
2023-12-31 15:03:37,861 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,861 INFO sqlalchemy.engine.Engine [cached since 0.707s ago] {}
2023-12-31 15:03:37,862 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,862 INFO sqlalchemy.engine.Engine [cached since 0.706s ago] {'code_1': 'noarch'}
2023-12-31 15:03:37,948 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:37,948 INFO sqlalchemy.engine.Engine [cached since 0.7935s ago] {}
2023-12-31 15:03:37,948 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:37,948 INFO sqlalchemy.engine.Engine [cached since 0.792s ago] {'code_1': 'noarch'}
2023-12-31 15:03:38,035 INFO sqlalchemy.engine.Engine SELECT firmware.id AS firmware_id, firmware.version AS firmware_version, firmware.build AS firmware_build
FROM firmware
2023-12-31 15:03:38,035 INFO sqlalchemy.engine.Engine [cached since 0.8809s ago] {}
2023-12-31 15:03:38,036 INFO sqlalchemy.engine.Engine SELECT architecture.id AS architecture_id, architecture.code AS architecture_code
FROM architecture
WHERE architecture.code != %(code_1)s
2023-12-31 15:03:38,036 INFO sqlalchemy.engine.Engine [cached since 0.8794s ago] {'code_1': 'noarch'}
2023-12-31 15:03:38,127 INFO sqlalchemy.engine.Engine INSERT INTO package (author_user_id, name, insert_date) VALUES (%(author_user_id)s, %(name)s, now()) RETURNING package.id
2023-12-31 15:03:38,127 INFO sqlalchemy.engine.Engine [generated in 0.00012s] ({'author_user_id': None, 'name': 'nzbget'}, {'author_user_id': None, 'name': 'sickbeard'}, {'author_user_id': None, 'name': 'git'}, {'author_user_id': None, 'name': 'bitlbee'})
2023-12-31 15:03:38,129 INFO sqlalchemy.engine.Engine INSERT INTO screenshot (package_id, path) VALUES (%(package_id)s, %(path)s) RETURNING screenshot.id
2023-12-31 15:03:38,130 INFO sqlalchemy.engine.Engine [generated in 0.00007s] ({'package_id': 1, 'path': 'nzbget/screenshot_0.png'}, {'package_id': 2, 'path': 'sickbeard/screenshot_0.png'}, {'package_id': 3, 'path': 'git/screenshot_0.png'}, {'package_id': 4, 'path': 'bitlbee/screenshot_0.png'})
2023-12-31 15:03:38,131 INFO sqlalchemy.engine.Engine INSERT INTO version (package_id, version, upstream_version, changelog, report_url, distributor, distributor_url, maintainer, maintainer_url, dependencies, conf_dependencies, conflicts, conf_conflicts, conf_privilege, conf_resource, install_wizard, upgrade_wizard, startable, license, insert_date) VALUES (%(package_id)s, %(version)s, %(upstream_version)s, %(changelog)s, %(report_url)s, %(distributor)s, %(distributor_url)s, %(maintainer)s, %(maintainer_url)s, %(dependencies)s, %(conf_dependencies)s, %(conflicts)s, %(conf_conflicts)s, %(conf_privilege)s, %(conf_resource)s, %(install_wizard)s, %(upgrade_wizard)s, %(startable)s, %(license)s, now()) RETURNING version.id
2023-12-31 15:03:38,131 INFO sqlalchemy.engine.Engine [generated in 0.00014s] ({'package_id': 1, 'version': 10, 'upstream_version': '12.0', 'changelog': 'Early coach fast you administration prevent nearly.', 'report_url': None, 'distributor': 'Brian Warren', 'distributor_url': 'http://cline-moran.com/', 'maintainer': 'Cynthia Holloway', 'maintainer_url': 'http://torres.com/', 'dependencies': None, 'conf_dependencies': '{"standard": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'name', 'conf_conflicts': '{"cover": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': True, 'upgrade_wizard': False, 'startable': None, 'license': 'Deal game debate hour. Six benefit finish. Subject case produce doctor.\nPull seat above together sometimes. Suffer hour those reality.\nTest hair minute southern think.'}, {'package_id': 1, 'version': 11, 'upstream_version': '13.0', 'changelog': 'Across common around ahead citizen loss thank.', 'report_url': None, 'distributor': 'James Curtis', 'distributor_url': 'http://carr-james.net/', 'maintainer': 'Brittany Miller', 'maintainer_url': 'https://moore-miller.biz/', 'dependencies': None, 'conf_dependencies': '{"matter": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'quickly', 'conf_conflicts': '{"cold": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': True, 'upgrade_wizard': False, 'startable': None, 'license': 'Glass then last necessary. Finish performance town single leader. Able none home plant this.'}, {'package_id': 2, 'version': 3, 'upstream_version': '20140528', 'changelog': 'Area soon knowledge.', 'report_url': None, 'distributor': 'Anthony Jefferson', 'distributor_url': 'https://www.wong.biz/', 'maintainer': 'Jennifer Rodriguez', 'maintainer_url': 'http://www.chan.org/', 'dependencies': 'git', 'conf_dependencies': '{"control": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'have', 'conf_conflicts': '{"those": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': True, 'license': 'Really sister use. Decide letter table interview rock want person.\nNewspaper skill relationship sound practice pay bed. Current TV law.'}, {'package_id': 2, 'version': 4, 'upstream_version': '20140702', 'changelog': 'Cut cause use less his not hotel people.', 'report_url': None, 'distributor': 'Crystal Mcguire', 'distributor_url': 'http://www.harris-patterson.biz/', 'maintainer': 'Timothy Caldwell', 'maintainer_url': 'https://www.garza.org/', 'dependencies': 'git', 'conf_dependencies': '{"develop": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'method', 'conf_conflicts': '{"social": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': True, 'license': 'Find other computer camera clear baby second probably. Arrive whose actually politics follow. Sea security coach management south.'}, {'package_id': 3, 'version': 3, 'upstream_version': '1.8.4', 'changelog': 'Structure person test.', 'report_url': None, 'distributor': 'Dana Brown', 'distributor_url': 'https://castillo-davis.net/', 'maintainer': 'Patricia Carter', 'maintainer_url': 'https://www.anderson.com/', 'dependencies': None, 'conf_dependencies': '{"performance": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'spring', 'conf_conflicts': '{"defense": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': False, 'license': 'Director point become occur he. Front step stay conference ago citizen. Poor Mrs history glass respond cause water. Evidence make agency few machine capital.'}, {'package_id': 3, 'version': 4, 'upstream_version': '2.1.2', 'changelog': 'A money check impact art improve very front.', 'report_url': None, 'distributor': 'Nicole Williamson', 'distributor_url': 'https://berger.com/', 'maintainer': 'Elizabeth Bush', 'maintainer_url': 'https://www.cruz-robinson.info/', 'dependencies': None, 'conf_dependencies': '{"how": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'weight', 'conf_conflicts': '{"stop": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': False, 'license': 'Same protect hand often sit look very. It center mean already.\nOrder agency team trip. Attack first state back anyone local. Main draw door east.'}, {'package_id': 4, 'version': 9, 'upstream_version': '3.2.2', 'changelog': 'Specific fill certain consider skin we rate.', 'report_url': None, 'distributor': 'Donna Oliver', 'distributor_url': 'http://nunez.com/', 'maintainer': 'Jeffery Graves', 'maintainer_url': 'https://www.adams.com/', 'dependencies': None, 'conf_dependencies': '{"there": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'finish', 'conf_conflicts': '{"growth": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': True, 'license': 'Candidate kind significant after piece. Dream according player just next.\nPut film change decade more card. Simply painting hour rate recently minute.'}, {'package_id': 4, 'version': 10, 'upstream_version': '3.2.3', 'changelog': 'Consider exactly move happen rock short maintain.', 'report_url': None, 'distributor': 'Nicholas Mcfarland', 'distributor_url': 'https://www.miller.com/', 'maintainer': 'Elizabeth Collins', 'maintainer_url': 'http://www.oliver.com/', 'dependencies': None, 'conf_dependencies': '{"history": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'cause', 'conf_conflicts': '{"carry": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': True, 'license': 'Able blood look north player. Ball certainly later but kitchen event.\nFear someone drop or wear black. Her house team. Support west customer rule.'}, {'package_id': 4, 'version': 11, 'upstream_version': '3.3.0', 'changelog': 'Choose keep gun executive season quite nothing.', 'report_url': 'https://edwards-smith.com/', 'distributor': 'Mr. Stephen Gibson', 'distributor_url': 'http://www.brown.com/', 'maintainer': 'Ricardo Bauer', 'maintainer_url': 'http://www.bradshaw.com/', 'dependencies': None, 'conf_dependencies': '{"stuff": {"dsm_min_ver": "5.0-4300"}}', 'conflicts': 'nothing', 'conf_conflicts': '{"half": {"dsm_min_ver": "5.0-4300"}}', 'conf_privilege': '{"defaults": {"run-as": "root"}}', 'conf_resource': '{"usr-local-linker": {"lib": ["lib/foo"], "bin": ["bin/foo"], "etc": ["etc/foo"]}}', 'install_wizard': False, 'upgrade_wizard': False, 'startable': True, 'license': 'Road kid billion suffer. Development team evening street gun crime these.'})
2023-12-31 15:03:38,132 INFO sqlalchemy.engine.Engine INSERT INTO version_service_dependency (version_id, service_id) VALUES (%(version_id)s, %(service_id)s)
2023-12-31 15:03:38,132 INFO sqlalchemy.engine.Engine [generated in 0.00006s] ({'version_id': 2, 'service_id': 2}, {'version_id': 1, 'service_id': 1})
2023-12-31 15:03:38,133 INFO sqlalchemy.engine.Engine INSERT INTO build (version_id, firmware_id, publisher_user_id, checksum, extract_size, path, md5, insert_date, active) VALUES (%(version_id)s, %(firmware_id)s, %(publisher_user_id)s, %(checksum)s, %(extract_size)s, %(path)s, %(md5)s, now(), %(active)s) RETURNING build.id
2023-12-31 15:03:38,133 INFO sqlalchemy.engine.Engine [generated in 0.00011s] ({'version_id': 1, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'nzbget/10/nzbget.v10.f731[ppc824x].spk', 'md5': '638d1d365d50ccd568364bf0245176a8', 'active': True}, {'version_id': 1, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'nzbget/10/nzbget.v10.f731[ppc854x].spk', 'md5': '1ab7ded4fa9ddd6a358d5bef89c165b5', 'active': True}, {'version_id': 2, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'nzbget/11/nzbget.v11.f731[ppc824x].spk', 'md5': '5f990a6f2869b9bf988c093a120ef502', 'active': True}, {'version_id': 2, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'nzbget/11/nzbget.v11.f731[ppc854x].spk', 'md5': 'ab4cbecb7a8833e22c7f9f89573936d7', 'active': True}, {'version_id': 3, 'firmware_id': 4, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'sickbeard/3/sickbeard.v3.f1139[noarch].spk', 'md5': '2fd167436f081088f4d1707fe93863fe', 'active': True}, {'version_id': 4, 'firmware_id': 2, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'sickbeard/4/sickbeard.v4.f844[noarch].spk', 'md5': '163275ead303fd30766b053c76fd5923', 'active': True}, {'version_id': 5, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'git/3/git.v3.f731[ppc824x].spk', 'md5': 'b1df658deda884f8a7e879989a3d5931', 'active': True}, {'version_id': 5, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'git/3/git.v3.f731[ppc854x].spk', 'md5': '5cf9120545323d8db4dfcf255edc4428', 'active': True}  ... displaying 10 of 21 total bound parameter sets ...  {'version_id': 9, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'bitlbee/11/bitlbee.v11.f731[ppc854x].spk', 'md5': '363b1e5c716a1e650a73d89ee5c606fa', 'active': True}, {'version_id': 9, 'firmware_id': 1, 'publisher_user_id': None, 'checksum': None, 'extract_size': None, 'path': 'bitlbee/11/bitlbee.v11.f731[ppc853x].spk', 'md5': 'fce8b5ed358e033aefdc6615e68fd42d', 'active': True})
2023-12-31 15:03:38,134 INFO sqlalchemy.engine.Engine INSERT INTO description (version_id, language_id, description) VALUES (%(version_id)s, %(language_id)s, %(description)s)
2023-12-31 15:03:38,134 INFO sqlalchemy.engine.Engine [generated in 0.00007s] ({'version_id': 1, 'language_id': 1, 'description': 'Plant agency hope real in. Film fire them public. Within more may buy. Tough statement hotel traditional option. Hot attention middle catch sound.'}, {'version_id': 2, 'language_id': 1, 'description': 'Customer major early off important color. Certain sit successful trouble. Book agent behavior stay full. Reflect modern country question economic as. Tough help American type real heavy.'}, {'version_id': 3, 'language_id': 1, 'description': 'Carry either risk I career challenge. Beautiful maybe school one live still discover. Nearly work condition nor subject. Threat fill picture minute response. Detail none oil total two conference.'}, {'version_id': 4, 'language_id': 1, 'description': 'Reveal prevent pretty store. Language hair experience learn some safe. Listen may determine chair century money involve understand. Today spring color star garden radio blood nature. Cover hope interesting relate see land.'}, {'version_id': 5, 'language_id': 1, 'description': 'Loss four oil question three beyond public. Property something knowledge garden year already. Another know than newspaper total of. Democratic camera seven charge far article. Whose debate range despite.'}, {'version_id': 6, 'language_id': 1, 'description': 'Page should project draw. Measure discuss bring. Dog exactly water increase professor history. Most rise art suddenly. Everyone difference seek involve.'}, {'version_id': 7, 'language_id': 1, 'description': 'Event cell happen line. Reveal fish hit already. Community fear than president. Around billion want. Receive first leave here property five different.'}, {'version_id': 8, 'language_id': 1, 'description': 'Difficult those even. Ten difficult seek them help.  Notice treat goal election better. No site human event environmental three sure.'}, {'version_id': 9, 'language_id': 1, 'description': 'Employee decade hope son road. Professional board some. Program maybe reach argue property night. Employee region late. Early conference money there.'})
2023-12-31 15:03:38,135 INFO sqlalchemy.engine.Engine INSERT INTO displayname (version_id, language_id, displayname) VALUES (%(version_id)s, %(language_id)s, %(displayname)s)
2023-12-31 15:03:38,135 INFO sqlalchemy.engine.Engine [generated in 0.00006s] ({'version_id': 1, 'language_id': 1, 'displayname': 'Nzbget'}, {'version_id': 2, 'language_id': 1, 'displayname': 'Nzbget'}, {'version_id': 3, 'language_id': 1, 'displayname': 'Sickbeard'}, {'version_id': 4, 'language_id': 1, 'displayname': 'Sickbeard'}, {'version_id': 5, 'language_id': 1, 'displayname': 'Git'}, {'version_id': 6, 'language_id': 1, 'displayname': 'Git'}, {'version_id': 7, 'language_id': 1, 'displayname': 'Bitlbee'}, {'version_id': 8, 'language_id': 1, 'displayname': 'Bitlbee'}, {'version_id': 9, 'language_id': 1, 'displayname': 'Bitlbee'})
2023-12-31 15:03:38,136 INFO sqlalchemy.engine.Engine INSERT INTO icon (version_id, size, path) VALUES (%(version_id)s, %(size)s, %(path)s) RETURNING icon.id
2023-12-31 15:03:38,136 INFO sqlalchemy.engine.Engine [generated in 0.00007s] ({'version_id': 1, 'size': '72', 'path': 'nzbget/10/icon_72.png'}, {'version_id': 2, 'size': '72', 'path': 'nzbget/11/icon_72.png'}, {'version_id': 3, 'size': '72', 'path': 'sickbeard/3/icon_72.png'}, {'version_id': 4, 'size': '72', 'path': 'sickbeard/4/icon_72.png'}, {'version_id': 5, 'size': '72', 'path': 'git/3/icon_72.png'}, {'version_id': 6, 'size': '72', 'path': 'git/4/icon_72.png'}, {'version_id': 7, 'size': '72', 'path': 'bitlbee/9/icon_72.png'}, {'version_id': 8, 'size': '72', 'path': 'bitlbee/10/icon_72.png'}, {'version_id': 9, 'size': '72', 'path': 'bitlbee/11/icon_72.png'})
2023-12-31 15:03:38,137 INFO sqlalchemy.engine.Engine INSERT INTO build_architecture (build_id, architecture_id) VALUES (%(build_id)s, %(architecture_id)s)
2023-12-31 15:03:38,137 INFO sqlalchemy.engine.Engine [generated in 0.00007s] ({'build_id': 8, 'architecture_id': 3}, {'build_id': 3, 'architecture_id': 2}, {'build_id': 13, 'architecture_id': 2}, {'build_id': 19, 'architecture_id': 2}, {'build_id': 10, 'architecture_id': 2}, {'build_id': 2, 'architecture_id': 3}, {'build_id': 20, 'architecture_id': 3}, {'build_id': 11, 'architecture_id': 3}  ... displaying 10 of 21 total bound parameter sets ...  {'build_id': 9, 'architecture_id': 4}, {'build_id': 14, 'architecture_id': 3})
2023-12-31 15:03:38,138 INFO sqlalchemy.engine.Engine COMMIT

Setup admin account

Create account
$ flask spkrepo create_user -u admin -e<EMAIL_ADDRESS>-p adminadmin
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-31 15:03:44,759 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-31 15:03:44,759 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:44,759 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-31 15:03:44,760 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:44,760 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-31 15:03:44,760 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:44,760 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-31 15:03:44,761 INFO sqlalchemy.engine.Engine INSERT INTO "user" (username, email, password, api_key, github_access_token, fs_uniquifier, active, confirmed_at) VALUES (%(username)s, %(email)s, %(password)s, %(api_key)s, %(github_access_token)s, %(fs_uniquifier)s, %(active)s, %(confirmed_at)s) RETURNING "user".id
2023-12-31 15:03:44,761 INFO sqlalchemy.engine.Engine [generated in 0.00011s] {'username': 'admin', 'email'<EMAIL_ADDRESS>'password': '$6$rounds=656000$3IdHQ418bv/V/zAp$M7HTms0eLFUsbUo.Az1vFvTRnMPt83YpPtm1dASOoZU1TfXyy1Skx7fu37eZR6xdxwjFRy0jr47XHKt9T9QIn1', 'api_key': 'df56639fb20eb2576dc2461e611bd6293a18c0fff8fda3608479cdc23f0e430a', 'github_access_token': None, 'fs_uniquifier': '8bf5e2d6ea1e1fcf28599985f80ec7f2', 'active': True, 'confirmed_at': datetime.datetime(2023, 12, 31, 15, 3, 44, 203974)}
2023-12-31 15:03:44,762 INFO sqlalchemy.engine.Engine COMMIT

Add account roles
$ flask roles add<EMAIL_ADDRESS>admin
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-31 15:03:54,591 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-31 15:03:54,591 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:54,592 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-31 15:03:54,592 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:54,592 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-31 15:03:54,592 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:03:54,593 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-31 15:03:54,596 INFO sqlalchemy.engine.Engine SELECT anon_1.user_id AS anon_1_user_id, anon_1.user_username AS anon_1_user_username, anon_1.user_email AS anon_1_user_email, anon_1.user_password AS anon_1_user_password, anon_1.user_api_key AS anon_1_user_api_key, anon_1.user_github_access_token AS anon_1_user_github_access_token, anon_1.user_fs_uniquifier AS anon_1_user_fs_uniquifier, anon_1.user_active AS anon_1_user_active, anon_1.user_confirmed_at AS anon_1_user_confirmed_at, role_1.id AS role_1_id, role_1.name AS role_1_name, role_1.description AS role_1_description
FROM (SELECT "user".id AS user_id, "user".username AS user_username, "user".email AS user_email, "user".password AS user_password, "user".api_key AS user_api_key, "user".github_access_token AS user_github_access_token, "user".fs_uniquifier AS user_fs_uniquifier, "user".active AS user_active, "user".confirmed_at AS user_confirmed_at
FROM "user"
WHERE lower("user".email) = lower(%(lower_1)s)
 LIMIT %(param_1)s) AS anon_1 LEFT OUTER JOIN (user_role AS user_role_1 JOIN role AS role_1 ON role_1.id = user_role_1.role_id) ON anon_1.user_id = user_role_1.user_id
2023-12-31 15:03:54,596 INFO sqlalchemy.engine.Engine [generated in 0.00033s] {'lower_1'<EMAIL_ADDRESS>'param_1': 1}
2023-12-31 15:03:54,598 INFO sqlalchemy.engine.Engine SELECT role.id AS role_id, role.name AS role_name, role.description AS role_description
FROM role
WHERE role.name = %(name_1)s
 LIMIT %(param_1)s
2023-12-31 15:03:54,599 INFO sqlalchemy.engine.Engine [generated in 0.00026s] {'name_1': 'admin', 'param_1': 1}
Role "admin" added to user<EMAIL_ADDRESS>successfully.
2023-12-31 15:03:54,601 INFO sqlalchemy.engine.Engine INSERT INTO user_role (user_id, role_id) VALUES (%(user_id)s, %(role_id)s)
2023-12-31 15:03:54,601 INFO sqlalchemy.engine.Engine [generated in 0.00024s] {'user_id': 1, 'role_id': 1}
2023-12-31 15:03:54,602 INFO sqlalchemy.engine.Engine COMMIT
$ flask roles add<EMAIL_ADDRESS>package_admin
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-31 15:04:02,314 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-31 15:04:02,315 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:02,315 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-31 15:04:02,315 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:02,316 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-31 15:04:02,316 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:02,316 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-31 15:04:02,319 INFO sqlalchemy.engine.Engine SELECT anon_1.user_id AS anon_1_user_id, anon_1.user_username AS anon_1_user_username, anon_1.user_email AS anon_1_user_email, anon_1.user_password AS anon_1_user_password, anon_1.user_api_key AS anon_1_user_api_key, anon_1.user_github_access_token AS anon_1_user_github_access_token, anon_1.user_fs_uniquifier AS anon_1_user_fs_uniquifier, anon_1.user_active AS anon_1_user_active, anon_1.user_confirmed_at AS anon_1_user_confirmed_at, role_1.id AS role_1_id, role_1.name AS role_1_name, role_1.description AS role_1_description
FROM (SELECT "user".id AS user_id, "user".username AS user_username, "user".email AS user_email, "user".password AS user_password, "user".api_key AS user_api_key, "user".github_access_token AS user_github_access_token, "user".fs_uniquifier AS user_fs_uniquifier, "user".active AS user_active, "user".confirmed_at AS user_confirmed_at
FROM "user"
WHERE lower("user".email) = lower(%(lower_1)s)
 LIMIT %(param_1)s) AS anon_1 LEFT OUTER JOIN (user_role AS user_role_1 JOIN role AS role_1 ON role_1.id = user_role_1.role_id) ON anon_1.user_id = user_role_1.user_id
2023-12-31 15:04:02,319 INFO sqlalchemy.engine.Engine [generated in 0.00024s] {'lower_1'<EMAIL_ADDRESS>'param_1': 1}
2023-12-31 15:04:02,321 INFO sqlalchemy.engine.Engine SELECT role.id AS role_id, role.name AS role_name, role.description AS role_description
FROM role
WHERE role.name = %(name_1)s
 LIMIT %(param_1)s
2023-12-31 15:04:02,321 INFO sqlalchemy.engine.Engine [generated in 0.00019s] {'name_1': 'package_admin', 'param_1': 1}
Role "package_admin" added to user<EMAIL_ADDRESS>successfully.
2023-12-31 15:04:02,323 INFO sqlalchemy.engine.Engine INSERT INTO user_role (user_id, role_id) VALUES (%(user_id)s, %(role_id)s)
2023-12-31 15:04:02,323 INFO sqlalchemy.engine.Engine [generated in 0.00010s] {'user_id': 1, 'role_id': 2}
2023-12-31 15:04:02,323 INFO sqlalchemy.engine.Engine COMMIT
$ flask roles add<EMAIL_ADDRESS>developer
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
2023-12-31 15:04:10,889 INFO sqlalchemy.engine.Engine select pg_catalog.version()
2023-12-31 15:04:10,889 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:10,897 INFO sqlalchemy.engine.Engine select current_schema()
2023-12-31 15:04:10,897 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:10,897 INFO sqlalchemy.engine.Engine show standard_conforming_strings
2023-12-31 15:04:10,898 INFO sqlalchemy.engine.Engine [raw sql] {}
2023-12-31 15:04:10,898 INFO sqlalchemy.engine.Engine BEGIN (implicit)
2023-12-31 15:04:10,902 INFO sqlalchemy.engine.Engine SELECT anon_1.user_id AS anon_1_user_id, anon_1.user_username AS anon_1_user_username, anon_1.user_email AS anon_1_user_email, anon_1.user_password AS anon_1_user_password, anon_1.user_api_key AS anon_1_user_api_key, anon_1.user_github_access_token AS anon_1_user_github_access_token, anon_1.user_fs_uniquifier AS anon_1_user_fs_uniquifier, anon_1.user_active AS anon_1_user_active, anon_1.user_confirmed_at AS anon_1_user_confirmed_at, role_1.id AS role_1_id, role_1.name AS role_1_name, role_1.description AS role_1_description
FROM (SELECT "user".id AS user_id, "user".username AS user_username, "user".email AS user_email, "user".password AS user_password, "user".api_key AS user_api_key, "user".github_access_token AS user_github_access_token, "user".fs_uniquifier AS user_fs_uniquifier, "user".active AS user_active, "user".confirmed_at AS user_confirmed_at
FROM "user"
WHERE lower("user".email) = lower(%(lower_1)s)
 LIMIT %(param_1)s) AS anon_1 LEFT OUTER JOIN (user_role AS user_role_1 JOIN role AS role_1 ON role_1.id = user_role_1.role_id) ON anon_1.user_id = user_role_1.user_id
2023-12-31 15:04:10,902 INFO sqlalchemy.engine.Engine [generated in 0.00029s] {'lower_1'<EMAIL_ADDRESS>'param_1': 1}
2023-12-31 15:04:10,905 INFO sqlalchemy.engine.Engine SELECT role.id AS role_id, role.name AS role_name, role.description AS role_description
FROM role
WHERE role.name = %(name_1)s
 LIMIT %(param_1)s
2023-12-31 15:04:10,905 INFO sqlalchemy.engine.Engine [generated in 0.00032s] {'name_1': 'developer', 'param_1': 1}
Role "developer" added to user<EMAIL_ADDRESS>successfully.
2023-12-31 15:04:10,906 INFO sqlalchemy.engine.Engine INSERT INTO user_role (user_id, role_id) VALUES (%(user_id)s, %(role_id)s)
2023-12-31 15:04:10,906 INFO sqlalchemy.engine.Engine [generated in 0.00010s] {'user_id': 1, 'role_id': 3}
2023-12-31 15:04:10,907 INFO sqlalchemy.engine.Engine COMMIT

Run and Test

Launch app
$ flask run
/home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_caching/__init__.py:114: UserWarning: Flask-Caching: CACHE_TYPE is set to null, caching is effectively disabled.
  warnings.warn(
 * Debug mode: off
WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
 * Running on http://<IP_ADDRESS>:5000
Press CTRL+C to quit

Test package upload
$ http --verify=no --ignore-stdin --auth df56639fb20eb2576dc2461e611bd6293a18c0fff8fda3608479cdc23f0e430a: POST http://localhost:5000/api/packages @git_88f6281-6.2.4_2.43.0-30.spk --print=hb
HTTP/1.1 201 CREATED
Connection: close
Content-Length: 98
Content-Type: application/json
Date: Sun, 31 Dec 2023 19:07:02 GMT
Server: Werkzeug/2.3.8 Python/3.11.7
Vary: Cookie

{
    "architectures": [
        "88f628x"
    ],
    "firmware": "6.2-25556",
    "package": "git",
    "version": "2.43.0-30"
}

Execute test suite
$ pytest -v
================================================================ test session starts =================================================================
platform linux -- Python 3.11.7, pytest-7.4.4, pluggy-1.3.0 -- /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/bin/python
cachedir: .pytest_cache
rootdir: /home/mreid/Documents/spkrepo
plugins: Faker-15.3.4
collected 140 items

spkrepo/tests/test_admin.py::IndexTestCase::test_admin PASSED                                                                                [  0%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous PASSED                                                                              [  1%]
spkrepo/tests/test_admin.py::IndexTestCase::test_anonymous_redirects_to_login PASSED                                                           [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_developer PASSED                                                                              [  2%]
spkrepo/tests/test_admin.py::IndexTestCase::test_package_admin PASSED                                                                          [  3%]
spkrepo/tests/test_admin.py::IndexTestCase::test_user PASSED                                                                                [  4%]
spkrepo/tests/test_admin.py::UserTestCase::test_action_activate_multi PASSED                                                                   [  5%]
spkrepo/tests/test_admin.py::UserTestCase::test_action_activate_one PASSED                                                                     [  5%]
spkrepo/tests/test_admin.py::UserTestCase::test_action_deactivate PASSED                                                                       [  6%]
spkrepo/tests/test_admin.py::UserTestCase::test_action_deactivate_multi PASSED                                                                 [  7%]
spkrepo/tests/test_admin.py::UserTestCase::test_admin PASSED                                                                                [  7%]
spkrepo/tests/test_admin.py::UserTestCase::test_anonymous PASSED                                                                               [  8%]
spkrepo/tests/test_admin.py::UserTestCase::test_developer PASSED                                                                               [  9%]
spkrepo/tests/test_admin.py::UserTestCase::test_package_admin PASSED                                                                           [ 10%]
spkrepo/tests/test_admin.py::UserTestCase::test_user PASSED                                                                                [ 10%]
spkrepo/tests/test_admin.py::PackageTestCase::test_admin PASSED                                                                                [ 11%]
spkrepo/tests/test_admin.py::PackageTestCase::test_anonymous PASSED                                                                            [ 12%]
spkrepo/tests/test_admin.py::PackageTestCase::test_developer PASSED                                                                            [ 12%]
spkrepo/tests/test_admin.py::PackageTestCase::test_on_model_create PASSED                                                                      [ 13%]
spkrepo/tests/test_admin.py::PackageTestCase::test_on_model_delete PASSED                                                                      [ 14%]
spkrepo/tests/test_admin.py::PackageTestCase::test_package_admin PASSED                                                                        [ 15%]
spkrepo/tests/test_admin.py::PackageTestCase::test_user PASSED                                                                                [ 15%]
spkrepo/tests/test_admin.py::VersionTestCase::test_admin PASSED                                                                                [ 16%]
spkrepo/tests/test_admin.py::VersionTestCase::test_anonymous PASSED                                                                            [ 17%]
spkrepo/tests/test_admin.py::VersionTestCase::test_developer PASSED                                                                            [ 17%]
spkrepo/tests/test_admin.py::VersionTestCase::test_on_model_delete PASSED                                                                      [ 18%]
spkrepo/tests/test_admin.py::VersionTestCase::test_package_admin PASSED                                                                        [ 19%]
spkrepo/tests/test_admin.py::VersionTestCase::test_user PASSED                                                                                [ 20%]
spkrepo/tests/test_admin.py::BuildTestCase::test_action_activate_multi PASSED                                                                  [ 20%]
spkrepo/tests/test_admin.py::BuildTestCase::test_action_activate_one PASSED                                                                    [ 21%]
spkrepo/tests/test_admin.py::BuildTestCase::test_action_deactivate PASSED                                                                      [ 22%]
spkrepo/tests/test_admin.py::BuildTestCase::test_action_deactivate_multi PASSED                                                                [ 22%]
spkrepo/tests/test_admin.py::BuildTestCase::test_admin PASSED                                                                                [ 23%]
spkrepo/tests/test_admin.py::BuildTestCase::test_anonymous PASSED                                                                              [ 24%]
spkrepo/tests/test_admin.py::BuildTestCase::test_developer PASSED                                                                              [ 25%]
spkrepo/tests/test_admin.py::BuildTestCase::test_package_admin PASSED                                                                          [ 25%]
spkrepo/tests/test_admin.py::BuildTestCase::test_user PASSED                                                                                [ 26%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_admin PASSED                                                                             [ 27%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_anonymous PASSED                                                                         [ 27%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_create PASSED                                                                            [ 28%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_developer PASSED                                                                         [ 29%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_package_admin PASSED                                                                     [ 30%]
spkrepo/tests/test_admin.py::ScreenshotTestCase::test_user PASSED                                                                              [ 30%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_120_icon PASSED                                                                         [ 31%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_anonymous_user PASSED                                                                   [ 32%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_conflict PASSED                                                                         [ 32%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_existing_package_maintainer_user PASSED                                                 [ 33%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_existing_package_not_author_not_maintainer_user PASSED                                  [ 34%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_icons_in_both PASSED                                                                    [ 35%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_icons_in_info_only PASSED                                                               [ 35%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_install_wizard PASSED                                                                   [ 36%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_invalid_firmware PASSED                                                                 [ 37%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_invalid_spk PASSED                                                                      [ 37%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_minimum PASSED                                                                          [ 38%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_new_package_not_author_not_maintainer_user PASSED                                       [ 39%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_no_data PASSED                                                                          [ 40%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_no_license PASSED                                                                       [ 40%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_not_startable PASSED                                                                    [ 41%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_signed PASSED                                                                           [ 42%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_simple_user PASSED                                                                      [ 42%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_startable PASSED                                                                        [ 43%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_unknown_architecture PASSED                                                             [ 44%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_unknown_firmware PASSED                                                                 [ 45%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_upgrade_wizard PASSED                                                                   [ 45%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_wrong_description_language PASSED                                                       [ 46%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_wrong_displayname_language PASSED                                                       [ 47%]
spkrepo/tests/test_api.py::PackagesTestCase::test_post_wrong_version PASSED                                                                    [ 47%]
spkrepo/tests/test_frontend.py::IndexTestCase::test_get_anonymous PASSED                                                                       [ 48%]
spkrepo/tests/test_frontend.py::IndexTestCase::test_get_logged_user PASSED                                                                     [ 49%]
spkrepo/tests/test_frontend.py::PackagesTestCase::test_get_active_not_stable PASSED                                                            [ 50%]
spkrepo/tests/test_frontend.py::PackagesTestCase::test_get_active_stable PASSED                                                                [ 50%]
spkrepo/tests/test_frontend.py::PackagesTestCase::test_get_not_active_not_stable PASSED                                                        [ 51%]
spkrepo/tests/test_frontend.py::PackagesTestCase::test_get_not_active_stable PASSED                                                            [ 52%]
spkrepo/tests/test_frontend.py::PackageTestCase::test_get PASSED                                                                               [ 52%]
spkrepo/tests/test_frontend.py::PackageTestCase::test_get_no_package PASSED                                                                    [ 53%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_get_anonymous PASSED                                                                     [ 54%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_get_developer PASSED                                                                     [ 55%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_get_no_api_key_by_default PASSED                                                         [ 55%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_get_user PASSED                                                                          [ 56%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_post_generate_api_key_developer PASSED                                                   [ 57%]
spkrepo/tests/test_frontend.py::ProfileTestCase::test_post_generate_api_key_not_developer PASSED                                               [ 57%]
spkrepo/tests/test_frontend.py::RegisterTestCase::test_unique_user_username PASSED                                                             [ 58%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_missing_data_arch PASSED                                                                      [ 59%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_missing_data_build PASSED                                                                     [ 60%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_missing_data_language PASSED                                                                  [ 60%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_not_stable_build_active_not_stable PASSED                                                     [ 61%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_not_stable_build_active_stable PASSED                                                         [ 62%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_not_stable_build_not_active_not_stable PASSED                                                 [ 62%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_not_stable_build_not_active_stable PASSED                                                     [ 63%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_not_stable PASSED                                                         [ 64%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable PASSED                                                             [ 65%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_5004 PASSED                                                        [ 65%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_different_arch PASSED                                              [ 66%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_different_firmware PASSED                                          [ 67%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_download_count PASSED                                              [ 67%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_no_distributor PASSED                                              [ 68%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_null_data PASSED                                                   [ 69%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_qinst PASSED                                                       [ 70%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_qstart PASSED                                                      [ 70%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_active_stable_qstart_startable PASSED                                            [ 71%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_not_active_not_stable PASSED                                                     [ 72%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_stable_build_not_active_stable PASSED                                                         [ 72%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_wrong_data_arch PASSED                                                                        [ 73%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_wrong_data_build PASSED                                                                       [ 74%]
spkrepo/tests/test_nas.py::CatalogTestCase::test_wrong_data_language PASSED                                                                    [ 75%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_generic PASSED                                                                               [ 75%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_inactive_build PASSED                                                                        [ 76%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_incorrect_architecture PASSED                                                                [ 77%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_incorrect_firmware_build PASSED                                                              [ 77%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_wrong_architecture PASSED                                                                    [ 78%]
spkrepo/tests/test_nas.py::DownloadTestCase::test_wrong_build PASSED                                                                           [ 79%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_checksum_mismatch PASSED                                                                   [ 80%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_empty_conf_folder PASSED                                                                   [ 80%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_generic PASSED                                                                             [ 81%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_info_blank_like PASSED                                                                     [ 82%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_info_boolean_no PASSED                                                                     [ 82%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_info_boolean_yes PASSED                                                                    [ 83%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_invalid_info PASSED                                                                        [ 84%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_invalid_info_boolean_startable PASSED                                                      [ 85%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_invalid_info_icon PASSED                                                                   [ 85%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_invalid_info_package PASSED                                                                [ 86%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_invalid_spk PASSED                                                                         [ 87%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_missing_72px_icon PASSED                                                                   [ 87%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_missing_conf_folder PASSED                                                                 [ 88%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_missing_info_package PASSED                                                                [ 89%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_no_info PASSED                                                                             [ 90%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_no_package_tgz PASSED                                                                      [ 90%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_post_conf_privilege_invalid_json PASSED                                                    [ 91%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_post_conf_resource_invalid_json PASSED                                                     [ 92%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_conf_conflicts_encoding PASSED                                                       [ 92%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_conf_dependencies_encoding PASSED                                                    [ 93%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_conf_privilege_encoding PASSED                                                       [ 94%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_conf_resource_encoding PASSED                                                        [ 95%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_info_encoding PASSED                                                                 [ 95%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_license_encoding PASSED                                                              [ 96%]
spkrepo/tests/test_utils.py::SPKParseTestCase::test_wrong_syno_signature_encoding PASSED                                                       [ 97%]
spkrepo/tests/test_utils.py::SPKSignTestCase::test_already_signed PASSED                                                                       [ 97%]
spkrepo/tests/test_utils.py::SPKSignTestCase::test_generic PASSED                                                                              [ 98%]
spkrepo/tests/test_utils.py::SPKUnsignTestCase::test_generic PASSED                                                                            [ 99%]
spkrepo/tests/test_utils.py::SPKUnsignTestCase::test_not_signed PASSED                                                                         [100%]

================================================================== warnings summary ==================================================================
../../.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/passlib/utils/__init__.py:854
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/passlib/utils/__init__.py:854: DeprecationWarning: 'crypt' is deprecated and slated for removal in Python 3.13
    from crypt import crypt as _crypt

../../.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/passlib/pwd.py:16
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/passlib/pwd.py:16: DeprecationWarning: pkg_resources is deprecated as an API. See https://setuptools.pypa.io/en/latest/pkg_resources.html
    import pkg_resources

../../.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/pkg_resources/__init__.py:2868
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/pkg_resources/__init__.py:2868: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('sphinxcontrib')`.
  Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
    declare_namespace(pkg)

../../.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_admin/contrib/__init__.py:2
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/flask_admin/contrib/__init__.py:2: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('flask_admin.contrib')`.
  Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
    __import__('pkg_resources').declare_namespace(__name__)

../../.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/pkg_resources/__init__.py:2348
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/pkg_resources/__init__.py:2348: DeprecationWarning: Deprecated call to `pkg_resources.declare_namespace('flask_admin')`.
  Implementing implicit namespace packages (as specified in PEP 420) is preferred to `pkg_resources.declare_namespace`. See https://setuptools.pypa.io/en/latest/references/keywords.html#keyword-namespace-packages
    declare_namespace(parent)

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66: PytestCollectionWarning: cannot collect test class 'TestLoader' because it has a __init__ constructor (from: spkrepo/tests/test_admin.py)
    class TestLoader(object):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: spkrepo/tests/test_admin.py)
    class TestSuite(BaseTestSuite):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66: PytestCollectionWarning: cannot collect test class 'TestLoader' because it has a __init__ constructor (from: spkrepo/tests/test_api.py)
    class TestLoader(object):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: spkrepo/tests/test_api.py)
    class TestSuite(BaseTestSuite):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66: PytestCollectionWarning: cannot collect test class 'TestLoader' because it has a __init__ constructor (from: spkrepo/tests/test_frontend.py)
    class TestLoader(object):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: spkrepo/tests/test_frontend.py)
    class TestSuite(BaseTestSuite):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66: PytestCollectionWarning: cannot collect test class 'TestLoader' because it has a __init__ constructor (from: spkrepo/tests/test_nas.py)
    class TestLoader(object):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: spkrepo/tests/test_nas.py)
    class TestSuite(BaseTestSuite):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/loader.py:66: PytestCollectionWarning: cannot collect test class 'TestLoader' because it has a __init__ constructor (from: spkrepo/tests/test_utils.py)
    class TestLoader(object):

../../.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92
  /home/mreid/.pyenv/versions/3.11.7/lib/python3.11/unittest/suite.py:92: PytestCollectionWarning: cannot collect test class 'TestSuite' because it has a __init__ constructor (from: spkrepo/tests/test_utils.py)
    class TestSuite(BaseTestSuite):

spkrepo/tests/test_admin.py::IndexTestCase::test_admin
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/factory/alchemy.py:122: RemovedIn20Warning: Deprecated API features detected! These feature(s) are not compatible with SQLAlchemy 2.0. To prevent incompatible upgrades prior to updating applications, ensure requirements files are pinned to "sqlalchemy<2.0". Set environment variable SQLALCHEMY_WARN_20=1 to show all deprecation warnings.  Set environment variable SQLALCHEMY_SILENCE_UBER_WARNING=1 to silence this message. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)
    obj = model_class(*args, **kwargs)

spkrepo/tests/test_api.py: 24 warnings
  /home/mreid/.cache/pypoetry/virtualenvs/spkrepo-DHYObr5C-py3.11/lib/python3.11/site-packages/werkzeug/datastructures/headers.py:297: DeprecationWarning: Passing bytes as a header value is deprecated and will not be supported in Werkzeug 3.0.
    _value = _str_header_value(_value)

-- Docs: https://docs.pytest.org/en/stable/how-to/capture-warnings.html
==================================================== 140 passed, 40 warnings in 79.85s (0:01:19) =====================================================

All in all things look good and we should be good to merge.

Thanks guys! Awesome job! :clap:


Pass cycle to intercept callback instead of binding the callback to it

Disclaimer: This is more like a suggestion I'd like to discuss.
Currently the callback that a user of hoxy passes to the intercept method is bound to an instance of cycle.
With es6 I'd like to define my callback using fat arrow functions to bind my current scope to the callback.
In order to achieve this at the moment, my code looks something like this:
proxy.intercept('request', function(req, res, done) {
  that._onInterceptRequest(req, res, this, done);
});

My suggestion would be to pass the cycle to the callback (like I do) instead of binding it to the callback.
While I agree that this changes the API, maybe the rewrite might be a good opportunity to do that.

It would be a breaking change since it messes with callback arity, which hoxy relies on as a signal for async (similar to mocha).
I like the idea however since I'm also using arrows a lot these days. Once 2.x is out, I'd like to look at a 3.x in which among other things the done() callback/arity hack goes away completely and the third arg is freed up. Async would be accomplished by returning either a promise or an iterator from the callback. (co would be used transmute the iterator to a promise in the latter case).
Although I'm inclined to continue passing the cycle as this for those that prefer that use case, even if redundantly passing it as a third arg.

3.0 is published now.


[Request] Choice to manually set pivot for revolve tool

It would allow more control over the size of each segment & overall curve of the final result.  I quickly slapped in a field to demonstrate, see here:
https://streamable.com/n5vyt

You prefer a textbox over just moving the green pivot further left and right of the shape, correct?

I mean I guess it makes sense if you have a super large revolved shape that spans the entire level. It would be a challenge to manually move the pivot so far away of the shape on the grid.

I am just asking because in the demo project I sent you it's quite far on the right, perhaps you didn't notice it. :)

Ahhh no I didn't notice that lol, that's the exact behavior I was after.  I tinkered with it a little, working with larger scale is definitely a bit difficult, I think the input field would be nice to have anyways just for easily setting exact values.  Not a big deal though :)


0.9.4 -> 0.9.5

Hi! This is the friendly automated conda-forge-linting service.
I just wanted to let you know that I linted all conda-recipes in your PR (recipe) and found it was in an excellent condition.

@pmlandwehr the failure,
    from .qt_compat import QtCore, QtGui, QtWidgets, _getSaveFileName, __version__
  File "/opt/conda/envs/_test/lib/python3.4/site-packages/matplotlib/backends/qt_compat.py", line 124, in <module>
    from PyQt4 import QtCore, QtGui
ImportError: libicui18n.so.56: cannot open shared object file: No such file or directory
TESTS FAILED: ggplot-0.9.5-py34_0

is not related to the update here.
Some Pythons were updated in defaults and they are compiled against xz 5.2.*, that pulls libxml from defaults and this version is not compiled with icu. Somehow qt from defaults is compiled with icu, but that is not in the metadata.

Ping @pelson another place where the xz pinning would come in handy

Agreed, but is this a case of bad metadata on defaults? If so, has this been raised?

Agreed, but is this a case of bad metadata on defaults? If so, has this been raised?

I think that is part of the problem but I could not find what part/dependency of qt causing it to link to icu.
Ping @ccordoba12 and @msarahan maybe you can help us figure this out.

I have tracked the issue down in https://github.com/conda-forge/matplotlib-feedstock/issues/36.

Well, 0.9.7 is out now. Ticking version again and rebuilding. Maybe everything upstream has been patched....?

It is weird as this issue doesn't crop up on Python 2.7 or 3.5 (tested locally), but does appear on Python 3.4.

I'm having trouble reproducing this problem with qt or pyqt alone. Maybe there is something else going on? Though it seems so clearly to be an issue with one of those two packages. 😕

@pmlandwehr a workaround is to "force" install icu as if it were a run-time dependency for ggplot. Just add a comment that it is a workaround and should be removed once we fix our stack.

Booo. Maybe just skip that build?

The py3k patch isn't related to the icu issue, but is going to be important to get in; see here. It should be done by 0.10.2

Well, poop emoji.

:tada:

yaaaaaay


⚠ gorzdrav.org has degraded performance

In 863a82d, gorzdrav.org (https://gorzdrav.org) experienced degraded performance:

HTTP code: 200
Response time: 2718 ms

Resolved: gorzdrav.org performance has improved in 6721311.


MWPW-141413 - JP - wbr tags are causing too many gaps in Firefox

Add shouldExclude function
Prevent the JP word wrap from being applied to the display flex/grid tags in Firefox

Resolves: MWPW-141413
Test URLs:

Before: https://main--milo--adobecom.hlx.page/jp/drafts/takyoshi/?martech=off
After: https://main--milo--tamanyan.hlx.page/jp/drafts/takyoshi/?martech=off

@overmyheadandbody Thank you.

Also, please make sure to add the appropriate labels to the PR - https://github.com/adobecom/milo/wiki/PR-Labels
I have no permission to add PR labels, please give me permission or you can add them instead of me.

@overmyheadandbody The score is low because of Japanese Adobe Clean Han font loading as far as I know. Please look at this message https://github.com/adobecom/milo/pull/405#issuecomment-1408161987

@overmyheadandbody @sharg1 Hi, what should I do to proceed with this pull request?

@tamanyan Since you have no dedicated QA resource, would be great if you can give it one more round of testing and leave a quick comment once you are done.
Since this only affects ja-JP we should be good to go ahead then and I'll merge this afterwards.

@mokimo Thank you. I have tested on Chrome, Firefox and Safari and make sure no error occurring.

@overmyheadandbody @sharg1 Hi, what should I do to proceed with this pull request?

PR LGTM.. I don't seem to have access to add labels or approve PRs yet. I'll lean on @overmyheadandbody @chrischrischris @narcis-radu @mokimo to help here with reviews, adding labels and approvals.


Float Button is wrong size, color unchangable

Based on the Material Design guidelines, the Floating Action button should be 56dp. The float button is smaller. It looks like the problem is caused by this file:
https://github.com/navasmdc/MaterialDesignLibrary/blob/master/MaterialDesign/res/drawable/background_button_float.xml
Additionally, changing the background color in the button's XML (e.g. android:background="#1E88E5") has no effect. It seems to be caused by the color being hard coded in the same file mentioned above.
I can't test it, but removing the following lines might fix the problem:
        android:bottom="2dp"
        android:left="1dp"
        android:top="1dp"
        android:right="1dp">

and
            <solid android:color="#1E88E5" />

Can anyone confirm this?
My workaround right now, which gets the button to the correct size, is to is to set the size in the XML as follows:
            android:layout_width="58dp"
            android:layout_height="59dp"

I was finally able to test the proposed fix. Removing the dimensions mentioned above does indeed fix the size but also reveals some other issues with the ripple effect and shadow (i.e. the shadow is too small and the ripple effect only extends to within 1 or 2 pixels of the edge of the button).
Removing the color made the button invisible. The color is only intended to be a default if none is provided in the XML. The color in the XML fails to have any effect, however, because line 165 of Button.java (LayerDrawable layer = (LayerDrawable) getBackground();) throws an exception (android.graphics.drawable.ColorDrawable cannot be cast to android.graphics.drawable.LayerDrawable) and the background color never gets set.
Someone more familiar with this library’s architecture may be better at fixing this.

Hi yhack. I had the same problem. And i fixed it in a merge request.
https://github.com/navasmdc/MaterialDesignLibrary/pull/225/files
As a workaround you can set the background color programmatically, i tested it and it should work.
".setBackgroundColor(backgroundColor);"
Greatings

Thanks @willybaer for the solution, worked on my API 19 device, too.
To be specific, it's better to do it with
setBackgroundColor(getResources().getColor(R.color.backgroundColor));

I run into this issue as well. No way to set colors from XML. Hopefully that pull request gets merged. Is this library still actively developed? It would be a shame for it to get unmaintained.

I am also wondering how to change the main color :/

@RogerParis The only way to do that, currently, is using the method setBackgroundColor. It's not possible with the XML.

Hi i fixed the background bug in the xml in the last version today! Sorry!

@navasmdc That's great, thanks a lot!


Django 2.1 support

Hi,
I'm wondering how Django 2.1 support is coming along. Your setup.py file specifically says 2.1 is not supported right now.

Yes, I'll fix that during the weekend!


updating byteorder dep version

I'm preparing a PR to address https://github.com/servo/servo/issues/7047 -- wanted to make sure deps were up to date and matched Servo's own. Thanks!

Thanks! Sorry for late response, I'm busy with my thesis now :)

@netvl Not a problem! Any chance we could release a new version of immeta with the updated dep? That would allow us to onboard it on Servo. No rush though -- and thanks again.

Oh, sorry - I forgot that committing an update and releasing it are different things >_< It is now available as 0.2.3.
I feel honored that Servo depends on my library :)

Oh, sorry - I forgot that committing an update and releasing it are different things >_< It is now available as 0.2.3.
I feel honored that Servo depends on my library :)

@netvl figured I'd let you know it finally landed :) https://github.com/servo/servo/pull/9208

@jmr0, thanks, that's great!


Fix for can't modify frozen String

hey @vitalinfo can you pls check the branch from https://github.com/railslove/rack-tracker/pull/116 ?

@DonSchado looks all good in your PR 👍


prisma2 generate tries to install @prisma/photon even in folder without package.json

I created a project by creating a folder and copying a prisma/schema.prisma into it. Then I ran prisma2 generate to see what would happen:
C:\Users\Jan\Documents\throwaway\modelTest>prisma2 generate
In order to use the "photonjs" generator, you need to install @prisma/photon to your project.
√ Do you want to install it now? ... yes

><EMAIL_ADDRESS>postinstall C:\Users\Jan\Documents\node_modules\@prisma\photon
> node scripts/generate.js

npm WARN saveError ENOENT: no such file or directory, open 'C:\Users\Jan\Documents\package.json'
npm WARN enoent ENOENT: no such file or directory, open 'C:\Users\Jan\Documents\package.json'
npm WARN Documents No description
npm WARN Documents No repository field.
npm WARN Documents No README data
npm WARN Documents No license field.

+<EMAIL_ADDRESS>added 1 package and audited 2 packages in 8.126s
found 0 vulnerabilities

> Downloading Prisma engines for windows [====================] 100%

Generating Photon.js to .\..\..\node_modules\@prisma\photon
Done in 3.76s

Seems it found a node_modules folder 2 levels up, where it then installed both Photon and also generated the client. Not sure if this is good behaviour.

@janpio : This is a design decision that we made and I would like to get it changed. It creates package.json + node_modules inside prisma/ folder.
This one almost always gets me with me ending up in a project structure that has 2 node_modules/package.json files once I set it up manually.
I would rather fail or have the cwd() where we create package.json.
Marking this as a candidate for further discussion.


Move concept explanations from "Quickstart" to a new "Concepts" section

Let's keep the Quickstart tutorial lean and fast-paced by explaining only exactly what is needed to understand the code and linking to more in-depth explanations of concepts in the "Concepts" section (needs to be created).
The "Concepts" section will also serve as a normalization point for a shared language surrounding GT4Py.

duplicate of #79 (submission seemed to have failed)