[LYN-5268] Copy resource mapping tool to install target and add argument for log path (#2819)

Updates to make resource mapping tool work with the installer. Ensure correct log path.
monroegm-disable-blank-issue-2
Vincent Liu 4 years ago committed by GitHub
parent ca3bc3d343
commit 8e3b25e606
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -166,3 +166,9 @@ if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
)
endif()
endif()
install(DIRECTORY "Tools/ResourceMappingTool"
DESTINATION "Gems/AWSCore/Code/Tools"
COMPONENT ${CMAKE_INSTALL_DEFAULT_COMPONENT_NAME}
PATTERN "__pycache__" EXCLUDE
)

@ -34,11 +34,6 @@ namespace AWSCore
//! @return The path of AWS resource mapping config file
virtual AZStd::string GetResourceMappingConfigFilePath() const = 0;
//! GetResourceMappingConfigFolderPath
//! Get the path of AWS resource mapping config folder
//! @return The path of AWS resource mapping config folder
virtual AZStd::string GetResourceMappingConfigFolderPath() const = 0;
//! ReloadConfiguration
//! Reload AWSCore configuration without restarting application
virtual void ReloadConfiguration() = 0;

@ -50,7 +50,6 @@ namespace AWSCore
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetResourceMappingConfigFilePath() const override;
AZStd::string GetResourceMappingConfigFolderPath() const override;
AZStd::string GetProfileName() const override;
void ReloadConfiguration() override;

@ -7,9 +7,11 @@
*/
#pragma once
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/string/string.h>
#include <QAction>
#include <QObject>
namespace AWSCore
{
@ -17,22 +19,26 @@ namespace AWSCore
: public QAction
{
public:
static constexpr const char AWSCoreResourceMappingToolActionName[] = "AWSCoreResourceMappingToolAction";
static constexpr const char ResourceMappingToolDirectoryPath[] = "Gems/AWSCore/Code/Tools/ResourceMappingTool";
static constexpr const char ResourceMappingToolLogDirectoryPath[] = "user/log/";
static constexpr const char EngineWindowsPythonEntryScriptPath[] = "python/python.cmd";
AWSCoreResourceMappingToolAction(const QString& text);
AWSCoreResourceMappingToolAction(const QString& text, QObject* parent = nullptr);
void InitAWSCoreResourceMappingToolAction();
AZStd::string GetToolLaunchCommand() const;
AZStd::string GetToolLogPath() const;
AZStd::string GetToolLogFilePath() const;
AZStd::string GetToolReadMePath() const;
private:
bool m_isDebug;
AZStd::string m_enginePythonEntryPath;
AZStd::string m_toolScriptPath;
AZStd::string m_toolQtBinDirectoryPath;
AZStd::string m_toolLogPath;
AZStd::string m_toolReadMePath;
AZ::IO::Path m_enginePythonEntryPath;
AZ::IO::Path m_toolScriptPath;
AZ::IO::Path m_toolQtBinDirectoryPath;
AZ::IO::Path m_toolLogDirectoryPath;
AZ::IO::Path m_toolConfigDirectoryPath;
AZ::IO::Path m_toolReadMePath;
};
} // namespace AWSCore

