<commit_before>#!/usr/bin/env python
# encoding: utf-8

"""
    jrnl

    license: MIT, see LICENSE for more details.
"""

import Journal
import exporters
import install
import os
import tempfile
import subprocess
import argparse
import sys
try: import simplejson as json
except ImportError: import json

__title__ = 'jrnl'
__version__ = '0.3.2'
__author__ = 'Manuel Ebert, Stephan Gabler'
__license__ = 'MIT'

CONFIG_PATH = os.path.expanduser('~/.jrnl_config')
PYCRYPTO = install.module_exists("Crypto")

def parse_args():
    parser = argparse.ArgumentParser()
    composing = parser.add_argument_group('Composing', 'Will make an entry out of whatever follows as arguments')
    composing.add_argument('-date', dest='date', help='Date, e.g. "yesterday at 5pm"')
    composing.add_argument('text', metavar='text', nargs="*",  help='Log entry (or tags by which to filter in viewing mode)')

    reading = parser.add_argument_group('Reading', 'Specifying either of these parameters will display posts of your journal')
    reading.add_argument('-from', dest='start_date', metavar="DATE", help='View entries after this date')
    reading.add_argument('-to', dest='end_date', metavar="DATE", help='View entries before this date')
    reading.add_argument('-and', dest='strict', action="store_true", help='Filter by tags using AND (default: OR)')
    reading.add_argument('-n', dest='limit', default=None, metavar="N", help='Shows the last n entries matching the filter', nargs="?", type=int)
    reading.add_argument('-short', dest='short', action="store_true", help='Show only titles or line containing the search tags')

    exporting = parser.add_argument_group('Export / Import', 'Options for transmogrifying your journal')
    exporting.add_argument('--tags', dest='tags', action="store_true", help='Returns a list of all tags and number of occurences')
    exporting.add_argument('--json', dest='json', action="store_true", help='Returns a JSON-encoded version of the Journal')
    exporting.add_argument('--markdown', dest='markdown', action="store_true", help='Returns a Markdown-formated version of the Journal')
    exporting.add_argument('--encrypt',  metavar='FILENAME', dest='encrypt', help='Encrypts your existing journal with a new password', nargs='?', default=False, const=None)
    exporting.add_argument('--decrypt',  metavar='FILENAME', dest='decrypt', help='Decrypts your journal and stores it in plain text', nargs='?', default=False, const=None)
    exporting.add_argument('--delete-last', dest='delete_last', help='Deletes the last entry from your journal file.', action="store_true")

    return parser.parse_args()

def guess_mode(args, config):
    """Guesses the mode (compose, read or export) from the given arguments"""
    compose = True
    export = False
    print args
    if args.json or args.decrypt is not False or args.encrypt is not False or args.markdown or args.tags or args.delete_last:
        compose = False
        export = True
    elif args.start_date or args.end_date or args.limit or args.strict or args.short:
        # Any sign of displaying stuff?
        compose = False
    elif not args.date and args.text and all(word[0] in config['tagsymbols'] for word in " ".join(args.text).split()):
        # No date and only tags?
        compose = False

    return compose, export

def get_text_from_editor(config):
    tmpfile = os.path.join(tempfile.gettempdir(), "jrnl")
    subprocess.call(config['editor'].split() + [tmpfile])
    if os.path.exists(tmpfile):
        with open(tmpfile) as f:
            raw = f.read()
        os.remove(tmpfile)
    else:
        print('[Nothing saved to file]')
        raw = ''

    return raw

def encrypt(journal, filename=None):
    """ Encrypt into new file. If filename is not set, we encrypt the journal file itself. """
    journal.config['password'] = ""
    journal.make_key(prompt="Enter new password:")
    journal.config['encrypt'] = True
    journal.write(filename)
    print("Journal encrypted to {}.".format(filename or journal.config['journal']))

def decrypt(journal, filename=None):
    """ Decrypts into new file. If filename is not set, we encrypt the journal file itself. """
    journal.config['encrypt'] = False
    journal.config['password'] = ""
    journal.write(filename)
    print("Journal decrypted to {}.".format(filename or journal.config['journal']))

def print_tags(journal):
        """Prints a list of all tags and the number of occurances."""
        # Astute reader: should the following line leave you as puzzled as me the first time
        # I came across this construction, worry not and embrace the ensuing moment of enlightment.
        tags = [tag
            for entry in journal.entries
            for tag in set(entry.tags)
        ]
        # To be read: [for entry in journal.entries: for tag in set(entry.tags): tag]
        tag_counts = {(tags.count(tag), tag) for tag in tags}
        for n, tag in sorted(tag_counts, reverse=True):
            print("{:20} : {}".format(tag, n))

def touch_journal(filename):
    """If filename does not exist, touch the file"""
    if not os.path.exists(filename):
        print("[Journal created at {}]".format(filename))
        open(filename, 'a').close()

def update_config(config, new_config, scope):
    """Updates a config dict with new values - either global if scope is None
    of config['journals'][scope] is just a string pointing to a journal file,
    or within the scope"""
    if scope and type(config['journals'][scope]) is dict: # Update to journal specific
        config['journals'][scope].update(new_config)
    else:
        config.update(new_config)

def cli():
    if not os.path.exists(CONFIG_PATH):
        config = install.install_jrnl(CONFIG_PATH)
    else:
        with open(CONFIG_PATH) as f:
            config = json.load(f)
        install.update_config(config, config_path=CONFIG_PATH)

    original_config = config.copy()
    # check if the configuration is supported by available modules
    if config['encrypt'] and not PYCRYPTO:
        print("According to your jrnl_conf, your journal is encrypted, however PyCrypto was not found. To open your journal, install the PyCrypto package from http://www.pycrypto.org.")
        sys.exit(-1)

    args = parse_args()

    # If the first textual argument points to a journal file,
    # use this!
    journal_name = args.text[0] if (args.text and args.text[0] in config['journals']) else 'default'
    if journal_name is not 'default':
        args.text = args.text[1:]
    journal_conf = config['journals'].get(journal_name)
    if type(journal_conf) is dict: # We can override the default config on a by-journal basis
        config.update(journal_conf)
    else: # But also just give them a string to point to the journal file
        config['journal'] = journal_conf
    touch_journal(config['journal'])
    mode_compose, mode_export = guess_mode(args, config)

    # open journal file
    journal = Journal.Journal(**config)
    if mode_compose and not args.text:
        if config['editor']:
            raw = get_text_from_editor(config)
        else:
            raw = raw_input("[Compose Entry] ")
        if raw:
            args.text = [raw]
        else:
            mode_compose = False

    # Writing mode
    if mode_compose:
        raw = " ".join(args.text).strip()
        journal.new_entry(raw, args.date)
        print("[Entry added to {} journal]").format(journal_name)
        journal.write()

    # Reading mode
    elif not mode_export:
        journal.filter(tags=args.text,
                       start_date=args.start_date, end_date=args.end_date,
                       strict=args.strict,
                       short=args.short)
        journal.limit(args.limit)
        print(journal)

    # Various export modes
    elif args.tags:
        print_tags(journal)

    elif args.json: # export to json
        print(exporters.to_json(journal))

    elif args.markdown: # export to json
        print(exporters.to_md(journal))

    elif (args.encrypt is not False or args.decrypt is not False) and not PYCRYPTO:
        print("PyCrypto not found. To encrypt or decrypt your journal, install the PyCrypto package from http://www.pycrypto.org.")

    elif args.encrypt is not False:
        encrypt(journal, filename=args.encrypt)
        # Not encrypting to a separate file: update config!
        if not args.encrypt:
            update_config(original_config, {"encrypt": True, "password": ""}, journal_name)
            install.save_config(original_config, config_path=CONFIG_PATH)

    elif args.decrypt is not False:
        decrypt(journal, filename=args.decrypt)
        # Not decrypting to a separate file: update config!
        if not args.decrypt:
            update_config(original_config, {"encrypt": False, "password": ""}, journal_name)
            install.save_config(original_config, config_path=CONFIG_PATH)

    elif args.delete_last:
        last_entry = journal.entries.pop()
        print("[Deleted Entry:]")
        print(last_entry)
        journal.write()

