<commit_before>import csv
import sys
from django.core.management.base import BaseCommand
from xbrowse.core.variant_filters import get_default_variant_filter
from xbrowse.variant_search.family import get_variants_with_inheritance_mode
from xbrowse_server import mall
from xbrowse_server.base.models import Project, Family
from xbrowse_server.mall import get_mall, get_reference

def get_gene_symbol(variant):
    gene_id = variant.annotation['vep_annotation'][
        variant.annotation['worst_vep_annotation_index']]['gene']
    return get_reference().get_gene_symbol(gene_id)

def get_variants_for_inheritance_for_project(project, inheritance_mode):
    """
    Get the variants for this project / inheritance combo
    Return dict of family -> list of variants
    """

    # create search specification
    # this could theoretically differ by project, if there are different reference populations
    variant_filter = get_default_variant_filter('moderate_impact')
    variant_filter.ref_freqs.append(('g1k_all', 0.01))
    variant_filter.ref_freqs.append(('exac', 0.01))
    variant_filter.ref_freqs.append(('exac-popmax', 0.01))
    #variant_filter.ref_freqs.append(('merck-wgs-3793', 0.05))
    quality_filter = {
        'filter': 'pass',
        'min_gq': 30,
        'min_ab': 15,
    }

    # run MendelianVariantSearch for each family, collect results
    family_results = {}
    for family in project.get_families():
        family_results[family] = list(get_variants_with_inheritance_mode(
            get_mall(project.project_id),
            family.xfamily(),
            inheritance_mode,
            variant_filter=variant_filter,
            quality_filter=quality_filter,
            ))

    return family_results

class Command(BaseCommand):

    def handle(self, *args, **options):
        if not args:
            sys.exit("ERROR: please specify project id on the command line")
        if len(args) > 1:
            sys.exit("ERROR: too many args: %s. Only one project id should be provided." % " ".join(args) )

        project_id = args[0]

        family_variants_f = open('family_variants_%s.tsv' % project_id, 'w')

        # create family_variants.tsv
        writer = csv.writer(family_variants_f, dialect='excel', delimiter='\t')

        header_fields = [
            '#inheritance_mode',
            'project_id',
            'family_id',
            'gene',
            'chrom',
            'pos',
            'ref',
            'alt',
            'rsid',
            'annotation',
            'exac_af',
            '1kg_af',
            'exac_popmax_af',
            'merck_wgs_3793_af',
            ]
        writer.writerow(header_fields)
        writer.flush()
        for inheritance_mode in ['homozygous_recessive', 'dominant', 'compound_het', 'de_novo', 'x_linked_recessive']:
                # collect the resources that we'll need here
                annotator = mall.get_annotator()
                custom_population_store = mall.get_custom_population_store()

                project = Project.objects.get(project_id=project_id)
                families = project.get_families()

                # get the variants for this inheritance / project combination
                family_results = get_variants_for_inheritance_for_project(project, inheritance_mode)

                for i, family in enumerate(families):
                    print("Processing %s - family %s  (%d / %d)" % (inheritance_mode, family.family_id, i, len(families)))
                    for variant in family_results[family]:
                        custom_populations = custom_population_store.get_frequencies(variant.xpos, variant.ref, variant.alt)
                        writer.writerow([
                            inheritance_mode,
                            project_id,
                            family.family_id,
                            get_gene_symbol(variant),
                            variant.chr,
                            str(variant.pos),
                            variant.ref,
                            variant.alt,
                            variant.vcf_id,
                            variant.annotation['vep_group'],
                            str(variant.annotation['freqs']['exac']),
                            str(variant.annotation['freqs']['g1k_all']),
                            str(custom_populations.get('exac-popmax', 0.0)),
                            str(custom_populations.get('merck-wgs-3793', 0.0)),
                            ])

        family_variants_f.close()

<commit_msg>csv writer doesn't have flush() method so removed it<commit_after>import csv
import sys
from django.core.management.base import BaseCommand
from xbrowse.core.variant_filters import get_default_variant_filter
from xbrowse.variant_search.family import get_variants_with_inheritance_mode
from xbrowse_server import mall
from xbrowse_server.base.models import Project, Family
from xbrowse_server.mall import get_mall, get_reference

def get_gene_symbol(variant):
    gene_id = variant.annotation['vep_annotation'][
        variant.annotation['worst_vep_annotation_index']]['gene']
    return get_reference().get_gene_symbol(gene_id)

def get_variants_for_inheritance_for_project(project, inheritance_mode):
    """
    Get the variants for this project / inheritance combo
    Return dict of family -> list of variants
    """

    # create search specification
    # this could theoretically differ by project, if there are different reference populations
    variant_filter = get_default_variant_filter('moderate_impact')
    variant_filter.ref_freqs.append(('g1k_all', 0.01))
    variant_filter.ref_freqs.append(('exac', 0.01))
    variant_filter.ref_freqs.append(('exac-popmax', 0.01))
    #variant_filter.ref_freqs.append(('merck-wgs-3793', 0.05))
    quality_filter = {
        'filter': 'pass',
        'min_gq': 30,
        'min_ab': 15,
    }

    # run MendelianVariantSearch for each family, collect results
    family_results = {}
    for family in project.get_families():
        family_results[family] = list(get_variants_with_inheritance_mode(
            get_mall(project.project_id),
            family.xfamily(),
            inheritance_mode,
            variant_filter=variant_filter,
            quality_filter=quality_filter,
            ))

    return family_results

class Command(BaseCommand):

    def handle(self, *args, **options):
        if not args:
            sys.exit("ERROR: please specify project id on the command line")
        if len(args) > 1:
            sys.exit("ERROR: too many args: %s. Only one project id should be provided." % " ".join(args) )

        project_id = args[0]

        family_variants_f = open('family_variants_%s.tsv' % project_id, 'w')

        # create family_variants.tsv
        writer = csv.writer(family_variants_f, dialect='excel', delimiter='\t')

        header_fields = [
            '#inheritance_mode',
            'project_id',
            'family_id',
            'gene',
            'chrom',
            'pos',
            'ref',
            'alt',
            'rsid',
            'annotation',
            'exac_af',
            '1kg_af',
            'exac_popmax_af',
            'merck_wgs_3793_af',
            ]
        writer.writerow(header_fields)
        for inheritance_mode in ['homozygous_recessive', 'dominant', 'compound_het', 'de_novo', 'x_linked_recessive']:
                # collect the resources that we'll need here
                annotator = mall.get_annotator()
                custom_population_store = mall.get_custom_population_store()

                project = Project.objects.get(project_id=project_id)
                families = project.get_families()

                # get the variants for this inheritance / project combination
                family_results = get_variants_for_inheritance_for_project(project, inheritance_mode)

                for i, family in enumerate(families):
                    print("Processing %s - family %s  (%d / %d)" % (inheritance_mode, family.family_id, i, len(families)))
                    for variant in family_results[family]:
                        custom_populations = custom_population_store.get_frequencies(variant.xpos, variant.ref, variant.alt)
                        writer.writerow([
                            inheritance_mode,
                            project_id,
                            family.family_id,
                            get_gene_symbol(variant),
                            variant.chr,
                            str(variant.pos),
                            variant.ref,
                            variant.alt,
                            variant.vcf_id,
                            variant.annotation['vep_group'],
                            str(variant.annotation['freqs']['exac']),
                            str(variant.annotation['freqs']['g1k_all']),
                            str(custom_populations.get('exac-popmax', 0.0)),
                            str(custom_populations.get('merck-wgs-3793', 0.0)),
                            ])

        family_variants_f.close()

<|endoftext|>


<commit_before>#!/usr/bin/python

# webbymail: a script to retrieve URLs via mail
# Ryan Tucker <rtucker@gmail.com>, 2010/05/02

__USERAGENT__ = "webbymail/0.01alpha1 +http://github.com/rtucker/webbymail/"
__SENDER__ = "webbymail@hoopycat.com"

import email
import logging
import logging.handlers
import smtplib
import sys
import urllib2
import urlparse

from email import encoders

from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Set up syslog
logger = logging.getLogger('')
loghandler = logging.handlers.SysLogHandler('/dev/log',
                facility=logging.handlers.SysLogHandler.LOG_DAEMON)
logformatter = logging.Formatter('%(filename)s: %(levelname)s: %(message)s')
loghandler.setFormatter(logformatter)
logger.addHandler(loghandler)

logger.setLevel(logging.DEBUG)

class UnauthorizedUserError(Exception):
    """Raised when an unauthorized e-mail address e-mails us"""
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class InvalidUrlError(Exception):
    """Raised when a URL isn't valid, or fails to parse or whatnot"""
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def verify_allowed_user(email):
    """
    Checks the sender's e-mail address to ensure they're allowed to use this
    service.
    """
    if email in ['rtucker@gmail.com']:
        return True

    return False

