diff --git a/CHANGELOG.md b/CHANGELOG.md
new file mode 100644
index 0000000..e69de29
diff --git a/LATEST_RELEASE.md b/LATEST_RELEASE.md
new file mode 100644
index 0000000..e69de29
diff --git a/MANIFEST.in b/MANIFEST.in
index fb49b40..f14a81d 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -1,2 +1,4 @@
recursive-include hubstore *
global-exclude *.py[cod]
+include VERSION
+
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..d169b2f
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+0.0.8
diff --git a/docs/reference/README.md b/docs/reference/README.md
new file mode 100644
index 0000000..7844e3b
--- /dev/null
+++ b/docs/reference/README.md
@@ -0,0 +1,106 @@
+
+# Reference Overview
+
+[hubstore.\_\_init\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.\_\_init\_\_.md)
+
+
+
+[hubstore.\_\_main\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.\_\_main\_\_.md)
+
+
+
+[hubstore.hooking.\_\_init\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.hooking.\_\_init\_\_.md)
+
+
+
+[hubstore.hooking.ante\_build\_hook](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.hooking.ante\_build\_hook.md)
+
+
+
+[hubstore.hooking.ante\_release\_hook](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.hooking.ante\_release\_hook.md)
+
+
+
+[hubstore.hooking.post\_build\_hook](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.hooking.post\_build\_hook.md)
+
+
+
+[hubstore.hooking.post\_release\_hook](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.hooking.post\_release\_hook.md)
+
+
+
+[hubstore.host.\_\_init\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.host.\_\_init\_\_.md)
+
+
+
+[hubstore.host.constants](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.host.constants.md)
+
+
+
+[hubstore.host.core](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.host.core.md)
+
+
+
+[hubstore.host.main\_host](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.host.main\_host.md)
+
+
+
+[hubstore.misc.\_\_init\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.misc.\_\_init\_\_.md)
+
+
+
+[hubstore.misc.funcs](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.misc.funcs.md)
+
+
+
+[hubstore.misc.my\_theme](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.misc.my\_theme.md)
+
+
+
+[hubstore.view.\_\_init\_\_](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.\_\_init\_\_.md)
+
+
+
+[hubstore.view.about\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.about\_view.md)
+
+
+
+[hubstore.view.app\_info\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.app\_info\_view.md)
+
+
+
+[hubstore.view.auth\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.auth\_view.md)
+
+
+
+[hubstore.view.central\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.central\_view.md)
+
+
+
+[hubstore.view.downloader\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.downloader\_view.md)
+
+
+
+[hubstore.view.exception\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.exception\_view.md)
+
+
+
+[hubstore.view.footer\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.footer\_view.md)
+
+
+
+[hubstore.view.header\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.header\_view.md)
+
+
+
+[hubstore.view.import\_list\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.import\_list\_view.md)
+
+
+
+[hubstore.view.init\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.init\_view.md)
+
+
+
+[hubstore.view.main\_view](https://github.com/pyrustic/hubstore/blob/master/docs/reference/content/hubstore.view.main\_view.md)
+
+
diff --git a/docs/reference/content/hubstore.__init__.md b/docs/reference/content/hubstore.__init__.md
new file mode 100644
index 0000000..a845c7d
--- /dev/null
+++ b/docs/reference/content/hubstore.__init__.md
@@ -0,0 +1,10 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.\_\_init\_\_
+
+
+
+
+
+
diff --git a/docs/reference/content/hubstore.__main__.md b/docs/reference/content/hubstore.__main__.md
new file mode 100644
index 0000000..fdd1eba
--- /dev/null
+++ b/docs/reference/content/hubstore.__main__.md
@@ -0,0 +1,19 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.\_\_main\_\_
+
+
+
+
+
+
+```python
+
+def main():
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.hooking.__init__.md b/docs/reference/content/hubstore.hooking.__init__.md
new file mode 100644
index 0000000..8ac5d66
--- /dev/null
+++ b/docs/reference/content/hubstore.hooking.__init__.md
@@ -0,0 +1,10 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.hooking.\_\_init\_\_
+
+
+
+
+
+
diff --git a/docs/reference/content/hubstore.hooking.ante_build_hook.md b/docs/reference/content/hubstore.hooking.ante_build_hook.md
new file mode 100644
index 0000000..725350d
--- /dev/null
+++ b/docs/reference/content/hubstore.hooking.ante_build_hook.md
@@ -0,0 +1,31 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.hooking.ante\_build\_hook
+
+
+
+
+
+
+```python
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+
+```
+
+
+
+```python
+
+def main():
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.hooking.ante_release_hook.md b/docs/reference/content/hubstore.hooking.ante_release_hook.md
new file mode 100644
index 0000000..527af4e
--- /dev/null
+++ b/docs/reference/content/hubstore.hooking.ante_release_hook.md
@@ -0,0 +1,83 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.hooking.ante\_release\_hook
+
+
+
+
+
+
+```python
+TEXT = "Released with [Pyrustic]({pyrustic_link}).
+"
+
+```
+
+
+
+```python
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+
+```
+
+
+
+```python
+
+def get_jayson(pyrustic_data_path, config_name, readonly):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_pyrustic_data_path(data):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_release_description(target, owner, repo):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def main():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def update_release_jayson(target, release_jayson, build_report_jayson, app_pkg, version):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.hooking.post_build_hook.md b/docs/reference/content/hubstore.hooking.post_build_hook.md
new file mode 100644
index 0000000..e02f2d9
--- /dev/null
+++ b/docs/reference/content/hubstore.hooking.post_build_hook.md
@@ -0,0 +1,31 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.hooking.post\_build\_hook
+
+
+
+
+
+
+```python
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+
+```
+
+
+
+```python
+
+def main():
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.hooking.post_release_hook.md b/docs/reference/content/hubstore.hooking.post_release_hook.md
new file mode 100644
index 0000000..c3d073d
--- /dev/null
+++ b/docs/reference/content/hubstore.hooking.post_release_hook.md
@@ -0,0 +1,54 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.hooking.post\_release\_hook
+
+
+
+
+
+
+```python
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+
+```
+
+
+
+```python
+
+def get_date():
+ """
+ Returns the current date. Format: Month day, year.
+ Example: January 15, 2020
+ """
+
+```
+
+
+
+```python
+
+def main():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def update_changelog(path, data, version):
+ """
+ Update the file CHANGELOG.md located at path, with data and version
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.host.__init__.md b/docs/reference/content/hubstore.host.__init__.md
new file mode 100644
index 0000000..b4678b7
--- /dev/null
+++ b/docs/reference/content/hubstore.host.__init__.md
@@ -0,0 +1,10 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.host.\_\_init\_\_
+
+
+
+
+
+
diff --git a/docs/reference/content/hubstore.host.constants.md b/docs/reference/content/hubstore.host.constants.md
new file mode 100644
index 0000000..2436c3f
--- /dev/null
+++ b/docs/reference/content/hubstore.host.constants.md
@@ -0,0 +1,21 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.host.constants
+
+
+
+
+
+
+```python
+HUBSTORE_SHARED_DATA_FILE = "/home/alex/PyrusticData/hubstore/hubstore_shared_data.json"
+
+HUBSTORE_SHARED_FOLDER = "/home/alex/PyrusticData/hubstore"
+
+PYRUSTIC_DATA = "/home/alex/PyrusticData"
+
+USER_AGENT = ('User-Agent', 'Pyrustic')
+
+```
+
diff --git a/docs/reference/content/hubstore.host.core.md b/docs/reference/content/hubstore.host.core.md
new file mode 100644
index 0000000..31a9833
--- /dev/null
+++ b/docs/reference/content/hubstore.host.core.md
@@ -0,0 +1,259 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.host.core
+
+
+
+
+
+
+```python
+
+def auth(token, kurl):
+ """
+ Auth
+ Return: (status_code, status_text, login_str)
+ login_str could be None
+ """
+
+```
+
+
+
+```python
+
+def backup(owner, repo):
+ """
+ Backup the current version of owner/repo
+ Return bool is_success, error
+ """
+
+```
+
+
+
+```python
+
+def download(owner, repo, name, url, kurl):
+ """
+ Download the resource (url) with kurl object
+ Return a boolean is_success, error, and tempfile
+ """
+
+```
+
+
+
+```python
+
+def fetch(owner, repo, kurl):
+ """
+ Fetch resource
+ Param:
+ - owner: str
+ - repo: str
+ - kurl: Kurl object
+
+ Return:
+ status_code, status_text, json_data
+ """
+
+```
+
+
+
+```python
+
+def find_install_script(owner, repo):
+ """
+ Find the install script
+ Return a data dict:
+ {"is_success": bool, "error": error, "module": str, "root_dir": str,
+ "path": str}
+ """
+
+```
+
+
+
+```python
+
+def get_app_pkg(owner, repo):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_kurl():
+ """
+ Generate a Kurl object
+ """
+
+```
+
+
+
+```python
+
+def get_list():
+ """
+ Return bool_success, error, data
+ Data is the list of apps stored in hubstore-apps
+ That list is in reality a dict like:
+ {"owner": ["repo_1", "repo_2", ...], "owner_2": [], ...}
+ """
+
+```
+
+
+
+```python
+
+def init_hubstore(path):
+ """
+ Initialize Hubstore.
+
+ Param:
+ - path: absolute path in which the folder "hubstore-apps"
+ will be created
+
+ Return:
+ A dict: {"error_code": int, "error": object, "root_dir": str}
+ - The "error_code" is one of:
+ 0 = all right
+ 1 = failed to create "hubstore-apps" folder
+ 2 = failed to register Hubstore in $HOME/PyrusticData
+ - "root_dir" is the absolute path to the folder "hubstore-apps".
+ Example: init_hubstore("/path/to/use") will return this "root_dir":
+ "/path/to/use/hubstore-apps"
+ Inside "hubstore-apps", two main folders:
+ - apps: to store apps by owner. Meaning that visible folders
+ in "apps" are owners, and inside each owner there are a repo
+ - backup: it mirrors the folder "apps" but only for backup.
+ And one JSON file: apps.json to store the owners/repos associations
+ """
+
+```
+
+
+
+```python
+
+def install(owner, repo, name):
+ """
+ Unpack the zip file cached in tempfile.name
+ Return bool is_success, error
+ """
+
+```
+
+
+
+```python
+
+def parse_owner_repo(val):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def path(owner, repo):
+ """
+ Use this to get the path to the app owner/repo
+ Return a path string or None
+ """
+
+```
+
+
+
+```python
+
+def rate(kurl):
+ """
+ Get Rate Limit
+ Return: status_code, status_text, data
+ data = {"limit": int, "remaining": int}
+ """
+
+```
+
+
+
+```python
+
+def rollback(owner, repo):
+ """
+ Rollback. Return boolean is_success, error
+ """
+
+```
+
+
+
+```python
+
+def run(owner, repo):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def should_init_hubstore():
+ """
+ Return a boolean to tell if the method
+ "init_HUBSTORE()" should be called or not
+ """
+
+```
+
+
+
+```python
+
+def split_arg(arg):
+ """
+ Split the string arg. Delimiters are space, simple and double quotes
+ """
+
+```
+
+
+
+```python
+
+def uninstall(owner, repo):
+ """
+ Uninstall an app by giving its owner and repo.
+ Return bool is_success, error
+ """
+
+```
+
+
+
+```python
+
+def useful_info(data):
+ """
+ Return useful info in a dict. Return None if the dict data is empty
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.host.main_host.md b/docs/reference/content/hubstore.host.main_host.md
new file mode 100644
index 0000000..367c80c
--- /dev/null
+++ b/docs/reference/content/hubstore.host.main_host.md
@@ -0,0 +1,149 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.host.main\_host
+
+
+
+
+
+
+```python
+
+class MainHost:
+ """
+
+ """
+
+ def __init__(self):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ @property
+ def login(self):
+ """
+
+ """
+
+ def auth(self, token):
+ """
+ Return: (status_code, status_text, login_str)
+ data = the login if status is 200 or 304, else data is None
+ """
+
+ def download(self, name, url, owner, repo):
+ """
+ Return {"success": bool, "error": object}
+ """
+
+ def get_image(self, owner, repo):
+ """
+ Return None or path
+ """
+
+ def get_info(self, owner, repo):
+ """
+ Return None or data.
+ data:
+ {"owner": str, "repo": str,
+ "path": str, "email": str,
+ "version": str,
+ "description": str,
+ "homepage": str}
+ """
+
+ def get_list(self):
+ """
+ Return success_bool, error, data
+ Data is the list of apps like this:
+ [ ("owner_1", "repo_1"), ("owner_2", "repo_2"),
+ ("owner_3", "repo_3"), ("owner_4", "repo_4") ]
+ """
+
+ def get_rate(self):
+ """
+ Get Rate Limit
+ Return:
+ {"status_code": int, "status_text": str,
+ "data": data}
+ data = {"limit": int, "remaining": int}
+ """
+
+ def init_hubstore(self, path):
+ """
+ Initialize Hubstore.
+
+ Param:
+ - path: absolute path in which the folder "hubstore-apps"
+ will be created
+
+ Return:
+ A dict: {"error_code": int, "error": object, "root_dir": str}
+ - The "error_code" is one of:
+ 0 = all right
+ 1 = failed to create "hubstore-apps" folder
+ 2 = failed to register Hubstore in $HOME/PyrusticData
+ - "root_dir" is the absolute path to the folder "hubstore-apps".
+ """
+
+ def parse_owner_repo(self, val):
+ """
+ Param:
+ val: string
+ Return:
+ A tuple of strings as ("owner", "repo")
+ or a tuple of None as (None, None)
+ """
+
+ def rollback(self, owner, repo):
+ """
+ Rollback. Return boolean is_success, error
+ """
+
+ def run(self, owner, repo, callback_process_id):
+ """
+
+ """
+
+ def search_offline(self, owner, repo):
+ """
+ Param
+ owner and repo are strings
+ Return
+ Boolean.
+ """
+
+ def search_online(self, owner, repo):
+ """
+ Return:
+ {"success": bool,
+ "status": tuple(status_code, status_text),
+ "release": dict of useful data,
+ "assets": list of dicts}
+ """
+
+ def should_init_hubstore(self):
+ """
+ Return a boolean to tell if the method
+ "init_hubstore()" should be called or not
+ """
+
+ def stop_process(self, process_id):
+ """
+
+ """
+
+ def unauth(self):
+ """
+
+ """
+
+ def uninstall(self, owner, repo):
+ """
+ Delete an app by giving its owner and repo.
+ Return bool is_success, error
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.misc.__init__.md b/docs/reference/content/hubstore.misc.__init__.md
new file mode 100644
index 0000000..004e13d
--- /dev/null
+++ b/docs/reference/content/hubstore.misc.__init__.md
@@ -0,0 +1,10 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.misc.\_\_init\_\_
+
+
+
+
+
+
diff --git a/docs/reference/content/hubstore.misc.funcs.md b/docs/reference/content/hubstore.misc.funcs.md
new file mode 100644
index 0000000..df98e2d
--- /dev/null
+++ b/docs/reference/content/hubstore.misc.funcs.md
@@ -0,0 +1,42 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.misc.funcs
+
+
+
+
+
+
+```python
+
+def convert_size(size):
+ """
+ Size should be in bytes.
+ Return a tuple (float_or_int_val, str_unit)
+ """
+
+```
+
+
+
+```python
+
+def tab_to_space(text, tab_size=4):
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def truncate_str(data, max_size=15, ellipsis='...'):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.misc.my_theme.md b/docs/reference/content/hubstore.misc.my_theme.md
new file mode 100644
index 0000000..85d19ea
--- /dev/null
+++ b/docs/reference/content/hubstore.misc.my_theme.md
@@ -0,0 +1,63 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.misc.my\_theme
+
+
+
+
+
+
+```python
+
+def get_button_auth_style():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_button_style():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_entry_repo_name_default_style():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_entry_repo_name_hovered_style():
+ """
+
+ """
+
+```
+
+
+
+```python
+
+def get_theme():
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.__init__.md b/docs/reference/content/hubstore.view.__init__.md
new file mode 100644
index 0000000..cbdf3cb
--- /dev/null
+++ b/docs/reference/content/hubstore.view.__init__.md
@@ -0,0 +1,10 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.\_\_init\_\_
+
+
+
+
+
+
diff --git a/docs/reference/content/hubstore.view.about_view.md b/docs/reference/content/hubstore.view.about_view.md
new file mode 100644
index 0000000..4aa702c
--- /dev/null
+++ b/docs/reference/content/hubstore.view.about_view.md
@@ -0,0 +1,85 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.about\_view
+
+
+
+
+
+
+```python
+ABOUT_TEXT = "Download, install, manage, and run Python desktop apps with Hubstore.
+Hubstore is available on PyPI and is built with Pyrustic.
+
+Hubstore web page:
+https://github.com/pyrustic/hubstore
+
+Pyrustic web page:
+https://github.com/pyrustic/pyrustic
+
+
+To install Hubstore:
+pip install hubstore
+
+To upgrade Hubstore:
+pip install hubstore --upgrade --upgrade-strategy eager
+
+
+"
+
+HUBSTORE_URL = "https://github.com/pyrustic/hubstore#readme"
+
+PYRUSTIC_URL = "https://github.com/pyrustic/pyrustic#readme"
+
+```
+
+
+
+```python
+
+class AboutView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.app_info_view.md b/docs/reference/content/hubstore.view.app_info_view.md
new file mode 100644
index 0000000..db7e9a2
--- /dev/null
+++ b/docs/reference/content/hubstore.view.app_info_view.md
@@ -0,0 +1,72 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.app\_info\_view
+
+
+
+
+
+
+```python
+
+class AppInfoView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view, footer_view, owner, repo):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ def notify_rollback(self, result):
+ """
+
+ """
+
+ def notify_uninstall(self, result):
+ """
+
+ """
+
+ def notify_update(self, owner, repo, result):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.auth_view.md b/docs/reference/content/hubstore.view.auth_view.md
new file mode 100644
index 0000000..8ad1417
--- /dev/null
+++ b/docs/reference/content/hubstore.view.auth_view.md
@@ -0,0 +1,62 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.auth\_view
+
+
+
+
+
+
+```python
+
+class AuthView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ def notify_auth(self, result):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.central_view.md b/docs/reference/content/hubstore.view.central_view.md
new file mode 100644
index 0000000..8c0df9e
--- /dev/null
+++ b/docs/reference/content/hubstore.view.central_view.md
@@ -0,0 +1,93 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.central\_view
+
+
+
+
+
+
+```python
+MAX_TILES_BY_ROW = 4
+
+```
+
+
+
+```python
+
+class CentralView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ @property
+ def footer_view(self):
+ """
+
+ """
+
+ @property
+ def header_view(self):
+ """
+
+ """
+
+ @property
+ def host(self):
+ """
+
+ """
+
+ @property
+ def threadom(self):
+ """
+
+ """
+
+ def load_data(self):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.downloader_view.md b/docs/reference/content/hubstore.view.downloader_view.md
new file mode 100644
index 0000000..0693c62
--- /dev/null
+++ b/docs/reference/content/hubstore.view.downloader_view.md
@@ -0,0 +1,57 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.downloader\_view
+
+
+
+
+
+
+```python
+
+class DownloaderView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view, owner, repo, release_data, asset_data):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.exception_view.md b/docs/reference/content/hubstore.view.exception_view.md
new file mode 100644
index 0000000..a644ec2
--- /dev/null
+++ b/docs/reference/content/hubstore.view.exception_view.md
@@ -0,0 +1,57 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.exception\_view
+
+
+
+
+
+
+```python
+
+class ExceptionView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view, data):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.footer_view.md b/docs/reference/content/hubstore.view.footer_view.md
new file mode 100644
index 0000000..520c552
--- /dev/null
+++ b/docs/reference/content/hubstore.view.footer_view.md
@@ -0,0 +1,88 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.footer\_view
+
+
+
+
+
+
+```python
+BUILT = "built"
+
+MAPPED = "mapped"
+
+```
+
+
+
+```python
+
+class FooterView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ @property
+ def host(self):
+ """
+
+ """
+
+ @property
+ def threadom(self):
+ """
+
+ """
+
+ def add_item(self, owner, repo, process_id):
+ """
+
+ """
+
+ def exited_app(self, data):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.header_view.md b/docs/reference/content/hubstore.view.header_view.md
new file mode 100644
index 0000000..37ef580
--- /dev/null
+++ b/docs/reference/content/hubstore.view.header_view.md
@@ -0,0 +1,115 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.header\_view
+
+
+
+
+
+
+```python
+
+class HeaderView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ @property
+ def central_view(self):
+ """
+
+ """
+
+ @property
+ def host(self):
+ """
+
+ """
+
+ @property
+ def threadom(self):
+ """
+
+ """
+
+ def notify_auth(self, success):
+ """
+ button_style = None
+ if success:
+ button_style = my_theme.get_button_auth_style()
+ else:
+ button_style = my_theme.get_button_style()
+ button_style.target(self._button_auth)
+ """
+
+ def notify_download(self, owner, repo, result):
+ """
+
+ """
+
+ def notify_list(self, result):
+ """
+
+ """
+
+ def notify_offline_search_result(self, owner, repo, result):
+ """
+
+ """
+
+ def notify_online_search_result(self, owner, repo, result):
+ """
+
+ """
+
+ def notify_rate(self, result):
+ """
+
+ """
+
+ def submit_url_to_download(self, owner, repo, name, url):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.import_list_view.md b/docs/reference/content/hubstore.view.import_list_view.md
new file mode 100644
index 0000000..af908b1
--- /dev/null
+++ b/docs/reference/content/hubstore.view.import_list_view.md
@@ -0,0 +1,62 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.import\_list\_view
+
+
+
+
+
+
+```python
+
+class ImportListView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view, header_view, data):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ def notify_online_search_result(self, owner, repo, result):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.init_view.md b/docs/reference/content/hubstore.view.init_view.md
new file mode 100644
index 0000000..15d6645
--- /dev/null
+++ b/docs/reference/content/hubstore.view.init_view.md
@@ -0,0 +1,62 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.init\_view
+
+
+
+
+
+
+```python
+
+class InitView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, parent_view):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ def notify_init_outcome(self, data):
+ """
+
+ """
+
+```
+
diff --git a/docs/reference/content/hubstore.view.main_view.md b/docs/reference/content/hubstore.view.main_view.md
new file mode 100644
index 0000000..7ee9393
--- /dev/null
+++ b/docs/reference/content/hubstore.view.main_view.md
@@ -0,0 +1,92 @@
+
+Back to [Reference Overview](https://github.com/pyrustic/hubstore/blob/master/docs/reference/README.md)
+
+# hubstore.view.main\_view
+
+
+
+
+
+
+```python
+
+class MainView:
+ """
+ Subclass this if you are going to create a view.
+
+ Lifecycle of a view:
+ 1- you instantiate the view
+ 2- '__init__()' is implicitly called
+ 3- you call the method '.build()'
+ 4- '_build()' is implicitly called
+ 5- '_on_map()' is implicitly called once the widget is mapped
+ 6- '_on_destroy()' is implicitly called when the widget is destroyed/closed
+
+ The rules to create your view is simple:
+ - You need to subclass Viewable.
+ - You need to implement the methods '_build()', and optionally
+ implement '_on_map()' and '_on_destroy()'.
+ - You need to set an instance variable '_body' with either a tk.Frame or tk.Toplevel
+ in the method '_on_build()'
+ That's all ! Of course, when you are ready to use the view, just call the 'build()' method.
+ Calling the 'build()' method will return the body of the view. The one that you assigned
+ to the instance variable '_body'. The same body can be retrieved with the property 'body'.
+ The 'build()' method should be called once. Calling it more than once will still return
+ the body object, but the view won't be built again.
+ You can't re-build your same view instance after destroying its body.
+ You can destroy the body directly, by calling the conventional tkinter destruction method
+ on the view's body. But it's recommended to destroy the view by calling the view's method
+ 'destroy()' inherited from the class Viewable.
+ The difference between these two ways of destruction is that when u call the Viewable's
+ 'destroy()' method, the method '_on_destroy()' will be called BEFORE the effective
+ destruction of the body. If u call directly 'destroy' conventionally on the tkinter
+ object (the body), the method '_on_destroy()' will be called AFTER the beginning
+ of destruction of the body.
+
+ By the way, you can use convenience methods "build_pack", "build_grid", "build_place"
+ to build and pack/grid/place your widget in the master !!
+ Use "build_wait" for toplevels if you want the app to wait till the window closes
+ """
+
+ def __init__(self, app):
+ """
+ Initialize self. See help(type(self)) for accurate signature.
+ """
+
+ @property
+ def central_view(self):
+ """
+
+ """
+
+ @property
+ def footer_view(self):
+ """
+
+ """
+
+ @property
+ def header_view(self):
+ """
+
+ """
+
+ @property
+ def main_host(self):
+ """
+
+ """
+
+ @property
+ def threadom(self):
+ """
+
+ """
+
+ def leave(self):
+ """
+
+ """
+
+```
+
diff --git a/hubstore/__main__.py b/hubstore/__main__.py
index 5a49412..1cba9fc 100644
--- a/hubstore/__main__.py
+++ b/hubstore/__main__.py
@@ -6,12 +6,17 @@
def main():
# The App
- app = App(__package__)
- app.root.title("Hubstore - built with Pyrustic")
+ app = App()
+ # Title
+ app.title = "Hubstore"
+ # Geometry
+ app.geometry = "900x550+0+0"
+ # Resizable
+ app.resizable = (False, False)
# Set theme
app.theme = my_theme.get_theme()
# Set view
- app.view = lambda: MainView(app)
+ app.view = MainView(app)
# Center the window
app.center()
# Lift off !
diff --git a/hubstore/hooking/__init__.py b/hubstore/hooking/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/hubstore/hooking/ante_build_hook.py b/hubstore/hooking/ante_build_hook.py
new file mode 100644
index 0000000..b2572b1
--- /dev/null
+++ b/hubstore/hooking/ante_build_hook.py
@@ -0,0 +1,22 @@
+# ante_build_hook.py generated by Pyrustic Manager
+import sys
+
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+ items = ("script", "target", "app_pkg", "version")
+ data = None
+ if len(sys.argv) == len(items):
+ data = {item: sys.argv[i] for i, item in enumerate(items)}
+ return data
+
+
+def main():
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/hubstore/hooking/ante_release_hook.py b/hubstore/hooking/ante_release_hook.py
new file mode 100644
index 0000000..872d667
--- /dev/null
+++ b/hubstore/hooking/ante_release_hook.py
@@ -0,0 +1,147 @@
+# ante_release_hook.py generated by Pyrustic Manager
+import os
+import os.path
+import sys
+from jayson import Jayson
+
+
+TEXT = """\
+Released with [Pyrustic]({pyrustic_link}).
+"""
+
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+ items = ("script", "target", "app_pkg", "version")
+ data = None
+ if len(sys.argv) == len(items):
+ data = {item: sys.argv[i] for i, item in enumerate(items)}
+ return data
+
+
+def get_pyrustic_data_path(data):
+ target = data["target"]
+ app_pkg = data["app_pkg"]
+ pyrustic_data_path = os.path.join(target, app_pkg,
+ "pyrustic_data")
+ if not os.path.exists(pyrustic_data_path):
+ return None
+ return pyrustic_data_path
+
+
+def get_jayson(pyrustic_data_path, config_name, readonly):
+ if not pyrustic_data_path:
+ return None
+ config_path = os.path.join(pyrustic_data_path,
+ config_name)
+ if not os.path.exists(config_path):
+ return None
+ jayson = Jayson(config_path, readonly=readonly)
+ return jayson
+
+
+def get_release_description(target, owner, repo):
+ latest_release_path = os.path.join(target, "LATEST_RELEASE.md")
+ cache = None
+ try:
+ with open(latest_release_path, "r") as file:
+ cache = file.read()
+ except Exception as e:
+ pass
+ text = None
+ if cache:
+ text = cache
+ else:
+ text = _get_default_release_description(owner, repo)
+ return text
+
+
+def update_release_jayson(target,
+ release_jayson,
+ build_report_jayson,
+ app_pkg, version):
+ text = "Missing data in $APP_DIR/pyrustic_data/{}"
+ if not build_report_jayson.data:
+ print(text.format("build_report.json"))
+ return False
+ if not release_jayson.data:
+ print(text.format("release_info.json"))
+ return False
+ # update owner
+ if not release_jayson.data["owner"]:
+ owner = input("Github owner: ")
+ print("")
+ release_jayson.data["owner"] = owner
+ # update repo
+ if not release_jayson.data["repository"]:
+ repo = os.path.basename(target)
+ release_jayson.data["repository"] = repo
+ # update name
+ repo = release_jayson.data["repository"]
+ name = "{} v{}".format(repo, version)
+ release_jayson.data["release_name"] = name
+ # update tag name
+ tag_name = "v{}".format(version)
+ release_jayson.data["tag_name"] = tag_name
+ # update target commitish
+ if not release_jayson.data["target_commitish"]:
+ release_jayson.data["target_commitish"] = "master"
+ # update description
+ owner = release_jayson.data["owner"]
+ repository = release_jayson.data["repository"]
+ description = get_release_description(target, owner, repository)
+ release_jayson.data["description"] = description
+ # update is_prerelease
+ if not release_jayson.data["is_prerelease"]:
+ release_jayson.data["is_prerelease"] = False
+ # update is_draft
+ if not release_jayson.data["is_draft"]:
+ release_jayson.data["is_draft"] = False
+ # update upload_asset
+ if release_jayson.data["upload_asset"] is None:
+ release_jayson.data["upload_asset"] = True
+ # update asset name
+ asset_name = build_report_jayson.data["wheel_asset"]
+ release_jayson.data["asset_name"] = asset_name
+ # update asset label
+ if not release_jayson.data["asset_label"]:
+ release_jayson.data["asset_label"] = "Download the Wheel"
+ # save the changes
+ release_jayson.save()
+ return True
+
+
+def _get_default_release_description(owner, repo):
+ pyrustic_link = "https://github.com/pyrustic/pyrustic"
+ text = TEXT.format(pyrustic_link=pyrustic_link)
+ return text
+
+
+def main():
+ data = get_data()
+ if not data:
+ print("Missing sys.argv data")
+ sys.exit(1)
+ pyrustic_data_path = get_pyrustic_data_path(data)
+ # get build_report jayson
+ build_report_jayson = get_jayson(pyrustic_data_path,
+ "build_report.json", True)
+ # get release info jayson
+ release_jayson = get_jayson(pyrustic_data_path,
+ "release_info.json", False)
+ # update release_info.json
+ if not update_release_jayson(data["target"],
+ release_jayson,
+ build_report_jayson,
+ data["app_pkg"],
+ data["version"]):
+ sys.exit(1)
+ # exit
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/hubstore/hooking/post_build_hook.py b/hubstore/hooking/post_build_hook.py
new file mode 100644
index 0000000..7945e01
--- /dev/null
+++ b/hubstore/hooking/post_build_hook.py
@@ -0,0 +1,22 @@
+# post_build_hook.py generated by Pyrustic Manager
+import sys
+
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+ items = ("script", "target", "app_pkg", "version")
+ data = None
+ if len(sys.argv) == len(items):
+ data = {item: sys.argv[i] for i, item in enumerate(items)}
+ return data
+
+
+def main():
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/hubstore/hooking/post_release_hook.py b/hubstore/hooking/post_release_hook.py
new file mode 100644
index 0000000..05c3cd8
--- /dev/null
+++ b/hubstore/hooking/post_release_hook.py
@@ -0,0 +1,77 @@
+# post_release_hook.py generated by Pyrustic Manager
+import sys
+import os
+import os.path
+from datetime import datetime
+import time
+
+
+def get_data():
+ """
+ Return None or a dict with the keys:
+ 'script', 'target', 'app_pkg' and 'version'
+ """
+ items = ("script", "target", "app_pkg", "version")
+ data = None
+ if len(sys.argv) == len(items):
+ data = {item: sys.argv[i] for i, item in enumerate(items)}
+ return data
+
+
+def get_date():
+ """ Returns the current date. Format: Month day, year.
+ Example: January 15, 2020
+ """
+ MONTHS = ("January", "February", "March", "April", "May",
+ "June", "July", "August", "September", "October",
+ "November", "December")
+ dt = datetime.fromtimestamp(time.time())
+ text = "{month} {day}, {year}".format(month=MONTHS[dt.month - 1],
+ day=dt.day, year=dt.year)
+ return text
+
+
+def update_changelog(path, data, version):
+ """ Update the file CHANGELOG.md located at path, with data and version """
+ if not data:
+ return
+ cache = "## Version {} of {}\n"
+ data.insert(0, cache.format(version, get_date()))
+ data.append("\n\n\n")
+ data = "".join(data)
+ try:
+ with open(path, "r+") as file:
+ cache = file.readlines()
+ cache.insert(0, data)
+ file.seek(0)
+ file.write("".join(cache))
+ file.truncate()
+ except Exception as e:
+ pass
+
+
+def main():
+ data = get_data()
+ if not data:
+ print("Missing sys.argv data")
+ sys.exit(1)
+ # cut LATEST_RELEASE.md content and then log it in CHANGELOG.md
+ target = data["target"]
+ latest_release_path = os.path.join(target, "LATEST_RELEASE.md")
+ try:
+ with open(latest_release_path, "r+") as file:
+ cache = file.readlines()
+ file.seek(0)
+ file.write("")
+ file.truncate()
+ except Exception as e:
+ pass
+ else:
+ changelog_path = os.path.join(target, "CHANGELOG.md")
+ update_changelog(changelog_path, cache, data["version"])
+ # exit
+ sys.exit(0)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/hubstore/host/core.py b/hubstore/host/core.py
index d27e337..25b29d7 100644
--- a/hubstore/host/core.py
+++ b/hubstore/host/core.py
@@ -6,8 +6,8 @@
import sys
import pkgutil
from hubstore.host import constants
-from pyrustic.jasonix import Jasonix
-from pyrustic.gurl import Gurl
+from jayson import Jayson
+from kurl import Kurl
def should_init_hubstore():
@@ -69,7 +69,7 @@ def init_hubstore(path):
return data
-def rate(gurl):
+def rate(kurl):
"""
Get Rate Limit
Return: status_code, status_text, data
@@ -77,7 +77,7 @@ def rate(gurl):
"""
target = "https://api.github.com"
url = "{}/rate_limit".format(target)
- response = gurl.request(url)
+ response = kurl.request(url)
json = response.json
status_code, status_text = response.status
data = {}
@@ -89,7 +89,7 @@ def rate(gurl):
return status_code, status_text, data
-def auth(token, gurl):
+def auth(token, kurl):
"""
Auth
Return: (status_code, status_text, login_str)
@@ -97,8 +97,8 @@ def auth(token, gurl):
"""
target = "https://api.github.com"
url = "{}/user".format(target)
- gurl.token = token
- response = gurl.request(url)
+ kurl.token = token
+ response = kurl.request(url)
json = response.json
status_code, status_text = response.status
data = None
@@ -109,19 +109,19 @@ def auth(token, gurl):
return status_code, status_text, data
-def fetch(owner, repo, gurl):
+def fetch(owner, repo, kurl):
""" Fetch resource
Param:
- owner: str
- repo: str
- - gurl: Gurl object
+ - kurl: Kurl object
Return:
status_code, status_text, json_data
"""
target = "https://api.github.com"
url = "{}/repos/{}/{}/releases/latest".format(target, owner, repo)
- response = gurl.request(url)
+ response = kurl.request(url)
json = response.json
status_code, status_text = response.status
if status_code == 304:
@@ -152,14 +152,14 @@ def useful_info(data):
return info
-def download(owner, repo, name, url, gurl):
+def download(owner, repo, name, url, kurl):
"""
- Download the resource (url) with gurl object
+ Download the resource (url) with kurl object
Return a boolean is_success, error, and tempfile
"""
is_success = True
error = None
- response = gurl.request(url)
+ response = kurl.request(url)
data = response.body
if response.code == 304:
if response.cached_response:
@@ -233,26 +233,28 @@ def install(owner, repo, name):
dest = os.path.join(hubstore_apps, "apps", owner,
"{}-habitat".format(repo))
try:
- p = subprocess.Popen([sys.executable, "-m", "pip",
- "install",
- "--target={}".format(dest), src],
+ args = ["-m", "pip", "install",
+ "--upgrade", "--upgrade-strategy", "eager",
+ "--target={}".format(dest), src]
+ p = subprocess.Popen([sys.executable, *args],
stderr=subprocess.PIPE,
stdout=subprocess.PIPE)
out, err = p.communicate()
if err:
- return False, err
+ #return False, err # pip outputs a warning error about its own version
+ pass
except Exception as e:
return False, e
# register app in apps.json
- jasonix = Jasonix(os.path.join(hubstore_apps, "apps.json"))
+ jayson = Jayson(os.path.join(hubstore_apps, "apps.json"))
app_pkg = name.split("-")[0]
cache = (repo, app_pkg)
- if owner in jasonix.data:
- if repo not in jasonix.data[owner]:
- jasonix.data[owner].append(cache)
+ if owner in jayson.data:
+ if repo not in jayson.data[owner]:
+ jayson.data[owner].append(cache)
else:
- jasonix.data[owner] = [cache]
- jasonix.save()
+ jayson.data[owner] = [cache]
+ jayson.save()
return True, None
@@ -313,8 +315,8 @@ def get_list():
apps_json = os.path.join(hubstore_apps, "apps.json")
data = None
try:
- jasonix = Jasonix(apps_json)
- data = jasonix.data
+ jayson = Jayson(apps_json)
+ data = jayson.data
except Exception as e:
return False, e, data
return True, None, data
@@ -329,17 +331,17 @@ def uninstall(owner, repo):
error = None
hubstore_apps = _hubstore_apps_folder()
apps_data = os.path.join(hubstore_apps, "apps.json")
- jasonix = Jasonix(apps_data)
+ jayson = Jayson(apps_data)
root_dir = os.path.join(hubstore_apps, "apps", owner, repo)
try:
- repos = jasonix.data[owner]
+ repos = jayson.data[owner]
index = None
for i, item in enumerate(repos):
if item[0] == repo:
index = i
break
- del jasonix.data[owner][index]
- jasonix.save()
+ del jayson.data[owner][index]
+ jayson.save()
except KeyError as e:
error = "Unknown owner"
except (IndexError, TypeError) as e:
@@ -473,10 +475,10 @@ def split_arg(arg):
def get_app_pkg(owner, repo):
hubstore_apps = _hubstore_apps_folder()
apps_data = os.path.join(hubstore_apps, "apps.json")
- jasonix = Jasonix(apps_data)
- if not jasonix.data:
+ jayson = Jayson(apps_data)
+ if not jayson.data:
return None
- for key, val in jasonix.data.items():
+ for key, val in jayson.data.items():
if key == owner:
for app in val:
if app[0] == repo:
@@ -484,14 +486,14 @@ def get_app_pkg(owner, repo):
return None
-def get_gurl():
+def get_kurl():
"""
- Generate a Gurl object
+ Generate a Kurl object
"""
headers = {"Accept": "application/vnd.github.v3+json",
"User-Agent": "Pyrustic"}
- gurl = Gurl(headers=headers)
- return gurl
+ kurl = Kurl(headers=headers)
+ return kurl
# ======================================
@@ -541,9 +543,9 @@ def _register_hubstore_in_pyrustic_data(hubstore_apps):
data = pkgutil.get_data("hubstore", resource)
with open(HUBSTORE_SHARED_DATA_FILE, "wb") as file:
file.write(data)
- jasonix = Jasonix(HUBSTORE_SHARED_DATA_FILE)
- jasonix.data["hubstore-apps"] = hubstore_apps
- jasonix.save()
+ jayson = Jayson(HUBSTORE_SHARED_DATA_FILE)
+ jayson.data["hubstore-apps"] = hubstore_apps
+ jayson.save()
except Exception as e:
return e
return None
@@ -596,8 +598,8 @@ def _moveto(src, dest):
def _hubstore_apps_folder():
- jasonix = Jasonix(constants.HUBSTORE_SHARED_DATA_FILE)
- hubstore_apps = jasonix.data.get("hubstore-apps")
+ jayson = Jayson(constants.HUBSTORE_SHARED_DATA_FILE)
+ hubstore_apps = jayson.data.get("hubstore-apps")
return hubstore_apps
@@ -605,8 +607,8 @@ def _search_install_script_in_pyrustic_data(root_dir):
about_json = os.path.join(root_dir, "pyrustic_data", "about.json")
if os.path.exists(about_json):
try:
- jasonix = Jasonix(about_json)
- module = jasonix.data.get("install_script", None)
+ jayson = Jayson(about_json)
+ module = jayson.data.get("install_script", None)
except Exception as e:
return False, e, None
else:
diff --git a/hubstore/host/main_host.py b/hubstore/host/main_host.py
index 04b3b81..3536660 100644
--- a/hubstore/host/main_host.py
+++ b/hubstore/host/main_host.py
@@ -5,8 +5,8 @@
import pkgutil
from hubstore.host import core
from pyrustic.manager import constant
-from pyrustic.jasonix import Jasonix
-from pyrustic.gurl import Gurl
+from jayson import Jayson
+from kurl import Kurl
class MainHost:
@@ -15,8 +15,8 @@ def __init__(self):
self._count_processes = 0
self._processes = dict()
self._login = None
- self._gurl = core.get_gurl()
- self._download_gurl = self._get_download_gurl()
+ self._kurl = core.get_kurl()
+ self._download_kurl = self._get_download_kurl()
self._setup()
# === PROPERTIES ===
@@ -56,11 +56,11 @@ def auth(self, token):
Return: (status_code, status_text, login_str)
data = the login if status is 200 or 304, else data is None
"""
- status_code, status_text, self._login = core.auth(token, self._gurl)
+ status_code, status_text, self._login = core.auth(token, self._kurl)
return status_code, status_text, self._login
def unauth(self):
- self._gurl.token = None
+ self._kurl.token = None
self._login = None
def parse_owner_repo(self, val):
@@ -98,7 +98,7 @@ def search_online(self, owner, repo):
assets = None
status_code, status_text, data = core.fetch(owner,
repo,
- self._gurl)
+ self._kurl)
status = (status_code, status_text)
if status_code in (200, 304):
success = True
@@ -122,7 +122,7 @@ def download(self, name, url, owner, repo):
repo,
name,
url,
- self._download_gurl)
+ self._download_kurl)
data = {"success": is_success, "error": error}
if not is_success:
return data
@@ -175,7 +175,7 @@ def get_rate(self):
"data": data}
data = {"limit": int, "remaining": int}
"""
- status_code, status_text, data = core.rate(self._gurl)
+ status_code, status_text, data = core.rate(self._kurl)
return {"status_code": status_code,
"status_text": status_text,
"data": data}
@@ -249,8 +249,8 @@ def get_image(self, owner, repo):
"pyrustic_data", "hubstore.json")
data = None
if os.path.exists(hubstore_json_path):
- jasonix = Jasonix(hubstore_json_path)
- path = jasonix.data.get("showcase_small_img", None)
+ jayson = Jayson(hubstore_json_path)
+ path = jayson.data.get("showcase_small_img", None)
if path:
path = path.replace("./", "", 1) if path.startswith("./") else path
path = os.path.join(root_dir, repo, path)
@@ -270,7 +270,7 @@ def stop_process(self, process_id):
del self._processes[process_id]
def _setup(self):
- shared_folder = os.path.join(constant.PYRUSTIC_DATA_FOLDER,
+ shared_folder = os.path.join(constant.SHARED_PYRUSTIC_DATA,
"hubstore")
shared_json_path = os.path.join(shared_folder,
"hubstore_shared_data.json")
@@ -282,7 +282,7 @@ def _setup(self):
resource)
with open(shared_json_path, "wb") as file:
file.write(default_json)
- self._jasonix = Jasonix(shared_json_path)
+ self._jayson = Jayson(shared_json_path)
# === PRIVATE ===
def _filter_assets(self, assets):
@@ -299,14 +299,14 @@ def _get_default_image(self):
data = pkgutil.get_data("hubstore", resource)
return data
- def _get_download_gurl(self):
+ def _get_download_kurl(self):
"""
- Generate a Gurl object
+ Generate a Kurl object
"""
headers = {"Accept": "application/octet-stream",
"User-Agent": "Pyrustic"}
- gurl = Gurl(headers=headers)
- return gurl
+ kurl = Kurl(headers=headers)
+ return kurl
def _metadata(self, path):
data = {"email": None, "version": None, "description": None,
diff --git a/hubstore/misc/funcs.py b/hubstore/misc/funcs.py
new file mode 100644
index 0000000..5a4d4d3
--- /dev/null
+++ b/hubstore/misc/funcs.py
@@ -0,0 +1,37 @@
+import math
+
+
+def tab_to_space(text, tab_size=4):
+ TAB = "\t"
+ SPACE = " "
+ lines = text.split("\n")
+ results = []
+ for line in lines:
+ cache = str()
+ for char in line:
+ if char == TAB:
+ while len(cache) % tab_size != 0:
+ cache += SPACE
+ else:
+ cache += char
+ results.append(cache)
+ return "\n".join(results)
+
+
+def convert_size(size):
+ """ Size should be in bytes.
+ Return a tuple (float_or_int_val, str_unit) """
+ if size == 0:
+ return (0, "B")
+ KILOBYTE = 1024
+ size_name = ("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
+ i = int(math.floor(math.log(size, KILOBYTE)))
+ p = math.pow(KILOBYTE, i)
+ result = round(size/p, 2)
+ return (result, size_name[i])
+
+
+def truncate_str(data, max_size=15, ellipsis="..."):
+ val = ((data[:max_size] + ellipsis)
+ if len(data) > max_size else data)
+ return val
\ No newline at end of file
diff --git a/hubstore/misc/my_theme.py b/hubstore/misc/my_theme.py
index d8012e3..5f91d2a 100644
--- a/hubstore/misc/my_theme.py
+++ b/hubstore/misc/my_theme.py
@@ -1,13 +1,12 @@
-# "my_theme.py" file generated by Pyrustic Manager
-from pyrustic.theme import Theme
-from pyrustic import default_style
-from tk_cyberpunk_theme.main import Cyberpunk
-from tk_cyberpunk_theme.native_widget import button
-from tk_cyberpunk_theme.native_widget import entry
-from tk_cyberpunk_theme.native_widget import label
-from tk_cyberpunk_theme.native_widget import text
-from tk_cyberpunk_theme.native_widget import radiobutton
-from tk_cyberpunk_theme import constant
+from themebase import Theme
+import stylebase
+from cyberpunk_theme import Cyberpunk
+from cyberpunk_theme.widget import button
+from cyberpunk_theme.widget import entry
+from cyberpunk_theme.widget import label
+from cyberpunk_theme.widget import text
+from cyberpunk_theme.widget import radiobutton
+from cyberpunk_theme import constant
# ========================================
@@ -158,7 +157,7 @@ def _get_entry_running_app_name_style():
return style
def _get_button_close_style():
- style = default_style.Button()
+ style = stylebase.Button()
style.background = "#191919"
style.background = constant.COLOR_BLACK
style.activeBackground = "#670000"
diff --git a/hubstore/pyrustic_data/gui.json b/hubstore/pyrustic_data/gui.json
deleted file mode 100644
index e10bc6f..0000000
--- a/hubstore/pyrustic_data/gui.json
+++ /dev/null
@@ -1,9 +0,0 @@
-{
- "root_geometry": "900x550+0+0",
- "root_background": "black",
- "ignore_geometry": false,
- "maximize_window": false,
- "resizable_width": false,
- "resizable_height": false,
- "allow_theme": true
-}
diff --git a/hubstore/pyrustic_data/hooking.json b/hubstore/pyrustic_data/hooking.json
new file mode 100644
index 0000000..386b311
--- /dev/null
+++ b/hubstore/pyrustic_data/hooking.json
@@ -0,0 +1,14 @@
+{
+ "ante_build": [
+ "hubstore.hooking.ante_build_hook"
+ ],
+ "ante_release": [
+ "hubstore.hooking.ante_release_hook"
+ ],
+ "post_build": [
+ "hubstore.hooking.post_build_hook"
+ ],
+ "post_release": [
+ "hubstore.hooking.post_release_hook"
+ ]
+}
\ No newline at end of file
diff --git a/hubstore/pyrustic_data/hubstore.json b/hubstore/pyrustic_data/hubstore.json
new file mode 100644
index 0000000..597040a
--- /dev/null
+++ b/hubstore/pyrustic_data/hubstore.json
@@ -0,0 +1,8 @@
+{
+ "showcase_small_img": null,
+ "showcase_medium_img": null,
+ "showcase_large_img": null,
+ "install_script": null,
+ "uninstall_script": null,
+ "requirements": null
+}
diff --git a/hubstore/pyrustic_data/release_info.json b/hubstore/pyrustic_data/release_info.json
new file mode 100644
index 0000000..116b476
--- /dev/null
+++ b/hubstore/pyrustic_data/release_info.json
@@ -0,0 +1,13 @@
+{
+ "owner": null,
+ "repository": null,
+ "release_name": null,
+ "tag_name": null,
+ "target_commitish": null,
+ "description": null,
+ "is_prerelease": null,
+ "is_draft": null,
+ "upload_asset": false,
+ "asset_name": null,
+ "asset_label": null
+}
diff --git a/hubstore/version.py b/hubstore/version.py
deleted file mode 100644
index 6526deb..0000000
--- a/hubstore/version.py
+++ /dev/null
@@ -1 +0,0 @@
-__version__ = "0.0.7"
diff --git a/hubstore/view/about_view.py b/hubstore/view/about_view.py
index a59f433..3e5aabd 100644
--- a/hubstore/view/about_view.py
+++ b/hubstore/view/about_view.py
@@ -1,6 +1,5 @@
import tkinter as tk
-from pyrustic import tkmisc
-from pyrustic.view import View
+from viewable import Viewable
import webbrowser
@@ -26,14 +25,14 @@
PYRUSTIC_URL = "https://github.com/pyrustic/pyrustic#readme"
-class AboutView(View):
+class AboutView(Viewable):
def __init__(self, parent_view):
super().__init__()
self._parent_view = parent_view
self._master = self._parent_view.body
self._body = None
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master, name="about_view")
self._body.title("About | Hubstore")
# text
@@ -60,14 +59,6 @@ def _on_build(self):
command=self.destroy)
button_close.pack(side=tk.RIGHT, padx=(0, 2), pady=2)
-
- def _on_display(self):
- pass
-
- def _toplevel_geometry(self):
- super()._toplevel_geometry()
- tkmisc.dialog_effect(self._body)
-
def _on_destroy(self):
pass
diff --git a/hubstore/view/app_info_view.py b/hubstore/view/app_info_view.py
index f3d4c64..f4c9646 100644
--- a/hubstore/view/app_info_view.py
+++ b/hubstore/view/app_info_view.py
@@ -1,12 +1,12 @@
import webbrowser
import tkinter as tk
-from pyrustic.view import View
-from pyrustic.widget.toast import Toast
-from pyrustic.widget.confirm import Confirm
+from viewable import Viewable
+from megawidget.toast import Toast
+from megawidget.confirm import Confirm
from hubstore.view.downloader_view import DownloaderView
-class AppInfoView(View):
+class AppInfoView(Viewable):
def __init__(self, parent_view, footer_view, owner, repo):
super().__init__()
self._parent_view = parent_view
@@ -67,7 +67,7 @@ def notify_uninstall(self, result):
self._parent_view.load_data()
self.destroy()
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master, name="toplevel_app_info")
self._body.title("App Info")
# gen header frame
@@ -81,7 +81,8 @@ def _on_build(self):
frame_footer = self._gen_footer_frame(self._body)
frame_footer.pack(fill=tk.X, pady=2)
- def _on_display(self):
+ def _on_map(self):
+ super()._on_map()
self._populate()
def _on_destroy(self):
diff --git a/hubstore/view/auth_view.py b/hubstore/view/auth_view.py
index 8de33c4..138a654 100644
--- a/hubstore/view/auth_view.py
+++ b/hubstore/view/auth_view.py
@@ -1,9 +1,9 @@
import tkinter as tk
-from pyrustic.view import View
-from pyrustic.widget.toast import Toast
+from viewable import Viewable
+from megawidget.toast import Toast
-class AuthView(View):
+class AuthView(Viewable):
def __init__(self, parent_view):
super().__init__()
@@ -33,7 +33,7 @@ def notify_auth(self, result):
toast.wait_window()
self._parent_view.notify_auth(True)
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master, name="auth_view")
self._body.resizable(False, False)
# title
@@ -58,10 +58,7 @@ def _on_build(self):
# alter gui if not auth
if self._is_auth:
self._alter_gui_auth_mode(label_title, entry_token,
- button_connect)
-
- def _on_display(self):
- pass
+ button_connect)
def _on_destroy(self):
pass
diff --git a/hubstore/view/central_view.py b/hubstore/view/central_view.py
index 037db20..105be77 100644
--- a/hubstore/view/central_view.py
+++ b/hubstore/view/central_view.py
@@ -1,8 +1,7 @@
import tkinter as tk
-import os.path
-from pyrustic.view import View
-from pyrustic.widget.scrollbox import Scrollbox
-from pyrustic.widget.toast import Toast
+from viewable import Viewable
+from megawidget.scrollbox import Scrollbox
+from megawidget.toast import Toast
from hubstore.view.app_info_view import AppInfoView
from hubstore.misc import my_theme
@@ -10,7 +9,7 @@
MAX_TILES_BY_ROW = 4
-class CentralView(View):
+class CentralView(Viewable):
def __init__(self, parent_view):
super().__init__()
self._parent_view = parent_view
@@ -41,17 +40,11 @@ def footer_view(self):
def load_data(self):
self._load_data()
- def _on_build(self):
+ def _build(self):
self._body = tk.Frame(self._master)
self._scrollbox = Scrollbox(self._body, orient="v", box_sticky="nswe")
self._scrollbox.pack(expand=1, fill=tk.BOTH)
- def _on_display(self):
- pass
-
- def _on_destroy(self):
- pass
-
def _load_data(self):
is_success, error, data = self._host.get_list()
if not is_success:
diff --git a/hubstore/view/downloader_view.py b/hubstore/view/downloader_view.py
index 00116dc..acfb39c 100644
--- a/hubstore/view/downloader_view.py
+++ b/hubstore/view/downloader_view.py
@@ -1,11 +1,11 @@
-from pyrustic.view import View
-from pyrustic.widget.scrollbox import Scrollbox
-from pyrustic.widget.toast import Toast
-from pyrustic import pymisc
+from viewable import Viewable
+from megawidget.scrollbox import Scrollbox
+from megawidget.toast import Toast
+from hubstore.misc import funcs
import tkinter as tk
-class DownloaderView(View):
+class DownloaderView(Viewable):
def __init__(self, parent_view, owner, repo,
release_data, asset_data):
super().__init__()
@@ -19,7 +19,7 @@ def __init__(self, parent_view, owner, repo,
self._body = None
self._intvar = tk.IntVar()
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master)
self._body.title("Download the latest release")
self._body.columnconfigure(0, weight=1)
@@ -43,12 +43,6 @@ def _on_build(self):
footer_frame = self._gen_footer_frame(self._body)
footer_frame.grid(row=2, column=0, sticky="swe")
- def _on_display(self):
- pass
-
- def _on_destroy(self):
- pass
-
def _gen_information_frame(self, master, app_name, release_data):
frame = tk.Frame(master, name="downloader_information_frame")
# title
@@ -142,7 +136,7 @@ def _gen_asset_frame(self, master, asset_data):
asset_frame = tk.Frame(scrollbox.box)
asset_frame.pack(fill=tk.X, padx=2)
# radiobutton
- cache = pymisc.truncate_str(asset["name"], max_size=42)
+ cache = funcs.truncate_str(asset["name"], max_size=42)
radiobutton = tk.Radiobutton(asset_frame,
variable=self._intvar,
value=i,
@@ -168,8 +162,7 @@ def _gen_footer_frame(self, master):
def _on_click_download(self):
if not self._asset_data:
- Toast(self._body,
- message="No asset to download")
+ Toast(self._body, message="No asset to download")
return
choice = self._intvar.get()
name = self._asset_data[choice]["name"]
@@ -180,5 +173,5 @@ def _on_click_download(self):
self.destroy()
def _stringify_size(self, data):
- val, unit = pymisc.convert_size(data)
+ val, unit = funcs.convert_size(data)
return "{} {}".format(val, unit)
diff --git a/hubstore/view/exception_view.py b/hubstore/view/exception_view.py
index 3e17f77..289ea6a 100644
--- a/hubstore/view/exception_view.py
+++ b/hubstore/view/exception_view.py
@@ -1,8 +1,8 @@
import tkinter as tk
-from pyrustic.view import View
+from viewable import Viewable
-class ExceptionView(View):
+class ExceptionView(Viewable):
def __init__(self, parent_view, data):
super().__init__()
self._parent_view = parent_view
@@ -10,7 +10,7 @@ def __init__(self, parent_view, data):
self._master = parent_view.body
self._body = None
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master, name="exception_view")
self._body.title("Oops ! An Exception occurred !")
text = tk.Text(self._body, width=50,
@@ -23,9 +23,3 @@ def _on_build(self):
text="Close",
command=self.destroy)
button_close.pack(anchor="e", padx=2, pady=(7, 2))
-
- def _on_display(self):
- pass
-
- def _on_destroy(self):
- pass
diff --git a/hubstore/view/footer_view.py b/hubstore/view/footer_view.py
index fb22f76..d8a768c 100644
--- a/hubstore/view/footer_view.py
+++ b/hubstore/view/footer_view.py
@@ -1,11 +1,11 @@
import tkinter as tk
-from pyrustic.view import View, BUILT, DISPLAYED
-from pyrustic.widget.scrollbox import Scrollbox
+from viewable import Viewable, BUILT, MAPPED
+from megawidget.scrollbox import Scrollbox
from hubstore.view.app_info_view import AppInfoView
from hubstore.view.exception_view import ExceptionView
-class FooterView(View):
+class FooterView(Viewable):
def __init__(self, parent_view):
super().__init__()
self._parent_view = parent_view
@@ -27,7 +27,7 @@ def threadom(self):
return self._threadom
def add_item(self, owner, repo, process_id):
- if self.state not in (BUILT, DISPLAYED):
+ if self.state not in (BUILT, MAPPED):
return
self._install_item(owner, repo, process_id)
# scroll to end
@@ -41,17 +41,11 @@ def exited_app(self, data):
process_id = data["id"]
self._remove_item(process_id)
- def _on_build(self):
+ def _build(self):
self._body = tk.Frame(self._master)
self._scrollbox = Scrollbox(self._body, orient="x", resizable_box=False)
self._scrollbox.pack(fill=tk.X)
- def _on_display(self):
- pass
-
- def _on_destroy(self):
- pass
-
def _install_item(self, owner, repo, process_id):
frame = tk.Frame(self._scrollbox.box)
self._running_processes[process_id] = frame
diff --git a/hubstore/view/header_view.py b/hubstore/view/header_view.py
index 3b42519..3f39636 100644
--- a/hubstore/view/header_view.py
+++ b/hubstore/view/header_view.py
@@ -1,18 +1,18 @@
import os
import os.path
import tkinter as tk
-from pyrustic import pymisc
from tkinter import filedialog
-from pyrustic.view import View
-from pyrustic.widget.toast import Toast
+from viewable import Viewable
+from megawidget.toast import Toast
from hubstore.view.downloader_view import DownloaderView
from hubstore.view.about_view import AboutView
from hubstore.view.auth_view import AuthView
from hubstore.view.app_info_view import AppInfoView
from hubstore.view.import_list_view import ImportListView
+from hubstore.misc import funcs
-class HeaderView(View):
+class HeaderView(Viewable):
def __init__(self, parent_view):
super().__init__()
@@ -89,7 +89,7 @@ def notify_rate(self, result):
if status_code in (200, 304):
message = "Rate Limit:\t{}\nRemaining :\t{}".format(data["limit"],
data["remaining"])
- message = pymisc.tab_to_space(message, tab_size=4)
+ message = funcs.tab_to_space(message, tab_size=4)
else:
duration = 1000
message = "Failed to load data\n{}".format(status_text)
@@ -136,7 +136,7 @@ def notify_auth(self, success):
button_style.target(self._button_auth)"""
pass
- def _on_build(self):
+ def _build(self):
self._body = tk.Frame(self._master)
# left frame
left_frame = self._gen_left_frame(self._body)
@@ -146,9 +146,6 @@ def _on_build(self):
right_frame = self._gen_right_frame(self._body)
right_frame.pack(side=tk.RIGHT, pady=2)
- def _on_display(self):
- pass
-
def _on_destroy(self):
pass
@@ -308,7 +305,6 @@ def _loop_install(self, data, index=0):
return
text = data[index]
self._strvar_search.set(text)
- self
index += 1
command = (lambda self=self,
data=data,
diff --git a/hubstore/view/import_list_view.py b/hubstore/view/import_list_view.py
index 1c1f78c..8203cc1 100644
--- a/hubstore/view/import_list_view.py
+++ b/hubstore/view/import_list_view.py
@@ -1,10 +1,10 @@
import tkinter as tk
-from pyrustic.view import View
-from pyrustic.widget.toast import Toast
-from pyrustic.widget.scrollbox import Scrollbox
+from viewable import Viewable
+from megawidget.toast import Toast
+from megawidget.scrollbox import Scrollbox
-class ImportListView(View):
+class ImportListView(Viewable):
def __init__(self, parent_view, header_view, data):
super().__init__()
self._parent_view = parent_view
@@ -23,7 +23,7 @@ def notify_online_search_result(self, owner, repo, result):
self._toast_cache = None
self._header_view.notify_online_search_result(owner, repo, result)
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel()
self._body.resizable(False, False)
self._body.rowconfigure(0, weight=0, uniform="a")
@@ -53,12 +53,6 @@ def _on_build(self):
command=self.destroy)
button_cancel.pack(side=tk.RIGHT, padx=(0, 2), pady=2)
- def _on_display(self):
- pass
-
- def _on_destroy(self):
- pass
-
def _on_click_download(self):
user_choice = self._intvar.get()
text = self._data[user_choice]
diff --git a/hubstore/view/init_view.py b/hubstore/view/init_view.py
index 9556fcd..2b2deae 100644
--- a/hubstore/view/init_view.py
+++ b/hubstore/view/init_view.py
@@ -1,13 +1,12 @@
import os.path
import tkinter as tk
from tkinter import filedialog
-from pyrustic.view import View
-from pyrustic.widget.toast import Toast
-from pyrustic.widget.pathentry import Pathentry
-from pyrustic import tkmisc
+from viewable import Viewable
+from megawidget.toast import Toast
+from megawidget.pathentry import Pathentry
-class InitView(View):
+class InitView(Viewable):
def __init__(self, parent_view):
super().__init__()
self._parent_view = parent_view
@@ -35,7 +34,7 @@ def notify_init_outcome(self, data):
toast = Toast(self._body, message=message)
toast.wait_window()
- def _on_build(self):
+ def _build(self):
self._body = tk.Toplevel(self._master, name="init_geet_view")
self._body.resizable(0, 0)
# Label Title
@@ -80,17 +79,10 @@ def _on_build(self):
command=self.destroy)
button_cancel.pack(side=tk.RIGHT, padx=(0, 2), pady=2)
- def _on_display(self):
- pass
-
def _on_destroy(self):
if not self._init_success:
self._parent_view.leave()
- def _toplevel_geometry(self):
- super()._toplevel_geometry()
- tkmisc.dialog_effect(self._body)
-
def _on_click_init(self):
path = self._strvar_path.get()
if path and os.path.isdir(path):
@@ -102,7 +94,6 @@ def _on_click_init(self):
message = ("Please set a path !" if path == ""
else "This path doesn't exist !")
toast = Toast(self._body, message=message)
- toast.build()
def _get_path(self):
initialdir = os.path.expanduser("~")
diff --git a/hubstore/view/main_view.py b/hubstore/view/main_view.py
index 9ca786c..be6b7ce 100644
--- a/hubstore/view/main_view.py
+++ b/hubstore/view/main_view.py
@@ -1,7 +1,7 @@
# a "view" module generated by Pyrustic Manager
import tkinter as tk
-from pyrustic.view import View
-from pyrustic.threadom import Threadom
+from viewable import Viewable
+from threadom import Threadom
from hubstore.view.init_view import InitView
from hubstore.view.header_view import HeaderView
from hubstore.view.central_view import CentralView
@@ -9,7 +9,7 @@
from hubstore.host.main_host import MainHost
-class MainView(View):
+class MainView(Viewable):
def __init__(self, app):
super().__init__()
@@ -51,8 +51,7 @@ def leave(self):
# === LIFECYCLE ===
- def _on_build(self):
- # body
+ def _build(self):
self._body = tk.Frame(self._root)
# header_view
self._header_view = HeaderView(self)
@@ -60,13 +59,13 @@ def _on_build(self):
# central_view
self._central_view = CentralView(self)
self._central_view.build_pack(fill=tk.BOTH,
- expand=1,
- pady=(10, 5))
+ expand=1, pady=(10, 5))
# footer_view
self._footer_view = FooterView(self)
self._footer_view.build_pack(fill=tk.X, anchor="s")
- def _on_display(self):
+ def _on_map(self):
+ super()._on_map()
self._init_geet()
self._menubar = tk.Menu(self._root)
self._root.config(menu=self._menubar)
diff --git a/setup.cfg b/setup.cfg
index 01d3436..0d6794b 100644
--- a/setup.cfg
+++ b/setup.cfg
@@ -1,6 +1,6 @@
[metadata]
name = hubstore
-version = attr: hubstore.version.__version__
+version = file: VERSION
url = https://github.com/pyrustic/hubstore
author = Pyrustic Evangelist
author_email = pyrustic@protonmail.com