Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dev' into master
Browse files Browse the repository at this point in the history
  • Loading branch information
fireundubh committed May 31, 2021
2 parents d2633e9 + 1b59f7e commit c97c7a1
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 28 deletions.
14 changes: 12 additions & 2 deletions pyro/Application.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import sys

from pyro.Enums.BuildEvent import BuildEvent
from pyro.Enums.ImportEvent import ImportEvent
from pyro.BuildFacade import BuildFacade
from pyro.Comparators import startswith
from pyro.PapyrusProject import PapyrusProject
Expand Down Expand Up @@ -102,6 +103,15 @@ def run(self) -> int:

options = ProjectOptions(self.args.__dict__)
ppj = PapyrusProject(options)
ppj.try_initialize_remotes()

ppj.try_import_event(ImportEvent.PRE)
ppj.try_populate_imports()
ppj.try_import_event(ImportEvent.POST)

ppj.try_set_game_type()
ppj.find_missing_scripts()
ppj.try_set_game_path()

self._validate_project(ppj)

Expand All @@ -120,7 +130,7 @@ def run(self) -> int:
Application.log.error('Cannot proceed with Package enabled without valid BSArch path')
self._print_help_and_exit()

build.try_build_event(BuildEvent.PRE)
ppj.try_build_event(BuildEvent.PRE)

build.try_compile()

Expand Down Expand Up @@ -153,6 +163,6 @@ def run(self) -> int:
Application.log.info('DONE!')

if build.failed_count == 0:
build.try_build_event(BuildEvent.POST)
ppj.try_build_event(BuildEvent.POST)

return 0
25 changes: 0 additions & 25 deletions pyro/BuildFacade.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,13 @@
import logging
import multiprocessing
import os
import re
import sys
import time
from copy import deepcopy

import psutil

from pyro.Anonymizer import Anonymizer
from pyro.Enums.BuildEvent import BuildEvent
from pyro.Comparators import is_command_node
from pyro.Constants import XmlAttributeName
from pyro.PackageManager import PackageManager
from pyro.PapyrusProject import PapyrusProject
from pyro.PathHelper import PathHelper
Expand Down Expand Up @@ -101,27 +97,6 @@ def _limit_priority() -> None:
process = psutil.Process(os.getpid())
process.nice(psutil.BELOW_NORMAL_PRIORITY_CLASS if sys.platform == 'win32' else 19)

def try_build_event(self, event: BuildEvent) -> None:
if event == BuildEvent.PRE:
has_event_node, event_node = self.ppj.has_pre_build_node, self.ppj.pre_build_node
elif event == BuildEvent.POST:
has_event_node, event_node = self.ppj.has_post_build_node, self.ppj.post_build_node
else:
raise NotImplementedError

if has_event_node:
BuildFacade.log.info(event_node.get(XmlAttributeName.DESCRIPTION))

ws: re.Pattern = re.compile('[ \t\n\r]+')

environ: dict = os.environ.copy()
command: str = ' && '.join(
ws.sub(' ', node.text.strip())
for node in filter(is_command_node, event_node)
)

ProcessManager.run_command(command, self.ppj.project_path, environ)

def try_compile(self) -> None:
"""Builds and passes commands to Papyrus Compiler"""
commands: list = self.ppj.build_commands()
Expand Down
2 changes: 2 additions & 0 deletions pyro/Constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,9 @@ class XmlTagName:
PACKAGES: str = 'Packages'
PAPYRUS_PROJECT: str = 'PapyrusProject'
POST_BUILD_EVENT: str = 'PostBuildEvent'
POST_IMPORT_EVENT: str = 'PostImportEvent'
PRE_BUILD_EVENT: str = 'PreBuildEvent'
PRE_IMPORT_EVENT: str = 'PreImportEvent'
SCRIPTS: str = 'Scripts'
VARIABLES: str = 'Variables'
ZIP_FILE: str = 'ZipFile'
Expand Down
6 changes: 6 additions & 0 deletions pyro/Enums/ImportEvent.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
from enum import Enum


class ImportEvent(Enum):
PRE = 0
POST = 1
36 changes: 36 additions & 0 deletions pyro/PapyrusProject.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@

from lxml import etree

