Troubleshooting pyinstaller.

This commit is contained in:
lwark
2024-07-29 08:21:47 -05:00
parent e85a4bba6f
commit f5e34991d7
8 changed files with 103 additions and 34 deletions

View File

@@ -112,14 +112,14 @@ This is meant to import .xslx files created from the Design & Analysis Software
## SETUP:
## Download:
## Download and Setup:
*Python v3.11 or greater must be installed on your system for this.*
1. Clone or download from github.
2. Enter the downloaded folder.
3. Open a terminal in the folder with the 'src' folder.
4. Create a new virtual environment: ```python -m venv venv```
5. Activate the virtual environment: (Windows) ```venv\Scripts\activate.bat```
4. Create a new virtual environment: ```python -m venv .venv```
5. Activate the virtual environment: (Windows) ```.venv\Scripts\activate.bat```
6. Install dependencies: ```pip install -r requirements.txt```
## Database:
@@ -133,6 +133,14 @@ This is meant to import .xslx files created from the Design & Analysis Software
## First Run:
1. On first run, the application copies src/config.yml to C:\Users\{USERNAME}\Local\submissions\config
2. Initially, the 'directory_path' variable is set to the 'sqlalchemy.url' variable in alembic.ini
3. If this folder cannot be found, C:\Users\{USERNAME}\Documents\submissions will be used.
2. If this folder cannot be found, C:\Users\{USERNAME}\Documents\submissions will be used.
1. If using Postgres, the 'database_path' and other variables will have to be updated manually.
3. Initially, the config variables are set parsing the 'sqlalchemy.url' variable in alembic.ini
## Building Portable Application:
*Download and Setup must have been performed beforehand*
1. Using pyinstaller, an exe can be created.
2. Open a terminal in the folder with the 'src' folder.
3. Activate the virtual environment: (Windows) ```.venv\Scripts\activate.bat```
4. Enter the following command: ```pyinstaller .\submissions.spec --noconfirm```

47
docs/source/conf.py Normal file
View File

@@ -0,0 +1,47 @@
# Configuration file for the Sphinx documentation builder.
#
# For the full list of built-in configuration values, see the documentation:
# https://www.sphinx-doc.org/en/master/usage/configuration.html
# -- Project information -----------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
import sys
from pathlib import Path
sys.path.append(Path(__file__).parents[2].joinpath('src').absolute().__str__())
from submissions import __version__, __copyright__, __author__
project = 'RSL Submissions'
copyright = __copyright__
author = f"{__author__['name']} - {__author__['email']}"
release = __version__
# -- General configuration ---------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
master_doc = "index"
extensions = [
'sphinx.ext.doctest',
'sphinx.ext.autodoc',
'sphinx.ext.autosummary',
'sphinx.ext.napoleon',
'sphinx_markdown_builder',
'sphinx_mdinclude',
]
templates_path = ['_templates']
exclude_patterns = []
sys.path.insert(0, Path(__file__).absolute().resolve().parents[2].joinpath("src").__str__())
sys.path.insert(0, Path(__file__).absolute().resolve().parents[2].joinpath("src/submissions").__str__())
# -- Options for HTML output -------------------------------------------------
# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
html_theme = 'alabaster'
# html_style = 'custom.css'
html_static_path = ['_static']
# autodoc_mock_imports = ["backend.db.models.submissions"]

Binary file not shown.

View File

@@ -1,5 +1,6 @@
import sys, os
from tools import ctx, setup_logger, check_if_app
# environment variable must be set to enable qtwebengine in network path
if check_if_app():
os.environ['QTWEBENGINE_DISABLE_SANDBOX'] = "1"

View File

@@ -188,7 +188,10 @@ class App(QMainWindow):
current_month_bak = current_month_bak.with_suffix(".db")
if not current_month_bak.exists() and "demo" not in self.ctx.database_path.__str__():
logger.info("No backup found for this month, backing up database.")
shutil.copyfile(self.ctx.database_path, current_month_bak)
try:
shutil.copyfile(self.ctx.backup_path, current_month_bak)
except PermissionError as e:
logger.error(f"Couldn't backup database due to: {e}")
case "postgresql+psycopg2":
logger.warning(f"Backup function not yet implemented for psql")
current_month_bak = current_month_bak.with_suffix(".psql")

View File

