Skip to content

Commit

Permalink
Merge 7db8014 into f8c14c9
Browse files Browse the repository at this point in the history
  • Loading branch information
BradenM committed Oct 5, 2019
2 parents f8c14c9 + 7db8014 commit a2886bf
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 163 deletions.
1 change: 1 addition & 0 deletions Pipfile
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ recommonmark = "*"
pytest-watch = "*"
pytest-testmon = "*"
sphinx-click = "*"
ptvsd = "*"

[packages]
click = ">=7"
Expand Down
102 changes: 52 additions & 50 deletions micropy/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,21 @@
from questionary import Choice

import micropy.exceptions as exc
from micropy import utils
from micropy import main, utils
from micropy.logger import Log
from micropy.main import MicroPy
from micropy.project import Project

pass_mpy = click.make_pass_decorator(main.MicroPy, ensure=True)


@click.group(invoke_without_command=True)
@click.version_option()
@pass_mpy
@click.pass_context
def cli(ctx):
def cli(ctx, mpy):
"""CLI Application for creating/managing Micropython Projects."""
if ctx.invoked_subcommand is None:
proj = Project.resolve('.')
if not proj:
if not mpy.project:
return click.echo(ctx.get_help())
latest = utils.is_update_available()
if latest:
Expand Down Expand Up @@ -62,15 +63,15 @@ def stubs():
required=False,
help=("Templates to generate for project."
" Multiple options can be passed."))
def init(path, name=None, template=None):
@pass_mpy
def init(mpy, path, name=None, template=None):
"""Create new Micropython Project
\b
When creating a new project, all files will be
placed under the generated <PROJECT_NAME> folder.
"""
mp = MicroPy()
mp.log.title("Creating New Project")
mpy.log.title("Creating New Project")
if not path:
path = Path.cwd()
default_name = path.name
Expand All @@ -81,10 +82,10 @@ def init(path, name=None, template=None):
for t, val in Project.TEMPLATES.items()]
template = prompt.checkbox(
f"Choose any Templates to Generate", choices=templ_choices).ask()
stubs = [Choice(str(s), value=s) for s in mp.STUBS]
stubs = [Choice(str(s), value=s) for s in mpy.stubs]
if not stubs:
mp.log.error("You don't have any stubs!")
mp.log.title(
mpy.log.error("You don't have any stubs!")
mpy.log.title(
"To add stubs to micropy, use $[micropy stubs add <STUB_NAME>]")
sys.exit(1)
stub_choices = prompt.checkbox(
Expand All @@ -93,17 +94,18 @@ def init(path, name=None, template=None):
name=name,
templates=template,
stubs=stub_choices,
stub_manager=mp.STUBS)
stub_manager=mpy.stubs)
proj_relative = project.create()
mp.log.title(f"Created $w[{project.name}] at $w[./{proj_relative}]")
mpy.log.title(f"Created $w[{project.name}] at $w[./{proj_relative}]")


@cli.command(short_help="Install Project Requirements")
@click.argument('packages', nargs=-1)
@click.option('-d', '--dev', is_flag=True, default=False,
help=("Adds Package to dev requirements,"
" but does not install stubs for it."))
def install(packages, dev=False):
@pass_mpy
def install(mpy, packages, dev=False):
"""Install Packages as Project Requirements
\b
Expand All @@ -125,20 +127,19 @@ def install(packages, dev=False):
# main.py
import <package_name>
"""
mp = MicroPy()
project = Project.resolve('.')
project = mpy.project
if not project:
mp.log.error("You are not currently in an active project!")
mpy.log.error("You are not currently in an active project!")
sys.exit(1)
if not packages:
mp.log.title("Installing all Requirements")
mpy.log.title("Installing all Requirements")
reqs = project.add_from_requirements()
if not reqs:
mp.log.error("No requirements.txt file found!")
mpy.log.error("No requirements.txt file found!")
sys.exit(1)
mp.log.success("\nRequirements Installed!")
mpy.log.success("\nRequirements Installed!")
sys.exit(0)
mp.log.title("Installing Packages")
mpy.log.title("Installing Packages")
for pkg in packages:
project.add_package(pkg, dev=dev)

