Skip to content
This repository has been archived by the owner on Mar 14, 2020. It is now read-only.

Commit

Permalink
Version 1.0 merge;
Browse files Browse the repository at this point in the history
  • Loading branch information
twiddli committed Feb 4, 2017
2 parents a32ed08 + 070ea07 commit 5d38cbc
Show file tree
Hide file tree
Showing 44 changed files with 7,021 additions and 5,673 deletions.
9 changes: 9 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@ setup.py
.DS_Store
downloads
.happypanda
# pycharm
.idea/

# User-specific files
*.suo
Expand Down Expand Up @@ -238,3 +240,10 @@ FakesAssemblies/
/res/sample.png
*.hpdb
/plugins
/compilerconfig.json
/compilerconfig.json.defaults
/happypanda.VC.db
/happypanda.VC.VC.opendb
/.vs/config/applicationhost.config
/data/happypanda.db
/main.spec
44 changes: 44 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,47 @@
*Happypanda v1.0*
* New stuff
- New GUI look
- New helpful color widgets added to `Settings -> Visual` [rachmadaniHaryono]
- Gallery Contextmenu:
- Added `Set rating` to quickly set gallery rating
- Added `Lookup Artist` to open a new tab on preffered site with the artist's galleries
- Added `Reset read count` under `Advanced`
- Gallery Lists are now included when exporting gallery data
- New sorting option: Gallery Rating
- It is now possible to also append tags to galleries instead of replacing when editing
- New gallery download source: `asmhentai.com` [rachmadaniHaryono]
- New [special namespaced tag](https://github.com/Pewpews/happypanda/wiki/Gallery-Searching#special-namespaced-tags): `URL`
- Use like this: `url:none` or `url:g.e-hentai`
- Many quality of life changes

* Changed stuff
- `g.e-hentai` to `e-hentai`
- Old URLs will automatically be converted to new on metadata fetch
- Displaying rating on galleries is now optional
- Improved search history
- Improved gallery downloader (now very reliable) [rachmadaniHaryono]
- Galleries will automatically be rated 5 stars on favorite
- Gallery List edit popup will now appear in the middle of the application
- Added a way to relogin into website

* Fixes
- E-Hentai login & gallery downloading
- `date added` metadata wasn't included when exporting gallery data
- `last read` Metadata wasn't included when importing gallery data
- backup database name would get unusually long [rachmadaniHaryono]
- Fixed HDoujin `info.txt` parsing
- Newly downloaded galleries would sometimes cause a crash
- Attempting to download exhentai links without being logged in would cause a crash
- Using the random gallery opener would in rare cases cause a crash
- Moving a gallery would cause a crash from a raised PermissionError exception
- Fetching metadata for galleries would return multiple unrelated galleries to choose among
- Fetching metadata for galleries with a colored cover whose gallery source is an archive would sometimes cause a crash
- Galleries with an empty tag field wouldn't show up on a `tag:none` filter search
- Gallery Deleted popup would appear when deleting gallery files from the application
- Attempting to download removed galleries would cause a crash
- Some gallery importing issues


*Happypanda v0.30*
- Someone finally convinced me into adding star ratings
- *Note:* Ratings won't be fetched from EH since I find them useless... Though I might make it an option later on.
Expand Down
46 changes: 20 additions & 26 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,57 +1,50 @@
### I will now be posting progress updates on twitter[(@pewspew)](https://twitter.com/pewspew) if you're interested.
### I'm looking for someone who want to work on the frontend. Language of your choice.

I'm available in the gitter chat if you have any questions!
>Note: Work on this program has been halted in favor of its successor HappypandaX (bugs and such won't be fixed)
[![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/Pewpews/happypanda?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Stories in Progress](https://badge.waffle.io/Pewpews/happypanda.png?label=In%20Progress&title=Features%20In%20Progress)](https://waffle.io/Pewpews/happypanda)
[![Stories in Before next release](https://badge.waffle.io/Pewpews/happypanda.png?label=Before%20next%20release&title=Before%20next%20release)](https://waffle.io/Pewpews/happypanda)

Development is done in alpha branch

For future plans, see [issues](https://github.com/Pewpews/happypanda/issues)

For general documentation, check the [wiki](https://github.com/Pewpews/happypanda/wiki)

# Screenshots
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot1.png" width="700">
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot2.png" width="700">
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot3.png" width="700">
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot4.png" width="700">
This is a cross platform manga/doujinshi manager with namespace & tag support.

# Features
- Portable, self-contained in folder and cross-platform
- Advanced gallery search with regex support
- Low memory footprint
- Advanced gallery search with regex support ([learn more about it here](https://github.com/Pewpews/happypanda/wiki/Gallery-Searching))
- Gallery tagging: userdefined namespaces and tags
- Gallery metadata fetching from the web (supports various sources)
- Gallery downloading from the web (supports various sources)
- Folder monitoring
- Gallery downloading from the web (supports various sources) *
- Folder monitoring that'll notify you of filesystem changes
- Multiple ways of adding galleries to make it as convienient as possible!
- Recursive directory/archive scanning
- Supports ZIP/CBZ, RAR/CBR and directories with loose files
- Customizable by lots of settings
- Very customizable
- And lots more...

\* Gallery downloading from E-Hentai costs Credits/GP

# Screenshots
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot1.png" width="700">
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot2.png" width="700">
<img src="https://raw.githubusercontent.com/Pewpews/happypanda/master/misc/screenshot3.png" width="700">

# How to install and run
#### Windows
1. Download the archive from [releases](https://github.com/Pewpews/happypanda/releases)
2. Extract the archive in it's own folder
2. Extract the archive to its own folder
3. Find Happypanda.exe and double click on it!

#### Mac and Linux
see [INSTALL.md](INSTALL.md)

# How to update
# Updating
Overwrite your previous installation.
More info in the [wiki](https://github.com/Pewpews/happypanda/wiki)

# Misc.
For general documentation (how to add galleries and usage of the search), check the [wiki](https://github.com/Pewpews/happypanda/wiki).

People wanting to import galleries from the Pururin database torrent should find [this](https://github.com/Exedge/Convertor) useful.

# Dependencies
- Qt5 (Install this first) >= 5.4
- PyQt5
- PyQt5 (pip)
- requests (pip)
- beautifulsoup4 (pip)
- watchdog (pip)
Expand All @@ -61,6 +54,7 @@ People wanting to import galleries from the Pururin database torrent should find
- Send2Trash (pip)
- Pillow (pip) or PIL
- python-dateutil (pip)
- QtAwesome (pip)

# Contributing
Please check the wiki.
Please refer to `HappypandaX` instead.
2 changes: 1 addition & 1 deletion VS.txt
Original file line number Diff line number Diff line change
@@ -1 +1 @@
0.30
1.0
Binary file modified misc/screenshot1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified misc/screenshot2.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified misc/screenshot3.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file removed misc/screenshot4.png
Binary file not shown.
3 changes: 3 additions & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-r requirements.txt

pytest==3.0.3
4 changes: 3 additions & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pyqt5
requests
beautifulsoup4
scandir
Expand All @@ -6,4 +7,5 @@ watchdog
robobrowser
Send2Trash
pillow
python-dateutil
python-dateutil
QtAwesome==0.3.3
Binary file removed res/btn_star.png
Binary file not shown.
Binary file removed res/btn_star2.png
Binary file not shown.
Binary file removed res/grid.png
Binary file not shown.
Binary file removed res/home.png
Binary file not shown.
Binary file removed res/list.png
Binary file not shown.
Binary file removed res/plus.png
Binary file not shown.
Binary file removed res/search_options.png
Binary file not shown.
Binary file removed res/sort.png
Binary file not shown.
Binary file removed res/star.png
Binary file not shown.
Binary file removed res/star_small.png
Binary file not shown.
5 changes: 0 additions & 5 deletions res/typicons/License.txt

This file was deleted.

1 change: 0 additions & 1 deletion res/typicons/group-outline.svg

This file was deleted.

1 change: 0 additions & 1 deletion res/typicons/media-stop-outline.svg

This file was deleted.

1 change: 0 additions & 1 deletion res/typicons/tags.svg

This file was deleted.

1 change: 0 additions & 1 deletion res/typicons/user-outline.svg

This file was deleted.

59 changes: 59 additions & 0 deletions tests/database/test_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
"""test db module."""
from itertools import product
from unittest import mock

import pytest


@pytest.mark.parametrize(
'path_isfile_retval, check_dbv_retval, path_is_dbc_path',
product([False, True], repeat=3)
)
def test_init_db(path_isfile_retval, check_dbv_retval, path_is_dbc_path):
"""test sqlite generation and db creation"""
with mock.patch('version.database.db.db_constants') as m_dbc, \
mock.patch('version.database.db.sqlite3') as m_sl3, \
mock.patch('version.database.db.os') as m_os, \
mock.patch('version.database.db.create_db_path') as m_create_db_path, \
mock.patch('version.database.db.check_db_version') \
as m_check_dbv:
from version.database import db
m_os.path.isfile.return_value = path_isfile_retval
m_check_dbv.return_value = check_dbv_retval
if path_is_dbc_path:
path = m_dbc.DB_PATH
else:
path = mock.Mock()
# run
res = db.init_db(path)
# test
if path_isfile_retval:
if path == m_dbc.DB_PATH and not check_dbv_retval:
m_sl3.assert_has_calls([
mock.call.connect(path, check_same_thread=False),
])
assert res is None
return
else:
m_sl3.assert_has_calls([
mock.call.connect(path, check_same_thread=False),
mock.call.connect().execute('PRAGMA foreign_keys = on')
])
else:
m_create_db_path.assert_called_once_with()

m_sl3.assert_has_calls([
mock.call.connect(path, check_same_thread=False),
mock.call.connect().cursor(),
mock.call.connect().cursor().execute(
'CREATE TABLE IF NOT EXISTS version(version REAL)'),
mock.call.connect().cursor().execute(
'INSERT INTO version(version) VALUES(?)',
(m_dbc.CURRENT_DB_VERSION,)
),
mock.call.connect().cursor().executescript(db.STRUCTURE_SCRIPT),
mock.call.connect().commit(),
mock.call.connect().execute('PRAGMA foreign_keys = on')
])
assert res == m_sl3.connect.return_value
assert res.isolation_level is None
64 changes: 64 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
"""test utils module."""
from unittest import mock
from itertools import product

import pytest

from version.utils import backup_database


@pytest.mark.parametrize(
'mock_exists_retval, mock_isdir_retval',
product([True, False], repeat=2)
)
def test_run_backup_database(mock_exists_retval, mock_isdir_retval):
"""test run with mock obj as input."""
mock_db_path = mock.Mock()
mock_base_path = mock.Mock()
mock_name = mock.Mock()
with mock.patch('version.utils.os') as mock_os, \
mock.patch('version.utils.shutil') as mock_shutil, \
mock.patch('version.utils.datetime') as mock_datetime:
mock_datetime.datetime.today.return_value = '2016-10-25 15:42:47.649416'
mock_os.path.split.return_value = (mock_base_path, mock_name)
mock_os.path.exists.return_value = mock_exists_retval
mock_os.path.isdir.return_value = mock_isdir_retval
res = backup_database(mock_db_path)
assert res
mock_datetime.datetime.today.assert_called_once_with()
os_calls = [
mock.call.path.split(mock_db_path),
mock.call.path.join(mock_base_path, 'backup'),
mock.call.path.isdir(mock_os.path.join.return_value),
mock.call.path.join(
mock_os.path.join.return_value,
"2016-10-25-{}".format(mock_name)),
mock.call.path.exists(mock_os.path.join.return_value),
]
if mock_exists_retval:
if mock_isdir_retval:
assert len(mock_os.mock_calls) == 103
else:
assert len(mock_os.mock_calls) == 104
os_calls.extend([
mock.call.path.join(
mock_os.path.join.return_value,
"2016-10-25(1)-2016-10-25-{}".format(mock_name)),
mock.call.path.join(
mock_os.path.join.return_value,
"2016-10-25(2)-2016-10-25-{}".format(mock_name)),
])
assert not mock_shutil.mock_calls
else:
if mock_isdir_retval:
assert len(mock_os.mock_calls) == 5
else:
assert len(mock_os.mock_calls) == 6
mock_shutil.copyfile.assert_called_once_with(
mock_db_path, mock_os.path.join.return_value)

if mock_isdir_retval:
assert not mock_os.mkdir.called
else:
mock_os.mkdir.assert_called_once_with(mock_os.path.join.return_value)
mock_os.assert_has_calls(os_calls, any_order=True)
Loading

0 comments on commit 5d38cbc

Please sign in to comment.