Skip to content

Commit

Permalink
Snapshot 2
Browse files Browse the repository at this point in the history
  • Loading branch information
Julian-O committed Sep 1, 2023
1 parent b630c19 commit 8756cd2
Show file tree
Hide file tree
Showing 8 changed files with 378 additions and 426 deletions.
39 changes: 16 additions & 23 deletions buildozer/buildsupport.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,15 @@
import buildozer.buildops as buildops
from buildozer.jsonstore import JsonStore
from buildozer.logger import Logger
from buildozer.pathatlas import PathAtlas, TargetedPathAtlas
from buildozer.pathatlas import GenericPaths, TargetPaths


class GenericBuildSupporter:
"""Handles only operations that do not require a target."""

logger = Logger()

def __init__(self, config, paths: PathAtlas):
def __init__(self, config, paths: GenericPaths):
self.config = config
self.paths = paths

Expand Down Expand Up @@ -105,11 +105,13 @@ def serve(self):


class TargetedBuildSupporter(GenericBuildSupporter):
"""Handles all build operations,
including those that do require a target."""
"""Handles all build operations, including those that do require a
target."""

def __init__(self, config, paths: TargetedPathAtlas, target_cls):
def __init__(self, config, paths, target_cls):
super().__init__(config, paths)

self.target_paths = TargetPaths(paths, target_cls.targetname)
self._ensure_target_directories_exist()

# Create the target instance.
Expand All @@ -123,11 +125,9 @@ def __init__(self, config, paths: TargetedPathAtlas, target_cls):
self._build_done = False

def _ensure_target_directories_exist(self):
assert isinstance(self.paths, TargetedPathAtlas)

buildops.mkdir(self.paths.global_platform_path)
buildops.mkdir(self.paths.platform_path)
buildops.mkdir(self.paths.app_path)
buildops.mkdir(self.target_paths.global_platform_path)
buildops.mkdir(self.target_paths.platform_path)
buildops.mkdir(self.target_paths.app_path)

def prepare_for_build(self):
"""Prepare the build."""
Expand Down Expand Up @@ -268,10 +268,8 @@ def _ensure_virtualenv(self):
self.env_venv["CXX"] = "/bin/false"

def clean_platform(self):
assert isinstance(self.paths, TargetedPathAtlas)

self.logger.info("Cleaning the platform build directory")
buildops.rmdir(self.paths.platform_path)
buildops.rmdir(self.target_paths.platform_path)

def get_app_version(self):
c = self.config
Expand Down Expand Up @@ -316,8 +314,6 @@ def build_application(self):
self._add_sitecustomize()

def _copy_application_sources(self):
assert isinstance(self.paths, TargetedPathAtlas)

