Skip to content

Commit

Permalink
Integrating the depender in the manager
Browse files Browse the repository at this point in the history
  • Loading branch information
palikar committed Jun 20, 2019
1 parent 7804c4e commit c836b6e
Show file tree
Hide file tree
Showing 9 changed files with 171 additions and 99 deletions.
2 changes: 1 addition & 1 deletion .pylintrc
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ max-branches=20

[FORMAT]
max-line-length = 120
disable=locally-disabled,locally-enabled,missing-docstring,duplicate-code,fixme,cyclic-import,redefined-variable-type,stop-iteration-return, R1705, E1136, W0613
disable=locally-disabled,locally-enabled,missing-docstring,duplicate-code,fixme,cyclic-import,redefined-variable-type,stop-iteration-return, R1705, E1136, W0613, R0902

[TYPECHECK]

4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ help:
@echo 'make snapshot: Create a tar.gz of the current git revision'
@echo 'make pypi_sdist: Release a new sdist to PyPI'

test: test_pylint test_flake8 test_pylint
test: test_pylint test_flake8 test_pytest
@echo "All test ran..."

test_pylint:
Expand All @@ -54,7 +54,7 @@ test_flake8:
@echo "Running flake8..."
flake8 $(TEST_PATHS)

test_pylint:
test_pytest:
@echo "Running pylint..."
pytest

