Skip to content

Commit

Permalink
Bugfix for #23 including some small changes
Browse files Browse the repository at this point in the history
  • Loading branch information
mathijs-dumon committed Dec 19, 2018
1 parent 4d4743f commit 5f79b20
Show file tree
Hide file tree
Showing 7 changed files with 350 additions and 7 deletions.
4 changes: 0 additions & 4 deletions pyxrd/application/controllers.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,6 @@
from os.path import basename, dirname
from functools import wraps

"""import gi
gi.require_version('Gtk', '3.0')
from gi.repository import Gtk"""

from mvc.adapters.gtk_support.dialogs.dialog_factory import DialogFactory
from mvc.support.gui_loop import stop_event_loop, add_idle_call

Expand Down
5 changes: 5 additions & 0 deletions pyxrd/application/glade/application.glade
Original file line number Diff line number Diff line change
Expand Up @@ -381,6 +381,7 @@
<property name="accel_group">PyXRD_Main</property>
<child>
<object class="GtkImageMenuItem" id="menu_item_new_project">
<property name="use_action_appearance">True</property>
<property name="related_action">new_project</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
Expand All @@ -391,6 +392,7 @@
</child>
<child>
<object class="GtkImageMenuItem" id="menu_item_open_project">
<property name="use_action_appearance">True</property>
<property name="related_action">open_project</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
Expand All @@ -401,6 +403,7 @@
</child>
<child>
<object class="GtkImageMenuItem" id="menu_item_save_project">
<property name="use_action_appearance">True</property>
<property name="related_action">save_project</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
Expand All @@ -411,6 +414,7 @@
</child>
<child>
<object class="GtkImageMenuItem" id="menu_item_save_project_as">
<property name="use_action_appearance">True</property>
<property name="related_action">save_project_as</property>
<property name="visible">True</property>
<property name="can_focus">False</property>
Expand Down Expand Up @@ -1255,6 +1259,7 @@ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.</property>
<property name="authors">Mathijs Dumon</property>
<property name="logo_icon_name">image-missing</property>
<child internal-child="vbox">
<object class="GtkBox" id="aboutdialog-vbox1">
<property name="can_focus">False</property>
Expand Down
31 changes: 30 additions & 1 deletion pyxrd/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,11 @@ def _run_user_script():
"""
Runs the user script specified in the command-line arguments.
"""

available, nv, cv = check_for_updates()
if available:
print("An update is available: current version is %s upstream version is %s - consider upgrading!" % cv, nv)

from pyxrd.data import settings

try:
Expand All @@ -39,6 +44,9 @@ def _run_gui(project=None):
splash = SplashScreen(filename, __version__)

# Run GUI:
splash.set_message("Checking for updates ...")
update_available, nv, cv = check_for_updates()

splash.set_message("Loading GUI ...")

# Now we can load these:
Expand Down Expand Up @@ -70,7 +78,8 @@ def _run_gui(project=None):
warnings.filterwarnings(action='ignore', category=Warning)

# Close splash screen
if splash: splash.close()
if splash:
splash.close()

# Nice GUI error handler:
gtk_exception_hook = plugin_gtk_exception_hook()
Expand All @@ -83,9 +92,29 @@ def _run_gui(project=None):
# Free this before continuing
del splash

if update_available:
from mvc.adapters.gtk_support.dialogs.dialog_factory import DialogFactory
DialogFactory.get_information_dialog(
"An update is available (%s) - consider upgrading!" % nv,
False, v.get_toplevel(), title = "Update available"
).run()
else:
print("PyXRD is up to date (current = %s)" % cv)

# lets get this show on the road:
start_event_loop()

def check_for_updates():
"""
Checks for updates and returns a tuple:
update_available, latest_version, current_version
"""
from pyxrd.generic.outdated import check_outdated
from pyxrd.__version import __version__
is_outdated, latest_version = check_outdated('pyxrd', __version__)

return is_outdated, latest_version, __version__

def run_main():
"""
Parsers command line arguments and launches PyXRD accordingly.
Expand Down
113 changes: 113 additions & 0 deletions pyxrd/generic/outdated/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
import json
from datetime import datetime
from threading import Thread
from warnings import warn

from . import utils
from .mywarnings import *

__version__ = '0.1.2'


def check_outdated(package, version):
"""
Given the name of a package on PyPI and a version (both strings), checks
if the given version is the latest version of the package available.
Returns a 2-tuple (is_outdated, latest_version) where
is_outdated is a boolean which is True if the given version is earlier
than the latest version, which is the string latest_version.
Attempts to cache on disk the HTTP call it makes for 24 hours. If this
somehow fails the exception is converted to a warning (OutdatedCacheFailedWarning)
and the function continues normally.
"""

from pkg_resources import parse_version

parsed_version = parse_version(version)
latest = None

with utils.cache_file(package, 'r') as f:
content = f.read()
if content: # in case cache_file fails and so f is a dummy file
latest, cache_dt = json.loads(content)
if not utils.cache_is_valid(cache_dt):
latest = None

def get_latest():
url = 'https://pypi.python.org/pypi/%s/json' % package
response = utils.get_url(url)
return json.loads(response)['info']['version']

if latest is None:
latest = get_latest()

parsed_latest = parse_version(latest)

if parsed_version > parsed_latest:

# Probably a stale cached value
latest = get_latest()
parsed_latest = parse_version(latest)

if parsed_version > parsed_latest:
raise ValueError('Version %s is greater than the latest version on PyPI: %s' %
(version, latest))

is_latest = parsed_version == parsed_latest
assert is_latest or parsed_version < parsed_latest

with utils.cache_file(package, 'w') as f:
data = [latest, utils.format_date(datetime.now())]
json.dump(data, f)

return not is_latest, latest


def warn_if_outdated(package,
version,
raise_exceptions=False,
background=True,
):
"""
Higher level convenience function using check_outdated.
The package and version arguments are the same.
If the package is outdated, a warning (OutdatedPackageWarning) will
be emitted.
Any exception in check_outdated will be converted to a warning (OutdatedCheckFailedWarning)
unless raise_exceptions if True.
If background is True (the default), the check will run in
a background thread so this function will return immediately.
In this case if an exception is raised and raise_exceptions if True
the traceback will be printed to stderr but the program will not be
interrupted.
This function doesn't return anything.
"""

def check():
# noinspection PyUnusedLocal
is_outdated = False
with utils.exception_to_warning('check for latest version of %s' % package,
OutdatedCheckFailedWarning,
always_raise=raise_exceptions):
is_outdated, latest = check_outdated(package, version)

if is_outdated:
warn('The package %s is out of date. Your version is %s, the latest is %s.'
% (package, version, latest),
OutdatedPackageWarning)

if background:
thread = Thread(target=check)
thread.start()
else:
check()


warn_if_outdated('outdated', __version__)
31 changes: 31 additions & 0 deletions pyxrd/generic/outdated/mywarnings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
from warnings import filterwarnings


class OutdatedWarningBase(Warning):
"""
Base class for warnings in this module. Use this to filter all
warnings from this module.
"""


class OutdatedPackageWarning(OutdatedWarningBase):
"""
Warning emitted when a package is found to be out of date.
"""


filterwarnings("always", category=OutdatedPackageWarning)


class OutdatedCheckFailedWarning(OutdatedWarningBase):
"""
Warning emitted when checking the version of a package fails
with an exception.
"""


class OutdatedCacheFailedWarning(OutdatedWarningBase):
"""
Warning emitted when writing to or reading from the cache
fails with an exception.
"""

0 comments on commit 5f79b20

Please sign in to comment.