if __name__ == "__main__":
    cli()

 <commit_msg>bump to 1.0.0-rc1<commit_after>#!/usr/bin/env python
# encoding: utf-8

"""
    jrnl

    license: MIT, see LICENSE for more details.
"""

import Journal
import exporters
import install
import os
import tempfile
import subprocess
import argparse
import sys
try: import simplejson as json
except ImportError: import json

__title__ = 'jrnl'
__version__ = '1.0.0-rc1'
__author__ = 'Manuel Ebert, Stephan Gabler'
__license__ = 'MIT'

CONFIG_PATH = os.path.expanduser('~/.jrnl_config')
PYCRYPTO = install.module_exists("Crypto")

def parse_args():
    parser = argparse.ArgumentParser()
    composing = parser.add_argument_group('Composing', 'Will make an entry out of whatever follows as arguments')
    composing.add_argument('-date', dest='date', help='Date, e.g. "yesterday at 5pm"')
    composing.add_argument('text', metavar='text', nargs="*",  help='Log entry (or tags by which to filter in viewing mode)')

    reading = parser.add_argument_group('Reading', 'Specifying either of these parameters will display posts of your journal')
    reading.add_argument('-from', dest='start_date', metavar="DATE", help='View entries after this date')
    reading.add_argument('-to', dest='end_date', metavar="DATE", help='View entries before this date')
    reading.add_argument('-and', dest='strict', action="store_true", help='Filter by tags using AND (default: OR)')
    reading.add_argument('-n', dest='limit', default=None, metavar="N", help='Shows the last n entries matching the filter', nargs="?", type=int)
    reading.add_argument('-short', dest='short', action="store_true", help='Show only titles or line containing the search tags')

    exporting = parser.add_argument_group('Export / Import', 'Options for transmogrifying your journal')
    exporting.add_argument('--tags', dest='tags', action="store_true", help='Returns a list of all tags and number of occurences')
    exporting.add_argument('--json', dest='json', action="store_true", help='Returns a JSON-encoded version of the Journal')
    exporting.add_argument('--markdown', dest='markdown', action="store_true", help='Returns a Markdown-formated version of the Journal')
    exporting.add_argument('--encrypt',  metavar='FILENAME', dest='encrypt', help='Encrypts your existing journal with a new password', nargs='?', default=False, const=None)
    exporting.add_argument('--decrypt',  metavar='FILENAME', dest='decrypt', help='Decrypts your journal and stores it in plain text', nargs='?', default=False, const=None)
    exporting.add_argument('--delete-last', dest='delete_last', help='Deletes the last entry from your journal file.', action="store_true")

    return parser.parse_args()

def guess_mode(args, config):
    """Guesses the mode (compose, read or export) from the given arguments"""
    compose = True
    export = False
    print args
    if args.json or args.decrypt is not False or args.encrypt is not False or args.markdown or args.tags or args.delete_last:
        compose = False
        export = True
    elif args.start_date or args.end_date or args.limit or args.strict or args.short:
        # Any sign of displaying stuff?
        compose = False
    elif not args.date and args.text and all(word[0] in config['tagsymbols'] for word in " ".join(args.text).split()):
        # No date and only tags?
        compose = False

    return compose, export

def get_text_from_editor(config):
    tmpfile = os.path.join(tempfile.gettempdir(), "jrnl")
    subprocess.call(config['editor'].split() + [tmpfile])
    if os.path.exists(tmpfile):
        with open(tmpfile) as f:
            raw = f.read()
        os.remove(tmpfile)
    else:
        print('[Nothing saved to file]')
        raw = ''

    return raw

def encrypt(journal, filename=None):
    """ Encrypt into new file. If filename is not set, we encrypt the journal file itself. """
    journal.config['password'] = ""
    journal.make_key(prompt="Enter new password:")
    journal.config['encrypt'] = True
    journal.write(filename)
    print("Journal encrypted to {}.".format(filename or journal.config['journal']))

def decrypt(journal, filename=None):
    """ Decrypts into new file. If filename is not set, we encrypt the journal file itself. """
    journal.config['encrypt'] = False
    journal.config['password'] = ""
    journal.write(filename)
    print("Journal decrypted to {}.".format(filename or journal.config['journal']))

def print_tags(journal):
        """Prints a list of all tags and the number of occurances."""
        # Astute reader: should the following line leave you as puzzled as me the first time
        # I came across this construction, worry not and embrace the ensuing moment of enlightment.
        tags = [tag
            for entry in journal.entries
            for tag in set(entry.tags)
        ]
        # To be read: [for entry in journal.entries: for tag in set(entry.tags): tag]
        tag_counts = {(tags.count(tag), tag) for tag in tags}
        for n, tag in sorted(tag_counts, reverse=True):
            print("{:20} : {}".format(tag, n))

def touch_journal(filename):
    """If filename does not exist, touch the file"""
    if not os.path.exists(filename):
        print("[Journal created at {}]".format(filename))
        open(filename, 'a').close()

def update_config(config, new_config, scope):
    """Updates a config dict with new values - either global if scope is None
    of config['journals'][scope] is just a string pointing to a journal file,
    or within the scope"""
    if scope and type(config['journals'][scope]) is dict: # Update to journal specific
        config['journals'][scope].update(new_config)
    else:
        config.update(new_config)

def cli():
    if not os.path.exists(CONFIG_PATH):
        config = install.install_jrnl(CONFIG_PATH)
    else:
        with open(CONFIG_PATH) as f:
            config = json.load(f)
        install.update_config(config, config_path=CONFIG_PATH)

    original_config = config.copy()
    # check if the configuration is supported by available modules
    if config['encrypt'] and not PYCRYPTO:
        print("According to your jrnl_conf, your journal is encrypted, however PyCrypto was not found. To open your journal, install the PyCrypto package from http://www.pycrypto.org.")
        sys.exit(-1)

    args = parse_args()

    # If the first textual argument points to a journal file,
    # use this!
    journal_name = args.text[0] if (args.text and args.text[0] in config['journals']) else 'default'
    if journal_name is not 'default':
        args.text = args.text[1:]
    journal_conf = config['journals'].get(journal_name)
    if type(journal_conf) is dict: # We can override the default config on a by-journal basis
        config.update(journal_conf)
    else: # But also just give them a string to point to the journal file
        config['journal'] = journal_conf
    touch_journal(config['journal'])
    mode_compose, mode_export = guess_mode(args, config)

    # open journal file
    journal = Journal.Journal(**config)
    if mode_compose and not args.text:
        if config['editor']:
            raw = get_text_from_editor(config)
        else:
            raw = raw_input("[Compose Entry] ")
        if raw:
            args.text = [raw]
        else:
            mode_compose = False

    # Writing mode
    if mode_compose:
        raw = " ".join(args.text).strip()
        journal.new_entry(raw, args.date)
        print("[Entry added to {} journal]").format(journal_name)
        journal.write()

    # Reading mode
    elif not mode_export:
        journal.filter(tags=args.text,
                       start_date=args.start_date, end_date=args.end_date,
                       strict=args.strict,
                       short=args.short)
        journal.limit(args.limit)
        print(journal)

    # Various export modes
    elif args.tags:
        print_tags(journal)

    elif args.json: # export to json
        print(exporters.to_json(journal))

    elif args.markdown: # export to json
        print(exporters.to_md(journal))

    elif (args.encrypt is not False or args.decrypt is not False) and not PYCRYPTO:
        print("PyCrypto not found. To encrypt or decrypt your journal, install the PyCrypto package from http://www.pycrypto.org.")

    elif args.encrypt is not False:
        encrypt(journal, filename=args.encrypt)
        # Not encrypting to a separate file: update config!
        if not args.encrypt:
            update_config(original_config, {"encrypt": True, "password": ""}, journal_name)
            install.save_config(original_config, config_path=CONFIG_PATH)

    elif args.decrypt is not False:
        decrypt(journal, filename=args.decrypt)
        # Not decrypting to a separate file: update config!
        if not args.decrypt:
            update_config(original_config, {"encrypt": False, "password": ""}, journal_name)
            install.save_config(original_config, config_path=CONFIG_PATH)

    elif args.delete_last:
        last_entry = journal.entries.pop()
        print("[Deleted Entry:]")
        print(last_entry)
        journal.write()

