Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Feature] - Create openbb assets folder #6101

Merged
merged 5 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 23 additions & 19 deletions openbb_platform/core/openbb_core/app/static/package_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,9 @@ def __init__(
def auto_build(self) -> None:
"""Trigger build if there are differences between built and installed extensions."""
if Env().AUTO_BUILD:
add, remove = PackageBuilder._diff(self.directory / "package")
add, remove = PackageBuilder._diff(
self.directory / "assets" / "extension_map.json"
)
if add:
a = ", ".join(add)
print(f"Extensions to add: {a}") # noqa: T201
Expand All @@ -98,7 +100,7 @@ def build(
) -> None:
"""Build the extensions for the Platform."""
self.console.log("\nBuilding extensions package...\n")
self._clean_package(modules)
self._clean(modules)
ext_map = self._get_extension_map()
self._save_extension_map(ext_map)
self._save_module_map()
Expand All @@ -107,8 +109,9 @@ def build(
if self.lint:
self._run_linters()

def _clean_package(self, modules: Optional[Union[str, List[str]]] = None) -> None:
"""Delete the package folder or modules before building."""
def _clean(self, modules: Optional[Union[str, List[str]]] = None) -> None:
"""Delete the assets and package folder or modules before building."""
shutil.rmtree(self.directory / "assets", ignore_errors=True)
if modules:
for module in modules:
module_path = self.directory / "package" / f"{module}.py"
Expand Down Expand Up @@ -141,7 +144,7 @@ def _save_extension_map(self, ext_map: Dict[str, List[str]]) -> None:
"""Save the map of extensions available at build time."""
code = dumps(obj=dict(sorted(ext_map.items())), indent=4)
self.console.log("Writing extension map...")
self._write(code=code, name="extension_map", extension="json")
self._write(code=code, name="extension_map", extension="json", folder="assets")

def _save_module_map(self):
"""Save the module map."""
Expand All @@ -152,7 +155,7 @@ def _save_module_map(self):
}
code = dumps(obj=dict(sorted(module_map.items())), indent=4)
self.console.log("\nWriting module map...")
self._write(code=code, name="module_map", extension="json")
self._write(code=code, name="module_map", extension="json", folder="assets")

def _save_modules(
self,
Expand Down Expand Up @@ -197,9 +200,11 @@ def _run_linters(self):
linters.ruff()
linters.black()

def _write(self, code: str, name: str, extension="py") -> None:
def _write(
self, code: str, name: str, extension: str = "py", folder: str = "package"
) -> None:
"""Write the module to the package."""
package_folder = self.directory / "package"
package_folder = self.directory / folder
package_path = package_folder / f"{name}.{extension}"

package_folder.mkdir(exist_ok=True)
Expand All @@ -209,33 +214,32 @@ def _write(self, code: str, name: str, extension="py") -> None:
file.write(code.replace("typing.", ""))

@staticmethod
def _read_extension_map(package: Path) -> dict:
"""Get extension map from package folder."""
ext_map_file = Path(package, "extension_map.json")
def _read(path: Path) -> dict:
"""Get content from folder."""
try:
with open(ext_map_file) as fp:
ext_map = load(fp)
with open(Path(path)) as fp:
content = load(fp)
except Exception:
ext_map = {}
content = {}

return ext_map
return content

@staticmethod
def _diff(package: Path) -> Tuple[Set[str], Set[str]]:
def _diff(path: Path) -> Tuple[Set[str], Set[str]]:
"""Check differences between built and installed extensions.

Parameters
----------
package: Path
The path to the package
path: Path
The path to the folder where the extension map is stored.

Returns
-------
Tuple[Set[str], Set[str]]
First element: set of installed extensions that are not in the package.
Second element: set of extensions in the package that are not installed.
"""
ext_map = PackageBuilder._read_extension_map(package)
ext_map = PackageBuilder._read(path)

add: Set[str] = set()
remove: Set[str] = set()
Expand Down
44 changes: 23 additions & 21 deletions openbb_platform/core/tests/app/static/test_package_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,14 +26,14 @@


@pytest.fixture(scope="module")
def tmp_package_dir(tmp_path_factory):
return tmp_path_factory.mktemp("package")
def tmp_openbb_dir(tmp_path_factory):
return tmp_path_factory.mktemp("openbb")


@pytest.fixture(scope="module")
def package_builder(tmp_package_dir):
def package_builder(tmp_openbb_dir):
"""Return package builder."""
return PackageBuilder(tmp_package_dir)
return PackageBuilder(tmp_openbb_dir)


def test_package_builder_init(package_builder):
Expand Down Expand Up @@ -544,14 +544,16 @@ def some_func():
assert "Returns" in doc


def test_read_extension_map(package_builder, tmp_package_dir):
def test_read_extension_map(package_builder, tmp_openbb_dir):
"""Test read extension map."""

PATH = "openbb_core.app.static.package_builder."
open_mock = mock_open()
with patch(PATH + "open", open_mock), patch(PATH + "load") as mock_load:
package_builder._read_extension_map(tmp_package_dir)
open_mock.assert_called_once_with(Path(tmp_package_dir, "extension_map.json"))
package_builder._read(Path(tmp_openbb_dir / "assets" / "extension_map.json"))
open_mock.assert_called_once_with(
Path(tmp_openbb_dir / "assets" / "extension_map.json")
)
mock_load.assert_called_once()


Expand Down Expand Up @@ -606,7 +608,7 @@ def test_read_extension_map(package_builder, tmp_package_dir):
)
def test_package_diff(
package_builder,
tmp_package_dir,
tmp_openbb_dir,
ext_built,
ext_installed,
ext_inst_version,
Expand All @@ -619,21 +621,19 @@ def mock_entry_points(group):
return ext_installed.select(**{"group": group})

PATH = "openbb_core.app.static.package_builder."
with patch.object(
PackageBuilder, "_read_extension_map"
) as mock_read_extension_map, patch(
with patch.object(PackageBuilder, "_read") as mock_read, patch(
PATH + "entry_points", mock_entry_points
), patch.object(
EntryPoint, "dist", new_callable=PropertyMock
) as mock_obj:
), patch.object(EntryPoint, "dist", new_callable=PropertyMock) as mock_obj:

class MockPathDistribution:
version = ext_inst_version

mock_obj.return_value = MockPathDistribution()
mock_read_extension_map.return_value = ext_built
mock_read.return_value = ext_built

add, remove = package_builder._diff(tmp_package_dir)
add, remove = package_builder._diff(
Path(tmp_openbb_dir, "assets", "extension_map.json")
)

# We add whatever is not built, but is installed
assert add == expected_add
Expand All @@ -651,20 +651,22 @@ class MockPathDistribution:
({"this"}, {"that"}, False),
],
)
def test_auto_build(package_builder, tmp_package_dir, add, remove, openbb_auto_build):
def test_auto_build(package_builder, tmp_openbb_dir, add, remove, openbb_auto_build):
"""Test auto build."""