def verify_url(url):
    """
    Checks to ensure the URL is a valid method and isn't too dodgy.
    """
    parsed = urlparse.urlparse(url)

    if parsed.scheme not in ['http', 'https']:
        raise InvalidUrlError, "Unacceptable scheme: " + parsed.scheme

    if parsed.port not in [None, 80, 443]:
        raise InvalidUrlError, "Unacceptable port: %i" + parsed.port

    return parsed.geturl()

def handle_mail_pipe(fd):
    """
    Handles a piped message in from the MTA, returning a list of URLs to fetch.
    """

    msg = email.message_from_file(fd)

    if msg.get('Message-Id'):
        logger.info("Processing Message-ID " + msg.get('Message-Id'))
    else:
        logger.error("Processing message with no Message-ID!")

    logger.debug("Headers found in mail: " + msg.keys())

    # Check user permissions
    if not msg.get('From'):
        raise KeyError, "No From: header found!"
    if not verify_allowed_user(msg.get('From')):
        logger.error("Unauthorized usage from " + msg.get('From'))
        raise UnauthorizedUserError, "Not allowed to accept mail from " + msg.get('From')

    # Check the Subject: header for the URL to fetch
    if not msg.get('Subject'):
        raise KeyError, "No Subject: header found!"

    return (msg.get('From'), [verify_url(msg.get('Subject'))])

def fetch_url(url):
    """
    Fetches a URL and returns a tuple of (Content-type, raw data)
    """

    # Set our headers
    headers = {
        'User-Agent': __USERAGENT__
    }

    # Check the URL is valid and open it
    logger.debug('Attempting open of ' + url)
    req = urllib2.Request(verify_url(url), headers=headers)
    response = urllib2.urlopen(req)
    contenttype = response.info().getheader('Content-type', 'application/octet-stream')
    data = response.read()

    logger.debug('Retrieved %i bytes of %s from %s' % (len(data), contenttype, url))

    return (contenttype, data)

def construct_mail(destination, subject='WebByMail Response', objectlist=[]):
    """
    Returns an email message object addressed to destination, with a
    Subject as specified and a list of tuples from fetch_url
    MIME-enveloped within.
    """
    msg = MIMEMultipart()
    msg['From'] = __SENDER__
    msg['To'] = destination
    msg['Subject'] = subject
    msg.preamble = "This page was retrieved for you by " + __USERAGENT__

    for obj in objectlist:
        logger.debug('Attaching object of type ' + obj[0])
        maintype, subtype = obj[0].split('/', 1)

        if maintype == 'text':
            attachment = MIMEText(obj[1], _subtype=subtype)
        elif maintype == 'image':
            attachment = MIMEImage(obj[1], _subtype=subtype)
        elif maintype == 'audio':
            attachment = MIMEAudio(obj[1], _subtype=subtype)
        else:
            attachment = MIMEBase(maintype, subtype)
            attachment.set_payload(obj[1])
            encoders.encode_base64(attachment)

        attachment.add_header('Content-Disposition', 'attachment')
        msg.attach(attachment)

    return msg

def send_mail(destination, message):
    """
    Sends the string message to the string destination.
    """
    s = smtplib.SMTP('localhost')
    s.sendmail(__SENDER__, destination, message)
    s.quit()

if __name__ == '__main__':
    destination, urllist = handle_mail_pipe(sys.stdin)
    for url in urllist:
        objectlist = [fetch_url(url)]

    msg = construct_mail(destination, objectlist=objectlist)
    send_mail(destination, msg.as_string())

<commit_msg>various fixes for actual e-mail handling<commit_after>#!/usr/bin/python

# webbymail: a script to retrieve URLs via mail
# Ryan Tucker <rtucker@gmail.com>, 2010/05/02

__USERAGENT__ = "webbymail/0.01alpha1 +http://github.com/rtucker/webbymail/"
__SENDER__ = "webbymail@hoopycat.com"

import email
import logging
import logging.handlers
import smtplib
import sys
import urllib2
import urlparse

from email import encoders

from email.mime.audio import MIMEAudio
from email.mime.base import MIMEBase
from email.mime.image import MIMEImage
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText

# Set up syslog
logger = logging.getLogger('')
loghandler = logging.handlers.SysLogHandler('/dev/log',
                facility=logging.handlers.SysLogHandler.LOG_DAEMON)
logformatter = logging.Formatter('%(filename)s: %(levelname)s: %(message)s')
loghandler.setFormatter(logformatter)
logger.addHandler(loghandler)

logger.setLevel(logging.DEBUG)

class UnauthorizedUserError(Exception):
    """Raised when an unauthorized e-mail address e-mails us"""
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

class InvalidUrlError(Exception):
    """Raised when a URL isn't valid, or fails to parse or whatnot"""
    def __init__(self, value):
        self.value = value
    def __str__(self):
        return repr(self.value)

def verify_allowed_user(email):
    """
    Checks the sender's e-mail address to ensure they're allowed to use this
    service.
    """
    if email in ['rtucker@gmail.com']:
        return True

    return False

def verify_url(url):
    """
    Checks to ensure the URL is a valid method and isn't too dodgy.
    """
    parsed = urlparse.urlparse(url)

    if parsed.scheme not in ['http', 'https']:
        raise InvalidUrlError, "Unacceptable scheme: " + parsed.scheme

    if parsed.port not in [None, 80, 443]:
        raise InvalidUrlError, "Unacceptable port: %i" + parsed.port

    return parsed.geturl()

def handle_mail_pipe(fd):
    """
    Handles a piped message in from the MTA, returning a list of URLs to fetch.
    """

    msg = email.message_from_file(fd)

    if msg.get('Message-Id'):
        logger.info("Processing Message-ID " + msg.get('Message-Id'))
    else:
        logger.error("Processing message with no Message-ID!")

    logger.debug("Headers found in mail: " + ' '.join(msg.keys()))

    # Check user permissions
    if not msg.get('From'):
        raise KeyError, "No From: header found!"
    fromaddr = email.utils.parseaddr(msg.get('From'))[1]
    if not verify_allowed_user(fromaddr):
        logger.error("Unauthorized usage from " + msg.get('From'))
        raise UnauthorizedUserError, "Not allowed to accept mail from " + msg.get('From')

    # Check the Subject: header for the URL to fetch
    if not msg.get('Subject'):
        raise KeyError, "No Subject: header found!"

    return (msg.get('From'), [verify_url(msg.get('Subject'))])

def fetch_url(url):
    """
    Fetches a URL and returns a tuple of (Content-type, raw data)
    """

    # Set our headers
    headers = {
        'User-Agent': __USERAGENT__
    }

    # Check the URL is valid and open it
    logger.debug('Attempting open of ' + url)
    req = urllib2.Request(verify_url(url), headers=headers)
    response = urllib2.urlopen(req)
    contenttype = response.info().getheader('Content-type', 'application/octet-stream')
    data = response.read()

    logger.debug('Retrieved %i bytes of %s from %s' % (len(data), contenttype, url))

    return (contenttype, data)

def construct_mail(destination, subject='WebByMail Response', objectlist=[]):
    """
    Returns an email message object addressed to destination, with a
    Subject as specified and a list of tuples from fetch_url
    MIME-enveloped within.
    """
    msg = MIMEMultipart()
    msg['From'] = __SENDER__
    msg['To'] = destination
    msg['Subject'] = subject
    msg.preamble = "This page was retrieved for you by " + __USERAGENT__

    for obj in objectlist:
        logger.debug('Attaching object of type ' + obj[0])
        maintype, subtype = obj[0].split('/', 1)

        if maintype == 'text':
            attachment = MIMEText(obj[1], _subtype=subtype)
        elif maintype == 'image':
            attachment = MIMEImage(obj[1], _subtype=subtype)
        elif maintype == 'audio':
            attachment = MIMEAudio(obj[1], _subtype=subtype)
        else:
            attachment = MIMEBase(maintype, subtype)
            attachment.set_payload(obj[1])
            encoders.encode_base64(attachment)

        attachment.add_header('Content-Disposition', 'attachment')
        msg.attach(attachment)

    return msg

def send_mail(destination, message):
    """
    Sends the string message to the string destination.
    """
    s = smtplib.SMTP('localhost')
    s.sendmail(__SENDER__, destination, message)
    s.quit()

if __name__ == '__main__':
    destination, urllist = handle_mail_pipe(sys.stdin)
    for url in urllist:
        objectlist = [fetch_url(url)]

    msg = construct_mail(destination, subject="Re: " + urllist[0], objectlist=objectlist)
    send_mail(destination, msg.as_string())