if __name__ == "__main__":
    cli()

 <|endoftext|>


<commit_before># unit tests for Binding Energy database taken from AME 2016.

import os

from pyreaclib.nucdata import BindingTable

class TestAME(object):
    @classmethod
    def setup_class(cls):
        """ this is run once for each class before any tests """
        pass

    @classmethod
    def teardown_class(cls):
        """ this is run once for each class after all tests """
        pass

    def setup_method(self):
        """ this is run before each test """
        self.bintable = BindingTable()

    def teardown_method(self):
        """ this is run after each test """
        self.bintable = None

    def test_get(self):
        nuc = self.bintable.get_nuclide(n=1, z=1)
        assert nuc.z == 1
        assert nuc.n == 1
        assert nuc.nucbind == 1.112283

<commit_msg>Add some more binding energy table tests.<commit_after># unit tests for Binding Energy database taken from AME 2016.

import os

from pyreaclib.nucdata import BindingTable

class TestAME(object):
    @classmethod
    def setup_class(cls):
        """ this is run once for each class before any tests """
        pass

    @classmethod
    def teardown_class(cls):
        """ this is run once for each class after all tests """
        pass

    def setup_method(self):
        """ this is run before each test """
        self.bintable = BindingTable()

    def teardown_method(self):
        """ this is run after each test """
        self.bintable = None

    def test_get(self):
        nuc = self.bintable.get_nuclide(n=1, z=1)
        assert nuc.z == 1
        assert nuc.n == 1
        assert nuc.nucbind == 1.112283

        nuc = self.bintable.get_nuclide(n=5, z=6)
        assert nuc.z == 6
        assert nuc.n == 5
        assert nuc.nucbind == 6.676456

        nuc = self.bintable.get_nuclide(n=17, z=23)
        assert nuc.z == 23
        assert nuc.n == 17
        assert nuc.nucbind == 7.317

        nuc = self.bintable.get_nuclide(n=90, z=78)
        assert nuc.z == 78
        assert nuc.n == 90
        assert nuc.nucbind == 7.773605
<|endoftext|>


<commit_before>##############################################################################
#
# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
#                    Fabien Pinckaers <fp@tiny.Be>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

import ir_sequence
import ir_ui_menu
import ir_ui_view
import ir_actions
import ir_default
import ir_model
import ir_report_custom
import ir_attachment
import ir_cron
import ir_values
import ir_translation
import ir_exports
import workflow
import ir_board
<commit_msg>Dashboard for project users and managers Statistics and planning module on analytic account Statistics on timesheets<commit_after>##############################################################################
#
# Copyright (c) 2004 TINY SPRL. (http://tiny.be) All Rights Reserved.
#                    Fabien Pinckaers <fp@tiny.Be>
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
#
##############################################################################

import ir_sequence
import ir_ui_menu
import ir_ui_view
import ir_actions
import ir_default
import ir_model
import ir_report_custom
import ir_attachment
import ir_cron
import ir_values
import ir_translation
import ir_exports
import workflow
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
#
# Copyright (C) 2005 Edgewall Software
# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://projects.edgewall.com/trac/.
#
# Author: Christopher Lenz <cmlenz@gmx.de>

from heapq import heappop, heappush

from trac.config import Option
from trac.core import *
from trac.perm import PermissionError

class IRepositoryConnector(Interface):
    """Extension point interface for components that provide support for a
    specific version control system."""

    def get_supported_types():
        """Return the types of version control systems that are supported by
        this connector, and their relative priorities.

        Highest number is highest priority.
        """

    def get_repository(repos_type, repos_dir, authname):
        """Return the Repository object for the given repository type and
        directory.
        """

class RepositoryManager(Component):
    """Component that keeps track of the supported version control systems, and
    provides easy access to the configured implementation."""

    connectors = ExtensionPoint(IRepositoryConnector)

    repository_type = Option('trac', 'repository_type', 'svn',
        """Repository connector type. (''since 0.10'')""")
    repository_dir = Option('trac', 'repository_dir', '',
        """Path to local repository""")

    def __init__(self):
        self._connector = None

    # Public API methods

    def get_repository(self, authname):
        if not self._connector:
            candidates = []
            for connector in self.connectors:
                for repos_type_, prio in connector.get_supported_types():
                    if self.repository_type != repos_type_:
                        continue
                    heappush(candidates, (-prio, connector))
            if not candidates:
                raise TracError, 'Unsupported version control system "%s"' \
                                 % self.repository_type
            self._connector = heappop(candidates)[1]
        return self._connector.get_repository(self.repository_type,
                                              self.repository_dir, authname)

class NoSuchChangeset(TracError):
    def __init__(self, rev):
        TracError.__init__(self, "No changeset %s in the repository" % rev)

class NoSuchNode(TracError):
    def __init__(self, path, rev, msg=None):
        TracError.__init__(self, "%sNo node %s at revision %s" \
                           % (msg and '%s: ' % msg or '', path, rev))

