Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ venv
*.egg-info
.DS_Store
.vscode

dist
secrets.yaml
secrets.yml
settings.json
inkBoard/platforms/*/
inkBoard/integrations/*/
inkBoard/packaging/*.json
inkBoarddesigner
11 changes: 8 additions & 3 deletions inkBoard/packaging.py → inkBoard/_packaging.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
"backup version of packaging.py for porting"

"Handles inkBoard packages, both creating and installing them."

import asyncio
Expand Down Expand Up @@ -25,6 +27,10 @@

import PythonScreenStackManager as PSSM

from .constants import (
ZIP_COMPRESSION,
ZIP_COMPRESSION_LEVEL,
)

if TYPE_CHECKING:
from inkBoard import CORE as CORE
Expand All @@ -38,8 +44,7 @@
except ModuleNotFoundError:
from pkg_resources import parse_version

ZIP_COMPRESSION = zipfile.ZIP_BZIP2
ZIP_COMPRESSION_LEVEL = 9


_LOGGER = inkBoard.getLogger(__name__)

Expand Down Expand Up @@ -124,7 +129,7 @@ def compare_versions(requirement: Union[str,"Version"], compare_version: Union[s
comp_str = f"compare_version {c[0]} required_version"
else:
req_version = requirement
comp_str = f"compare_version >= required_version"
comp_str = "compare_version >= required_version"

return eval(comp_str, {}, {"compare_version": compare_version, "required_version": parse_version(req_version)})

Expand Down
4 changes: 2 additions & 2 deletions inkBoard/arguments.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ def command_logs(args):

def command_designer(args):
if not DESIGNER_MOD:
print("Running inkBoard designer require the inkBoard designer to be installed")
print("Running inkBoard designer requires the inkBoard designer to be installed")
print("Run 'pip install inkBoarddesigner' to install it")
return 1

Expand All @@ -53,7 +53,7 @@ def command_pack(args):
const.COMMAND_VERSION: command_version,
const.COMMAND_DESIGNER: command_designer,
const.COMMAND_INSTALL: command_install,
const.COMMAND_LOGS: command_logs
const.COMMAND_LOGS: command_logs,
}
"Action that can/have to be run before creating the CORE object"

Expand Down
11 changes: 7 additions & 4 deletions inkBoard/logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import logging
import logging.handlers
from pathlib import Path
from typing import Any, Optional, TYPE_CHECKING, Union, TypedDict
from typing import Any, Optional, TYPE_CHECKING, Union, TypedDict, Callable
from functools import partial, partialmethod
from contextlib import suppress
from dataclasses import asdict
Expand Down Expand Up @@ -119,11 +119,14 @@ class BaseFormatter(logging.Formatter):
formatter = logging.Formatter(log_format, log_dateformat, style="$")

@classmethod
def format(cls, record):
if not "YAML" in record.__dict__:
def format(cls, record, format_func : Callable = None):
#[ ]: This should be a method. And return super().format
if "YAML" not in record.__dict__:
record.__dict__["YAML"] = ""
else:
record.__dict__["YAML"] = cls._format_yaml(record.__dict__["YAML"])
if format_func:
return format_func(record)
return cls.formatter.format(record)

@staticmethod
Expand Down Expand Up @@ -159,7 +162,7 @@ def __init__(self, fmt = log_format, datefmt = log_dateformat, style = "$", vali
super().__init__(fmt, datefmt, style, validate)

def format(self, record):
formatted = BaseFormatter.format(record)
formatted = BaseFormatter.format(record, super().format)
if record.levelno < DEBUG:
format_level = 0
elif record.levelno in ANSI_FORMATS:
Expand Down
113 changes: 113 additions & 0 deletions inkBoard/packaging/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
"Handles inkBoard packages, both creating and installing them."

import asyncio
from typing import TYPE_CHECKING, Union
from pathlib import Path

import inkBoard
# from inkBoard.types import *
from inkBoard import constants as bootstrap
from .types import internalinstalltypes


if TYPE_CHECKING:
from inkBoard import CORE as CORE

_LOGGER = inkBoard.getLogger(__name__)
_LOGGER.warning("Dont forget to write tests fro this")

def confirm_input(msg: str):
answer = input(f"{msg}\n(Y/N): ")
if answer.lower() in {"y","yes"}:
return True
elif answer.lower() in {"n","no"}:
return False
else:
print("Please answer one of Y(es) or N(o) (Not case sensitive)")
return confirm_input(msg)

def create_config_package(configuration: str, name: str = None, pack_all: bool = False, config: bool = False, platform: bool = False, integrations: bool = False):
"""Sets up a core instance and creates a package from it

Parameters
----------
configuration : str
The YAML file to use
name : str, optional
The name of the package, by default None
pack_all : bool, optional
Packages all components (config stuff, platform and integrations), by default False
config : bool, optional
Packages the config folder, by default False
platform : bool, optional
Packages the platform, by default False
integrations : bool, optional
Packages the imported integrations, by default False

Returns
-------
int
Return code
"""
core = asyncio.run(bootstrap.setup_core(configuration, bootstrap.loaders.IntegrationLoader))
return create_core_package(core, name, pack_all, config, platform, integrations)

def create_core_package(core: "CORE", name: str = None, pack_all: bool = False, config: bool = False, platform: bool = False, integrations: bool = False):
"""Creates an inkBoard package from a core instance.

This bundles all required files and folders from the configuration folder, as well in the required platforms and integrations.

Parameters
----------
core : CORE
The core object constructed from the config
"""
from .package import Packager

if pack_all:
Packager(core).create_package(name)
else:
pack = []
if config: pack.append("configuration")
if platform: pack.append("platform")
if integrations: pack.append('integration')

Packager(core).create_package(name, pack)
return 0


def run_install_command(file: str, name: str, no_input: bool):
##Add functionality to installer for internal installs (platforms and integrations)
##Usage: install [platform/integration] [name]

if file in internalinstalltypes.__args__:
return install_internal(file, name, no_input)
else:
return install_packages(file, no_input)

def install_internal(install_type: str, name:str, no_input: bool = False):
from .install import InternalInstaller
return InternalInstaller(install_type, name, no_input, confirm_input).install()

def install_packages(file: Union[str, Path] = None, no_input: bool = False):

##https://gist.github.com/oculushut/193a7c2b6002d808a791
##Found this gist, that may allow downloading files from github
##Would make installing integrations and platforms A LOT more user friendly
##Especially when simply needing to update
##Better yet, see this code: https://github.com/fbunaren/GitHubFolderDownloader
##Only relies on requests. That is a library I am a-okay with implementing
from .install import PackageInstaller
if file:
return PackageInstaller(file, skip_confirmations=no_input, confirmation_function=confirm_input).install()
else:
packages = PackageInstaller.gather_inkboard_packages()

print(f"Found {len(packages)} {'package' if len(packages) == 1 else 'packages'} that can be installed")
for package in packages:
##Add a confirmation message for each file.
PackageInstaller(package, skip_confirmations=no_input, confirmation_function=confirm_input).install()
return 0



33 changes: 33 additions & 0 deletions inkBoard/packaging/constants.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@

from types import MappingProxyType
import zipfile

from .types import (
packagetypes,
)

INKBOARD_PACKAGE_INTERNAL_FOLDER = ".inkBoard"
#Folder name where files from a package are put which are gotten from or destined to the site-packages inkBoard folder.

PACKAGE_INDEX_URL = "https://github.com/Slalamander/inkBoard-package-index"
"url to the package index"

INTERNAL_PACKAGE_INDEX_FILE = "package_index.json"

ZIP_COMPRESSION = zipfile.ZIP_BZIP2
ZIP_COMPRESSION_LEVEL = 9

PACKAGE_ID_FILES : dict[packagetypes,str] = MappingProxyType({
'package': 'package.json',
'integration': 'manifest.json',
'platform': 'platform.json'
})

VERSION_COMPARITORS = ('==', '!=', '>=', '<=', '>', '<') ##The order of this is important!
"Comparison operators allowed for versioning, so they can be evaluated internally"

DESIGNER_FILES = {"designer", "designer.py"}
#Files in integrations etc. meant for the designer. Currently these are not included in files in the package index

REQUIREMENTS_FILE = 'requirements.txt'

Loading