Expand Down
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
Build status: [![Build Status](https://travis-ci.org/palikar/code_manager.svg?branch=master)](https://travis-ci.org/palikar/code_manager)
Build status:
[![Build Status](https://travis-ci.org/palikar/code_manager.svg?branch=master)](https://travis-ci.org/palikar/code_manager)
[![Build Status](https://pyup.io/repos/github/palikar/code_manager/shield.svg)](https://pyup.io/repos/github/palikar/code_manager)
[![Build Status](https://pyup.io/repos/github/palikar/code_manager/python-3-shield.svg)](https://pyup.io/repos/github/palikar/code_manager/)
[![Coverage Status](https://coveralls.io/repos/github/palikar/code_manager/badge.svg?branch=master)](https://coveralls.io/github/palikar/code_manager?branch=master)


# Code Manager

![img](https://travis-ci.org/palikar/code_manager.svg?branch=master) ![img](https://pyup.io/repos/github/palikar/code_manager/shield.svg) ![img](https://pyup.io/repos/github/palikar/code_manager/python-3-shield.svg) ![img](https://coveralls.io/repos/github/palikar/code_manager/badge.svg?branch=master)


## Abstract

Expand Down
14 changes: 9 additions & 5 deletions README.org
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,19 @@
#+CREATOR: Emacs 26.1 (Org mode 9.1.13)



#+BEGIN_EXAMPLE
Build status:
[![Build Status](https://travis-ci.org/palikar/code_manager.svg?branch=master)](https://travis-ci.org/palikar/code_manager)
[![Build Status](https://pyup.io/repos/github/palikar/code_manager/shield.svg)](https://pyup.io/repos/github/palikar/code_manager)
[![Build Status](https://pyup.io/repos/github/palikar/code_manager/python-3-shield.svg)](https://pyup.io/repos/github/palikar/code_manager/)
[![Coverage Status](https://coveralls.io/repos/github/palikar/code_manager/badge.svg?branch=master)](https://coveralls.io/github/palikar/code_manager?branch=master)
#+END_EXAMPLE

* Code Manager

![[https://travis-ci.org/palikar/code_manager.svg?branch=master][img]]
![[https://pyup.io/repos/github/palikar/code_manager/shield.svg][img]]
![[https://pyup.io/repos/github/palikar/code_manager/python-3-shield.svg][img]]
![[https://coveralls.io/repos/github/palikar/code_manager/badge.svg?branch=master][img]]

** Abstract

This is my personal tool now for managing my github repositories, some system software that I use and pretty much everything that can be downloaded, compiled locally and then installed on a Debian based Linux system. Through this utility one can quickly download and install random things from all over the internet. I've always wanted some small program that would allow me to quickly bring my github repositories on my local machine so I end it up writing this in my spare time. The program is focused on automation but also on flexibility in the installation process. A lot of software is compiled and installed in some standard way but there are also things that are a little bit trickier. The utility - named appropriately ~code_manager~ - aims to provide a unified interface for the installation process of all types of software -- the trickier kind included.


Expand All @@ -33,6 +36,7 @@ Currently the project is not on [[https://pypi.org/][PyPi]] so you have to clone
** Installation

The installation from source is possible through this repository.

#+BEGIN_SRC sh
git clone https://github.com/palikar/code_manager
cd code_manager
Expand Down
29 changes: 18 additions & 11 deletions code_manager/core/debgrapher.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ def get_packages(self, group=""): # pylint: disable=R1705

def verify_package_list(self, package_names):
all_packs = set(flatten(self.packages_list.values()))
print(all_packs)
for pack in package_names:
if pack not in all_packs:
logging.info("The package %s is not\
in the list with packags.", pack)
in the list with packags.", pack)
logging.info("Did you mean any of the following: %s",
",".join(difflib.get_close_matches(pack, all_packs, 5)))
exit(1)
Expand All @@ -39,32 +38,40 @@ def verify_packages_tree(self):
all_packs_list = set(flatten(self.packages_list.values()))
all_packs_nodes = set(self.packages.keys()) # pylint: disable=E1101

broken = []
# Every package is in a group
for pack in all_packs_nodes:
if pack not in all_packs_list:
logging.critical("Incosistant packages file!\
The package %s is not in any group", pack)
exit(1)
broken.append(pack)

if broken:
logging.critical("Inconsistent packages file!\
The packages [%s] are not in any group", ','.join(broken))
exit(1)

broken = []
# Every package in a group is in the nodes
for pack in all_packs_list:
if pack not in all_packs_nodes:
logging.critical("Incosistant packages file!\
The package %s does not have node", pack)
exit(1)
broken.append(pack)

if broken:
logging.critical("Incosistant packages file!\
The packages [%s] do not have node", ','.join(broken))
exit(1)

# Every dependency is in the packages.json
for pack in all_packs_nodes:
for deb in self.get_dependencies(pack):
if deb not in all_packs_nodes:
logging.critical("%s is dependency\
of %s but it is not in the packages.json", deb, pack)
of %s but it is not in the packages.json", deb, pack)
exit(1)

def get_dependencies(self, package):
if package not in self.packages.keys(): # pylint: disable=E1101
logging.critical("The package %s\
is not in the packages.json.", package) # pylint: disable=E1136
is not in the packages.json.", package) # pylint: disable=E1136
exit(1)
if 'dependencies' in self.packages[package].keys():
return self.packages[package]['dependencies'] # pylint: disable=E1136
Expand Down Expand Up @@ -102,7 +109,7 @@ def get_build_order(self, packages):
available = [pack for pack, deps in sub_tree.items() if not deps]
if not available:
logging.critical('Build order cannot be generated.\
The packages tree is maybe broken.')
The packages tree is maybe broken.')
exit(1)
for pack in available:
build_order.append(pack)
Expand Down
33 changes: 27 additions & 6 deletions code_manager/core/installation.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,28 +76,49 @@ def _add_installer(self, installer, file):
def run_installer(self, name, installer):

if installer not in self.installers.keys():
logging.critical('There is no installer with the name %s', name)
logging.critical('There is no installer with the name %s', installer)

if installer not in self.installer_objects.keys():
installer_obj = self.installers[installer]()
self.installer_objects[installer] = installer_obj
else:
installer_obj = self.installer_objects[installer]

node = self.packages()[name]
node = self.packages[name]
installer_obj.node = node

if hasattr(installer_obj, 'manditory_attr') and isinstance(installer_obj.manditory_attr, list):
for attr in installer_obj.manditory_attr:
if attr not in node.keys():
logging.critical('The attribute %s is mandatory for the installer %s\
but it is not in the package node.',
attr, installer_obj.name)
but it is not in the package node of %s.',
attr, installer_obj.name, name)

result = installer_obj.execute(name)

if result > 0:
logging.critical('The installer %s failed to execute properly', installer_obj.nam)
if result is None:
logging.critical('The installer [%s] failed to execute properly', installer_obj.name)

def install(self, package):
assert package is not None
node = self.packages[package]

if 'install' not in node.keys():
return 0

installer = node['install']
if isinstance(installer, str):
self.run_installer(package, installer)
return 0
elif isinstance(installer, list):
for inst in installer:
self.run_installer(package, inst)
return 0
else:
logging.critical('Can\'t install %s.\
Installation node is nor a list, nor a string.', package)
exit(1)
return None


# class Installer:
Expand Down
119 changes: 74 additions & 45 deletions code_manager/core/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
from code_manager.core.debgrapher import DebGrapher
from code_manager.core.cache_container import CacheContainer
from code_manager.utils.utils import flatten
from code_manager.utils.logger import debug_red


class Manager(ConfigurationAware):
Expand All @@ -30,52 +29,82 @@ def __init__(self):
def _setup_all(self):
self.installation.load_installer()
self.cache.load_cache()
self.depender.verify_packages_tree()

def _invoke(self):
pass
logging.info('Invoking installation with: %s',
','.join(self.install_queue))
logging.info('Steps configuration:')
logging.info('\tInstall:%s', self.install)
logging.info('\tBuild:%s', self.build)
logging.info('\tFetching:%s', self.fetching)

self.depender.verify_package_list(self.install_queue)

if self.install:
self._invoke_install()

if self.fetching:
self._invoke_fetch()

if self.fetching:
self._invoke_build()

def _invoke_fetch(self):
for pack in self.install_queue:
with self.cache as cache:

if not cache.is_fetched(pack):
if self.fetcher.download(pack, pack) is None:
logging.critical("The fetching of '%s' failed.", pack)
cache.set_fetched(pack, True)
else:
logging.info("\'%s\' is already fetched", pack)

def _invoke_build(self):
pass

def _invoke_install(self):
pass

def fetch_package(self, package):
with self.cache as cache:
if cache.is_fetched(package):
debug_red("The package '%s' is already fetched", package)
return None
if self.fetcher.download(package, package) is None:
debug_red("The fetching of '%s' failed.", package)
return None
else:
cache.set_fetched(package, True)
cache.set_root(package, package)
return 0

def fetch_group(self, group):
for pack in self.packages_list[group]:
self.fetch_package(pack)

def fetch_thing(self, thing):
if thing in self.packages_list.keys():
logging.info("'%s' is a group. Fetching all packages in it.", thing)
self.fetch_group(thing)
elif thing in flatten(self.packages_list.values()):
logging.info("'%s' is a package. Fetching it.", thing)
self.fetch_package(thing)
else:
logging.info("There is no thing with name '%s'", thing)

def fetch(self, thing):
if isinstance(thing, list):
for thingy in thing:
self.fetch_thing(thingy)
elif isinstance(thing, str):
self.fetch_thing(thing)
else:
logging.critical("Can't install %s. It's \
no string nor list", thing)
extended_queue = set(self.install_queue)
for pack in self.install_queue:
extended_queue.update(self.depender.get_deep_dependencies(pack))
logging.debug('Extended queue: %s', ','.join(extended_queue))

ordered_packages = self.depender.get_build_order(list(extended_queue))
logging.debug('Build order: %s', ','.join(ordered_packages))

self._check_install_nodes(ordered_packages)

for pack in ordered_packages:
with self.cache as cache:

if not cache.is_fetched(pack):
if self.fetcher.download(pack, pack) is None:
logging.critical("The fetching of '%s' failed.", pack)
cache.set_fetched(pack, True)
else:
logging.info("\'%s\' is already fetched", pack)

if not cache.is_installed(pack):
if self.installation.install(pack) == 0:
logging.info("\'%s\' was installed", pack)
cache.set_installed(pack, True)
else:
logging.info("\'%s\' is already installed", pack)
# TODO: Update\Build the package here

cache.set_built(pack, True)

def _check_install_nodes(self, packages):
for pack in packages:
pack_node = self.packages[pack]
if 'install' not in pack_node.keys():
continue
installer = pack_node['install']
if not isinstance(installer, str) and not isinstance(installer, list):
logging.critical('Can\'t install %s.\
Installation node is nor a list, nor a string.', pack)
exit(1)

def _install_thing(self, thing):

Expand All @@ -90,16 +119,16 @@ def _install_thing(self, thing):
self.install_queue.append(thing)

else:
logging.critical("There is no thing with name %s", thing)
self.install_queue.append(thing)

def install_thing(self, thing, install=True, fetch=False, build=False):
if install:
self.install = True
self.fetching = True
self.build = True
self.fetching = False
self.build = False
elif build:
self.install = False
self.fetching = True
self.fetching = False
self.build = True
elif fetch:
self.install = False
Expand All @@ -113,5 +142,5 @@ def install_thing(self, thing, install=True, fetch=False, build=False):
self._install_thing(thing)

if self.install_queue:
self._setup_all()
# self._setup_all()
self._invoke()
4 changes: 2 additions & 2 deletions code_manager/installers/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ def __init__(self):
BasicInstaller.__init__(self)

def execute(self, name):
pass
return 0

def update(self, name):
pass
return 0


ExportedClass = CommandInstaller
Loading

0 comments on commit c836b6e

Please sign in to comment.