Skip to content

Commit

Permalink
add get_file_path (#15)
Browse files Browse the repository at this point in the history
* add get_file_path

* add tests

* fix docs

* fix test

* fix linter

* fix method name

* update docs

* fix for files without ending
  • Loading branch information
MP91 authored Jun 14, 2024
1 parent 56ba28f commit 17f8271
Show file tree
Hide file tree
Showing 6 changed files with 209 additions and 3 deletions.
6 changes: 6 additions & 0 deletions .devcontainer/devcontainer.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,11 @@
"vscode": {
// Set *default* container specific settings.json values on container create.
"settings": {
"python.testing.pytestArgs": [
"tests"
],
"python.testing.unittestEnabled": false,
"python.testing.pytestEnabled": true,
"python.pythonPath": "/usr/bin/python3",
"python.defaultInterpreterPath": "/usr/bin/python3",
"[python]": {
Expand Down Expand Up @@ -46,5 +51,6 @@
}
},
// Comment out connect as root instead. More info: https://aka.ms/vscode-remote/containers/non-root.
"onCreateCommand": "bash .devcontainer/scripts/onCreateCommand.sh",
"remoteUser": "vscode"
}
32 changes: 32 additions & 0 deletions .devcontainer/scripts/onCreateCommand.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/bin/bash
# Copyright (c) 2022-2024 Contributors to the Eclipse Foundation
#
# This program and the accompanying materials are made available under the
# terms of the Apache License, Version 2.0 which is available at
# https://www.apache.org/licenses/LICENSE-2.0.
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
# SPDX-License-Identifier: Apache-2.0

echo "#######################################################"
echo "### Install python requirements ###"
echo "#######################################################"
# Update pip before installing requirements
pip3 install --upgrade pip
pip3 install -r requirements.txt
pip3 install -r tests/requirements.txt

# Add repo to git safe.directory
REPO=$(pwd)
git config --global --add safe.directory $REPO

# Add git name and email from env variables
if [[ -n "${GIT_CONFIG_NAME}" && -n "${GIT_CONFIG_EMAIL}" ]]; then
git config --global user.name $GIT_CONFIG_NAME
git config --global user.email $GIT_CONFIG_EMAIL
fi
2 changes: 2 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@
- [`velocitas_lib.get_script_path`](./velocitas_lib.md#function-get_script_path): Return the absolute path to the directory the invoked Python script
- [`velocitas_lib.get_valid_arch`](./velocitas_lib.md#function-get_valid_arch): Return a known architecture for the given `arch`.
- [`velocitas_lib.get_workspace_dir`](./velocitas_lib.md#function-get_workspace_dir): Return the workspace directory.
- [`velocitas_lib.is_uri`](./velocitas_lib.md#function-is_uri): Check if the provided path is a URI.
- [`velocitas_lib.obtain_local_file_path`](./velocitas_lib.md#function-obtain_local_file_path): Return the absolute path to the file, specified by a absolute/relative local path or with an URI.
- [`velocitas_lib.replace_in_file`](./velocitas_lib.md#function-replace_in_file): Replace all occurrences of text in a file with a replacement.
- [`velocitas_lib.require_env`](./velocitas_lib.md#function-require_env): Require and return an environment variable.
- [`velocitas_lib.to_camel_case`](./velocitas_lib.md#function-to_camel_case): Return a camel case version of a snake case string.
Expand Down
54 changes: 54 additions & 0 deletions docs/velocitas_lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,60 @@ download_file(uri: str, local_file_path: str) → None



---

<a href="../velocitas_lib/__init__.py#L227"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `is_uri`

```python
is_uri(path: str) → bool
```

Check if the provided path is a URI.



**Args:**

- <b>`path`</b> (str): The path to check.



**Returns:**

- <b>`bool`</b>: True if the path is a URI. False otherwise.


---

<a href="../velocitas_lib/__init__.py#L239"><img align="right" style="float:right;" src="https://img.shields.io/badge/-source-cccccc?style=flat-square"></a>

## <kbd>function</kbd> `obtain_local_file_path`

```python
obtain_local_file_path(
path_or_uri: str,
download_path: Optional[str] = None
) → str
```

Return the absolute path to the file, specified by a absolute/relative local path or with an URI.



**Args:**

- <b>`path_or_uri`</b> (str): Absolute/relative local path or URI.
- <b>`download_path`</b> (str): The path to download the file.



**Returns:**

- <b>`str`</b>: The absolute path to the file.




---
Expand Down
67 changes: 66 additions & 1 deletion tests/test_velocitas_lib.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,12 @@
from velocitas_lib import (
get_app_manifest,
get_cache_data,
obtain_local_file_path,
get_package_path,
get_script_path,
get_workspace_dir,
require_env,
get_project_cache_dir,
)
from velocitas_lib.services import get_services

Expand All @@ -45,6 +47,18 @@ def set_velocitas_workspace_dir() -> str:
return os.environ["VELOCITAS_WORKSPACE_DIR"]


@pytest.fixture()
def set_velocitas_package_dir() -> str:
os.environ["VELOCITAS_PACKAGE_DIR"] = "./tests/package"
return os.environ["VELOCITAS_PACKAGE_DIR"]


@pytest.fixture()
def set_velocitas_cache_dir() -> str:
os.environ["VELOCITAS_CACHE_DIR"] = "/test/cache"
return os.environ["VELOCITAS_CACHE_DIR"]


@pytest.fixture()
def set_app_manifest() -> str:
app_manifest = {"vehicleModel": {"src": "test"}}
Expand Down Expand Up @@ -101,7 +115,7 @@ def test_get_script_path__returns_script_path():
assert get_script_path() == os.path.dirname(os.path.realpath(sys.argv[0]))


def test_get_package_path__returns_package_path():
def test_get_package_path__returns_package_path(set_velocitas_package_dir):
assert get_package_path() == "./tests/package"


Expand All @@ -111,6 +125,7 @@ def test_get_cache_data__returns_cache_data(set_velocitas_cache_data): # type:


def test_get_services__no_overwrite_provided__returns_default_services(
set_velocitas_package_dir,
mock_filesystem: FakeFilesystem,
):
os.environ["runtimeFilePath"] = "runtime.json"
Expand All @@ -127,6 +142,7 @@ def test_get_services__no_overwrite_provided__returns_default_services(


def test_get_services__overwrite_provided__returns_overwritten_services(
set_velocitas_package_dir,
mock_filesystem: FakeFilesystem,
):
os.environ["runtimeFilePath"] = "runtime.json"
Expand All @@ -147,3 +163,52 @@ def test_get_services__overwrite_provided__returns_overwritten_services(
assert all_services[0].config.image == "image-my-custom-service"

mock_filesystem.reset()


def test_obtain_local_file_path__absolute_local_path(set_velocitas_workspace_dir):
root = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
assert obtain_local_file_path(f"{root}/README.md") == f"{root}/README.md"


def test_obtain_local_file_path__relative_local_path(set_velocitas_workspace_dir):
assert obtain_local_file_path("README.md") == "README.md"


def test_obtain_local_file_path__absolute_local_path_not_available(
set_velocitas_workspace_dir,
):
pytest.raises(
FileNotFoundError,
obtain_local_file_path,
"/workspaces/velocitas-lib/README2.md",
)


def test_obtain_local_file_path__relative_local_path_not_available(
set_velocitas_workspace_dir,
):
pytest.raises(FileNotFoundError, obtain_local_file_path, "README2.md")


def test_obtain_local_file_path__uri(set_velocitas_workspace_dir):
assert (
obtain_local_file_path(
"https://raw.githubusercontent.com/eclipse-velocitas/velocitas-lib/main/README.md",
"/workspaces/velocitas-lib/.pytest_cache/README.md",
)
== "/workspaces/velocitas-lib/.pytest_cache/README.md"
)
Path.unlink(Path("/workspaces/velocitas-lib/.pytest_cache/README.md"))


def test_obtain_local_file_path__uri_no_download_path(
set_velocitas_cache_dir,
mock_filesystem: FakeFilesystem,
):
mock_filesystem.create_dir(get_project_cache_dir())
assert (
obtain_local_file_path(
"https://raw.githubusercontent.com/eclipse-velocitas/velocitas-lib/main/README.md"
)
== "/test/cache/downloads/README.md"
)
51 changes: 49 additions & 2 deletions velocitas_lib/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@
import json
import os
import sys
import re
import requests
from io import TextIOWrapper
from typing import Any, Callable, Dict, List, Optional

import requests


def to_camel_case(snake_str: str) -> str:
"""Return a camel case version of a snake case string.
Expand Down Expand Up @@ -222,3 +222,50 @@ def download_file(uri: str, local_file_path: str) -> None:
with open(local_file_path, "wb") as outfile:
for chunk in infile.iter_content(chunk_size=8192):
outfile.write(chunk)


def is_uri(path: str) -> bool:
"""Check if the provided path is a URI.
Args:
path (str): The path to check.
Returns:
bool: True if the path is a URI. False otherwise.
"""
return re.match(r"(\w+)\:\/\/(\w+)", path) is not None


def obtain_local_file_path(
path_or_uri: str, download_path: Optional[str] = None
) -> str:
"""Return the absolute path to the file, specified by a absolute/relative local path or with an URI.
Args:
path_or_uri (str): Absolute/relative local path or URI.
download_path (str): The path to download the file.
Returns:
str: The absolute path to the file.
"""
if not is_uri(path_or_uri):
if os.path.isfile(path_or_uri):
return path_or_uri
elif os.path.isfile(os.path.join(get_workspace_dir(), path_or_uri)):
return os.path.join(get_workspace_dir(), path_or_uri)
else:
raise FileNotFoundError(f"File {path_or_uri} not found!")

if download_path is None:
download_path = os.path.join(
get_project_cache_dir(), "downloads", path_or_uri.split("/")[-1]
)
if os.path.isfile(download_path):
path, file = os.path.split(download_path)
parts = file.split(".", 1)
filename = f"{parts[0]}_1.{parts[1]}" if len(parts) > 1 else f"{parts[0]}_1"

download_path = os.path.join(path, filename)

download_file(path_or_uri, download_path)
return download_path

0 comments on commit 17f8271

Please sign in to comment.