class Repository(object):
    """
    Base class for a repository provided by a version control system.
    """

    def __init__(self, name, authz, log):
        self.name = name
        self.authz = authz or Authorizer()
        self.log = log

    def close(self):
        """
        Close the connection to the repository.
        """
        raise NotImplementedError

    def get_changeset(self, rev):
        """
        Retrieve a Changeset object that describes the changes made in
        revision 'rev'.
        """
        raise NotImplementedError

    def get_changesets(self, start, stop):
        """
        Generate Changeset belonging to the given time period (start, stop).
        """
        rev = self.youngest_rev
        while rev:
            if self.authz.has_permission_for_changeset(rev):
                chgset = self.get_changeset(rev)
                if chgset.date < start:
                    return
                if chgset.date < stop:
                    yield chgset
            rev = self.previous_rev(rev)

    def has_node(self, path, rev=None):
        """
        Tell if there's a node at the specified (path,rev) combination.

        When `rev` is `None`, the latest revision is implied.
        """
        try:
            self.get_node(path, rev)
            return True
        except TracError:
            return False

    def get_node(self, path, rev=None):
        """
        Retrieve a Node (directory or file) from the repository at the
        given path. If the rev parameter is specified, the version of the
        node at that revision is returned, otherwise the latest version
        of the node is returned.
        """
        raise NotImplementedError

    def get_oldest_rev(self):
        """
        Return the oldest revision stored in the repository.
        """
        raise NotImplementedError
    oldest_rev = property(lambda x: x.get_oldest_rev())

    def get_youngest_rev(self):
        """
        Return the youngest revision in the repository.
        """
        raise NotImplementedError
    youngest_rev = property(lambda x: x.get_youngest_rev())

    def previous_rev(self, rev):
        """
        Return the revision immediately preceding the specified revision.
        """
        raise NotImplementedError

    def next_rev(self, rev, path=''):
        """
        Return the revision immediately following the specified revision.
        """
        raise NotImplementedError

    def rev_older_than(self, rev1, rev2):
        """
        Return True if rev1 is older than rev2, i.e. if rev1 comes before rev2
        in the revision sequence.
        """
        raise NotImplementedError

    def get_youngest_rev_in_cache(self, db):
        """
        Return the youngest revision currently cached.
        The way revisions are sequenced is version control specific.
        By default, one assumes that the revisions are sequenced in time.
        """
        cursor = db.cursor()
        cursor.execute("SELECT rev FROM revision ORDER BY time DESC LIMIT 1")
        row = cursor.fetchone()
        return row and row[0] or None

    def get_path_history(self, path, rev=None, limit=None):
        """
        Retrieve all the revisions containing this path (no newer than 'rev').
        The result format should be the same as the one of Node.get_history()
        """
        raise NotImplementedError

    def normalize_path(self, path):
        """
        Return a canonical representation of path in the repos.
        """
        return NotImplementedError

    def normalize_rev(self, rev):
        """
        Return a canonical representation of a revision in the repos.
        'None' is a valid revision value and represents the youngest revision.
        """
        return NotImplementedError

    def short_rev(self, rev):
        """
        Return a compact representation of a revision in the repos.
        """
        return self.normalize_rev(rev)

    def get_changes(self, old_path, old_rev, new_path, new_rev,
                    ignore_ancestry=1):
        """
        Generator that yields change tuples (old_node, new_node, kind, change)
        for each node change between the two arbitrary (path,rev) pairs.

        The old_node is assumed to be None when the change is an ADD,
        the new_node is assumed to be None when the change is a DELETE.
        """
        raise NotImplementedError

class Node(object):
    """
    Represents a directory or file in the repository.
    """

    DIRECTORY = "dir"
    FILE = "file"

    def __init__(self, path, rev, kind):
        assert kind in (Node.DIRECTORY, Node.FILE), "Unknown node kind %s" % kind
        self.path = unicode(path)
        self.rev = rev
        self.kind = kind

    def get_content(self):
        """
        Return a stream for reading the content of the node. This method
        will return None for directories. The returned object should provide
        a read([len]) function.
        """
        raise NotImplementedError

    def get_entries(self):
        """
        Generator that yields the immediate child entries of a directory, in no
        particular order. If the node is a file, this method returns None.
        """
        raise NotImplementedError

    def get_history(self, limit=None):
        """
        Generator that yields (path, rev, chg) tuples, one for each revision in which
        the node was changed. This generator will follow copies and moves of a
        node (if the underlying version control system supports that), which
        will be indicated by the first element of the tuple (i.e. the path)
        changing.
        Starts with an entry for the current revision.
        """
        raise NotImplementedError

    def get_previous(self):
        """
        Return the (path, rev, chg) tuple corresponding to the previous
        revision for that node.
        """
        skip = True
        for p in self.get_history(2):
            if skip:
                skip = False
            else:
                return p

    def get_properties(self):
        """
        Returns a dictionary containing the properties (meta-data) of the node.
        The set of properties depends on the version control system.
        """
        raise NotImplementedError

    def get_content_length(self):
        raise NotImplementedError
    content_length = property(lambda x: x.get_content_length())

    def get_content_type(self):
        raise NotImplementedError
    content_type = property(lambda x: x.get_content_type())

    def get_name(self):
        return self.path.split('/')[-1]
    name = property(lambda x: x.get_name())

    def get_last_modified(self):
        raise NotImplementedError
    last_modified = property(lambda x: x.get_last_modified())

    isdir = property(lambda x: x.kind == Node.DIRECTORY)
    isfile = property(lambda x: x.kind == Node.FILE)

class Changeset(object):
    """
    Represents a set of changes of a repository.
    """

    ADD = 'add'
    COPY = 'copy'
    DELETE = 'delete'
    EDIT = 'edit'
    MOVE = 'move'

    def __init__(self, rev, message, author, date):
        self.rev = rev
        self.message = message
        self.author = author
        self.date = date

    def get_properties(self):
        """Generator that provide additional metadata for this changeset.

        Each additional property is a 4 element tuple:
         * `name` is the name of the property,
         * `text` its value
         * `wikiflag` indicates whether the `text` should be interpreted as
            wiki text or not
         * `htmlclass` enables to attach special formatting to the displayed
            property, e.g. `'author'`, `'time'`, `'message'` or `'changeset'`.
        """

    def get_changes(self):
        """
        Generator that produces a (path, kind, change, base_rev, base_path)
        tuple for every change in the changeset, where change can be one of
        Changeset.ADD, Changeset.COPY, Changeset.DELETE, Changeset.EDIT or
        Changeset.MOVE, and kind is one of Node.FILE or Node.DIRECTORY.
        """
        raise NotImplementedError

class PermissionDenied(PermissionError):
    """
    Exception raised by an authorizer if the user has insufficient permissions
    to view a specific part of the repository.
    """
    def __str__(self):
        return self.action

class Authorizer(object):
    """
    Base class for authorizers that are responsible to granting or denying
    access to view certain parts of a repository.
    """

    def assert_permission(self, path):
        if not self.has_permission(path):
            raise PermissionDenied, \
                  'Insufficient permissions to access %s' % path

    def assert_permission_for_changeset(self, rev):
        if not self.has_permission_for_changeset(rev):
            raise PermissionDenied, \
                  'Insufficient permissions to access changeset %s' % rev

    def has_permission(self, path):
        return True

    def has_permission_for_changeset(self, rev):
        return True
<commit_msg>Small documentation fix for the `Changeset.get_changes` method.<commit_after># -*- coding: utf-8 -*-
#
# Copyright (C) 2005 Edgewall Software
# Copyright (C) 2005 Christopher Lenz <cmlenz@gmx.de>
# All rights reserved.
#
# This software is licensed as described in the file COPYING, which
# you should have received as part of this distribution. The terms
# are also available at http://trac.edgewall.com/license.html.
#
# This software consists of voluntary contributions made by many
# individuals. For the exact contribution history, see the revision
# history and logs, available at http://projects.edgewall.com/trac/.
#
# Author: Christopher Lenz <cmlenz@gmx.de>

from heapq import heappop, heappush

from trac.config import Option
from trac.core import *
from trac.perm import PermissionError

class IRepositoryConnector(Interface):
    """Extension point interface for components that provide support for a
    specific version control system."""

    def get_supported_types():
        """Return the types of version control systems that are supported by
        this connector, and their relative priorities.

        Highest number is highest priority.
        """

    def get_repository(repos_type, repos_dir, authname):
        """Return the Repository object for the given repository type and
        directory.
        """

class RepositoryManager(Component):
    """Component that keeps track of the supported version control systems, and
    provides easy access to the configured implementation."""

    connectors = ExtensionPoint(IRepositoryConnector)

    repository_type = Option('trac', 'repository_type', 'svn',
        """Repository connector type. (''since 0.10'')""")
    repository_dir = Option('trac', 'repository_dir', '',
        """Path to local repository""")

    def __init__(self):
        self._connector = None

    # Public API methods

    def get_repository(self, authname):
        if not self._connector:
            candidates = []
            for connector in self.connectors:
                for repos_type_, prio in connector.get_supported_types():
                    if self.repository_type != repos_type_:
                        continue
                    heappush(candidates, (-prio, connector))
            if not candidates:
                raise TracError, 'Unsupported version control system "%s"' \
                                 % self.repository_type
            self._connector = heappop(candidates)[1]
        return self._connector.get_repository(self.repository_type,
                                              self.repository_dir, authname)