Expand All @@ -147,7 +148,8 @@ def install(packages, dev=False):
@click.argument('stub_name', required=True)
@click.option('-f', '--force', is_flag=True, default=False,
help="Overwrite Stub if it exists.")
def add(stub_name, force=False):
@pass_mpy
def add(mpy, stub_name, force=False):
"""Add Stubs from package or path
\b
Expand All @@ -164,73 +166,73 @@ def add(stub_name, force=False):
Checkout the docs on Github for more info.
"""
mp = MicroPy()
mp.STUBS.verbose_log(True)
proj = Project('.', stub_manager=mp.STUBS)
mp.log.title(f"Adding $[{stub_name}] to stubs")
mpy.stubs.verbose_log(True)
proj = Project('.', stub_manager=mpy.stubs)
mpy.log.title(f"Adding $[{stub_name}] to stubs")
try:
stub = mp.STUBS.add(stub_name, force=force)
stub = mpy.stubs.add(stub_name, force=force)
except exc.StubNotFound:
mp.log.error(f"$[{stub_name}] could not be found!")
mpy.log.error(f"$[{stub_name}] could not be found!")
sys.exit(1)
except exc.StubError:
mp.log.error(f"$[{stub_name}] is not a valid stub!")
mpy.log.error(f"$[{stub_name}] is not a valid stub!")
sys.exit(1)
else:
if proj.exists():
mp.log.title(f"Adding $[{stub.name}] to $[{proj.name}]")
mpy.log.title(f"Adding $[{stub.name}] to $[{proj.name}]")
proj.add_stub(stub)


@stubs.command()
@click.argument('query', required=True)
def search(query):
@pass_mpy
def search(mpy, query):
"""Search available Stubs"""
mp = MicroPy()
mp.log.title(f"Searching Stub Repositories...")
results = mp.STUBS.search_remote(query)
mp.log.title(f"Results for $[{query}]:")
mpy.log.title(f"Searching Stub Repositories...")
results = mpy.stubs.search_remote(query)
mpy.log.title(f"Results for $[{query}]:")
for pkg, installed in results:
name = f"{pkg} $B[(Installed)]" if installed else pkg
mp.log.info(name)
mpy.log.info(name)


@stubs.command()
def list():
@pass_mpy
def list(mpy):
"""List installed stubs"""
def print_stubs(stub_list):
for firm, stubs in stub_list:
if stubs:
title = str(firm).capitalize()
mp.log.title(f"$[{title}]:")
mpy.log.title(f"$[{title}]:")
for stub in stubs:
mp.log.info(str(stub))
mp = MicroPy()
mp.log.title("Installed Stubs:")
mp.log.info(f"Total: {len(mp.STUBS)}")
print_stubs(mp.STUBS.iter_by_firmware())
proj = Project.resolve('.', verbose=False)
mpy.log.info(str(stub))
mpy.log.title("Installed Stubs:")
mpy.log.info(f"Total: {len(mpy.stubs)}")
print_stubs(mpy.stubs.iter_by_firmware())
mpy.verbose = False
proj = mpy.resolve_project('.')
if proj:
mp.log.title(f"Stubs used in {proj.name}:")
mp.log.info(f"Total: {len(proj.stubs)}")
stubs = mp.STUBS.iter_by_firmware(stubs=proj.stubs)
mpy.log.title(f"Stubs used in {proj.name}:")
mpy.log.info(f"Total: {len(proj.stubs)}")
stubs = mpy.stubs.iter_by_firmware(stubs=proj.stubs)
print_stubs(stubs)


@stubs.command(short_help="Create Stubs from Pyboard")
@click.argument('port', required=True)
@click.option('-v', '--verbose', is_flag=True, default=False,
help="Enable verbose output")
def create(port, verbose=False):
@pass_mpy
def create(mpy, port, verbose=False):
"""Create stubs from a pyboard at <PORT>
\b
MicropyCli uses Josverl's micropython-stubber for stub creation.
For more information, please visit the repository
at: https://github.com/Josverl/micropython-stubber
"""
mp = MicroPy()
return mp.create_stubs(port, verbose=verbose)
return mpy.create_stubs(port, verbose=verbose)


if __name__ == "__main__":
Expand Down
52 changes: 39 additions & 13 deletions micropy/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,36 +9,62 @@
from micropy import data, utils
from micropy.lib.stubber import process as stubber
from micropy.logger import Log
from micropy.project import Project
from micropy.stubs import StubManager, source


class MicroPy:
"""Parent class for handling setup and variables"""
"""Handles App State Management"""
LIB = Path(__file__).parent / 'lib'
STUBBER = LIB / 'stubber'
FILES = Path.home() / '.micropy'
STUB_DIR = FILES / 'stubs'
STUBS = None

REPOS = data.PATH / 'sources.json'

def __init__(self):
self.log = Log.get_logger('MicroPy')
self.setup()
self.verbose = True
self.log.debug("\n---- MicropyCLI Session ----")
if not self.STUB_DIR.exists():
self.setup()