@@ -85,7 +85,10 @@ class ControlsViewer(QWidget):
self.mode = self.mode_typer.currentText()
self.sub_typer.clear()
# NOTE: lookup subtypes
sub_types = ControlType.query(name=self.con_type).get_subtypes(mode=self.mode)
try:
sub_types = ControlType.query(name=self.con_type).get_subtypes(mode=self.mode)
except AttributeError:
sub_types = []
if sub_types != []:
# NOTE: block signal that will rerun controls getter and update sub_typer
with QSignalBlocker(self.sub_typer) as blocker:

View File

@@ -5,9 +5,7 @@ from __future__ import annotations
import json
import pprint
import weakref
from json import JSONDecodeError
import jinja2
import numpy as np
import logging, re, yaml, sys, os, stat, platform, getpass, inspect, csv
import pandas as pd
@@ -15,7 +13,7 @@ from jinja2 import Environment, FileSystemLoader
from logging import handlers
from pathlib import Path
from sqlalchemy.orm import Session
from sqlalchemy import create_engine, text
from sqlalchemy import create_engine, text, MetaData
from pydantic import field_validator, BaseModel, Field
from pydantic_settings import BaseSettings, SettingsConfigDict
from typing import Any, Tuple, Literal, List
@@ -302,11 +300,11 @@ class Settings(BaseSettings, extra="allow"):
check = value.exists()
except AttributeError:
check = False
if not check: #and values.data['database_schema'] == "sqlite":
if not check: # and values.data['database_schema'] == "sqlite":
# print(f"No directory found, using Documents/submissions")
# value = Path.home().joinpath("Documents", "submissions")
value.mkdir(exist_ok=True)
print(f"Final return of directory_path: {value}")
# print(f"Final return of directory_path: {value}")
return value
@field_validator('database_path', mode="before")
@@ -314,8 +312,8 @@ class Settings(BaseSettings, extra="allow"):
def ensure_database_exists(cls, value, values):
# if value == ":memory:":
# return value
# and values.data['database_schema'] == "sqlite":
# value = values.data['directory_path']
# and values.data['database_schema'] == "sqlite":
# value = values.data['directory_path']
match values.data['database_schema']:
case "sqlite":
if value is None:
@@ -366,7 +364,7 @@ class Settings(BaseSettings, extra="allow"):
alembic_path = project_path.joinpath("alembic.ini")
# print(f"Getting alembic path: {alembic_path}")
value = cls.get_alembic_db_path(alembic_path=alembic_path, mode='user')
print(f"Got {value} for user")
# print(f"Got {value} for user")
return value
@field_validator("database_password", mode='before')
@@ -379,10 +377,9 @@ class Settings(BaseSettings, extra="allow"):
alembic_path = project_path.joinpath("alembic.ini")
# print(f"Getting alembic path: {alembic_path}")
value = cls.get_alembic_db_path(alembic_path=alembic_path, mode='pass')
print(f"Got {value} for pass")
# print(f"Got {value} for pass")
return value
@field_validator('database_session', mode="before")
@classmethod
def create_database_session(cls, value, values):
@@ -395,8 +392,9 @@ class Settings(BaseSettings, extra="allow"):
value = f"/{values.data['database_path']}"
db_name = f"{values.data['database_name']}.db"
case _:
print(pprint.pprint(values.data))
tmp = jinja_template_loading().from_string("{% if values['database_user'] %}{{ values['database_user'] }}{% if values['database_password'] %}:{{ values['database_password'] }}{% endif %}{% endif %}@{{ values['database_path'] }}")
# print(pprint.pprint(values.data))
tmp = jinja_template_loading().from_string(
"{% if values['database_user'] %}{{ values['database_user'] }}{% if values['database_password'] %}:{{ values['database_password'] }}{% endif %}{% endif %}@{{ values['database_path'] }}")
value = tmp.render(values=values.data)
db_name = values.data['database_name']
template = jinja_template_loading().from_string(
@@ -422,7 +420,7 @@ class Settings(BaseSettings, extra="allow"):
# database_path = database_path
# else:
# raise FileNotFoundError("No database file found. Exiting program.")
print(f"Using {database_path} for database file.")
# print(f"Using {database_path} for database file.")
# engine = create_engine(f"sqlite:///{database_path}") #, echo=True, future=True)
# engine = create_engine("postgresql+psycopg2://postgres:RE,4321q@localhost:5432/submissions")
engine = create_engine(database_path)
@@ -439,15 +437,22 @@ class Settings(BaseSettings, extra="allow"):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.set_from_db(db_path=kwargs['database_path'])
self.set_from_db()
def set_from_db(self, db_path: Path):
def set_from_db(self):
if 'pytest' in sys.modules:
output = dict(power_users=['lwark', 'styson', 'ruwang'])
else:
# session = Session(create_engine(f"sqlite:///{db_path}"))
logger.debug(self.__dict__)
session = self.database_session
metadata = MetaData()
try:
tables = metadata.reflect(bind=session.get_bind()).tables.keys()
except AttributeError:
return
if "_configitem" not in tables:
return
config_items = session.execute(text("SELECT * FROM _configitem")).all()
session.close()
# print(config_items)
@@ -480,14 +485,14 @@ class Settings(BaseSettings, extra="allow"):
try:
return url[:url.index("@")].split(":")[0]
except (IndexError, ValueError) as e:
print(f"Error on user: {e}")
# print(f"Error on user: {e}")
return None
case "pass":
url = re.sub(r"^.*//", "", url)
try:
return url[:url.index("@")].split(":")[1]
except (IndexError, ValueError) as e:
print(f"Error on user: {e}")
# print(f"Error on user: {e}")
return None
def save(self, settings_path: Path):
@@ -498,18 +503,18 @@ class Settings(BaseSettings, extra="allow"):
continue
match v:
case Path():
print("Path")
# print("Path")
if v.is_dir():
print("dir")
# print("dir")
v = v.absolute().__str__()
elif v.is_file():
print("file")
# print("file")
v = v.parent.absolute().__str__()
else:
v = v.__str__()
case _:
pass
print(f"Key: {k}, Value: {v}")
# print(f"Key: {k}, Value: {v}")
dicto[k] = v
with open(settings_path, 'w') as f:
yaml.dump(dicto, f)
@@ -570,7 +575,7 @@ def get_config(settings_path: Path | str | None = None) -> Settings:
# settings = Settings(**copy_settings(settings_path=CONFIGDIR.joinpath("config.yml"), settings=default_settings))
settings = Settings(**default_settings)
settings.save(settings_path=CONFIGDIR.joinpath("config.yml"))
print(f"Default settings: {pprint.pprint(settings.__dict__)}")
# print(f"Default settings: {pprint.pprint(settings.__dict__)}")
return settings
else:
# NOTE: check if user defined path is directory
@@ -758,7 +763,7 @@ def jinja_template_loading() -> Environment:
if check_if_app():
loader_path = Path(sys._MEIPASS).joinpath("files", "templates")
else:
loader_path = Path(__file__).parent.joinpath('templates').absolute() #.__str__()
loader_path = Path(__file__).parents[1].joinpath('templates').absolute() # .__str__()
# NOTE: jinja template loading
loader = FileSystemLoader(loader_path)
env = Environment(loader=loader)

View File

@@ -7,14 +7,16 @@ import sys, subprocess
from pathlib import Path
sys.path.append(Path(".").parent.joinpath('src').absolute().__str__())
from submissions import __version__, __project__, bcolors, project_path
print(f"Using {project_path} as project path.")
doc_path = project_path.joinpath("docs").absolute()
build_path = project_path.joinpath(".venv", "Scripts", "sphinx-build").absolute().__str__()
print(bcolors.BOLD + "Running Sphinx subprocess to generate rst files..." + bcolors.ENDC)
api_path = project_path.joinpath(".venv", "Scripts", "sphinx-apidoc").absolute().__str__()
subprocess.run([api_path, "-o", doc_path.joinpath("source").__str__(), project_path.joinpath("src", "submissions").__str__(), "-f"])
print(bcolors.BOLD + "Running Sphinx subprocess to generate html docs..." + bcolors.ENDC)
subprocess.run([build_path, doc_path.joinpath("source").__str__(), doc_path.joinpath("build").__str__(), "-a"])
docs_build = doc_path.joinpath("build")
#docs_build.mkdir(exist_ok=True, parents=True)
subprocess.run([build_path, doc_path.joinpath("source").__str__(), docs_build.__str__(), "-a"])
#########################################################
a = Analysis(