class NoSuchChangeset(TracError):
    def __init__(self, rev):
        TracError.__init__(self, "No changeset %s in the repository" % rev)

class NoSuchNode(TracError):
    def __init__(self, path, rev, msg=None):
        TracError.__init__(self, "%sNo node %s at revision %s" \
                           % (msg and '%s: ' % msg or '', path, rev))

class Repository(object):
    """
    Base class for a repository provided by a version control system.
    """

    def __init__(self, name, authz, log):
        self.name = name
        self.authz = authz or Authorizer()
        self.log = log

    def close(self):
        """
        Close the connection to the repository.
        """
        raise NotImplementedError

    def get_changeset(self, rev):
        """
        Retrieve a Changeset object that describes the changes made in
        revision 'rev'.
        """
        raise NotImplementedError

    def get_changesets(self, start, stop):
        """
        Generate Changeset belonging to the given time period (start, stop).
        """
        rev = self.youngest_rev
        while rev:
            if self.authz.has_permission_for_changeset(rev):
                chgset = self.get_changeset(rev)
                if chgset.date < start:
                    return
                if chgset.date < stop:
                    yield chgset
            rev = self.previous_rev(rev)

    def has_node(self, path, rev=None):
        """
        Tell if there's a node at the specified (path,rev) combination.

        When `rev` is `None`, the latest revision is implied.
        """
        try:
            self.get_node(path, rev)
            return True
        except TracError:
            return False

    def get_node(self, path, rev=None):
        """
        Retrieve a Node (directory or file) from the repository at the
        given path. If the rev parameter is specified, the version of the
        node at that revision is returned, otherwise the latest version
        of the node is returned.
        """
        raise NotImplementedError

    def get_oldest_rev(self):
        """
        Return the oldest revision stored in the repository.
        """
        raise NotImplementedError
    oldest_rev = property(lambda x: x.get_oldest_rev())

    def get_youngest_rev(self):
        """
        Return the youngest revision in the repository.
        """
        raise NotImplementedError
    youngest_rev = property(lambda x: x.get_youngest_rev())

    def previous_rev(self, rev):
        """
        Return the revision immediately preceding the specified revision.
        """
        raise NotImplementedError

    def next_rev(self, rev, path=''):
        """
        Return the revision immediately following the specified revision.
        """
        raise NotImplementedError

    def rev_older_than(self, rev1, rev2):
        """
        Return True if rev1 is older than rev2, i.e. if rev1 comes before rev2
        in the revision sequence.
        """
        raise NotImplementedError

    def get_youngest_rev_in_cache(self, db):
        """
        Return the youngest revision currently cached.
        The way revisions are sequenced is version control specific.
        By default, one assumes that the revisions are sequenced in time.
        """
        cursor = db.cursor()
        cursor.execute("SELECT rev FROM revision ORDER BY time DESC LIMIT 1")
        row = cursor.fetchone()
        return row and row[0] or None

    def get_path_history(self, path, rev=None, limit=None):
        """
        Retrieve all the revisions containing this path (no newer than 'rev').
        The result format should be the same as the one of Node.get_history()
        """
        raise NotImplementedError

    def normalize_path(self, path):
        """
        Return a canonical representation of path in the repos.
        """
        return NotImplementedError

    def normalize_rev(self, rev):
        """
        Return a canonical representation of a revision in the repos.
        'None' is a valid revision value and represents the youngest revision.
        """
        return NotImplementedError

    def short_rev(self, rev):
        """
        Return a compact representation of a revision in the repos.
        """
        return self.normalize_rev(rev)

    def get_changes(self, old_path, old_rev, new_path, new_rev,
                    ignore_ancestry=1):
        """
        Generator that yields change tuples (old_node, new_node, kind, change)
        for each node change between the two arbitrary (path,rev) pairs.

        The old_node is assumed to be None when the change is an ADD,
        the new_node is assumed to be None when the change is a DELETE.
        """
        raise NotImplementedError

class Node(object):
    """
    Represents a directory or file in the repository.
    """

    DIRECTORY = "dir"
    FILE = "file"

    def __init__(self, path, rev, kind):
        assert kind in (Node.DIRECTORY, Node.FILE), "Unknown node kind %s" % kind
        self.path = unicode(path)
        self.rev = rev
        self.kind = kind

    def get_content(self):
        """
        Return a stream for reading the content of the node. This method
        will return None for directories. The returned object should provide
        a read([len]) function.
        """
        raise NotImplementedError

    def get_entries(self):
        """
        Generator that yields the immediate child entries of a directory, in no
        particular order. If the node is a file, this method returns None.
        """
        raise NotImplementedError

    def get_history(self, limit=None):
        """
        Generator that yields (path, rev, chg) tuples, one for each revision in which
        the node was changed. This generator will follow copies and moves of a
        node (if the underlying version control system supports that), which
        will be indicated by the first element of the tuple (i.e. the path)
        changing.
        Starts with an entry for the current revision.
        """
        raise NotImplementedError

    def get_previous(self):
        """
        Return the (path, rev, chg) tuple corresponding to the previous
        revision for that node.
        """
        skip = True
        for p in self.get_history(2):
            if skip:
                skip = False
            else:
                return p

    def get_properties(self):
        """
        Returns a dictionary containing the properties (meta-data) of the node.
        The set of properties depends on the version control system.
        """
        raise NotImplementedError

    def get_content_length(self):
        raise NotImplementedError
    content_length = property(lambda x: x.get_content_length())

    def get_content_type(self):
        raise NotImplementedError
    content_type = property(lambda x: x.get_content_type())

    def get_name(self):
        return self.path.split('/')[-1]
    name = property(lambda x: x.get_name())

    def get_last_modified(self):
        raise NotImplementedError
    last_modified = property(lambda x: x.get_last_modified())

    isdir = property(lambda x: x.kind == Node.DIRECTORY)
    isfile = property(lambda x: x.kind == Node.FILE)

class Changeset(object):
    """
    Represents a set of changes of a repository.
    """

    ADD = 'add'
    COPY = 'copy'
    DELETE = 'delete'
    EDIT = 'edit'
    MOVE = 'move'

    def __init__(self, rev, message, author, date):
        self.rev = rev
        self.message = message
        self.author = author
        self.date = date

    def get_properties(self):
        """Generator that provide additional metadata for this changeset.

        Each additional property is a 4 element tuple:
         * `name` is the name of the property,
         * `text` its value
         * `wikiflag` indicates whether the `text` should be interpreted as
            wiki text or not
         * `htmlclass` enables to attach special formatting to the displayed
            property, e.g. `'author'`, `'time'`, `'message'` or `'changeset'`.
        """

    def get_changes(self):
        """
        Generator that produces a (path, kind, change, base_path, base_rev)
        tuple for every change in the changeset, where change can be one of
        Changeset.ADD, Changeset.COPY, Changeset.DELETE, Changeset.EDIT or
        Changeset.MOVE, and kind is one of Node.FILE or Node.DIRECTORY.
        """
        raise NotImplementedError

class PermissionDenied(PermissionError):
    """
    Exception raised by an authorizer if the user has insufficient permissions
    to view a specific part of the repository.
    """
    def __str__(self):
        return self.action