def setup(self):
"""creates necessary directories for micropy"""
self.log.debug("\n---- MicropyCLI Session ----")
self.log.debug("Loading stubs...")
if self.STUB_DIR.exists():
repo_list = self.REPOS.read_text()
repos = source.StubRepo.from_json(repo_list)
self.STUBS = StubManager(resource=self.STUB_DIR, repos=repos)
return self.STUBS
self.log.debug("Running first time setup...")
self.log.debug(f"Creating .micropy directory @ {self.FILES}")
self.FILES.mkdir(exist_ok=True)
self.STUB_DIR.mkdir()
return self.setup()

@utils.lazy_property
def stubs(self):
repo_list = self.REPOS.read_text()
repos = source.StubRepo.from_json(repo_list)
return StubManager(resource=self.STUB_DIR, repos=repos)

@utils.lazy_property
def project(self):
proj = self.resolve_project('.', verbose=self.verbose)
return proj

def resolve_project(self, path, verbose=True):
"""Returns project from path if it exists
Args:
path (str): Path to test
verbose (bool): Log to stdout. Defaults to True.
Returns:
(Project|None): Project if it exists
"""
path = Path(path).absolute()
proj = Project(path)
if proj.exists():
if verbose:
self.log.title(f"Loading Project")
proj.load(stub_manager=self.stubs, verbose=verbose)
return proj
return None

def create_stubs(self, port, verbose=False):
"""Create and add stubs from Pyboard
Expand Down Expand Up @@ -82,7 +108,7 @@ def create_stubs(self, port, verbose=False):
out_dir = pyb.copy_dir("/stubs", tmpdir)
stub_path = next(out_dir.iterdir())
self.log.info(f"Copied Stubs: $[{stub_path.name}]")
stub_path = self.STUBS.from_stubber(stub_path, out_dir)
stub = self.STUBS.add(stub_path)
stub_path = self.stubs.from_stubber(stub_path, out_dir)
stub = self.stubs.add(stub_path)
self.log.success(f"Added {stub.name} to stubs!")
return stub
21 changes: 0 additions & 21 deletions micropy/project/project.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
from micropy import utils
from micropy.exceptions import StubError
from micropy.logger import Log
from micropy.main import MicroPy
from micropy.project.template import TemplateProvider


Expand Down Expand Up @@ -366,23 +365,3 @@ def create(self):
self.to_json()
self.log.success(f"Project Created!")
return self.path.relative_to(Path.cwd())

@classmethod
def resolve(cls, path, verbose=True):
"""Returns project from path if it exists
Args:
path (str): Path to test
verbose (bool): Log to stdout. Defaults to True.
Returns:
(Project|None): Project if it exists
"""
path = Path(path).resolve()
proj = cls(path)
if proj.exists():
micropy = MicroPy()
if verbose:
micropy.log.title(f"Loading Project")
proj.load(stub_manager=micropy.STUBS, verbose=verbose)
return proj
6 changes: 4 additions & 2 deletions micropy/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@
MicropyCli.
"""

from . import helpers
from . import decorators, helpers
from .decorators import * # noqa
from .helpers import * # noqa
from .pybwrapper import PyboardWrapper # noqa
from .validate import Validator # noqa

__all__ = ["Validator", "PyboardWrapper"] + helpers.__all__
__all__ = (["Validator", "PyboardWrapper"] +
helpers.__all__ + decorators.__all__)
23 changes: 23 additions & 0 deletions micropy/utils/decorators.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# -*- coding: utf-8 -*-

"""
micropy.utils.decorators
~~~~~~~~~~~~~~
This module contains generic decorators
used by MicropyCli
"""

__all__ = ['lazy_property']


def lazy_property(fn):
attr = '_lazy__' + fn.__name__

@property
def _lazy_property(self):
if not hasattr(self, attr):
setattr(self, attr, fn(self))
return getattr(self, attr)

return _lazy_property
6 changes: 3 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,9 @@ def test_headers(type): return {

@pytest.fixture
def mock_mp_stubs(mock_micropy, mocker, shared_datadir):
mock_micropy.STUBS.add((shared_datadir / 'fware_test_stub'))
mock_micropy.STUBS.add((shared_datadir / 'esp8266_test_stub'))
mock_micropy.STUBS.add((shared_datadir / 'esp32_test_stub'))
mock_micropy.stubs.add((shared_datadir / 'fware_test_stub'))
mock_micropy.stubs.add((shared_datadir / 'esp8266_test_stub'))
mock_micropy.stubs.add((shared_datadir / 'esp32_test_stub'))
return mock_micropy


Expand Down

0 comments on commit a2886bf

Please sign in to comment.