<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
"""
Basic unit tests related to content libraries.

Higher-level tests are in `cms/djangoapps/contentstore`.
"""
from bson.objectid import ObjectId
import ddt
from mock import patch
from opaque_keys.edx.locator import LibraryLocator
from xblock.fragment import Fragment
from xblock.runtime import Runtime as VanillaRuntime
from xmodule.modulestore.exceptions import DuplicateCourseError
from xmodule.modulestore.tests.factories import LibraryFactory, ItemFactory, check_mongo_calls
from xmodule.modulestore.tests.utils import MixedSplitTestCase
from xmodule.x_module import AUTHOR_VIEW

@ddt.ddt
class TestLibraries(MixedSplitTestCase):
    """
    Test for libraries.
    Mostly tests code found throughout split mongo, but also tests library_root_xblock.py
    """
    def test_create_library(self):
        """
        Test that we can create a library, and see how many mongo calls it uses to do so.

        Expected mongo calls, in order:
        find_one({'org': '...', 'run': 'library', 'course': '...'})
        insert(definition: {'block_type': 'library', 'fields': {}})

        insert_structure(bulk)
        insert_course_index(bulk)
        get_course_index(bulk)
        """
        with check_mongo_calls(2, 3):
            LibraryFactory.create(modulestore=self.store)

    def test_duplicate_library(self):
        """
        Make sure we cannot create duplicate libraries
        """
        org, lib_code = ('DuplicateX', "DUP")
        LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
        with self.assertRaises(DuplicateCourseError):
            LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)

    @ddt.data(
        "This is a test library!",
        u"Ωμέγα Βιβλιοθήκη",
    )
    def test_str_repr(self, name):
        """
        Test __unicode__() and __str__() methods of libraries
        """
        library = LibraryFactory.create(metadata={"display_name": name}, modulestore=self.store)
        self.assertIn(name, unicode(library))
        if not isinstance(name, unicode):
            self.assertIn(name, str(library))

    def test_display_with_default_methods(self):
        """
        Check that the display_x_with_default methods have been implemented, for
        compatibility with courses.
        """
        org = 'TestOrgX'
        lib_code = 'LC101'
        library = LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
        self.assertEqual(library.display_org_with_default, org)
        self.assertEqual(library.display_number_with_default, lib_code)

    def test_block_with_children(self):
        """
        Test that blocks used from a library can have children.
        """
        library = LibraryFactory.create(modulestore=self.store)

        # In the library, create a vertical block with a child:
        vert_block = ItemFactory.create(
            category="vertical",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        child_block = ItemFactory.create(
            category="html",
            parent_location=vert_block.location,
            user_id=self.user_id,
            publish_item=False,
            metadata={"data": "Hello world", },
            modulestore=self.store,
        )
        self.assertEqual(child_block.parent.replace(version_guid=None, branch=None), vert_block.location)

    def test_update_item(self):
        """
        Test that update_item works for a block in a library
        """
        library = LibraryFactory.create(modulestore=self.store)

        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            metadata={"data": "Hello world", },
            modulestore=self.store,
        )
        block_key = block.location
        block.data = "NEW"
        old_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
        self.store.update_item(block, self.user_id)
        # Reload block from the modulestore
        block = self.store.get_item(block_key)
        self.assertEqual(block.data, "NEW")
        self.assertEqual(block.location, block_key)
        new_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
        self.assertNotEqual(old_version, new_version)

    def test_delete_item(self):
        """
        Test to make sure delete_item() works on blocks in a library
        """
        library = LibraryFactory.create(modulestore=self.store)
        lib_key = library.location.library_key
        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        library = self.store.get_library(lib_key)
        self.assertEqual(len(library.children), 1)
        self.store.delete_item(block.location, self.user_id)
        library = self.store.get_library(lib_key)
        self.assertEqual(len(library.children), 0)

    def test_get_library_non_existent(self):
        """ Test get_library() with non-existent key """
        result = self.store.get_library(LibraryLocator("non", "existent"))
        self.assertEqual(result, None)

    def test_get_libraries(self):
        """ Test get_libraries() """
        libraries = [LibraryFactory.create(modulestore=self.store) for _ in range(0, 3)]
        lib_dict = dict([(lib.location.library_key, lib) for lib in libraries])

        lib_list = self.store.get_libraries()

        self.assertEqual(len(lib_list), len(libraries))
        for lib in lib_list:
            self.assertIn(lib.location.library_key, lib_dict)

    def test_strip(self):
        """
        Test that library keys coming out of MixedModuleStore are stripped of
        branch and version info by default.
        """
        # Create a library
        lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
        # Re-load the library from the modulestore, explicitly including version information:
        lib = self.store.get_library(lib_key)
        self.assertEqual(lib.location.version_guid, None)
        self.assertEqual(lib.location.branch, None)
        self.assertEqual(lib.location.library_key.version_guid, None)
        self.assertEqual(lib.location.library_key.branch, None)

    def test_get_lib_version(self):
        """
        Test that we can get version data about a library from get_library()
        """
        # Create a library
        lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
        # Re-load the library from the modulestore, explicitly including version information:
        lib = self.store.get_library(lib_key, remove_version=False, remove_branch=False)
        version = lib.location.library_key.version_guid
        self.assertIsInstance(version, ObjectId)

    @patch('xmodule.modulestore.split_mongo.caching_descriptor_system.CachingDescriptorSystem.render', VanillaRuntime.render)
    def test_library_author_view(self):
        """
        Test that LibraryRoot.author_view can run and includes content from its
        children.
        We have to patch the runtime (module system) in order to be able to
        render blocks in our test environment.
        """
        library = LibraryFactory.create(modulestore=self.store)
        # Add one HTML block to the library:
        ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        library = self.store.get_library(library.location.library_key)

        context = {'reorderable_items': set(), }
        # Patch the HTML block to always render "Hello world"
        message = u"Hello world"
        hello_render = lambda _, context: Fragment(message)
        with patch('xmodule.html_module.HtmlDescriptor.author_view', hello_render, create=True):
            with patch('xmodule.x_module.DescriptorSystem.applicable_aside_types', lambda self, block: []):
                result = library.render(AUTHOR_VIEW, context)
        self.assertIn(message, result.content)

    def test_xblock_in_lib_have_published_version_returns_false(self):
        library = LibraryFactory.create(modulestore=self.store)
        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        self.assertFalse(self.store.has_published_version(block))
<commit_msg>Added test to exercise library root paged rendering<commit_after># -*- coding: utf-8 -*-
"""
Basic unit tests related to content libraries.

Higher-level tests are in `cms/djangoapps/contentstore`.
"""
from bson.objectid import ObjectId
import ddt
from mock import patch
from opaque_keys.edx.locator import LibraryLocator
from xblock.fragment import Fragment
from xblock.runtime import Runtime as VanillaRuntime
from xmodule.modulestore.exceptions import DuplicateCourseError
from xmodule.modulestore.tests.factories import LibraryFactory, ItemFactory, check_mongo_calls
from xmodule.modulestore.tests.utils import MixedSplitTestCase
from xmodule.x_module import AUTHOR_VIEW