class Authorizer(object):
    """
    Base class for authorizers that are responsible to granting or denying
    access to view certain parts of a repository.
    """

    def assert_permission(self, path):
        if not self.has_permission(path):
            raise PermissionDenied, \
                  'Insufficient permissions to access %s' % path

    def assert_permission_for_changeset(self, rev):
        if not self.has_permission_for_changeset(rev):
            raise PermissionDenied, \
                  'Insufficient permissions to access changeset %s' % rev

    def has_permission(self, path):
        return True

    def has_permission_for_changeset(self, rev):
        return True
<|endoftext|>


<commit_before>from typing import Optional, Union

import aioredis
from aioworkers.core.base import (
    AbstractConnector, AbstractNestedEntity, LoggingEntity
)
from aioworkers.core.formatter import FormattedEntity

class Connector(
    AbstractNestedEntity,
    AbstractConnector,
    FormattedEntity,
    LoggingEntity,
):
    def __init__(self, *args, **kwargs):
        self._joiner: str = ':'
        self._prefix: str = ''
        self._connector: Optional[Connector] = None
        self._pool: Optional[aioredis.Redis] = None
        super().__init__(*args, **kwargs)

    def set_config(self, config):
        self._joiner = config.get('joiner', ':')
        self._prefix = config.get('prefix', '')
        cfg = config.new_parent(logger='aioworkers_redis')
        super().set_config(cfg)

    @property
    def pool(self) -> aioredis.Redis:
        connector = self._connector or self._get_connector()
        assert connector._pool is not None, 'Pool not ready'
        return connector._pool

    def _get_connector(self) -> 'Connector':
        cfg = self.config.get('connection')
        if isinstance(cfg, str):
            self.logger.debug('Connect to %s', cfg)
            self._connector = self.context.get_object(cfg)
            assert self._connector is not None, 'Not found reference %s' % cfg
        else:
            self._connector = self
        return self._connector

    async def init(self):
        await super().init()
        for k, child in self._children.items():
            if isinstance(child, Connector):
                child._connector = self._connector

    def factory(self, item, config=None):
        if item not in self._children:
            inst = super().factory(item, config)
            if isinstance(inst, Connector):
                inst._connector = self._connector
                inst._joiner = self._joiner
                inst._formatter = self._formatter
                inst._prefix = self.raw_key(item)
        else:
            inst = self._children[item]
        return inst

    def raw_key(self, key: str) -> str:
        k = [i for i in (self._prefix, key) if i]
        return self._joiner.join(k)

    def clean_key(self, raw_key: Union[str, bytes]) -> str:
        result = raw_key[len(self._prefix) + len(self._joiner):]
        if isinstance(result, str):
            return result
        return result.decode()

    def acquire(self):
        return AsyncConnectionContextManager(self._connector)

    async def connect(self):
        connector = self._connector or self._get_connector()
        if connector is not self:
            return

        cfg = self.config.get('connection')

        c = self
        while True:
            if c._connector is not c:
                c = c._connector
            else:
                if self.config.get('connect'):
                    self._connector = self
                    cfg = c.config.get('connection')
                break
        self._pool = await self.pool_factory(cfg or {})

    async def pool_factory(self, cfg: dict) -> Optional[aioredis.Redis]:
        address = cfg.pop('host', 'localhost'), cfg.pop('port', 6379)
        self.logger.debug('Create pool with address %s', address)
        return await aioredis.create_redis_pool(
            address, **cfg, loop=self.loop,
        )

    async def disconnect(self):
        pool = self._pool
        if pool is not None:
            self.logger.debug('Close pool')
            pool.close()
            await pool.wait_closed()

    def decode(self, b):
        if b is not None:
            return super().decode(b)

    def encode(self, b):
        if b is not None:
            return super().encode(b)

    async def __aenter__(self):
        await self.connect()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.disconnect()

class AsyncConnectionContextManager:
    __slots__ = ('_connector',)

    def __init__(self, connector: Connector):
        self._connector: Connector = connector

    async def __aenter__(self):
        return self._connector.pool

    async def __aexit__(self, exc_type, exc_value, tb):
        pass
<commit_msg>fix connect<commit_after>from typing import Optional, Union

import aioredis
from aioworkers.core.base import (
    AbstractConnector, AbstractNestedEntity, LoggingEntity
)
from aioworkers.core.formatter import FormattedEntity

class Connector(
    AbstractNestedEntity,
    AbstractConnector,
    FormattedEntity,
    LoggingEntity,
):
    def __init__(self, *args, **kwargs):
        self._joiner: str = ':'
        self._prefix: str = ''
        self._connector: Optional[Connector] = None
        self._pool: Optional[aioredis.Redis] = None
        super().__init__(*args, **kwargs)

    def set_config(self, config):
        self._joiner = config.get('joiner', ':')
        self._prefix = config.get('prefix', '')
        cfg = config.new_parent(logger='aioworkers_redis')
        super().set_config(cfg)

    @property
    def pool(self) -> aioredis.Redis:
        connector = self._connector or self._get_connector()
        assert connector._pool is not None, 'Pool not ready'
        return connector._pool

    def _get_connector(self) -> 'Connector':
        cfg = self.config.get('connection')
        if isinstance(cfg, str):
            self.logger.debug('Connect to %s', cfg)
            self._connector = self.context.get_object(cfg)
            assert self._connector is not None, 'Not found reference %s' % cfg
        else:
            self._connector = self
        return self._connector

    async def init(self):
        await super().init()
        for k, child in self._children.items():
            if isinstance(child, Connector):
                child._connector = self._connector

    def factory(self, item, config=None):
        if item not in self._children:
            inst = super().factory(item, config)
            if isinstance(inst, Connector):
                inst._connector = self._connector
                inst._joiner = self._joiner
                inst._formatter = self._formatter
                inst._prefix = self.raw_key(item)
        else:
            inst = self._children[item]
        return inst

    def raw_key(self, key: str) -> str:
        k = [i for i in (self._prefix, key) if i]
        return self._joiner.join(k)

    def clean_key(self, raw_key: Union[str, bytes]) -> str:
        result = raw_key[len(self._prefix) + len(self._joiner):]
        if isinstance(result, str):
            return result
        return result.decode()

    def acquire(self):
        return AsyncConnectionContextManager(self._connector)

    async def connect(self):
        connector = self._connector or self._get_connector()
        if connector is not self:
            return

        cfg = self.config.get('connection')

        c = self
        while True:
            if c._connector is not c:
                c = c._connector
            else:
                if self.config.get('connect'):
                    self._connector = self
                    cfg = c.config.get('connection')
                break
        if cfg:
            cfg = dict(cfg)
        else:
            cfg = {}
        self._pool = await self.pool_factory(cfg)

    async def pool_factory(self, cfg: dict) -> Optional[aioredis.Redis]:
        address = cfg.pop('host', 'localhost'), cfg.pop('port', 6379)
        self.logger.debug('Create pool with address %s', address)
        return await aioredis.create_redis_pool(
            address, **cfg, loop=self.loop,
        )

    async def disconnect(self):
        pool = self._pool
        if pool is not None:
            self.logger.debug('Close pool')
            pool.close()
            await pool.wait_closed()

    def decode(self, b):
        if b is not None:
            return super().decode(b)

    def encode(self, b):
        if b is not None:
            return super().encode(b)

    async def __aenter__(self):
        await self.connect()
        return self

    async def __aexit__(self, exc_type, exc_val, exc_tb):
        await self.disconnect()

class AsyncConnectionContextManager:
    __slots__ = ('_connector',)

    def __init__(self, connector: Connector):
        self._connector: Connector = connector

    async def __aenter__(self):
        return self._connector.pool

    async def __aexit__(self, exc_type, exc_value, tb):
        pass
