Exemple #1
0
def test_remove():

    env = ODir('bin', push_up=True)

    a1 = env.add('A1')
    env.A1.add('A2')
    b1 = env.add('B1')
    env.B1.add('B2')

    assert hasattr(env, 'A1')
    assert hasattr(env, 'B1')
    assert hasattr(env.A1, 'A2')
    assert hasattr(env.B1, 'B2')
    assert hasattr(env, 'A2')
    assert hasattr(env, 'B2')

    env.A1.remove_parent()

    g = env.descendents()

    # Cannot access A1 from env. Can still access A2 from a1
    assert not hasattr(env, 'A1')
    assert not hasattr(env, 'A2')
    assert hasattr(a1, 'A2')

    # B1 and B2 are still exist
    assert hasattr(env, 'B1')
    assert hasattr(env.B1, 'B2')
    assert hasattr(env, 'B2')
Exemple #2
0
def test_attr():
    env = ODir('bin')
    name = 'somethigldj'
    attr = 'asldkfjlsdfj'
    env.add(name, attr=attr)
    assert hasattr(env, attr)
    assert not hasattr(env, name)
Exemple #3
0
    def __init__(self, dir, name="FishTank", meta_dir=None, meta_name=None):
        """
        SessionManager constructor

        :param dir: directory
        :type dir: str
        :param name: name of the folder
        :type name: str
        :param meta_dir: directory to store the metadata
        :type meta_dir: str
        :param meta_name: name of the file to store the metadata
        :type meta_name: str
        """
        super().__init__(name, push_up=False, check_attr=False)
        self.set_dir(dir)

        # Add metadata (has default)
        # this is where session manager information will be stored
        if meta_dir is None:
            meta_dir = self.DEFAULT_METADATA_LOC
        if meta_name is None:
            meta_name = self.DEFAULT_METADATA_NAME
        self.metadata = ODir(meta_dir)
        self.metadata.add_file(meta_name, 'env_settings')

        self._curr_session_name = None
Exemple #4
0
def test_paths():
    env = ODir('bin')
    env.add('session1')
    env.session1.add('cat1')
    env.session1.add('cat2')

    assert len(env.paths) == 4
    print(env.paths)
Exemple #5
0
def test_list_dirs():

    env = ODir('bin')
    env.add('A1').add('B1')
    env.add('C1').add("D1")

    dirs = env.list_dirs()
    assert env.A1 in dirs
    assert env.C1 in dirs
    assert not env.B1 in dirs
    assert not env.D1 in dirs
Exemple #6
0
def test_dont_sanitize_attr():
    env = ODir('bin')
    with pytest.raises(AttributeError):
        env.add('in')
    env.add('in', attr='myin')
    assert env.has('myin')
    assert not env.has('in')
Exemple #7
0
def env(tmpdir):
    tmpdir = str(tmpdir)
    env = ODir('bin')
    env.set_dir(tmpdir)
    env.add('A1')
    env.A1.add('A2')
    env.add('B1')
    env.B1.add('B2')
    return env
Exemple #8
0
def test_print_tree():
    env = ODir('bin', push_up=True)
    env.add('session1')
    env.session1.add('cat1')
    env.session1.add('cat2')
    env.add('session2')
    env.session2.add('cat1', attr="s2cat1")

    print(env._children)

    env.print()
Exemple #9
0
def a(request):
    env = ODir('bin', push_up=request.param)
    labels = ['a', 'b']

    for l1 in labels:
        env.add(l1)
        assert hasattr(env, l1)

        level = getattr(env, l1)
        for l2 in labels:

            next_level = l1 + l2
            getattr(env, l1).add(next_level)

            if request.param:
                assert hasattr(env, next_level)
            else:
                assert not hasattr(env, next_level)
            assert hasattr(level, next_level)
Exemple #10
0
def test_remove_children():

    env = ODir('bin', push_up=True)

    a1 = env.add('A1')
    env.A1.add('A2')
    b1 = env.add('B1')
    env.B1.add('B2')

    assert hasattr(env, 'A1')
    assert hasattr(env, 'B1')
    assert hasattr(env.A1, 'A2')
    assert hasattr(env.B1, 'B2')
    assert hasattr(env, 'A2')
    assert hasattr(env, 'B2')

    print(env.children.remove_parent())

    g = env.descendents()
    assert len(g) == 0
Exemple #11
0
def test_path():
    env = ODir('bin')
    env.add('session1')
    env.session1.add('cat1')
    env.session1.add('cat2')
    env.add('session2')
    env.session2.add('cat1', attr="s2cat1")

    assert str(env.path) == 'bin'
    assert str(env.s2cat1.path) == 'bin/session2/cat1'
    assert str(env.cat1.path) == 'bin/session1/cat1'
    assert str(env.cat2.path) == 'bin/session1/cat2'