# XXX clean the inclusion/exclusion algo.
source_dir = realpath(
expanduser(self.config.getdefault("app", "source.dir", "."))
Expand All @@ -340,7 +336,7 @@ def _copy_application_sources(self):

self.logger.debug("Copy application source from {}".format(source_dir))

buildops.rmdir(self.paths.app_path)
buildops.rmdir(self.target_paths.app_path)

for root, dirs, files in walk(source_dir, followlinks=True):
# avoid hidden directory
Expand Down Expand Up @@ -411,7 +407,7 @@ def _copy_application_sources(self):

sfn = join(root, fn)
rfn = (
self.paths.app_path / root[len(source_dir) + 1 :] / fn
self.target_paths.app_path / root[len(source_dir) + 1 :] / fn
).resolve()

# ensure the directory exists
Expand All @@ -423,20 +419,17 @@ def _copy_application_sources(self):

def _copy_application_libs(self):
# copy also the libs
assert isinstance(self.paths, TargetedPathAtlas)
buildops.file_copytree(
self.paths.applibs_path, self.paths.app_path / "_applibs"
self.paths.applibs_path, self.target_paths.app_path / "_applibs"
)

def _add_sitecustomize(self):
assert isinstance(self.paths, TargetedPathAtlas)

buildops.file_copy(
Path(__file__).parent / "sitecustomize.py",
self.paths.app_path / "sitecustomize.py",
self.target_paths.app_path / "sitecustomize.py",
)

main_py = join(self.paths.app_path, "service", "main.py")
main_py = join(self.target_paths.app_path, "service", "main.py")
if not buildops.file_exists(main_py):
return

Expand Down
124 changes: 95 additions & 29 deletions buildozer/commandline.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
import buildozer.buildops as buildops
from buildozer.jsonstore import JsonStore
from buildozer.logger import Logger
from buildozer.pathatlas import PathAtlas, TargetedPathAtlas
from buildozer.pathatlas import GenericPaths, TargetPaths
from buildozer.specparser import SpecParser

logger = Logger()
Expand All @@ -38,9 +38,9 @@ def run(args):
Parse the command line arguments, handle the basic operations.
Handle any options first.
Set up a ConfigSpec and PathAtlas and handle any generic commands (that
need no target).
Otherwise, set up a Buildozer instance, and handle target commands.
Set up a ConfigSpec and GenericPaths instance and handle any generic
commands (that have no target).
Otherwise, set up a Builder instance, and handle target commands.
"""

# Profiles can be used to customise buildozer.spec on some runs.
Expand Down Expand Up @@ -72,31 +72,19 @@ def run(args):
elif arg in ("-p", "--profile"):
profile = args.pop(0)

# Start function
config = SpecParser(profile)

spec_name = "buildozer.spec"
if buildops.file_exists(spec_name):
config.read(spec_name, "utf-8")
_check_and_migrate_config(config)

# End function
config = _load_spec()

if not log_level_set_by_command_line:
try:
logger.set_level(
int(config.getdefault("buildozer", "log_level", "2"))
)
except Exception:
pass
_set_log_level_from_config(config)

_check_if_root_user(config)

paths = GenericPaths(base_dir=".", config=config)

# If no arguments are given, see if default arguments were provided
# (else exit).
if not args:
path_atlas = PathAtlas(".", config)
args = _get_default_args(path_atlas)
args = _get_default_args(paths)

# There are three types of remaining commands:
# <generic_command> <arguments>
Expand All @@ -105,13 +93,12 @@ def run(args):

available_targets = _targets()

command = args[0]
command = args.pop(0)

# Generic commands don't need a target.
if command in GENERIC_COMMANDS:
path_atlas = PathAtlas(".", config)
action = GENERIC_COMMANDS[command][2]
action(config, path_atlas, args[1:])
action(config, paths, args)
return

command = command.lower()
Expand All @@ -122,17 +109,96 @@ def run(args):
exit(1)

# We have a target.
tpa = TargetedPathAtlas(
specfile_path=".", config=config, target_name=command

if not args:
logger.error('Missing target command')
_usage()
exit(1)

_run_target_command(
config=config,
paths=paths,
target_cls=available_targets[command],
args=args[1:],
)
_run_target_command(config, tpa, available_targets[command], args[1:])


def _run_target_command(config, paths, target_cls, *args):
def _load_spec(profile):
"""Load spec file, if present."""
config = SpecParser(profile)

spec_name = "buildozer.spec"
if buildops.file_exists(spec_name):
config.read(spec_name, "utf-8")
_check_and_migrate_config(config)
return config


def _set_log_level_from_config(config):
try:
logger.set_level(int(config.getdefault("buildozer", "log_level", "2")))
except Exception:
pass


def _run_target_command(config, paths, target_cls, args):

# Parse a list of commands. Each command is a single word, optionally
# followed by --options. A "--" token indicates the rest of the arguments
# on the line should be passed to the command (even if they don't start
# with "--")

valid_command_names = set(target_cls.get_custom_commands() + GENERIC_COMMANDS)

# Commands that have been parsed.
complete_commands = []

# Latest command that is partially parsed.
partial_command = []

while args:
arg = args.pop(0)
if arg == '--':
if partial_command:
# Rest of arguments are part of the current command.
partial_command += args
break
else:
logger.error('-- arguments passed without a command')
_usage()
exit(1)

if not arg.startswith('--'):
# New command starting.
if arg.lower() not in valid_command_names:
logger.error('Unrecognised command: {}'.format(arg))
_usage()
exit(1)

# Previous command, if any, is completed.
if partial_command:
complete_commands.append(partial_command)
partial_command = []

partial_command.append(arg.lower())
else:
if not partial_command:
logger.error('Argument passed without a command')
_usage()
exit(1)
partial_command.append(arg)
if partial_command:
complete_commands.append(partial_command)

if not complete_commands:
logger.error('No command for target provided')
_usage()
exit(1)

# Create the target instance, and ask it to run the command.
buildsupport = TargetedBuildSupporter(config, paths, target_cls)
target = target_cls(buildsupport)
target.run_commands(*args)
target.run_commands(complete_commands)


def _check_if_root_user(config):
Expand Down
39 changes: 18 additions & 21 deletions buildozer/pathatlas.py
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
from pathlib import Path


class PathAtlas:
"""
The PathAtlas maintains a lookup table of directories relevant to the build.
It ensures that the folders exist.
"""
class GenericPaths:
"""Responsible for the structure of directories relevant to all builds."""

def __init__(self, specfile_path, config):
self.specfile_path = Path(specfile_path)
def __init__(self, base_dir, config):
# base_dir is the directory in which the spec_file was found was
# expected to be in.

# The path the specfile is in.
self.root_path = self.specfile_path.parent.expanduser().resolve()
# The folder the specfile is in (or was expected to be in).
self.root_path = Path(base_dir).expanduser().resolve()

# The user-provided build dir, if any.
# Check the (deprecated) builddir option, for backwards compatibility
# ToDo: Move this code in commandline's migrate functinality.
old_style_build_dir = config.getdefault("buildozer", "builddir", None)
if old_style_build_dir:
# for backwards compatibility, append .buildozer to builddir
Expand Down Expand Up @@ -54,23 +53,21 @@ def __init__(self, specfile_path, config):
self.global_cache_path = self.global_buildozer_path / "cache"


class TargetedPathAtlas(PathAtlas):
"""
Subclass of PathAtlas that also handles directories once target has been
provided.
"""
class TargetPaths:
"""Responsible for the structure of directories relevant to all targeted
builds."""

def __init__(self, specfile_path, config, target_name):
super().__init__(specfile_path, config)

self.platform_path = self.buildozer_path / target_name / "platform"
def __init__(self, generic_paths, target_name):
self.platform_path = (
generic_paths.buildozer_path / target_name / "platform"
)

self.app_path = self.buildozer_path / target_name / "app"
self.app_path = generic_paths.buildozer_path / target_name / "app"

self.global_platform_path = (
self.global_buildozer_path / target_name / "platform"
generic_paths.global_buildozer_path / target_name / "platform"
)

self.global_packages_path = (
self.global_platform_path / target_name / "packages"
generic_paths.global_platform_path / target_name / "packages"
)
Loading

0 comments on commit 8756cd2

Please sign in to comment.