@ -56,19 +56,6 @@ namespace AWSCore
return configFilePath;
}
AZStd::string AWSCoreConfiguration::GetResourceMappingConfigFolderPath() const
{
if (m_sourceProjectFolder.empty())
{
AZ_Warning(AWSCoreConfigurationName, false, ProjectSourceFolderNotFoundErrorMessage);
return "";
}
AZStd::string configFolderPath = AZStd::string::format(
"%s/%s", m_sourceProjectFolder.c_str(), AWSCoreResourceMappingConfigFolderName);
AzFramework::StringFunc::Path::Normalize(configFolderPath);
return configFolderPath;
}
void AWSCoreConfiguration::InitConfig()
{
InitSourceProjectFolderPath();

@ -80,7 +80,7 @@ namespace AWSCore
{
#ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED
AWSCoreResourceMappingToolAction* resourceMappingTool =
new AWSCoreResourceMappingToolAction(QObject::tr(AWSResourceMappingToolActionText));
new AWSCoreResourceMappingToolAction(QObject::tr(AWSResourceMappingToolActionText), this);
QObject::connect(resourceMappingTool, &QAction::triggered, this,
[resourceMappingTool, this]() {
AZStd::string launchCommand = resourceMappingTool->GetToolLaunchCommand();
@ -109,7 +109,7 @@ namespace AWSCore
if (!m_resourceMappingToolWatcher || !m_resourceMappingToolWatcher->IsProcessRunning())
{
AZStd::string resourceMappingToolLogPath = resourceMappingTool->GetToolLogPath();
AZStd::string resourceMappingToolLogPath = resourceMappingTool->GetToolLogFilePath();
AZStd::string message = AZStd::string::format(AWSResourceMappingToolLogWarningText, resourceMappingToolLogPath.c_str());
QMessageBox::warning(QApplication::activeWindow(), "Warning", message.c_str(), QMessageBox::Ok);
}

@ -6,133 +6,89 @@
*
*/
#include <AzCore/IO/FileIO.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <AWSCoreInternalBus.h>
#include <Configuration/AWSCoreConfiguration.h>
#include <Editor/UI/AWSCoreResourceMappingToolAction.h>
namespace AWSCore
{
AWSCoreResourceMappingToolAction::AWSCoreResourceMappingToolAction(const QString& text)
: QAction(text)
AWSCoreResourceMappingToolAction::AWSCoreResourceMappingToolAction(const QString& text, QObject* parent)
: QAction(text, parent)
, m_isDebug(false)
, m_enginePythonEntryPath("")
, m_toolScriptPath("")
, m_toolQtBinDirectoryPath("")
, m_toolLogPath("")
, m_toolReadMePath("")
{
auto engineRootPath = AZ::IO::FileIOBase::GetInstance()->GetAlias("@engroot@");
if (!engineRootPath)
{
AZ_Error("AWSCoreEditor", false, "Failed to determine engine root path.");
}
else
{
m_enginePythonEntryPath = AZStd::string::format("%s/%s", engineRootPath, EngineWindowsPythonEntryScriptPath);
AzFramework::StringFunc::Path::Normalize(m_enginePythonEntryPath);
if (!AZ::IO::SystemFile::Exists(m_enginePythonEntryPath.c_str()))
{
AZ_Error("AWSCoreEditor", false, "Failed to find engine python entry at %s.", m_enginePythonEntryPath.c_str());
m_enginePythonEntryPath.clear();
InitAWSCoreResourceMappingToolAction();
}
m_toolScriptPath = AZStd::string::format("%s/%s/resource_mapping_tool.py", engineRootPath, ResourceMappingToolDirectoryPath);
AzFramework::StringFunc::Path::Normalize(m_toolScriptPath);
if (!AZ::IO::SystemFile::Exists(m_toolScriptPath.c_str()))
void AWSCoreResourceMappingToolAction::InitAWSCoreResourceMappingToolAction()
{
AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool python script at %s.", m_toolScriptPath.c_str());
m_toolScriptPath.clear();
}
AZ::IO::Path engineRootPath = AZ::IO::PathView(AZ::Utils::GetEnginePath());
m_enginePythonEntryPath = (engineRootPath / EngineWindowsPythonEntryScriptPath).LexicallyNormal();
m_toolScriptPath = (engineRootPath / ResourceMappingToolDirectoryPath / "resource_mapping_tool.py").LexicallyNormal();
m_toolReadMePath = (engineRootPath / ResourceMappingToolDirectoryPath / "README.md").LexicallyNormal();
m_toolLogPath = AZStd::string::format("%s/%s/resource_mapping_tool.log", engineRootPath, ResourceMappingToolDirectoryPath);
AzFramework::StringFunc::Path::Normalize(m_toolLogPath);
if (!AZ::IO::SystemFile::Exists(m_toolLogPath.c_str()))
{
AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool log file at %s.", m_toolLogPath.c_str());
m_toolLogPath.clear();
}
AZ::IO::Path projectPath = AZ::IO::PathView(AZ::Utils::GetProjectPath());
m_toolLogDirectoryPath = (projectPath / ResourceMappingToolLogDirectoryPath).LexicallyNormal();
m_toolConfigDirectoryPath = (projectPath / AWSCoreConfiguration::AWSCoreResourceMappingConfigFolderName).LexicallyNormal();
m_toolReadMePath = AZStd::string::format("%s/%s/README.md", engineRootPath, ResourceMappingToolDirectoryPath);
AzFramework::StringFunc::Path::Normalize(m_toolReadMePath);
if (!AZ::IO::SystemFile::Exists(m_toolReadMePath.c_str()))
{
AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool README file at %s.", m_toolReadMePath.c_str());
m_toolReadMePath.clear();
}
AZ::IO::Path executablePath = AZ::IO::PathView(AZ::Utils::GetExecutableDirectory());
m_toolQtBinDirectoryPath = (executablePath / "AWSCoreEditorQtBin").LexicallyNormal();
char executablePath[AZ_MAX_PATH_LEN];
auto result = AZ::Utils::GetExecutablePath(executablePath, AZ_MAX_PATH_LEN);
if (result.m_pathStored != AZ::Utils::ExecutablePathResult::Success)
{
AZ_Error("AWSCoreEditor", false, "Failed to find engine executable path.");
}
else
{
if (result.m_pathIncludesFilename)
{
// Remove the file name if it exists, and keep the parent folder only
char* lastSeparatorAddress = strrchr(executablePath, AZ_CORRECT_FILESYSTEM_SEPARATOR);
if (lastSeparatorAddress)
{
*lastSeparatorAddress = '\0';
}
}
}
AZStd::string binDirectoryPath(executablePath);
auto lastSeparator = binDirectoryPath.find_last_of(AZ_CORRECT_FILESYSTEM_SEPARATOR);
if (lastSeparator != AZStd::string::npos)
{
m_isDebug = binDirectoryPath.substr(lastSeparator).contains("debug");
}
m_toolQtBinDirectoryPath = AZStd::string::format("%s/%s", binDirectoryPath.c_str(), "AWSCoreEditorQtBin");
AzFramework::StringFunc::Path::Normalize(m_toolQtBinDirectoryPath);
if (!AZ::IO::SystemFile::Exists(m_toolQtBinDirectoryPath.c_str()))
{
AZ_Error("AWSCoreEditor", false, "Failed to find ResourceMappingTool Qt binaries at %s.", m_toolQtBinDirectoryPath.c_str());
m_toolQtBinDirectoryPath.clear();
}
}
m_isDebug = AZStd::string_view(AZ_BUILD_CONFIGURATION_TYPE) == "debug";
}
AZStd::string AWSCoreResourceMappingToolAction::GetToolLaunchCommand() const
{
if (m_enginePythonEntryPath.empty() || m_toolScriptPath.empty() || m_toolQtBinDirectoryPath.empty())
if (!AZ::IO::SystemFile::Exists(m_enginePythonEntryPath.c_str()) ||
!AZ::IO::SystemFile::Exists(m_toolScriptPath.c_str()) ||
!AZ::IO::SystemFile::Exists(m_toolQtBinDirectoryPath.c_str()) ||
!AZ::IO::SystemFile::Exists(m_toolConfigDirectoryPath.c_str()) ||
!AZ::IO::SystemFile::Exists(m_toolLogDirectoryPath.c_str()))
{
AZ_Error(AWSCoreResourceMappingToolActionName, false,
"Expected parameter for tool launch command is invalid, engine python path: %s, tool script path: %s, tool qt binaries path: %s, tool config path: %s, tool log path: %s",
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
return "";
}
AZStd::string profileName = "default";
AWSCoreInternalRequestBus::BroadcastResult(profileName, &AWSCoreInternalRequests::GetProfileName);
AZStd::string configPath = "";
AWSCoreInternalRequestBus::BroadcastResult(configPath, &AWSCoreInternalRequests::GetResourceMappingConfigFolderPath);
if (m_isDebug)
{
return AZStd::string::format(
"%s debug %s --binaries_path %s --debug --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
"\"%s\" debug -B \"%s\" --binaries-path \"%s\" --debug --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(),
profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
}
else
{
return AZStd::string::format(
"%s %s --binaries_path %s --profile %s --config_path %s", m_enginePythonEntryPath.c_str(),
m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(), profileName.c_str(), configPath.c_str());
"\"%s\" -B \"%s\" --binaries-path \"%s\" --profile \"%s\" --config-path \"%s\" --log-path \"%s\"",
m_enginePythonEntryPath.c_str(), m_toolScriptPath.c_str(), m_toolQtBinDirectoryPath.c_str(),
profileName.c_str(), m_toolConfigDirectoryPath.c_str(), m_toolLogDirectoryPath.c_str());
}
}
AZStd::string AWSCoreResourceMappingToolAction::GetToolLogPath() const
AZStd::string AWSCoreResourceMappingToolAction::GetToolLogFilePath() const
{
AZ::IO::Path toolLogFilePath = (m_toolLogDirectoryPath / "resource_mapping_tool.log").LexicallyNormal();
if (!AZ::IO::SystemFile::Exists(toolLogFilePath.c_str()))
{
return m_toolLogPath;
AZ_Error(AWSCoreResourceMappingToolActionName, false, "Invalid tool log file path: %s", toolLogFilePath.c_str());
return "";
}
return toolLogFilePath.Native();
}
AZStd::string AWSCoreResourceMappingToolAction::GetToolReadMePath() const
{
return m_toolReadMePath;
if (!AZ::IO::SystemFile::Exists(m_toolReadMePath.c_str()))
{
AZ_Error(AWSCoreResourceMappingToolActionName, false, "Invalid tool readme path: %s", m_toolReadMePath.c_str());
return "";
}
return m_toolReadMePath.Native();
}
} // namespace AWSCore

@ -73,7 +73,6 @@ public:
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return m_profileName; }
AZStd::string GetResourceMappingConfigFilePath() const override { return ""; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return ""; }
void ReloadConfiguration() override {}
std::shared_ptr<EnvironmentAWSCredentialsProviderMock> m_environmentCredentialsProviderMock;

@ -34,8 +34,6 @@ class AWSCoreEditorManagerTest
TEST_F(AWSCoreEditorManagerTest, AWSCoreEditorManager_Constructor_HaveExpectedUIResourcesCreated)
{
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreEditorManager testManager;
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
EXPECT_TRUE(testManager.GetAWSCoreEditorMenu());
}

@ -41,9 +41,7 @@ class AWSCoreEditorSystemComponentTest
m_entity = aznew AZ::Entity();
m_coreEditorSystemsComponent.reset(m_entity->CreateComponent<AWSCoreEditorSystemComponent>());
AZ_TEST_START_TRACE_SUPPRESSION;
m_entity->Init();
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
m_entity->Activate();
}

@ -42,18 +42,9 @@ class AWSCoreEditorMenuTest
}
};
TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_NoEngineRootFolder_ExpectOneError)
{
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreEditorMenu testMenu("dummy title");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
}
TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_GetAllActions_GetExpectedNumberOfActions)
{
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreEditorMenu testMenu("dummy title");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
QList<QAction*> actualActions = testMenu.actions();
#ifdef AWSCORE_EDITOR_RESOURCE_MAPPING_TOOL_ENABLED
@ -65,9 +56,7 @@ TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_GetAllActions_GetExpectedNumberO
TEST_F(AWSCoreEditorMenuTest, AWSCoreEditorMenu_BroadcastFeatureGemsAreEnabled_CorrespondingActionsAreEnabled)
{
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreEditorMenu testMenu("dummy title");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
AWSCoreEditorRequestBus::Broadcast(&AWSCoreEditorRequests::SetAWSClientAuthEnabled);
AWSCoreEditorRequestBus::Broadcast(&AWSCoreEditorRequests::SetAWSMetricsEnabled);

@ -7,6 +7,7 @@
*/
#include <AzTest/AzTest.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <Editor/UI/AWSCoreResourceMappingToolAction.h>
#include <Editor/UI/AWSCoreEditorUIFixture.h>
@ -24,7 +25,6 @@ class AWSCoreResourceMappingToolActionTest
{
AWSCoreEditorUIFixture::SetUp();
AWSCoreFixture::SetUp();
m_localFileIO->SetAlias("@engroot@", "dummy engine root");
}
void TearDown() override
@ -34,20 +34,12 @@ class AWSCoreResourceMappingToolActionTest
}
};
TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_NoEngineRootFolder_ExpectOneError)
TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_NoEngineRootPath_ExpectErrorsAndResult)
{
m_localFileIO->ClearAlias("@engroot@");
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreResourceMappingToolAction testAction("dummy title");
AZ_TEST_STOP_TRACE_SUPPRESSION(1); // expect the above have thrown an AZ_Error
}
TEST_F(AWSCoreResourceMappingToolActionTest, AWSCoreResourceMappingToolAction_UnableToFindExpectedFileOrFolder_ExpectFiveErrorsAndEmptyResult)
{
AZ_TEST_START_TRACE_SUPPRESSION;
AWSCoreResourceMappingToolAction testAction("dummy title");
AZ_TEST_STOP_TRACE_SUPPRESSION_NO_COUNT;
EXPECT_TRUE(testAction.GetToolLaunchCommand() == "");
EXPECT_TRUE(testAction.GetToolLogPath() == "");
EXPECT_TRUE(testAction.GetToolLogFilePath() == "");
EXPECT_TRUE(testAction.GetToolReadMePath() == "");
AZ_TEST_STOP_TRACE_SUPPRESSION(3);
}