@ddt.ddt
class TestLibraries(MixedSplitTestCase):
    """
    Test for libraries.
    Mostly tests code found throughout split mongo, but also tests library_root_xblock.py
    """
    def test_create_library(self):
        """
        Test that we can create a library, and see how many mongo calls it uses to do so.

        Expected mongo calls, in order:
        find_one({'org': '...', 'run': 'library', 'course': '...'})
        insert(definition: {'block_type': 'library', 'fields': {}})

        insert_structure(bulk)
        insert_course_index(bulk)
        get_course_index(bulk)
        """
        with check_mongo_calls(2, 3):
            LibraryFactory.create(modulestore=self.store)

    def test_duplicate_library(self):
        """
        Make sure we cannot create duplicate libraries
        """
        org, lib_code = ('DuplicateX', "DUP")
        LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
        with self.assertRaises(DuplicateCourseError):
            LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)

    @ddt.data(
        "This is a test library!",
        u"Ωμέγα Βιβλιοθήκη",
    )
    def test_str_repr(self, name):
        """
        Test __unicode__() and __str__() methods of libraries
        """
        library = LibraryFactory.create(metadata={"display_name": name}, modulestore=self.store)
        self.assertIn(name, unicode(library))
        if not isinstance(name, unicode):
            self.assertIn(name, str(library))

    def test_display_with_default_methods(self):
        """
        Check that the display_x_with_default methods have been implemented, for
        compatibility with courses.
        """
        org = 'TestOrgX'
        lib_code = 'LC101'
        library = LibraryFactory.create(org=org, library=lib_code, modulestore=self.store)
        self.assertEqual(library.display_org_with_default, org)
        self.assertEqual(library.display_number_with_default, lib_code)

    def test_block_with_children(self):
        """
        Test that blocks used from a library can have children.
        """
        library = LibraryFactory.create(modulestore=self.store)

        # In the library, create a vertical block with a child:
        vert_block = ItemFactory.create(
            category="vertical",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        child_block = ItemFactory.create(
            category="html",
            parent_location=vert_block.location,
            user_id=self.user_id,
            publish_item=False,
            metadata={"data": "Hello world", },
            modulestore=self.store,
        )
        self.assertEqual(child_block.parent.replace(version_guid=None, branch=None), vert_block.location)

    def test_update_item(self):
        """
        Test that update_item works for a block in a library
        """
        library = LibraryFactory.create(modulestore=self.store)

        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            metadata={"data": "Hello world", },
            modulestore=self.store,
        )
        block_key = block.location
        block.data = "NEW"
        old_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
        self.store.update_item(block, self.user_id)
        # Reload block from the modulestore
        block = self.store.get_item(block_key)
        self.assertEqual(block.data, "NEW")
        self.assertEqual(block.location, block_key)
        new_version = self.store.get_item(block_key, remove_version=False, remove_branch=False).location.version_guid
        self.assertNotEqual(old_version, new_version)

    def test_delete_item(self):
        """
        Test to make sure delete_item() works on blocks in a library
        """
        library = LibraryFactory.create(modulestore=self.store)
        lib_key = library.location.library_key
        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        library = self.store.get_library(lib_key)
        self.assertEqual(len(library.children), 1)
        self.store.delete_item(block.location, self.user_id)
        library = self.store.get_library(lib_key)
        self.assertEqual(len(library.children), 0)

    def test_get_library_non_existent(self):
        """ Test get_library() with non-existent key """
        result = self.store.get_library(LibraryLocator("non", "existent"))
        self.assertEqual(result, None)

    def test_get_libraries(self):
        """ Test get_libraries() """
        libraries = [LibraryFactory.create(modulestore=self.store) for _ in range(0, 3)]
        lib_dict = dict([(lib.location.library_key, lib) for lib in libraries])

        lib_list = self.store.get_libraries()

        self.assertEqual(len(lib_list), len(libraries))
        for lib in lib_list:
            self.assertIn(lib.location.library_key, lib_dict)

    def test_strip(self):
        """
        Test that library keys coming out of MixedModuleStore are stripped of
        branch and version info by default.
        """
        # Create a library
        lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
        # Re-load the library from the modulestore, explicitly including version information:
        lib = self.store.get_library(lib_key)
        self.assertEqual(lib.location.version_guid, None)
        self.assertEqual(lib.location.branch, None)
        self.assertEqual(lib.location.library_key.version_guid, None)
        self.assertEqual(lib.location.library_key.branch, None)

    def test_get_lib_version(self):
        """
        Test that we can get version data about a library from get_library()
        """
        # Create a library
        lib_key = LibraryFactory.create(modulestore=self.store).location.library_key
        # Re-load the library from the modulestore, explicitly including version information:
        lib = self.store.get_library(lib_key, remove_version=False, remove_branch=False)
        version = lib.location.library_key.version_guid
        self.assertIsInstance(version, ObjectId)

    @patch('xmodule.modulestore.split_mongo.caching_descriptor_system.CachingDescriptorSystem.render', VanillaRuntime.render)
    def test_library_author_view(self):
        """
        Test that LibraryRoot.author_view can run and includes content from its
        children.
        We have to patch the runtime (module system) in order to be able to
        render blocks in our test environment.
        """
        library = LibraryFactory.create(modulestore=self.store)
        # Add one HTML block to the library:
        ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        library = self.store.get_library(library.location.library_key)

        context = {'reorderable_items': set(), }
        # Patch the HTML block to always render "Hello world"
        message = u"Hello world"
        hello_render = lambda _, context: Fragment(message)
        with patch('xmodule.html_module.HtmlDescriptor.author_view', hello_render, create=True):
            with patch('xmodule.x_module.DescriptorSystem.applicable_aside_types', lambda self, block: []):
                result = library.render(AUTHOR_VIEW, context)
        self.assertIn(message, result.content)

    @patch('xmodule.modulestore.split_mongo.caching_descriptor_system.CachingDescriptorSystem.render', VanillaRuntime.render)
    def test_library_author_view_with_paging(self):
        """
        Test that LibraryRoot.author_view can apply paging
        We have to patch the runtime (module system) in order to be able to
        render blocks in our test environment.
        """
        library = LibraryFactory.create(modulestore=self.store)
        # Add five HTML blocks to the library:
        blocks = [
            ItemFactory.create(
                category="html",
                parent_location=library.location,
                user_id=self.user_id,
                publish_item=False,
                modulestore=self.store,
                data="HtmlBlock"+str(i)
            )
            for i in range(5)
        ]
        library = self.store.get_library(library.location.library_key)

        def render_and_check_contents(page, page_size):
            context = {'reorderable_items': set(), 'paging': {'page_number': page, 'page_size': page_size}}
            expected_blocks = blocks[page_size*page:page_size*(page+1)]
            result = library.render(AUTHOR_VIEW, context)

            for expected_block in expected_blocks:
                self.assertIn(expected_block.data, result.content)

        hello_render = lambda block, _: Fragment(block.data)
        with patch('xmodule.html_module.HtmlDescriptor.author_view', hello_render, create=True):
            with patch('xmodule.x_module.DescriptorSystem.applicable_aside_types', lambda self, block: []):
                render_and_check_contents(0, 3)
                render_and_check_contents(1, 3)
                render_and_check_contents(0, 2)
                render_and_check_contents(1, 2)

    def test_xblock_in_lib_have_published_version_returns_false(self):
        library = LibraryFactory.create(modulestore=self.store)
        block = ItemFactory.create(
            category="html",
            parent_location=library.location,
            user_id=self.user_id,
            publish_item=False,
            modulestore=self.store,
        )
        self.assertFalse(self.store.has_published_version(block))
<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
# @COPYRIGHT_begin
#
# Copyright [2015] Michał Szczygieł, M4GiK Software
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# @COPYRIGHT_end
from rest_framework import viewsets
from core.utils.python_object_encoder import SetEncoder
from database.models.installed_applications import InstalledApplications
from virtual_controller.api.serializers.installed_applications_serializer import InstalledApplicationsSerializer
from virtual_controller.api.permissions import base_permissions as api_permissions
from rest_framework.decorators import list_route
from rest_framework.response import Response
from virtual_controller.tasks import reserved_pool_ip
from json import dumps

class InstalledApplicationList(viewsets.ReadOnlyModelViewSet):
    """
    List of all available applications.
    """
    queryset = InstalledApplications.objects.all()
    serializer_class = InstalledApplicationsSerializer
    permission_classes = {api_permissions.UsersPermission}

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

    @list_route(methods=['get'], url_path='obtain-ip')
    def obtain_ip(self, request):
        """
        Gets available IP address.
        @param request:
        @return: Public IP address.
        """
        user_id = api_permissions.UsersPermission.get_user(request).id
        result = reserved_pool_ip.request(args=(user_id,))
        j = dumps(result, cls=SetEncoder)
        return Response(j)<commit_msg>#7 2 Add missing method<commit_after># -*- coding: utf-8 -*-
# @COPYRIGHT_begin
#
# Copyright [2015] Michał Szczygieł, M4GiK Software
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# @COPYRIGHT_end
from rest_framework import viewsets
from core.utils.python_object_encoder import SetEncoder
from database.models.installed_applications import InstalledApplications
from virtual_controller.api.serializers.installed_applications_serializer import InstalledApplicationsSerializer
from virtual_controller.api.permissions import base_permissions as api_permissions
from rest_framework.decorators import list_route
from rest_framework.response import Response
from virtual_controller.tasks import reserved_pool_ip
from json import dumps

class InstalledApplicationList(viewsets.ReadOnlyModelViewSet):
    """
    List of all available applications.
    """
    queryset = InstalledApplications.objects.all()
    serializer_class = InstalledApplicationsSerializer
    permission_classes = {api_permissions.UsersPermission}

    def perform_create(self, serializer):
        serializer.save(owner=self.request.user)

    @list_route(methods=['get'], url_path='obtain-ip')
    def obtain_ip(self, request):
        """
        Gets available IP address.
        @param request:
        @return: Public IP address.
        """
        user_id = api_permissions.UsersPermission.get_user(request).id
        result = reserved_pool_ip.request.apply_async(args=(user_id,))
        j = dumps(result, cls=SetEncoder)
        return Response(j)<|endoftext|>


<commit_before># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013-2014 Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import time

from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as D_FMT
import openerp.tests.common as common
from . import logistic_requisition
from . import purchase_requisition
from . import purchase_order