from pyro.Enums.BuildEvent import BuildEvent
from pyro.Enums.ImportEvent import ImportEvent
from pyro.CommandArguments import CommandArguments
from pyro.Comparators import (endswith,
is_folder_node,
Expand All @@ -22,6 +24,7 @@
XmlTagName)
from pyro.PathHelper import PathHelper
from pyro.PexReader import PexReader
from pyro.ProcessManager import ProcessManager
from pyro.ProjectBase import ProjectBase
from pyro.ProjectOptions import ProjectOptions
from pyro.Remotes import (GenericRemote,
Expand Down Expand Up @@ -131,6 +134,12 @@ def __init__(self, options: ProjectOptions) -> None:
self.post_build_node = self.ppj_root.find(XmlTagName.POST_BUILD_EVENT)
self.has_post_build_node = self.post_build_node is not None

self.pre_import_node = self.ppj_root.find(XmlTagName.PRE_IMPORT_EVENT)
self.has_pre_import_node = self.pre_import_node is not None

self.post_import_node = self.ppj_root.find(XmlTagName.POST_IMPORT_EVENT)
self.has_post_import_node = self.post_import_node is not None

if self.options.package and self.has_packages_node:
if not self.options.package_path:
self.options.package_path = self.packages_node.get(XmlAttributeName.OUTPUT)
Expand All @@ -139,6 +148,7 @@ def __init__(self, options: ProjectOptions) -> None:
if not self.options.zip_output_path:
self.options.zip_output_path = self.zip_files_node.get(XmlAttributeName.OUTPUT)

def try_initialize_remotes(self):
# initialize remote if needed
if self.remote_paths:
if not self.options.remote_temp_path:
Expand Down Expand Up @@ -173,6 +183,7 @@ def __init__(self, options: ProjectOptions) -> None:
PapyrusProject.log.error(f'Cannot proceed while node contains invalid URL: "{path}"')
sys.exit(1)

def try_populate_imports(self):
# we need to populate the list of import paths before we try to determine the game type
# because the game type can be determined from import paths
self.import_paths = self._get_import_paths()
Expand Down Expand Up @@ -210,6 +221,7 @@ def __init__(self, options: ProjectOptions) -> None:

PathHelper.merge_implicit_import_paths(implicit_script_paths, self.import_paths)

def try_set_game_type(self):
# we need to set the game type after imports are populated but before pex paths are populated
# allow xml to set game type but defer to passed argument
if self.options.game_type not in GameType.values():
Expand All @@ -226,12 +238,14 @@ def __init__(self, options: ProjectOptions) -> None:
PapyrusProject.log.error('Cannot determine game type from arguments or Papyrus Project')
sys.exit(1)

def find_missing_scripts(self):
# get expected pex paths - these paths may not exist and that is okay!
self.pex_paths = self._get_pex_paths()

# these are relative paths to psc scripts whose pex counterparts are missing
self.missing_scripts: dict = self._find_missing_script_paths()

def try_set_game_path(self):
# game type must be set before we call this
if not self.options.game_path:
self.options.game_path = self.get_game_path(self.options.game_type)
Expand Down Expand Up @@ -693,3 +707,25 @@ def build_commands(self) -> list:
self.import_paths = source_import_paths

return commands

def try_build_event(self, event: BuildEvent) -> None:
if event == BuildEvent.PRE:
has_event_node, event_node = self.has_pre_build_node, self.pre_build_node
elif event == BuildEvent.POST:
has_event_node, event_node = self.has_post_build_node, self.post_build_node
else:
raise NotImplementedError

if has_event_node:
ProcessManager.run_event(event_node, self.project_path)

def try_import_event(self, event: ImportEvent) -> None:
if event == ImportEvent.PRE:
has_event_node, event_node = self.has_pre_import_node, self.pre_import_node
elif event == ImportEvent.POST:
has_event_node, event_node = self.has_post_import_node, self.post_import_node
else:
raise NotImplementedError

if has_event_node:
ProcessManager.run_event(event_node, self.project_path)
2 changes: 2 additions & 0 deletions pyro/PapyrusProject.xsd
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
<xs:element minOccurs="0" name="ZipFiles" type="pyro:zipList"/>
<xs:element minOccurs="0" name="PreBuildEvent" type="pyro:commandList"/>
<xs:element minOccurs="0" name="PostBuildEvent" type="pyro:commandList"/>
<xs:element minOccurs="0" name="PreImportEvent" type="pyro:commandList"/>
<xs:element minOccurs="0" name="PostImportEvent" type="pyro:commandList"/>
</xs:choice>
</xs:sequence>
<xs:attribute name="Game" type="pyro:gameType"/>
Expand Down
20 changes: 19 additions & 1 deletion pyro/ProcessManager.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,13 @@
import subprocess
from decimal import Decimal

from lxml import etree

from pyro.Enums.ProcessState import ProcessState

from pyro.Comparators import startswith
from pyro.Comparators import (is_command_node,
startswith)
from pyro.Constants import XmlAttributeName


class ProcessManager:
Expand All @@ -22,6 +26,20 @@ def _format_time(hours: Decimal, minutes: Decimal, seconds: Decimal) -> str:
return f'{seconds}s'
return f'{hours}h {minutes}m {seconds}s'

@staticmethod
def run_event(event_node: etree.ElementBase, project_path: str):
ProcessManager.log.info(event_node.get(XmlAttributeName.DESCRIPTION))

ws: re.Pattern = re.compile('[ \t\n\r]+')

environ: dict = os.environ.copy()
command: str = ' && '.join(
ws.sub(' ', node.text.strip())
for node in filter(is_command_node, event_node)
)

ProcessManager.run_command(command, project_path, environ)

@staticmethod
def run_command(command: str, cwd: str, env: dict) -> ProcessState:
try:
Expand Down
1 change: 1 addition & 0 deletions pyro/ProjectOptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

from pyro.Comparators import endswith


@dataclass
class ProjectOptions:
args: dict = field(repr=False, default_factory=dict)
Expand Down

0 comments on commit c97c7a1

Please sign in to comment.