@ -115,7 +115,6 @@ public:
// AWSCoreInternalRequestBus interface implementation
AZStd::string GetProfileName() const override { return ""; }
AZStd::string GetResourceMappingConfigFilePath() const override { return m_normalizedConfigFilePath; }
AZStd::string GetResourceMappingConfigFolderPath() const override { return m_normalizedConfigFolderPath; }
void ReloadConfiguration() override { m_reloadConfigurationCounter++; }
AZStd::unique_ptr<AWSCore::AWSResourceMappingManager> m_resourceMappingManager;

@ -89,3 +89,13 @@ you can create the virtualenv manually.
```
$ python3 resource_mapping_tool.py
```
## Tool Arguments
* `--binaries-path` **[Optional]** Path to QT Binaries necessary for PySide,
required if launching tool with engine python environment.
* `--config-path` **[Optional]** Path to resource mapping config directory,
if not provided tool will use current directory.
* `--debug` **[Optional]** Execute on debug mode to enable DEBUG logging level.
* `--log-path` **[Optional]** Path to resource mapping tool logging directory,
if not provided tool will store logging under tool source code directory.
* `--profile` **[Optional]** Named AWS profile to use for querying AWS resources,
if not provided tool will use `default` aws profile.

@ -9,15 +9,16 @@ from argparse import (ArgumentParser, Namespace)
import logging
import sys
from utils import aws_utils
from utils import environment_utils
from utils import file_utils
# arguments setup
argument_parser: ArgumentParser = ArgumentParser()
argument_parser.add_argument('--binaries_path', help='Path to QT Binaries necessary for PySide.')
argument_parser.add_argument('--config_path', help='Path to resource mapping config directory.')
argument_parser.add_argument('--binaries-path', help='Path to QT Binaries necessary for PySide.')
argument_parser.add_argument('--config-path', help='Path to resource mapping config directory.')
argument_parser.add_argument('--debug', action='store_true', help='Execute on debug mode to enable DEBUG logging level')
argument_parser.add_argument('--log-path', help='Path to resource mapping tool logging directory '
'(if not provided, logging file will be located at tool directory)')
argument_parser.add_argument('--profile', default='default', help='Named AWS profile to use for querying AWS resources')
arguments: Namespace = argument_parser.parse_args()
@ -25,8 +26,11 @@ arguments: Namespace = argument_parser.parse_args()
logging_level: int = logging.INFO
if arguments.debug:
logging_level = logging.DEBUG
logging_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__),
'resource_mapping_tool.log')
logging_path: str = file_utils.join_path(file_utils.get_parent_directory_path(__file__), 'resource_mapping_tool.log')
if arguments.log_path:
normalized_logging_path: str = file_utils.normalize_file_path(arguments.log_path, False)
if normalized_logging_path and file_utils.create_directory(normalized_logging_path):
logging_path = file_utils.join_path(normalized_logging_path, 'resource_mapping_tool.log')
logging.basicConfig(filename=logging_path, filemode='w', level=logging_level,
format='%(asctime)s,%(msecs)d %(name)s %(levelname)s %(message)s', datefmt='%H:%M:%S')
logging.getLogger('boto3').setLevel(logging.CRITICAL)
@ -34,6 +38,7 @@ logging.getLogger('botocore').setLevel(logging.CRITICAL)
logging.getLogger('s3transfer').setLevel(logging.CRITICAL)
logging.getLogger('urllib3').setLevel(logging.CRITICAL)
logger = logging.getLogger(__name__)
logger.info(f"Using {logging_path} for logging.")
if __name__ == "__main__":
if arguments.binaries_path and not environment_utils.is_qt_linked():