class test_mto_workflow(common.TransactionCase):
    """ Test the workflows of MTO products accross the models
    logistic requisition, to purchase orders, to sale orders
    passing through stock pickings.

    We create a logistic requisition for 100 products A.
    From there, we create a purchase requisition for these products.
    From the purchase requisition, we create one or several bids. We
    select lines to keep in the bids.

    From the logistic requisition (now sourced), we create a sales
    order. This sales order is confirmed, and the full complexity
    appears now. At the moment when the sales order is confirmed,
    a purchase quotation is generated (using the selected bid lines).

    The sales order lines created in this way are MTO and direct
    delivery (dropshipping). The procurement generated for these lines
    should be linked to the purchase quotation created before and not
    generate a new one. The stock move (reservation) of the procurement
    should be the same than the stock move generated for the Incoming
    Shipment of the purchase order.

    Finally, when the Incoming Shipment of the purchase order is done,
    the sales orders should be "delivered" and the purchase order
    should be "received" as well.

    In order to achieve that, when the procurement of the sales order line
    is generated, we leave the procurement as draft, we link it with the PO
    and we leave the move_id empty. Only at the moment when the picking
    of the purchase order is generated, we link the procurement's move_id
    to the picking's move and confirm the procurement.
    """

    def setUp(self):
        super(test_mto_workflow, self).setUp()
        self.log_req_model = self.env['logistic.requisition']
        self.log_req_line_model = self.env['logistic.requisition.line']
        self.purchase_order_model = self.env['purchase.order']
        self.purch_req_model = self.env['purchase.requisition']
        self.sale_model = self.env['sale.order']
        self.picking_in_model = self.env['stock.picking']

        data_model = self.env['ir.model.data']
        self.partner_1 = data_model.xmlid_to_object('base.res_partner_1')
        self.partner_3 = data_model.xmlid_to_object('base.res_partner_3')
        self.partner_4 = data_model.xmlid_to_object('base.res_partner_4')
        self.partner_12 = data_model.xmlid_to_object('base.res_partner_12')
        self.user_demo = data_model.xmlid_to_object('base.user_demo')
        route_mto_id = self.ref('stock.route_warehouse0_mto')
        self.product_32 = data_model.xmlid_to_object(
            'product.product_product_32')
        self.browse_ref('product.product_product_32').write(
            {'route_ids': [(6, 0, [route_mto_id])]})
        self.product_25 = data_model.xmlid_to_object(
            'product.product_product_25')
        self.browse_ref('product.product_product_25').write(
            {'route_ids': [(6, 0, [route_mto_id])]})
        self.product_uom_pce = data_model.xmlid_to_object(
            'product.product_uom_unit')
        self.pricelist_sale = data_model.xmlid_to_object('product.list0')
        self.vals = {
            'partner_id': self.partner_4.id,
            'consignee_id': self.partner_3.id,
            'date': time.strftime(D_FMT),
            'date_delivery': time.strftime(D_FMT),
            'user_id': self.user_demo.id,
            'pricelist_id': self.pricelist_sale.id,
        }
        self.line_vals = {
            'product_id': self.product_32.id,
            'description': "[HEAD] Headset standard",
            'requested_qty': 100,
            'requested_uom_id': self.product_uom_pce.id,
            'date_delivery': time.strftime(D_FMT),
            'source_ids': [{'proposed_qty': 100,
                            'proposed_product_id': self.product_32.id,
                            'proposed_uom_id': self.product_uom_pce.id,
                            'procurement_method': 'procurement',
                            'price_is': 'estimated'}],
        }

    def _setup_initial_data(self, lines_vals):
        """ Create objects and initialize the data for the tests

            - creates and confirm a logistic requisition
            - assign the lines
            - create a purchase requisition and bids for the lines
            - source the lines
            - Create a sales quotation
        """
        # logistic requisition creation
        requisition = self.log_req_model.create(self.vals)
        lines = self.log_req_line_model.browse()
        purchase_orders = []
        for line_vals in lines_vals:
            source_vals = line_vals.pop('source_ids')
            line = logistic_requisition.add_line(
                self, requisition, line_vals)
            requisition.button_confirm()
            logistic_requisition.assign_lines(self, line, self.user_demo.id)
            for src_vals in source_vals:
                source = logistic_requisition.add_source(
                    self, line, src_vals)

                # purchase requisition creation, bids selection
                purch_req = logistic_requisition.create_purchase_requisition(
                    self, source)
                purchase_requisition.confirm_call(self, purch_req)
                draft_po = purchase_requisition.create_draft_purchase_order(
                    self, purch_req, self.partner_1.id)
                bid, bid_line = draft_po
                bid_line.write({'price_unit': 10})
                purchase_order.select_line(self, bid_line,
                                           src_vals['proposed_qty'])
                purchase_order.bid_encoded(self, bid)
                purchase_requisition.close_call(self, purch_req)
                purchase_requisition.bids_selected(self, purch_req)
                purch_req.generate_po()
                po = self.env['purchase.order'].search(
                    [('requisition_id', '=', purch_req.id),
                     ('type', '=', 'purchase'),
                     ('state', 'in', ['draftpo'])])
                purchase_orders.append(po)

            lines |= line

        # set lines as sourced
        logistic_requisition.source_lines(self, lines)

        # sales order creation
        sale, __ = logistic_requisition.create_quotation(
            self, requisition, lines)

        for line in sale.order_line:
            for po in purchase_orders:
                po.order_line.ensure_one()
                if line.product_id == po.order_line.product_id:
                    line.sourced_by = po.order_line.id
                    break

        # if sale_exception is installed, ignore exceptions because they are
        # irrelevant to this test. If not, assigning a missing field is no_op
        sale.ignore_exceptions = True

        # the confirmation of the sale order link the
        # purchase order on the purchase requisition
        sale.signal_workflow('order_confirm')
        sale.action_ship_create()
        return requisition, lines, sale

    def _check_sale_line(self, sale_line):
        """ For a sales order lines, """
        # check if the sale order line is linked with the purchase order
        # line
        assert sale_line.sourced_by
        self.assertTrue(sale_line.manually_sourced,
                        "The sale order line should be set as manually "
                        "sourced")

        # check if the procurement is linked with the correct purchase
        # order
        purchase = sale_line.sourced_by.order_id
        # proc = sale_line.procurement_group_id.procurement_ids
        # XXX procurement isn't linked to a PO yet ???
        # self.assertEquals(proc.purchase_id, purchase,
        #                 "The purchase of the procurement should be "
        #                 "the same than the one generated by the purchase "
        #                 "requisition.")

        self.assertEquals(purchase.state, 'draftpo')
        purchase.refresh()
        purchase.signal_workflow('purchase_confirm')

        # the incoming shipment of the purchase order has been generated
        purchase.refresh()
        self.assertEquals(len(purchase.picking_ids), 1)
        picking = purchase.picking_ids[0]
        # receive it
        picking.do_transfer()
        self.assertEquals(picking.state, 'done')

        # the purchase order should be received as we received the
        # picking
        self.assertTrue(purchase.shipped,
                        "The sales order should be considered as 'received' "
                        "because the picking 'in' has been received.")

    def test_workflow_with_1_line(self):
        """ Test the full workflow and check if sale and purchase are both
        delivered

        """
        requisition, lines, sale = self._setup_initial_data([self.line_vals])

        assert len(sale.order_line) == 1
        self._check_sale_line(sale.order_line[0])

        # the sale order should be delivered as well
        # XXX sale procurement is in exception
        # self.assertTrue(sale.shipped,
        #                 "The sales order should be considered as 'shipped' "
        #                 "because the procurement is the same than the one "
        #                 "of the purchase order.")

    def test_workflow_with_2_lines(self):
        """ Test the full workflow and check if sale and purchase are both
        delivered for 2 lines

        """
        # add a line in the logistic requisition
        line2 = {
            'product_id': self.product_25.id,
            'description': "[LAP-E5] Laptop E5023",
            'requested_qty': 200,
            'requested_uom_id': self.product_uom_pce.id,
            'date_delivery': time.strftime(D_FMT),
            'source_ids': [{'proposed_qty': 200,
                            'proposed_product_id': self.product_25.id,
                            'proposed_uom_id': self.product_uom_pce.id,
                            'procurement_method': 'procurement',
                            'price_is': 'estimated'}],
        }
        lines = [self.line_vals, line2]
        requisition, lines, sale = self._setup_initial_data(lines)

        # the confirmation of the sale order generates the
        # purchase order of the purchase requisition
        assert len(sale.order_line) == 2
        self._check_sale_line(sale.order_line[0])

        self.assertFalse(sale.shipped,
                         "The sale is not shipped, not all lines "
                         "are delivered")
        self._check_sale_line(sale.order_line[1])

        # the sale order should be delivered as well
        # XXX sale procurement is in exception
        # self.assertTrue(sale.shipped,
        #                 "The sales order should be 'shipped' "
        #                 "because the procurement is the same than the one "
        #                 "of the purchase order.")
