diff --git a/.gitignore b/.gitignore index 40e59bb..da2ee48 100644 --- a/.gitignore +++ b/.gitignore @@ -5,12 +5,15 @@ /__pycache__ /parsing/__pycache__ /choice/__pycache__ -/main/__pycache__ -/second/__pycache__ /choice/form.py +/main/__pycache__ /main/form.py +/second/__pycache__ /second/form.py +## Ignoring UPX +/upx + ## Ignoring build from cx_Freeze /prog_build diff --git a/README.md b/README.md index 73c6639..6657dcd 100644 --- a/README.md +++ b/README.md @@ -17,11 +17,11 @@ Features: *** -Requirments: -* Python 3.7.7 -* PyQt5 5.15.0 -* requests 2.24.0 -* cx_Freeze 6.2 +Requirments to build project: +* Python >=3.5.4 +* PyQt5 >=5.6.0 +* requests >=2.24.0 +* cx_Freeze >=6.0 (or PyInstaller >=3.6) *** diff --git a/build.spec b/build.spec index e37f866..a34cf60 100644 --- a/build.spec +++ b/build.spec @@ -1,38 +1,33 @@ # -*- mode: python ; coding: utf-8 -*- -block_cipher = None +app = Analysis( + ['init_main_program.py'], + pathex=['.'], + datas=[ + ('configs/ats', 'configs/ats'), + ('configs/ets2', 'configs/ets2') + ] +) + +app_pyz = PYZ(app.pure, app.zipped_data) + +app_exe = EXE( + app_pyz, + app.scripts, + [], + exclude_binaries=True, + name='SaveWizard', + debug=False, + bootloader_ignore_signals=False, + strip=False, + console=False +) +app_coll = COLLECT( + app_exe, + app.binaries, + app.zipfiles, + app.datas, + strip=False, + name='app_build' +) -a = Analysis(['__init__.py'], - pathex=['.'], - binaries=[], - datas=[ - ('ats_configs', 'ats_configs'), - ('ets2_configs', 'ets2_configs') - ], - hiddenimports=[], - hookspath=[], - runtime_hooks=[], - excludes=[], - 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, - [], - exclude_binaries=True, - name='SaveWizard', - debug=False, - bootloader_ignore_signals=False, - strip=False, - upx=True, - console=False ) -coll = COLLECT(exe, - a.binaries, - a.zipfiles, - a.datas, - strip=False, - upx=True, - upx_exclude=[], - name='build') diff --git a/choice/script.py b/choice/script.py index 2e2b797..4251a1a 100644 --- a/choice/script.py +++ b/choice/script.py @@ -7,7 +7,7 @@ from ast import literal_eval from .form import Ui_Choice from main.script import MainWindow from parsing.script import check_remote_hashes, update_configs -from util import update_config_name +from statics import update_config_name class ChoiceWindow(QDialog, Ui_Choice): diff --git a/compile_pyinstaller.bat b/compile_pyinstaller.bat index c3d2dfc..25d6f9e 100644 --- a/compile_pyinstaller.bat +++ b/compile_pyinstaller.bat @@ -1 +1 @@ -pyinstaller build.spec +pyinstaller build.spec --noupx diff --git a/dataIO.py b/dataIO.py index d212344..e2d6192 100644 --- a/dataIO.py +++ b/dataIO.py @@ -2,9 +2,6 @@ # -*- coding: utf-8 -*- from json import decoder, load, dump -from os import replace -from os.path import splitext -from random import randint class DataIO: @@ -30,18 +27,12 @@ class DataIO: def save_json(self, filename, data): """Atomically saves json file""" - rnd = randint(1000, 9999) - path, ext = splitext(filename) - tmp_file = "{}-{}.tmp".format(path, rnd) - # self._save_json(filename, data) with open(filename, encoding="utf-8", mode="w") as f: - dump(data, f, indent=4, sort_keys=True, separators=(",", " : ")) - # return data (?) + dump(data, f, indent=4, separators=(",", " : ")) try: - self._read_json(tmp_file) + self._read_json(filename) except decoder.JSONDecodeError: return False - replace(tmp_file, filename) return True diff --git a/__init__.py b/init_main_program.py similarity index 100% rename from __init__.py rename to init_main_program.py diff --git a/parsing/script.py b/parsing/script.py index 0fa6357..2b0d725 100644 --- a/parsing/script.py +++ b/parsing/script.py @@ -2,61 +2,49 @@ # -*- coding: utf-8 -*- from requests import get -from hashlib import md5 from ast import literal_eval import os +from statics import github_link, update_config_name from dataIO import dataIO -from util import github_link, update_config_name +from util import generate_md5 -def send_response(txt): - response = get(txt) - return response if response.status_code == 200 else False +def get_response_result(url): + response = get(url) + return response.status_code == 200, response -def generate_md5(fn): - hash_md5 = md5() - try: - with open(fn, "rb") as f: - for chunk in iter(lambda: f.read(4096), b""): - hash_md5.update(chunk) - return hash_md5.hexdigest() - except FileNotFoundError: - return False - - -def check_files(path): - temp = os.getcwd() +def check_path(path): + current_path = os.getcwd() for item in path.split("/"): - temp = os.path.join(temp, item) - if not os.path.exists(temp): + current_path = os.path.join(current_path, item) + if not os.path.exists(current_path): if item.find(".json") > 0: - f = open(temp, "w") - f.close() + open(current_path, "w").close() else: - os.mkdir(temp) + os.mkdir(current_path) def check_remote_hashes(): - response = send_response(github_link + "configs/version.cfg") - if response is not False: + response_status, response = get_response_result(github_link + "configs/version.cfg") + if response_status: remote_cfg = literal_eval(response.text) - need_to_be_updated = [] + need_update = [] for key, value in remote_cfg.items(): path = key.split("_") path = "configs/{}/{}.json".format(path[0], path[1]) if generate_md5(path) != value: - need_to_be_updated.append(path) - return need_to_be_updated + need_update.append(path) + return need_update return False def update_configs(is_save, cfg_list): if is_save in (0, 1): for cfg in cfg_list: - check_files(cfg) - response = send_response(github_link + cfg) - if response is not False: + check_path(cfg) + response_status, response = get_response_result(github_link + cfg) + if response_status: remote_cfg = literal_eval(response.text) if dataIO.is_valid_json(cfg) or os.path.exists(cfg): dataIO.save_json(cfg, remote_cfg) diff --git a/second/form.ui b/second/form.ui index 5484325..f4e6f53 100644 --- a/second/form.ui +++ b/second/form.ui @@ -39,25 +39,6 @@ - - - - - Times New Roman - 11 - - - - false - - - Qt::ScrollBarAlwaysOff - - - false - - - @@ -90,6 +71,25 @@ + + + + + Times New Roman + 11 + + + + false + + + Qt::ScrollBarAlwaysOff + + + true + + + @@ -119,7 +119,7 @@ - + Times New Roman @@ -132,8 +132,8 @@ Qt::ScrollBarAlwaysOff - - false + + true @@ -166,7 +166,7 @@ - + Times New Roman @@ -179,8 +179,8 @@ Qt::ScrollBarAlwaysOff - - false + + true @@ -213,7 +213,7 @@ - + Times New Roman @@ -226,8 +226,8 @@ Qt::ScrollBarAlwaysOff - - false + + true diff --git a/second/script.py b/second/script.py index e7f38d2..a053583 100644 --- a/second/script.py +++ b/second/script.py @@ -115,8 +115,10 @@ class SecondWindow(QDialog, Ui_SecondWindow): def check_garages(self): self.ui.garages_text.clear() - for garage in self.purchased_garages(): + garages = self.purchased_garages() + for garage in garages: self.ui.garages_text.append(garage) + self.ui.garages_text.scrollToAnchor(garages[0]) def add_garage(self): garage = self.ui.garage_edit.text().lower() @@ -175,6 +177,7 @@ class SecondWindow(QDialog, Ui_SecondWindow): return for city in visited_cities: self.ui.cities_text.append(city) + self.ui.cities_text.scrollToAnchor(visited_cities[0]) def add_city(self): city = self.ui.city_edit.text().lower() @@ -207,6 +210,7 @@ class SecondWindow(QDialog, Ui_SecondWindow): return for dealer in visited_dealers: self.ui.dealerships_text.append(dealer) + self.ui.dealerships_text.scrollToAnchor(visited_dealers[0]) def add_all_dealers(self): all_cities = self.all_cities() @@ -225,6 +229,7 @@ class SecondWindow(QDialog, Ui_SecondWindow): return for agency in visited_agencies: self.ui.agencies_text.append(agency) + self.ui.agencies_text.scrollToAnchor(visited_agencies[0]) def add_all_agencies(self): all_cities = self.all_cities() diff --git a/setup.py b/setup.py index 02020ea..de23fb1 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,9 @@ base = None if platform == 'win32': base = 'Win32GUI' -executables = [Executable('__init__.py', targetName='SaveWizard.exe', base=base)] +executables = [ + Executable('init_main_program.py', targetName='SaveWizard.exe', base=base) +] excludes = ['html', 'pydoc_data', 'unittest', 'xml', 'pwd', 'shlex', 'platform', 'webbrowser', 'pydoc', 'tty', 'inspect', 'doctest', 'plistlib', 'subprocess', 'bz2', '_strptime', 'dummy_threading'] @@ -27,7 +29,14 @@ zip_include_packages = [ 'parsing', 'choice', 'main', 'second' ] -include_files = ['dlls/imageformats', 'dlls/platforms', 'dlls/styles', 'SII_Decrypt.exe', 'configs'] +include_files = [ + 'dlls/imageformats', + 'dlls/platforms', + 'dlls/styles', + 'SII_Decrypt.exe', + ('configs/ats', 'configs/ats'), + ('configs/ets2', 'configs/ets2') +] options = { 'build_exe': { @@ -42,7 +51,7 @@ options = { setup( name='SaveWizard', - version='1.2', + version='1.2.1', description='For editing ETS2 sii files', executables=executables, options=options, diff --git a/statics.py b/statics.py new file mode 100644 index 0000000..dcc579e --- /dev/null +++ b/statics.py @@ -0,0 +1,6 @@ +#!/usr/bin/python3 +# -*- coding: utf-8 -*- + +update_config_name = "update.cfg" +github_link = "https://raw.githubusercontent.com/JDM170/SaveWizard/master/" +hash_chunk_size = 4096 diff --git a/util.py b/util.py index 5d7c591..3b59091 100644 --- a/util.py +++ b/util.py @@ -4,9 +4,9 @@ # from re import search, match, sub from re import search, match from PyQt5.QtWidgets import QMessageBox +from hashlib import md5 +from statics import hash_chunk_size -github_link = "https://raw.githubusercontent.com/JDM170/SaveWizard/master/" -update_config_name = "update.cfg" lines = [] @@ -28,6 +28,17 @@ def show_message(icon, title, text): box.exec() +def generate_md5(fn): + try: + hash_md5 = md5() + with open(fn, "rb") as f: + for chunk in iter(lambda: f.read(hash_chunk_size), b""): + hash_md5.update(chunk) + return hash_md5.hexdigest() + except FileNotFoundError: + return False + + # Stock functions def search_line(term, start=0, cancel=r"this_string_must_not_exist"): global lines