<|endoftext|>


<commit_before>'''Test .NET autoapi domain'''

import unittest
import time
from contextlib import nested

from mock import patch

from autoapi.domains import dotnet

class DomainTests(unittest.TestCase):

    def test_config(self):
        '''Sphinx app config'''

        class _config(object):
            autoapi_dir = '/tmp/autoapi/tmp'
            autoapi_root = '/tmp/autoapi/root'

        class _application(object):
            config = _config()

        dom = dotnet.DotNetDomain(_application())
        self.assertEqual(dom.get_config('autoapi_dir'), '/tmp/autoapi/tmp')
        self.assertEqual(dom.get_config('autoapi_dir'), '/tmp/autoapi/tmp')

    def test_create_class(self):
        '''Test .NET class instance creation helper'''
        dom = dotnet.DotNetDomain({})
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Namespace'})
        self.assertIsInstance(cls, dotnet.DotNetNamespace)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Class'})
        self.assertIsInstance(cls, dotnet.DotNetClass)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Property'})
        self.assertIsInstance(cls, dotnet.DotNetProperty)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Method'})
        self.assertIsInstance(cls, dotnet.DotNetMethod)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Enum'})
        self.assertIsInstance(cls, dotnet.DotNetEnum)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Constructor'})
        self.assertIsInstance(cls, dotnet.DotNetConstructor)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Struct'})
        self.assertIsInstance(cls, dotnet.DotNetStruct)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Interface'})
        self.assertIsInstance(cls, dotnet.DotNetInterface)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Delegate'})
        self.assertIsInstance(cls, dotnet.DotNetDelegate)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Field'})
        self.assertIsInstance(cls, dotnet.DotNetField)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Event'})
        self.assertIsInstance(cls, dotnet.DotNetEvent)

    def test_create_class_with_children(self):
        dom = dotnet.DotNetDomain({})
        cls = dom.create_class({'id': 'Foo.Bar',
                                'type': 'Class',
                                'items': [
                                    {'id': 'Foo.Bar.Baz',
                                     'type': 'Method'}
                                ]})
        self.assertIsInstance(cls, dotnet.DotNetClass)
        self.assertDictEqual(cls.item_map, {})

    def test_get_objects(self):
        '''Test basic get objects'''
        objs = []

        def _mock_find(self):
            return ['foo', 'bar']

        def _mock_read(self, path):
            return {'id': 'Foo.Bar', 'type': 'Class', 'summary': path}

        def _mock_add(self, obj):
            objs.append(obj)

        def _mock_config(self, key):
            return 'foo'

        with nested(
                patch('autoapi.domains.dotnet.DotNetDomain.find_files', _mock_find),
                patch('autoapi.domains.dotnet.DotNetDomain.read_file', _mock_read),
                patch('autoapi.domains.dotnet.DotNetDomain.add_object', _mock_add),
                patch('autoapi.domains.dotnet.DotNetDomain.get_config', _mock_config),
                ):
            dom = dotnet.DotNetDomain({})
            dom.get_objects()
            self.assertEqual(len(objs), 2)
            self.assertEqual(objs[0].id, 'Foo.Bar')
            self.assertEqual(objs[0].summary, 'foo/foo')
            self.assertEqual(objs[1].id, 'Foo.Bar')
            self.assertEqual(objs[1].summary, 'foo/bar')
<commit_msg>Update dotnet domain tests for latest data structures<commit_after>'''Test .NET autoapi domain'''

import unittest
import time
from contextlib import nested

from mock import patch

from autoapi.domains import dotnet

class DomainTests(unittest.TestCase):

    def test_config(self):
        '''Sphinx app config'''

        class _config(object):
            autoapi_dir = '/tmp/autoapi/tmp'
            autoapi_root = '/tmp/autoapi/root'

        class _application(object):
            config = _config()

        dom = dotnet.DotNetDomain(_application())
        self.assertEqual(dom.get_config('autoapi_dir'), '/tmp/autoapi/tmp')
        self.assertEqual(dom.get_config('autoapi_dir'), '/tmp/autoapi/tmp')

    def test_create_class(self):
        '''Test .NET class instance creation helper'''
        dom = dotnet.DotNetDomain({})
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Namespace'})
        self.assertIsInstance(cls, dotnet.DotNetNamespace)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Class'})
        self.assertIsInstance(cls, dotnet.DotNetClass)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Property'})
        self.assertIsInstance(cls, dotnet.DotNetProperty)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Method'})
        self.assertIsInstance(cls, dotnet.DotNetMethod)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Enum'})
        self.assertIsInstance(cls, dotnet.DotNetEnum)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Constructor'})
        self.assertIsInstance(cls, dotnet.DotNetConstructor)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Struct'})
        self.assertIsInstance(cls, dotnet.DotNetStruct)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Interface'})
        self.assertIsInstance(cls, dotnet.DotNetInterface)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Delegate'})
        self.assertIsInstance(cls, dotnet.DotNetDelegate)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Field'})
        self.assertIsInstance(cls, dotnet.DotNetField)
        cls = dom.create_class({'id': 'Foo.Bar', 'type': 'Event'})
        self.assertIsInstance(cls, dotnet.DotNetEvent)

    def test_create_class_with_children(self):
        dom = dotnet.DotNetDomain({})
        cls = dom.create_class({'id': 'Foo.Bar',
                                'type': 'Class',
                                'items': [
                                    {'id': 'Foo.Bar.Baz',
                                     'type': 'Method'}
                                ]})
        self.assertIsInstance(cls, dotnet.DotNetClass)
        self.assertDictEqual(cls.item_map, {})

    def test_get_objects(self):
        '''Test basic get objects'''
        objs = []

        def _mock_find(self, pattern):
            return {'items': ['foo', 'bar']}

        def _mock_read(self, path):
            return {'items': [{'id': 'Foo.Bar', 'name': 'Foo', 'type': 'property'},
                              {'id': 'Foo.Bar2', 'name': 'Bar', 'type': 'property'}],
                    'id': 'Foo.Bar', 'type': 'Class', 'summary': path}

        def _mock_add(self, obj):
            objs.append(obj)

        def _mock_config(self, key):
            return 'foo'

        with nested(
                patch('autoapi.domains.dotnet.DotNetDomain.find_files', _mock_find),
                patch('autoapi.domains.dotnet.DotNetDomain.read_file', _mock_read),
                patch('autoapi.domains.dotnet.DotNetDomain.get_config', _mock_config),
                ):
            dom = dotnet.DotNetDomain({})
            dom.get_objects('*')
            objs = dom.objects
            self.assertEqual(len(objs), 2)
            self.assertEqual(objs['Foo.Bar'].id, 'Foo.Bar')
            self.assertEqual(objs['Foo.Bar'].name, 'Foo.Bar')
            self.assertEqual(objs['Foo.Bar2'].id, 'Foo.Bar2')
            self.assertEqual(objs['Foo.Bar2'].name, 'Foo.Bar2')
<|endoftext|>


<commit_before>from __future__ import unicode_literals

from os.path import dirname

from pipeline.conf import settings
from pipeline.compilers import SubProcessCompiler

class SASSCompiler(SubProcessCompiler):
    output_extension = 'css'

    def match_file(self, filename):
        return filename.endswith(('.scss', '.sass'))

    def compile_file(self, infile, outfile, outdated=False, force=False):
        command = "%s %s %s:%s" % (
            settings.PIPELINE_SASS_BINARY,
            settings.PIPELINE_SASS_ARGUMENTS,
            infile,
            outfile
        )
        return self.execute_command(command, cwd=dirname(infile))
