Skip to content

Commit

Permalink
Build improvements (#176)
Browse files Browse the repository at this point in the history
* Cleaning up PanBase for easier setup and build purposes
	* Moving `PanBase` to its own file
* Proper version (i.e. `pocs.__version__` works)
  • Loading branch information
wtgee committed Dec 17, 2017
1 parent 3768304 commit b3ca111
Show file tree
Hide file tree
Showing 8 changed files with 178 additions and 184 deletions.
128 changes: 8 additions & 120 deletions pocs/__init__.py
Expand Up @@ -6,123 +6,11 @@
"""

from __future__ import absolute_import

import os
import sys

from warnings import warn

from .utils import config
from .utils.database import PanMongo
from .utils.logger import get_root_logger

try:
from .version import version as __version__
except ImportError: # pragma: no cover
__version__ = ''

##################################################################################################
# Private Methods
##################################################################################################


def _check_environment():
""" Checks to see if environment is set up correctly
There are a number of environmental variables that are expected
to be set in order for PANOPTES to work correctly. This method just
sanity checks our environment and shuts down otherwise.
PANDIR Base directory for PANOPTES
POCS Base directory for POCS
"""
if sys.version_info[:2] < (3, 0): # pragma: no cover
warn("POCS requires Python 3.x to run")

pandir = os.getenv('PANDIR')
if not os.path.exists(pandir):
sys.exit("$PANDIR dir does not exist or is empty: {}".format(pandir))

pocs = os.getenv('POCS')
if pocs is None: # pragma: no cover
sys.exit('Please make sure $POCS environment variable is set')

if not os.path.exists(pocs):
sys.exit("$POCS directory does not exist or is empty: {}".format(pocs))

if not os.path.exists("{}/logs".format(pandir)):
print("Creating log dir at {}/logs".format(pandir))
os.makedirs("{}/logs".format(pandir))


def _check_config(temp_config):
""" Checks the config file for mandatory items """

if 'directories' not in temp_config:
sys.exit('directories must be specified in config')

if 'mount' not in temp_config:
sys.exit('Mount must be specified in config')

if 'state_machine' not in temp_config:
sys.exit('State Table must be specified in config')


_check_environment()

# Global vars
_config = None


class PanBase(object):

""" Base class for other classes within the Pan ecosystem
Defines common properties for each class (e.g. logger, config)self.
"""

def __init__(self, *args, **kwargs):
# Load the default and local config files
global _config
if _config is None:
ignore_local_config = kwargs.get('ignore_local_config', False)
_config = config.load_config(ignore_local=ignore_local_config)

# Update with run-time config
if 'config' in kwargs:
_config.update(kwargs['config'])

_check_config(_config)
self.config = _config

self.logger = kwargs.get('logger')
if not self.logger:
self.logger = get_root_logger()

self.__version__ = __version__

if 'simulator' in kwargs:
if 'all' in kwargs['simulator']:
self.config['simulator'] = ['camera', 'mount', 'weather', 'night']
else:
self.config['simulator'] = kwargs['simulator']

# Set up connection to database
db = kwargs.get('db', self.config['db']['name'])
_db = PanMongo(db=db)

self.db = _db

def __getstate__(self): # pragma: no cover
d = dict(self.__dict__)

if 'logger' in d:
del d['logger']

if 'db' in d:
del d['db']

return d


from .core import POCS
from pocs.version import __version__
from pocs.base import PanBase
from pocs.core import POCS

__copyright__ = "Copyright (c) 2017 Project PANOPTES"
__license__ = "MIT"
__summary__ = "PANOPTES Observatory Control System"
__uri__ = "https://github.com/panoptes/POCS"
73 changes: 73 additions & 0 deletions pocs/base.py
@@ -0,0 +1,73 @@
import sys

from pocs import __version__
from pocs.utils import config
from pocs.utils.database import PanMongo
from pocs.utils.logger import get_root_logger

# Global vars
_config = None


class PanBase(object):

""" Base class for other classes within the PANOPTES ecosystem
Defines common properties for each class (e.g. logger, config).
"""

def __init__(self, *args, **kwargs):
# Load the default and local config files
global _config
if _config is None:
ignore_local_config = kwargs.get('ignore_local_config', False)
_config = config.load_config(ignore_local=ignore_local_config)

self.__version__ = __version__

# Update with run-time config
if 'config' in kwargs:
_config.update(kwargs['config'])

self._check_config(_config)
self.config = _config

self.logger = kwargs.get('logger')
if not self.logger:
self.logger = get_root_logger()
self.logger.info('{:*^80}'.format(' Starting POCS '))

if 'simulator' in kwargs:
if 'all' in kwargs['simulator']:
self.config['simulator'] = ['camera', 'mount', 'weather', 'night']
else:
self.config['simulator'] = kwargs['simulator']

# Set up connection to database
db = kwargs.get('db', self.config['db']['name'])
_db = PanMongo(db=db)

self.db = _db

def _check_config(self, temp_config):
""" Checks the config file for mandatory items """

if 'directories' not in temp_config:
sys.exit('directories must be specified in config')

if 'mount' not in temp_config:
sys.exit('Mount must be specified in config')

if 'state_machine' not in temp_config:
sys.exit('State Table must be specified in config')

def __getstate__(self): # pragma: no cover
d = dict(self.__dict__)

if 'logger' in d:
del d['logger']

if 'db' in d:
del d['db']

return d
59 changes: 46 additions & 13 deletions pocs/core.py
@@ -1,17 +1,19 @@
import os
import sys
import queue
import time
import warnings
import multiprocessing
import zmq

from multiprocessing import Process
from multiprocessing import Queue

from astropy import units as u

from . import PanBase
from .state.machine import PanStateMachine
from .utils import current_time
from .utils import get_free_space
from .utils.messaging import PanMessaging
from pocs import PanBase
from pocs.observatory import Observatory
from pocs.state.machine import PanStateMachine
from pocs.utils import current_time
from pocs.utils import get_free_space
from pocs.utils.messaging import PanMessaging


class POCS(PanStateMachine, PanBase):
Expand Down Expand Up @@ -48,6 +50,8 @@ def __init__(
# Explicitly call the base classes in the order we want
PanBase.__init__(self, **kwargs)

assert isinstance(observatory, Observatory)

self.name = self.config.get('name', 'Generic PANOPTES Unit')
self.logger.info('Initializing PANOPTES unit - {} - {}',
self.name,
Expand Down Expand Up @@ -418,6 +422,34 @@ def wait_until_safe(self):
# Private Methods
##################################################################################################

def _check_environment(self):
""" Checks to see if environment is set up correctly
There are a number of environmental variables that are expected
to be set in order for PANOPTES to work correctly. This method just
sanity checks our environment and shuts down otherwise.
PANDIR Base directory for PANOPTES
POCS Base directory for POCS
"""
if sys.version_info[:2] < (3, 0): # pragma: no cover
warnings.warn("POCS requires Python 3.x to run")

pandir = os.getenv('PANDIR')
if not os.path.exists(pandir):
sys.exit("$PANDIR dir does not exist or is empty: {}".format(pandir))

pocs = os.getenv('POCS')
if pocs is None: # pragma: no cover
sys.exit('Please make sure $POCS environment variable is set')

if not os.path.exists(pocs):
sys.exit("$POCS directory does not exist or is empty: {}".format(pocs))

if not os.path.exists("{}/logs".format(pandir)):
print("Creating log dir at {}/logs".format(pandir))
os.makedirs("{}/logs".format(pandir))

def _check_messages(self, queue_type, q):
cmd_dispatch = {
'command': {
Expand Down Expand Up @@ -464,19 +496,19 @@ def create_forwarder(port):
except Exception:
pass

cmd_forwarder_process = Process(
cmd_forwarder_process = multiprocessing.Process(
target=create_forwarder, args=(
cmd_port,), name='CmdForwarder')
cmd_forwarder_process.start()

msg_forwarder_process = Process(
msg_forwarder_process = multiprocessing.Process(
target=create_forwarder, args=(
msg_port,), name='MsgForwarder')
msg_forwarder_process.start()

self._do_cmd_check = True
self._cmd_queue = Queue()
self._sched_queue = Queue()
self._cmd_queue = multiprocessing.Queue()
self._sched_queue = multiprocessing.Queue()

self._msg_publisher = PanMessaging.create_publisher(msg_port)

Expand Down Expand Up @@ -505,7 +537,8 @@ def check_message_loop(cmd_queue):
pass

self.logger.debug('Starting command message loop')
check_messages_process = Process(target=check_message_loop, args=(self._cmd_queue,))
check_messages_process = multiprocessing.Process(
target=check_message_loop, args=(self._cmd_queue,))
check_messages_process.name = 'MessageCheckLoop'
check_messages_process.start()
self.logger.debug('Command message subscriber set up on port {}'.format(cmd_port))
Expand Down
4 changes: 2 additions & 2 deletions pocs/tests/test_observatory.py
Expand Up @@ -4,11 +4,11 @@
from astropy import units as u
from astropy.time import Time

import pocs.version
from pocs.observatory import Observatory
from pocs.scheduler.dispatch import Scheduler
from pocs.scheduler.observation import Observation
from pocs.utils import error
from pocs.version import version


@pytest.fixture
Expand Down Expand Up @@ -158,7 +158,7 @@ def test_standard_headers(observatory):

test_headers = {
'airmass': 1.091778,
'creator': 'POCSv{}'.format(version),
'creator': 'POCSv{}'.format(pocs.version.__version__),
'elevation': 3400.0,
'ha_mnt': 1.6844671878927793,
'latitude': 19.54,
Expand Down

0 comments on commit b3ca111

Please sign in to comment.