~techalchemy/mojo/python3-fixes

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
from __future__ import absolute_import, division, print_function
import logging
import os
import shutil
from .exceptions import ArgumentError
from .spec import Spec


class NoSuchWorkspaceError(Exception):
    pass


class Workspace(object):
    "A mojo workspace"
    def __init__(self, name, path, stage=None, spec_url=None, manifest_file=None, logfile=None):
        if name is None:
            raise ArgumentError("Workspace setting missing. Use --workspace or set MOJO_WORKSPACE")
        self.name = name
        self.manifest_file = manifest_file
        if not path:
            self.path = os.path.abspath(os.curdir)
            logging.info("No workspace path specified, using {}"
                         "".format(self.path))
        else:
            self.path = os.path.abspath(path)
        if not os.path.exists(self.path):
            raise NoSuchWorkspaceError(path)
        self.stage = stage
        self.spec_url = spec_url
        self.logfile = logfile
        self._spec = None

    @property
    def spec(self):
        if self._spec is None:
            self._spec = Spec(self.spec_dir, self.spec_url, stage=self.stage, manifest_file=self.manifest_file)
        return self._spec

    @property
    def all_dirs(self):
        return [self.path,
                self.build_dir,
                self.local_dir,
                self.log_dir,
                self.spec_dir,
                ]

    def prepare(self):
        "Set up the workspace. Returns True on success, False on failure."
        for path in self.all_dirs:
            if path == self.spec_dir:  # spec dir is initialized next
                continue
            if not os.path.isdir(path):
                try:
                    os.makedirs(path)
                except OSError as e:
                    logging.error("{} ({})".format(e.strerror, e.filename))
                    return False
        self.spec  # Initializes spec
        self.create_file_logger()
        return True

    def clean(self):
        "Reset the workspace"
        existing_directories = (d for d in self.all_dirs if os.path.exists(d))
        for directory in existing_directories:
            shutil.rmtree(directory)
        return self.prepare()

    def delete(self):
        "Destroy the workspace"
        realpath = os.path.realpath(self.path)
        shutil.rmtree(realpath)

    def create_file_logger(self):
        "If we haven't already, attach a file logger"
        if logging.getLogger('file').handlers:
            return

        if not self.logfile:
            self.logfile = os.path.join(self.log_dir, "mojo.log")

        try:
            logFormatter = logging.Formatter(
                fmt="%(asctime)s [%(levelname)s] %(message)s",
                datefmt="%Y-%m-%d %H:%M:%S")

            rootLogger = logging.getLogger()
            fileLogger = logging.getLogger('file')
            # If we send output to the file logger specifically, don't propagate it
            # to the root logger as well to avoid duplicate output. So if we want
            # to only send logging output to the file, you would do this:
            #  logging.getLogger('file').info("message for logfile only")
            # rather than this:
            #  logging.info("message for console and logfile")
            fileLogger.propagate = False

            fileHandler = logging.FileHandler(self.logfile)
            fileHandler.setFormatter(logFormatter)
            rootLogger.addHandler(fileHandler)
            fileLogger.addHandler(fileHandler)
        except IOError:
            logging.error("Unable to write to logfile: {}".format(self.logfile))

    @property
    def build_dir(self):
        return os.path.join(self.path, "build")

    @property
    def repo_dir(self):
        return os.path.join(self.path, "charms")

    @property
    def local_dir(self):
        return os.path.join(self.path, "local")

    @property
    def log_dir(self):
        if self.logfile:
            return os.path.dirname(os.path.abspath(self.logfile))
        return os.path.join(self.path, "log")

    @property
    def spec_dir(self):
        return os.path.join(self.path, "spec")