<commit_msg>Make the SASS compiler compatible with libsass-python<commit_after>from __future__ import unicode_literals

from os.path import dirname

from pipeline.conf import settings
from pipeline.compilers import SubProcessCompiler

class SASSCompiler(SubProcessCompiler):
    output_extension = 'css'

    def match_file(self, filename):
        return filename.endswith(('.scss', '.sass'))

    def compile_file(self, infile, outfile, outdated=False, force=False):
        command = "%s %s %s %s" % (
            settings.PIPELINE_SASS_BINARY,
            settings.PIPELINE_SASS_ARGUMENTS,
            infile,
            outfile
        )
        return self.execute_command(command, cwd=dirname(infile))
<|endoftext|>


<commit_before>#!/usr/bin/env python

# Standard packages
import sys
import argparse

# Third-party packages
from toil.job import Job

# Package methods
from ddb import configuration
from ddb_ngsflow import gatk
from ddb_ngsflow import pipeline
from ddb_ngsflow.rna import star
from ddb_ngsflow.rna import bowtie
from ddb_ngsflow.rna import cufflinks

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-s', '--samples_file', help="Input configuration file for samples")
    parser.add_argument('-c', '--configuration', help="Configuration file for various settings")
    Job.Runner.addToilOptions(parser)
    args = parser.parse_args()
    args.logLevel = "INFO"

    sys.stdout.write("Parsing configuration data\n")
    config = configuration.configure_runtime(args.configuration)

    sys.stdout.write("Parsing sample data\n")
    samples = configuration.configure_samples(args.samples_file, config)

    # Workflow Graph definition. The following workflow definition should create a valid Directed Acyclic Graph (DAG)
    root_job = Job.wrapJobFn(pipeline.spawn_batch_jobs, cores=1)

    # Per sample jobs
    for sample in samples:
        # Alignment and Refinement Stages
        flags = ("local", "unstranded", "removeNonCanonical", "2-stage", "cufflinks")

        align_job = Job.wrapJobFn(star.star_unpaired, config, sample, samples, flags,
                                  cores=int(config['star']['num_cores']),
                                  memory="{}G".format(config['star']['max_mem']))

        samples[sample]['star'] = "{}.star.Aligned.sortedByCoord.out.bam".format(sample)
        samples[sample]['unmapped_fastq'] = "{}.star.Unmapped.out.mate1".format(sample)

        # bowtie_job = Job.wrapJobFn(bowtie.bowtie_unpaired, config, sample, samples, flags,
        #                            cores=int(config['bowtie']['num_cores']),
        #                            memory="{}G".format(config['bowtie']['max_mem']))

        input_bams = list()
        input_bams.append(samples[sample]['star'])
        input_bams.append(samples[sample]['bowtie'])

        merge_job = Job.wrapFn(gatk.merge_sam, config, sample, input_bams,
                               cores=int(config['picard-merge']['num_cores']),
                               memory="{}G".format(config['picard-merge']['max_mem']))

        cufflinks_job = Job.wrapFn(cufflinks.cufflinks, config, sample, merge_job.rv(),
                                   cores=int(config['cufflinks']['num_cores']),
                                   memory="{}G".format(config['cufflinks']['max_mem']))

        # Create workflow from created jobs
        root_job.addChild(align_job)
        # align_job.addChild(bowtie_job)
        # bowtie_job.addChild(merge_job)
        align_job.addChild(merge_job)
        merge_job.addChild(cufflinks_job)

    cuffmerge_job = Job.wrapJobFn(cufflinks.cuffmerge, config, "blah", samples,
                                  cores=int(config['cuffmerge']['num_cores']),
                                  memory="{}G".format(config['cuffmerge']['max_mem']))

    root_job.addFollowOn(cuffmerge_job)

    for sample in samples:
        cuffquant_job = Job.wrapJobFn(cufflinks.cuffquant, config, sample, samples,
                                      cores=int(config['cuffquant']['num_cores']),
                                      memory="{}G".format(config['cuffquant']['max_mem']))
        cuffmerge_job.addChild(cuffquant_job)

    # Start workflow execution
    Job.Runner.startToil(root_job, args)
<commit_msg>bug fix in method wrapper function calls<commit_after>#!/usr/bin/env python

# Standard packages
import sys
import argparse

# Third-party packages
from toil.job import Job

# Package methods
from ddb import configuration
from ddb_ngsflow import gatk
from ddb_ngsflow import pipeline
from ddb_ngsflow.rna import star
from ddb_ngsflow.rna import bowtie
from ddb_ngsflow.rna import cufflinks

if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument('-s', '--samples_file', help="Input configuration file for samples")
    parser.add_argument('-c', '--configuration', help="Configuration file for various settings")
    Job.Runner.addToilOptions(parser)
    args = parser.parse_args()
    args.logLevel = "INFO"

    sys.stdout.write("Parsing configuration data\n")
    config = configuration.configure_runtime(args.configuration)

    sys.stdout.write("Parsing sample data\n")
    samples = configuration.configure_samples(args.samples_file, config)

    # Workflow Graph definition. The following workflow definition should create a valid Directed Acyclic Graph (DAG)
    root_job = Job.wrapJobFn(pipeline.spawn_batch_jobs, cores=1)

    # Per sample jobs
    for sample in samples:
        # Alignment and Refinement Stages
        flags = ("local", "unstranded", "removeNonCanonical", "2-stage", "cufflinks")

        align_job = Job.wrapJobFn(star.star_unpaired, config, sample, samples, flags,
                                  cores=int(config['star']['num_cores']),
                                  memory="{}G".format(config['star']['max_mem']))

        samples[sample]['star'] = "{}.star.Aligned.sortedByCoord.out.bam".format(sample)
        samples[sample]['unmapped_fastq'] = "{}.star.Unmapped.out.mate1".format(sample)

        # bowtie_job = Job.wrapJobFn(bowtie.bowtie_unpaired, config, sample, samples, flags,
        #                            cores=int(config['bowtie']['num_cores']),
        #                            memory="{}G".format(config['bowtie']['max_mem']))

        input_bams = list()
        input_bams.append(samples[sample]['star'])
        input_bams.append(samples[sample]['bowtie'])

        merge_job = Job.wrapJobFn(gatk.merge_sam, config, sample, input_bams,
                               cores=int(config['picard-merge']['num_cores']),
                               memory="{}G".format(config['picard-merge']['max_mem']))

        cufflinks_job = Job.wrapJobFn(cufflinks.cufflinks, config, sample, merge_job.rv(),
                                   cores=int(config['cufflinks']['num_cores']),
                                   memory="{}G".format(config['cufflinks']['max_mem']))

        # Create workflow from created jobs
        root_job.addChild(align_job)
        # align_job.addChild(bowtie_job)
        # bowtie_job.addChild(merge_job)
        align_job.addChild(merge_job)
        merge_job.addChild(cufflinks_job)

    cuffmerge_job = Job.wrapJobFn(cufflinks.cuffmerge, config, "blah", samples,
                                  cores=int(config['cuffmerge']['num_cores']),
                                  memory="{}G".format(config['cuffmerge']['max_mem']))

    root_job.addFollowOn(cuffmerge_job)

    for sample in samples:
        cuffquant_job = Job.wrapJobFn(cufflinks.cuffquant, config, sample, samples,
                                      cores=int(config['cuffquant']['num_cores']),
                                      memory="{}G".format(config['cuffquant']['max_mem']))
        cuffmerge_job.addChild(cuffquant_job)

    # Start workflow execution
    Job.Runner.startToil(root_job, args)
<|endoftext|>