Skip to content

Commit

Permalink
Added Qt GUI, server integration, migrate to pyinstaller & more
Browse files Browse the repository at this point in the history
  • Loading branch information
puigru committed Jul 31, 2019
1 parent de4ea71 commit a7bbc89
Show file tree
Hide file tree
Showing 11 changed files with 536 additions and 64 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
__pycache__/
build/
dist/
10 changes: 10 additions & 0 deletions asInvoker.manifest
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="asInvoker" uiAccess="false"/>
</requestedPrivileges>
</security>
</trustInfo>
</assembly>
62 changes: 62 additions & 0 deletions build.spec
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# -*- mode: python ; coding: utf-8 -*-

block_cipher = None


a = Analysis(['update.py'],
binaries=[],
datas=[],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=['matplotlib', 'numpy'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
a.binaries,
a.zipfiles,
a.datas,
[],
name='FlashpointUpdater',
debug=False,
manifest='asInvoker.manifest',
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=True , icon='icon.ico')

b = Analysis(['update_gui.py'],
binaries=[],
datas=[('icon.png', '.')],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=['matplotlib', 'numpy'],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(b.pure, b.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
b.scripts,
b.binaries,
b.zipfiles,
b.datas,
[],
name='FlashpointUpdaterQt',
debug=False,
manifest='asInvoker.manifest',
bootloader_ignore_signals=False,
strip=False,
upx=True,
upx_exclude=[],
runtime_tmpdir=None,
console=False , icon='icon.ico')
4 changes: 2 additions & 2 deletions config.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"index_endpoint": "https://unstable.life/fp-index",
"file_endpoint": "https://unstable.life/fp"
"index_endpoint": "https://unstable.life/fp-index/",
"file_endpoint": "https://unstable.life/fp/"
}
145 changes: 145 additions & 0 deletions core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
from collections import namedtuple
from urllib.parse import urljoin
import threading
import requests
import datetime
import logging
import queue
import time
import lzma
import json
import math

# Allows you to retrieve the arguments passed to a function and
# an arbitrary value by passing a 'store' or '_store' argument
# as its return value. Good for use with concurrent.futures.
def wrap_call(function, *args, **kwargs):
store = kwargs.pop('_store', kwargs.pop('store', None))
Wrap = namedtuple('Wrap', ['result', 'store', 'args', 'kwargs'])
return Wrap(function(*args, **kwargs), store, args, kwargs)

class IndexServer(object):
# Index metadata schema:
# { name.str: { path.str, lzma.bool, info.str }, ... }
def __init__(self, endpoint):
self.endpoint = endpoint
r = requests.get(urljoin(self.endpoint, 'meta.json'))
r.raise_for_status()
self.meta = r.json()

def available_indexes(self):
return self.meta['indexes'].keys()

def get_latest(self):
return self.meta['latest']

def get_anchor(self):
return self.meta.get('anchor', None)

def autodetect_anchor(self, anchor_hash):
anchor = self.get_anchor()
autodetect = dict()
if anchor:
autodetect = anchor['autodetect']
return autodetect.get(anchor_hash, None)

def info(self, name):
return self.meta['indexes'][name]['info']

def fetch(self, name, reporter, block_size=2048):
index_meta = self.meta['indexes'][name]
r = requests.get(urljoin(self.endpoint, index_meta['path']), stream=True)
r.raise_for_status()
data = bytearray()
total_size = int(r.headers.get('content-length', 0))
for chunk, report in reporter.task_it('Fetching index %s' % name, r.iter_content(block_size), length=math.ceil(total_size / block_size)):
report()
data += chunk
if index_meta['lzma']:
data = lzma.decompress(data)
return json.loads(data)

class PoisonPill(object):
pass

class Task(object):
def __init__(self, title, unit, length):
self.title = title
self.unit = unit
self.length = length

class ProgressReporter(object):
def __init__(self, logger='reporter'):
self._start = None
self._stopped = False
self._task = None
self._report_event = threading.Event()
self._step_queue = queue.Queue()
self._task_queue = queue.Queue()
self.logger = logging.getLogger(logger)

def stop(self):
self._stopped = True
self._step_queue.put(PoisonPill())
self._task_queue.put(PoisonPill())

def is_stopped(self):
return self._stopped

def task(self, title, unit=None, length=None):
if self._stopped:
raise ValueError('operation on stopped reporter')
self._task = Task(title, unit, length)
self._task_queue.put(self._task)
if not self._start:
self._start = time.time()
else:
self._step_queue.put(PoisonPill())

def task_it(self, title, iterator, unit=None, length=None):
if not length:
length = len(iterator) if iterator else None
self.task(title, unit=unit, length=length)
for item in iterator:
if self._stopped:
raise ValueError('operation on stopped reporter')
yield item, self.report
if not self._report_event.isSet():
raise RuntimeError('report not called in previous iteration')
self._report_event.clear()

def report(self, payload=None):
if not self._report_event.isSet():
self._step_queue.put(payload)
self._report_event.set()

def get_current_task(self):
return self._task

def tasks(self):
while True:
payload = self._task_queue.get()
if isinstance(payload, PoisonPill):
break
self.logger.info('*** Task Start: %s ***' % payload.title)
yield payload
self.logger.info('*** Task End: %s ***' % payload.title)

def steps(self):
while True:
payload = self._step_queue.get()
if isinstance(payload, PoisonPill):
break
#self.logger.info('Step > %s' % payload)
yield payload

def step(self, payload=None):
if self._stopped:
raise ValueError('operation on stopped reporter')
self._step_queue.put(payload)

def elapsed(self):
elapsed = 0
if self._start:
elapsed = time.time() - self._start
return str(datetime.timedelta(seconds=elapsed))
Binary file added icon.ico
Binary file not shown.
Binary file added icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
1 change: 1 addition & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
requests
backoff
tqdm
pyqt5
19 changes: 0 additions & 19 deletions setup.py

This file was deleted.

Loading

0 comments on commit a7bbc89

Please sign in to comment.