@ -44,6 +44,23 @@ class TestFileUtils(TestCase):
mocked_path.exists.assert_called_once()
assert not actual_result
def test_create_directory_return_true(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
actual_result: bool = file_utils.create_directory("dummy")
self._mock_path.assert_called_once()
mocked_path.mkdir.assert_called_once()
assert actual_result
def test_create_directory_return_false_when_exception_raised(self) -> None:
mocked_path: MagicMock = self._mock_path.return_value
mocked_path.mkdir.side_effect = FileExistsError()
actual_result: bool = file_utils.create_directory("dummy")
self._mock_path.assert_called_once()
mocked_path.mkdir.assert_called_once()
assert not actual_result
def test_get_current_directory_path_return_expected_path_name(self) -> None:
self._mock_path.cwd.return_value = TestFileUtils._expected_path_name

@ -20,6 +20,15 @@ def check_path_exists(file_path: str) -> bool:
return pathlib.Path(file_path).exists()
def create_directory(dir_path: str) -> bool:
try:
pathlib.Path(dir_path).mkdir(parents=True, exist_ok=True)
return True
except FileExistsError:
logger.warning(f"Failed to create directory at {dir_path}")
return False
def get_current_directory_path() -> str:
return str(pathlib.Path.cwd())
@ -40,10 +49,10 @@ def find_files_with_suffix_under_directory(dir_path: str, suffix: str) -> List[s
return results
def normalize_file_path(file_path: str) -> str:
def normalize_file_path(file_path: str, strict: bool = True) -> str:
if file_path:
try:
return str(pathlib.Path(file_path).resolve(True))
return str(pathlib.Path(file_path).resolve(strict))
except (FileNotFoundError, RuntimeError):
logger.warning(f"Failed to normalize file path {file_path}, return empty string instead")
return ""

Loading…
Cancel
Save