<commit_msg>remove blank line<commit_after># -*- coding: utf-8 -*-
##############################################################################
#
#    Author: Guewen Baconnier
#    Copyright 2013-2014 Camptocamp SA
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 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 Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#
##############################################################################

import time

from openerp.tools import DEFAULT_SERVER_DATE_FORMAT as D_FMT
import openerp.tests.common as common
from . import logistic_requisition
from . import purchase_requisition
from . import purchase_order

class test_mto_workflow(common.TransactionCase):
    """ Test the workflows of MTO products accross the models
    logistic requisition, to purchase orders, to sale orders
    passing through stock pickings.

    We create a logistic requisition for 100 products A.
    From there, we create a purchase requisition for these products.
    From the purchase requisition, we create one or several bids. We
    select lines to keep in the bids.

    From the logistic requisition (now sourced), we create a sales
    order. This sales order is confirmed, and the full complexity
    appears now. At the moment when the sales order is confirmed,
    a purchase quotation is generated (using the selected bid lines).

    The sales order lines created in this way are MTO and direct
    delivery (dropshipping). The procurement generated for these lines
    should be linked to the purchase quotation created before and not
    generate a new one. The stock move (reservation) of the procurement
    should be the same than the stock move generated for the Incoming
    Shipment of the purchase order.

    Finally, when the Incoming Shipment of the purchase order is done,
    the sales orders should be "delivered" and the purchase order
    should be "received" as well.

    In order to achieve that, when the procurement of the sales order line
    is generated, we leave the procurement as draft, we link it with the PO
    and we leave the move_id empty. Only at the moment when the picking
    of the purchase order is generated, we link the procurement's move_id
    to the picking's move and confirm the procurement.
    """

    def setUp(self):
        super(test_mto_workflow, self).setUp()
        self.log_req_model = self.env['logistic.requisition']
        self.log_req_line_model = self.env['logistic.requisition.line']
        self.purchase_order_model = self.env['purchase.order']
        self.purch_req_model = self.env['purchase.requisition']
        self.sale_model = self.env['sale.order']
        self.picking_in_model = self.env['stock.picking']

        data_model = self.env['ir.model.data']
        self.partner_1 = data_model.xmlid_to_object('base.res_partner_1')
        self.partner_3 = data_model.xmlid_to_object('base.res_partner_3')
        self.partner_4 = data_model.xmlid_to_object('base.res_partner_4')
        self.partner_12 = data_model.xmlid_to_object('base.res_partner_12')
        self.user_demo = data_model.xmlid_to_object('base.user_demo')
        route_mto_id = self.ref('stock.route_warehouse0_mto')
        self.product_32 = data_model.xmlid_to_object(
            'product.product_product_32')
        self.browse_ref('product.product_product_32').write(
            {'route_ids': [(6, 0, [route_mto_id])]})
        self.product_25 = data_model.xmlid_to_object(
            'product.product_product_25')
        self.browse_ref('product.product_product_25').write(
            {'route_ids': [(6, 0, [route_mto_id])]})
        self.product_uom_pce = data_model.xmlid_to_object(
            'product.product_uom_unit')
        self.pricelist_sale = data_model.xmlid_to_object('product.list0')
        self.vals = {
            'partner_id': self.partner_4.id,
            'consignee_id': self.partner_3.id,
            'date': time.strftime(D_FMT),
            'date_delivery': time.strftime(D_FMT),
            'user_id': self.user_demo.id,
            'pricelist_id': self.pricelist_sale.id,
        }
        self.line_vals = {
            'product_id': self.product_32.id,
            'description': "[HEAD] Headset standard",
            'requested_qty': 100,
            'requested_uom_id': self.product_uom_pce.id,
            'date_delivery': time.strftime(D_FMT),
            'source_ids': [{'proposed_qty': 100,
                            'proposed_product_id': self.product_32.id,
                            'proposed_uom_id': self.product_uom_pce.id,
                            'procurement_method': 'procurement',
                            'price_is': 'estimated'}],
        }

    def _setup_initial_data(self, lines_vals):
        """ Create objects and initialize the data for the tests

            - creates and confirm a logistic requisition
            - assign the lines
            - create a purchase requisition and bids for the lines
            - source the lines
            - Create a sales quotation
        """
        # logistic requisition creation
        requisition = self.log_req_model.create(self.vals)
        lines = self.log_req_line_model.browse()
        purchase_orders = []
        for line_vals in lines_vals:
            source_vals = line_vals.pop('source_ids')
            line = logistic_requisition.add_line(
                self, requisition, line_vals)
            requisition.button_confirm()
            logistic_requisition.assign_lines(self, line, self.user_demo.id)
            for src_vals in source_vals:
                source = logistic_requisition.add_source(
                    self, line, src_vals)

                # purchase requisition creation, bids selection
                purch_req = logistic_requisition.create_purchase_requisition(
                    self, source)
                purchase_requisition.confirm_call(self, purch_req)
                draft_po = purchase_requisition.create_draft_purchase_order(
                    self, purch_req, self.partner_1.id)
                bid, bid_line = draft_po
                bid_line.write({'price_unit': 10})
                purchase_order.select_line(self, bid_line,
                                           src_vals['proposed_qty'])
                purchase_order.bid_encoded(self, bid)
                purchase_requisition.close_call(self, purch_req)
                purchase_requisition.bids_selected(self, purch_req)
                purch_req.generate_po()
                po = self.env['purchase.order'].search(
                    [('requisition_id', '=', purch_req.id),
                     ('type', '=', 'purchase'),
                     ('state', 'in', ['draftpo'])])
                purchase_orders.append(po)

            lines |= line

        # set lines as sourced
        logistic_requisition.source_lines(self, lines)

        # sales order creation
        sale, __ = logistic_requisition.create_quotation(
            self, requisition, lines)

        for line in sale.order_line:
            for po in purchase_orders:
                po.order_line.ensure_one()
                if line.product_id == po.order_line.product_id:
                    line.sourced_by = po.order_line.id
                    break

        # if sale_exception is installed, ignore exceptions because they are
        # irrelevant to this test. If not, assigning a missing field is no_op
        sale.ignore_exceptions = True

        # the confirmation of the sale order link the
        # purchase order on the purchase requisition
        sale.signal_workflow('order_confirm')
        sale.action_ship_create()
        return requisition, lines, sale

    def _check_sale_line(self, sale_line):
        """ For a sales order lines, """
        # check if the sale order line is linked with the purchase order
        # line
        assert sale_line.sourced_by
        self.assertTrue(sale_line.manually_sourced,
                        "The sale order line should be set as manually "
                        "sourced")

        # check if the procurement is linked with the correct purchase
        # order
        purchase = sale_line.sourced_by.order_id
        # proc = sale_line.procurement_group_id.procurement_ids
        # XXX procurement isn't linked to a PO yet ???
        # self.assertEquals(proc.purchase_id, purchase,
        #                 "The purchase of the procurement should be "
        #                 "the same than the one generated by the purchase "
        #                 "requisition.")

        self.assertEquals(purchase.state, 'draftpo')
        purchase.refresh()
        purchase.signal_workflow('purchase_confirm')

        # the incoming shipment of the purchase order has been generated
        purchase.refresh()
        self.assertEquals(len(purchase.picking_ids), 1)
        picking = purchase.picking_ids[0]
        # receive it
        picking.do_transfer()
        self.assertEquals(picking.state, 'done')

        # the purchase order should be received as we received the
        # picking
        self.assertTrue(purchase.shipped,
                        "The sales order should be considered as 'received' "
                        "because the picking 'in' has been received.")

    def test_workflow_with_1_line(self):
        """ Test the full workflow and check if sale and purchase are both
        delivered

        """
        requisition, lines, sale = self._setup_initial_data([self.line_vals])

        assert len(sale.order_line) == 1
        self._check_sale_line(sale.order_line[0])

        # the sale order should be delivered as well
        # XXX sale procurement is in exception
        # self.assertTrue(sale.shipped,
        #                 "The sales order should be considered as 'shipped' "
        #                 "because the procurement is the same than the one "
        #                 "of the purchase order.")

    def test_workflow_with_2_lines(self):
        """ Test the full workflow and check if sale and purchase are both
        delivered for 2 lines

        """
        # add a line in the logistic requisition
        line2 = {
            'product_id': self.product_25.id,
            'description': "[LAP-E5] Laptop E5023",
            'requested_qty': 200,
            'requested_uom_id': self.product_uom_pce.id,
            'date_delivery': time.strftime(D_FMT),
            'source_ids': [{'proposed_qty': 200,
                            'proposed_product_id': self.product_25.id,
                            'proposed_uom_id': self.product_uom_pce.id,
                            'procurement_method': 'procurement',
                            'price_is': 'estimated'}],
        }
        lines = [self.line_vals, line2]
        requisition, lines, sale = self._setup_initial_data(lines)

        # the confirmation of the sale order generates the
        # purchase order of the purchase requisition
        assert len(sale.order_line) == 2
        self._check_sale_line(sale.order_line[0])

        self.assertFalse(sale.shipped,
                         "The sale is not shipped, not all lines "
                         "are delivered")
        self._check_sale_line(sale.order_line[1])

        # the sale order should be delivered as well
        # XXX sale procurement is in exception
        # self.assertTrue(sale.shipped,
        #                 "The sales order should be 'shipped' "
        #                 "because the procurement is the same than the one "
        #                 "of the purchase order.")