with patch.object(PackageBuilder, "_diff") as mock_package_diff, patch.object(
with patch.object(PackageBuilder, "_diff") as mock_assets_diff, patch.object(
PackageBuilder, "build"
) as mock_build, patch.object(Env, "AUTO_BUILD", openbb_auto_build):
mock_package_diff.return_value = add, remove
mock_assets_diff.return_value = add, remove

package_builder.auto_build()

if openbb_auto_build:
mock_package_diff.assert_called_once_with(Path(tmp_package_dir, "package"))
mock_assets_diff.assert_called_once_with(
Path(tmp_openbb_dir, "assets", "extension_map.json")
)
if add or remove:
mock_build.assert_called_once()
else:
mock_package_diff.assert_not_called()
mock_assets_diff.assert_not_called()
mock_build.assert_not_called()
2 changes: 1 addition & 1 deletion openbb_platform/tests/test_extension_map.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ def test_extension_map():
"""Ensure only required extensions are built and versions respect pyproject.toml"""
this_dir = Path(__file__).parent
ext_map = load_ext_map(
Path(this_dir, "..", "openbb", "package", "extension_map.json")
Path(this_dir, "..", "openbb", "assets", "extension_map.json")
)
req_ext = load_req_ext(Path(this_dir, "..", "pyproject.toml"))

Expand Down
Loading