Exemple #12
0
def test_list_files():

    env = ODir('bin')
    env.add('A1').add_file('afile')
    env.add('C1').add_file("dfile")
    env.add_file('efile')
    env.add_file('ffile')

    files = env.list_files()
    assert not env.A1 in files
    assert not env.afile in files
    assert not env.C1 in files
    assert not env.dfile in files

    assert env.efile in files
    assert env.ffile in files
Exemple #13
0
def test_unsanitized_attr():
    env = ODir('bin')
    assert env.add('something') == env.add('something')
    assert env.something.add('core') == env.add('something').add(
        'core') == env.something.core
    with pytest.raises(AttributeError):
        env.add('alskdf;;asd;flj')
    with pytest.raises(AttributeError):
        env.add('in')
    with pytest.raises(AttributeError):
        env.add('something', attr='somethingelse')
Exemple #14
0
class SessionManager(ODir):
    """
    Manages multiple :class:`SessionEnvironment` instances.
    SessionEnvironments live in a single directory managed by this class.
    Information about where the SessionManager directory resides is stored in
    the 'environment_data/environment_settings.json` file.
    By default, this is located where ParrotFish is installed so that is can be
    used globally on the machine.
    Alternatively, a SessionManager can be constructed that uses a new
    environement_settings file.
    The **environment_settings.json** also stores an encryption key so that
    :class:`SessionEnvironment`s can be decrypted and used properly.

    Example session structure::

        meta_dir
        └──environment_data
            └──environment_settings.json      (information about top directory)

        SessionManagerName          (Master or root directory)
        |──SessionEnvironment1      (Aquarium session)
        |   └──Category1            (Protocol Category)
        |       |──.env_pkl         (SessionEnvironment1's AqSession)
        |       |──protocols        (protocols folder)
        |       |   |──OperationType1
        |       |   |   |──OperationType1.json
        |       |   |   |──OperationType1.rb
        |       |   |   |──OperationType1__cost_model.rb
        |       |   |   |──OperationType1__documentation.rb
        |       |   |   |──OperationType1__precondition.rb
        |       |   |   └──test_data.rb
        |       |   └──LibraryType1
        |       |       |──LibraryType1.rb
        |       |       └──LibraryType1.json
        |       └──OperationType1
        └──SessionEnvironment2
            └── ...
    """

    DEFAULT_METADATA_LOC = os.path.join(
        os.path.dirname(os.path.abspath(__file__)), 'environment_data')
    DEFAULT_METADATA_NAME = 'environment_settings.json'

    def __init__(self, dir, name="FishTank", meta_dir=None, meta_name=None):
        """
        SessionManager constructor

        :param dir: directory
        :type dir: str
        :param name: name of the folder
        :type name: str
        :param meta_dir: directory to store the metadata
        :type meta_dir: str
        :param meta_name: name of the file to store the metadata
        :type meta_name: str
        """
        super().__init__(name, push_up=False, check_attr=False)
        self.set_dir(dir)

        # Add metadata (has default)
        # this is where session manager information will be stored
        if meta_dir is None:
            meta_dir = self.DEFAULT_METADATA_LOC
        if meta_name is None:
            meta_name = self.DEFAULT_METADATA_NAME
        self.metadata = ODir(meta_dir)
        self.metadata.add_file(meta_name, 'env_settings')

        self._curr_session_name = None

    def register_session(self, login, password, aquarium_url, name):
        """
        Registers a new session by creating a AqSession, creating
        a SessionEnvironment and adding it to the SessionManager
        """
        if name in self.sessions:
            logger.warning("'{}' already exists!".format(name))
            return
        key = str.encode(self.__meta['encryption_key'])
        session_env = SessionEnvironment(
            name, login, password, aquarium_url, key)
        self._add_session_env(session_env)

    def remove_session(self, name):
        """
        Removes and deletes a managed session

        :param name: name of the session to delete
        :type name: str
        :return: None
        :rtype: None
        """
        session = self.get(name)
        session.remove_parent()
        session.rmdirs()

    def _add_session_env(self, session_env):
        """Adds the session environment to the session manager"""
        self._add(session_env.name, session_env,
                  push_up=False, check_attr=False)

    @property
    def __meta(self):
        if not self.metadata.env_settings.exists():
            self.save()
        return self.metadata.env_settings.load_json()

    @property
    def current_env(self):
        """Current session environment"""
        if self._curr_session_name is None:
            return None
        return self.get(self._curr_session_name)

    @property
    def current_session(self):
        """Returns the current session"""
        if self._curr_session_name is None:
            return None
        return self.get_session(self._curr_session_name)

    def set_current(self, name):
        """Sets the current session name"""
        if name is None:
            return
        if name in self.sessions:
            self._curr_session_name = name
        else:
            logger.warning("'{}' not in sessions ({})".format(
                name, ', '.join(self.sessions.keys())))

    @property
    def session_env_list(self):
        """Return all session environments"""
        return [env for env in self.list_dirs()
                if isinstance(env, SessionEnvironment)]

    @property
    def sessions(self):
        """Returns all sessions"""
        return {env.name: env.aquarium_session
                for env in self.session_env_list}

    def get_session(self, name):
        """Gets a AqSession by name"""
        session_env = self.get(name)
        return session_env.aquarium_session

    def delete_session(self, name):
        """Deletes a session, removing the folders and files as well as the
        abstract ODir link"""
        session_env = self.get(name)
        session_env.rmdirs()
        session_env.remove_parent()

    def move_repo(self, path):
        """Move all of the folders to a new location"""
        super().mvdirs(path)
        self.save()

    def __new_encryption_key(self):
        return Fernet.generate_key()

    def save(self, force_new_key=False, key=None):
        """Save the metadata"""
        encryption_key = None
        if not self.metadata.env_settings.exists() or force_new_key:
            if key is None:
                logger.warning(
                    "No encryption key found. Generating new key...")
                encryption_key = self.__new_encryption_key().decode()
            else:
                encryption_key = key
        else:
            encryption_key = self.metadata.env_settings.load_json()[
                'encryption_key']
        self.metadata.env_settings.dump_json(
            {
                "root": str(self.abspath),
                'current': self._curr_session_name,
                "updated_at": str(datetime.datetime.now()),
                "version": __version__,
                "encryption_key": encryption_key,
                "container_id": self.get_container_id()
            },
            indent=4)
        self.save_environments()

    def load(self, meta=None):
        """Load from the metadata"""
        if meta is None:
            meta = self.__meta
        if __version__ != meta['version']:
            logger.warning("Version mismatched! Environment data stored using "
                           "ParrotFish version '{}' but currently using '{}'"
                           .format(meta['version'], __version__))

        # load encryption key from meta
        encryption_key = meta['encryption_key']
        env = self.load_environments(encryption_key)
        env.set_current(meta['current'])
        self.save()
        return env

    def save_environments(self):
        """Save all of the session environments"""
        for session_env in self.session_env_list:
            session_env.save_to_pkl()

    def update_encryption_key(self, new_key):
        """
        Updates the encryption key used to decrypt :class:`SessionEnvironment`s
        """
        old_key = self.__meta['encryption_key']
        for session_env in self.session_env_list:
            if session_env:
                session_env.update_encryption_key(old_key, new_key)

    # TODO: consolidate password hashes here
    def load_environments(self, encryption_key):
        """
        Collects the SessionEnvironment pickles and returns a SessionManager
        with these session_environments.

        For examples `dir="User/Documents/Fishtank"` would load a
        SessionManager with the name "Fishtank."
        Environments would be loaded from `User/Documents/FishTank/*/.env_pkl`
        """
        meta = self.__meta
        self.name = os.path.basename(self.metadata.env_settings.name)

        # set root path
        root_dir = os.path.dirname(meta['root'])
        root_name = os.path.basename(meta['root'])
        self.set_dir(root_dir)
        self.name = root_name

        env_pkls = glob(os.path.join(str(self.abspath),
                                     "*", SessionEnvironment.ENV_PKL))
        for env_pkl in env_pkls:
            session_env = SessionEnvironment.load_from_pkl(
                env_pkl, encryption_key)
            if session_env is not None:
                self._add_session_env(session_env)
        self.set_current(meta['current'])
        return self

    def get_container_id(self):
        try:
            with self.metadata.env_settings.open(mode='r') as f:
                settings = json.load(f)
                return settings.get('container_id', '')
        except FileNotFoundError:
            return ''

    def set_container_id(self, cid):
        with self.metadata.env_settings.open(mode='r') as f:
            settings = json.load(f)
            settings['container_id'] = cid
            self.metadata.env_settings.write(json.dumps(settings), 'w')

    def __str__(self):
        return "SessionManager(\n" \
               "  name={name}\n" \
               "  current_session={current}\n" \
               "  environment_location=\"{metadata}\"\n" \
               "  session_directory=\"{dir}\"\n" \
               "  container_id=\"{container_id}\")".format(
                   name=self.name,
                   metadata=str(self.metadata.env_settings.abspath),
                   current=self.current_session,
                   container_id=self.get_container_id(),
                   dir=str(self.abspath)
               )

    def __repr__(self):
        return "SessionManager(name={name}, env={env}".format(
            name=self.name,
            env=str(self.metadata.env_settings.abspath))
Exemple #15
0
def test_unique_attrs():
    env = ODir('bin')
    with pytest.raises(AttributeError):
        env.add('L1').add('L2')
        env.add('L1a').add('L2')
Exemple #16
0
def test_chained():

    env = ODir('bin')
    env.add('A1').add('B1')
    env.add('C1').add("D1")
Exemple #17
0
def test_resolve():
    env = ODir('bin')
    env.add('session1')
    env.session1.add('cat1')
    env.session1.add('cat2')
    print(env.paths.resolve)