<|endoftext|>


<commit_before># coding=utf-8
<commit_msg>Code review changes<commit_after><|endoftext|>


<commit_before>import os
import sys
import unittest
import time
import click
from ykman.util import TRANSPORT
from test.util import ykman_cli

URI_HOTP_EXAMPLE = 'otpauth://hotp/Example:demo@example.com?' \
        'secret=JBSWY3DPK5XXE3DEJ5TE6QKUJA======&issuer=Example&counter=1'

URI_TOTP_EXAMPLE = (
        'otpauth://totp/ACME%20Co:john.doe@email.com?'
        'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co'
        '&algorithm=SHA1&digits=6&period=30')

_one_yubikey = False
if os.environ.get('INTEGRATION_TESTS') == 'TRUE':
    try:
        from ykman.descriptor import get_descriptors
        click.confirm(
            "Run integration tests? This will erase data on the YubiKey,"
            " make sure it is a key used for development.", abort=True)
        _one_yubikey = len(list(get_descriptors())) == 1
    except Exception:
        sys.exit()
    _skip = False
else:
    _skip = True

def _has_mode(mode):
    if not _one_yubikey:
        return False
    yubikeys = list(get_descriptors())
    if len(yubikeys) is not 1:
        return False
    return yubikeys[0].mode.has_transport(mode)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
class TestYkmanInfo(unittest.TestCase):

    def test_ykman_info(self):
        time.sleep(3)
        info = ykman_cli('info')
        self.assertIn('Device name:', info)
        self.assertIn('Serial number:', info)
        self.assertIn('Firmware version:', info)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotStatus(unittest.TestCase):

    def test_ykman_slot_info(self):
        info = ykman_cli('slot', 'info')
        self.assertIn('Slot 1:', info)
        self.assertIn('Slot 2:', info)

    def test_ykman_swap_slots(self):
        output = ykman_cli('slot', 'swap', '-f')
        self.assertIn('Swapping slots...', output)
        output = ykman_cli('slot', 'swap', '-f')
        self.assertIn('Swapping slots...', output)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotProgramming(unittest.TestCase):

    def test_ykman_program_otp_slot_2(self):
        output = ykman_cli('slot', 'otp', '2', '-f')
        self.assertIn('Using device serial as public ID:', output)
        self.assertIn('Using a randomly generated private ID:', output)
        self.assertIn('Using a randomly generated secret key:', output)
        self._check_slot_2_programmed()

    def test_ykman_program_chalresp_slot_2(self):
        output = ykman_cli('slot', 'chalresp', '2', '-f')
        self.assertIn('Using a randomly generated key', output)
        self._check_slot_2_programmed()

    def test_chal_resp_totp(self):
        ykman_cli('slot', 'chalresp', '2', '-T', 'abba', '-f')
        self._check_slot_2_programmed()

    def test_ykman_program_hotp_slot_2(self):
        ykman_cli(
            'slot', 'hotp', '2',
            '27KIZZE3SD7GE2FVJJBAXEI3I6RRTPGM', '-f')
        self._check_slot_2_programmed()

    def test_ykman_program_static_slot_2(self):
        ykman_cli(
            'slot', 'static', '2',
            'higngdukgerjktbbikrhirngtlkkttkb', '-f')
        self._check_slot_2_programmed()

    def test_update_settings_enter_slot_2(self):
        ykman_cli('slot', 'otp', '2', '-f')
        output = ykman_cli('slot', 'settings', '2', '-f', '--no-enter')
        self.assertIn('Updating settings for slot', output)

    def test_delete_slot_2(self):
        ykman_cli('slot', 'otp', '2', '-f')
        output = ykman_cli('slot', 'delete', '2', '-f')
        self.assertIn('Deleting the configuration', output)
        status = ykman_cli('slot', 'info')
        self.assertIn('Slot 2: empty', status)

    def _check_slot_2_programmed(self):
        status = ykman_cli('slot', 'info')
        self.assertIn('Slot 2: programmed', status)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotCalculate(unittest.TestCase):

    def test_calculate_hex(self):
        ykman_cli('slot', 'delete', '2', '-f')
        ykman_cli('slot', 'chalresp', '2', 'abba', '-f')
        output = ykman_cli('slot', 'calculate', '2', 'abba')
        self.assertIn('f8de2586056d89d8b961a072d1245a495d2155e1', output)

    def test_calculate_totp(self):
        ykman_cli('slot', 'delete', '2', '-f')
        ykman_cli('slot', 'chalresp', '2', 'abba', '-f')
        output = ykman_cli('slot', 'calculate', '2', '999', '-T')
        self.assertEqual('533486', output.strip())
        output = ykman_cli('slot', 'calculate', '2', '999', '-T', '-d', '8')
        self.assertEqual('04533486', output.strip())
        output = ykman_cli('slot', 'calculate', '2', '-T')
        self.assertEqual(6, len(output.strip()))
        output = ykman_cli('slot', 'calculate', '2', '-T', '-d', '8')
        self.assertEqual(8, len(output.strip()))

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(
    not _has_mode(TRANSPORT.CCID),
    "CCID needs to be enabled for this test.")
class TestOpenPGP(unittest.TestCase):

    def test_openpgp_info(self):
        output = ykman_cli('openpgp', 'info')
        self.assertIn('OpenPGP version:', output)

    def test_openpgp_reset(self):
        output = ykman_cli('openpgp', 'reset', '-f')
        self.assertIn(
            'Success! All data has been cleared and default PINs are set.',
            output)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(
    not _has_mode(TRANSPORT.CCID),
    "CCID needs to be enabled for this test.")
class TestOATH(unittest.TestCase):

    def test_oath_info(self):
        output = ykman_cli('oath', 'info')
        self.assertIn('OATH version:', output)

    def test_oath_add_credential(self):
        ykman_cli('oath', 'add', 'test-name', 'abba')
        creds = ykman_cli('oath', 'list')
        self.assertIn('test-name', creds)

    def test_oath_add_credential_with_space(self):
        ykman_cli('oath', 'add', 'test-name-space', 'ab ba')
        creds = ykman_cli('oath', 'list')
        self.assertIn('test-name-space', creds)

    def test_oath_hidden_cred(self):
        ykman_cli('oath', 'add', '_hidden:name', 'abba')
        creds = ykman_cli('oath', 'code')
        self.assertNotIn('_hidden:name', creds)
        creds = ykman_cli('oath', 'code', '-H')
        self.assertIn('_hidden:name', creds)

    def test_oath_add_uri_hotp(self):
        ykman_cli('oath', 'uri', URI_HOTP_EXAMPLE)
        creds = ykman_cli('oath', 'list')
        self.assertIn('Example:demo', creds)

    def test_oath_add_uri_totp(self):
        ykman_cli('oath', 'uri', URI_TOTP_EXAMPLE)
        creds = ykman_cli('oath', 'list')
        self.assertIn('john.doe', creds)

    def test_oath_code(self):
        ykman_cli('oath', 'add', 'test-name2', 'abba')
        creds = ykman_cli('oath', 'code')
        self.assertIn('test-name2', creds)

    def test_oath_reset(self):
        output = ykman_cli('oath', 'reset', '-f')
        self.assertIn(
            'Success! All credentials have been cleared from the device.',
            output)

    def test_oath_hotp_code(self):
        ykman_cli('oath', 'add', '-o', 'HOTP', 'hotp-cred', 'abba')
        cred = ykman_cli('oath', 'code', 'hotp-cred')
        self.assertIn('659165', cred)

    def test_oath_hotp_steam_code(self):
        ykman_cli('oath', 'add', '-o', 'HOTP', 'Steam:steam-cred', 'abba')
        cred = ykman_cli('oath', 'code', 'steam-cred')
        self.assertIn('CGC3K', cred)

    def test_oath_remove(self):
        ykman_cli('oath', 'add', 'remove-me', 'abba')
        ykman_cli('oath', 'remove', 'remove-me')
        self.assertNotIn('remove-me', ykman_cli('oath', 'list'))
<commit_msg>piv: add basic test cases<commit_after>import os
import sys
import unittest
import time
import click
from ykman.util import TRANSPORT
from test.util import ykman_cli

URI_HOTP_EXAMPLE = 'otpauth://hotp/Example:demo@example.com?' \
        'secret=JBSWY3DPK5XXE3DEJ5TE6QKUJA======&issuer=Example&counter=1'

URI_TOTP_EXAMPLE = (
        'otpauth://totp/ACME%20Co:john.doe@email.com?'
        'secret=HXDMVJECJJWSRB3HWIZR4IFUGFTMXBOZ&issuer=ACME%20Co'
        '&algorithm=SHA1&digits=6&period=30')

_one_yubikey = False
if os.environ.get('INTEGRATION_TESTS') == 'TRUE':
    try:
        from ykman.descriptor import get_descriptors
        click.confirm(
            "Run integration tests? This will erase data on the YubiKey,"
            " make sure it is a key used for development.", abort=True)
        _one_yubikey = len(list(get_descriptors())) == 1
    except Exception:
        sys.exit()
    _skip = False
else:
    _skip = True

def _has_mode(mode):
    if not _one_yubikey:
        return False
    yubikeys = list(get_descriptors())
    if len(yubikeys) is not 1:
        return False
    return yubikeys[0].mode.has_transport(mode)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
class TestYkmanInfo(unittest.TestCase):

    def test_ykman_info(self):
        time.sleep(3)
        info = ykman_cli('info')
        self.assertIn('Device name:', info)
        self.assertIn('Serial number:', info)
        self.assertIn('Firmware version:', info)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotStatus(unittest.TestCase):

    def test_ykman_slot_info(self):
        info = ykman_cli('slot', 'info')
        self.assertIn('Slot 1:', info)
        self.assertIn('Slot 2:', info)

    def test_ykman_swap_slots(self):
        output = ykman_cli('slot', 'swap', '-f')
        self.assertIn('Swapping slots...', output)
        output = ykman_cli('slot', 'swap', '-f')
        self.assertIn('Swapping slots...', output)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotProgramming(unittest.TestCase):

    def test_ykman_program_otp_slot_2(self):
        output = ykman_cli('slot', 'otp', '2', '-f')
        self.assertIn('Using device serial as public ID:', output)
        self.assertIn('Using a randomly generated private ID:', output)
        self.assertIn('Using a randomly generated secret key:', output)
        self._check_slot_2_programmed()

    def test_ykman_program_chalresp_slot_2(self):
        output = ykman_cli('slot', 'chalresp', '2', '-f')
        self.assertIn('Using a randomly generated key', output)
        self._check_slot_2_programmed()

    def test_chal_resp_totp(self):
        ykman_cli('slot', 'chalresp', '2', '-T', 'abba', '-f')
        self._check_slot_2_programmed()

    def test_ykman_program_hotp_slot_2(self):
        ykman_cli(
            'slot', 'hotp', '2',
            '27KIZZE3SD7GE2FVJJBAXEI3I6RRTPGM', '-f')
        self._check_slot_2_programmed()

    def test_ykman_program_static_slot_2(self):
        ykman_cli(
            'slot', 'static', '2',
            'higngdukgerjktbbikrhirngtlkkttkb', '-f')
        self._check_slot_2_programmed()

    def test_update_settings_enter_slot_2(self):
        ykman_cli('slot', 'otp', '2', '-f')
        output = ykman_cli('slot', 'settings', '2', '-f', '--no-enter')
        self.assertIn('Updating settings for slot', output)

    def test_delete_slot_2(self):
        ykman_cli('slot', 'otp', '2', '-f')
        output = ykman_cli('slot', 'delete', '2', '-f')
        self.assertIn('Deleting the configuration', output)
        status = ykman_cli('slot', 'info')
        self.assertIn('Slot 2: empty', status)

    def _check_slot_2_programmed(self):
        status = ykman_cli('slot', 'info')
        self.assertIn('Slot 2: programmed', status)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(not _has_mode(TRANSPORT.OTP), "OTP needs to be enabled")
class TestSlotCalculate(unittest.TestCase):

    def test_calculate_hex(self):
        ykman_cli('slot', 'delete', '2', '-f')
        ykman_cli('slot', 'chalresp', '2', 'abba', '-f')
        output = ykman_cli('slot', 'calculate', '2', 'abba')
        self.assertIn('f8de2586056d89d8b961a072d1245a495d2155e1', output)

    def test_calculate_totp(self):
        ykman_cli('slot', 'delete', '2', '-f')
        ykman_cli('slot', 'chalresp', '2', 'abba', '-f')
        output = ykman_cli('slot', 'calculate', '2', '999', '-T')
        self.assertEqual('533486', output.strip())
        output = ykman_cli('slot', 'calculate', '2', '999', '-T', '-d', '8')
        self.assertEqual('04533486', output.strip())
        output = ykman_cli('slot', 'calculate', '2', '-T')
        self.assertEqual(6, len(output.strip()))
        output = ykman_cli('slot', 'calculate', '2', '-T', '-d', '8')
        self.assertEqual(8, len(output.strip()))

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(
    not _has_mode(TRANSPORT.CCID),
    "CCID needs to be enabled for this test.")
class TestOpenPGP(unittest.TestCase):

    def test_openpgp_info(self):
        output = ykman_cli('openpgp', 'info')
        self.assertIn('OpenPGP version:', output)

    def test_openpgp_reset(self):
        output = ykman_cli('openpgp', 'reset', '-f')
        self.assertIn(
            'Success! All data has been cleared and default PINs are set.',
            output)

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(
    not _has_mode(TRANSPORT.CCID),
    "CCID needs to be enabled for this test.")
class TestOATH(unittest.TestCase):

    def test_oath_info(self):
        output = ykman_cli('oath', 'info')
        self.assertIn('OATH version:', output)

    def test_oath_add_credential(self):
        ykman_cli('oath', 'add', 'test-name', 'abba')
        creds = ykman_cli('oath', 'list')
        self.assertIn('test-name', creds)

    def test_oath_add_credential_with_space(self):
        ykman_cli('oath', 'add', 'test-name-space', 'ab ba')
        creds = ykman_cli('oath', 'list')
        self.assertIn('test-name-space', creds)

    def test_oath_hidden_cred(self):
        ykman_cli('oath', 'add', '_hidden:name', 'abba')
        creds = ykman_cli('oath', 'code')
        self.assertNotIn('_hidden:name', creds)
        creds = ykman_cli('oath', 'code', '-H')
        self.assertIn('_hidden:name', creds)

    def test_oath_add_uri_hotp(self):
        ykman_cli('oath', 'uri', URI_HOTP_EXAMPLE)
        creds = ykman_cli('oath', 'list')
        self.assertIn('Example:demo', creds)

    def test_oath_add_uri_totp(self):
        ykman_cli('oath', 'uri', URI_TOTP_EXAMPLE)
        creds = ykman_cli('oath', 'list')
        self.assertIn('john.doe', creds)

    def test_oath_code(self):
        ykman_cli('oath', 'add', 'test-name2', 'abba')
        creds = ykman_cli('oath', 'code')
        self.assertIn('test-name2', creds)

    def test_oath_reset(self):
        output = ykman_cli('oath', 'reset', '-f')
        self.assertIn(
            'Success! All credentials have been cleared from the device.',
            output)

    def test_oath_hotp_code(self):
        ykman_cli('oath', 'add', '-o', 'HOTP', 'hotp-cred', 'abba')
        cred = ykman_cli('oath', 'code', 'hotp-cred')
        self.assertIn('659165', cred)

    def test_oath_hotp_steam_code(self):
        ykman_cli('oath', 'add', '-o', 'HOTP', 'Steam:steam-cred', 'abba')
        cred = ykman_cli('oath', 'code', 'steam-cred')
        self.assertIn('CGC3K', cred)

    def test_oath_remove(self):
        ykman_cli('oath', 'add', 'remove-me', 'abba')
        ykman_cli('oath', 'remove', 'remove-me')
        self.assertNotIn('remove-me', ykman_cli('oath', 'list'))

@unittest.skipIf(_skip, "INTEGRATION_TESTS != TRUE")
@unittest.skipIf(not _one_yubikey, "A single YubiKey need to be connected.")
@unittest.skipIf(
    not _has_mode(TRANSPORT.CCID),
    "CCID needs to be enabled for this test.")
class TestPIV(unittest.TestCase):

    def test_piv_info(self):
        output = ykman_cli('piv', 'info')
        self.assertIn('PIV version:', output)

    def test_piv_reset(self):
        output = ykman_cli('piv', 'reset', '-f')
        self.assertIn('Success!', output)
<|endoftext|>