<commit_before>import time
import pypandoc
import os
import re
import csv
import string
import copy
from itertools import groupby
import yaml

LEXICON_COLUMN_DEFAULTS = {'word': 0, 'local': 1, 'part_of_speech': 3,
                           'definition': 5, 'pronunciation': 2}

base_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

with open(os.path.join(base_directory, 'themes', 'latex', 'Dictionary.tex')) as f:
    DICTIONARY_TEMPLATE = f.read()

DEFINITION_TEMPLATE = '''
$word
    $local_word ($part)

        $definition

'''

DICTIONARY_ENTRY_TEMPLATE = '''
\entry{$word}{$pronunciation}{$part_of_speech}{$local_word: $definition}
'''

HTML_DICTIONARY_TEMPLATE = '''
# Lexicon
$definitions
'''

HTML_DICTIONARY_ENTRY_TEMPLATE = '''

$word

$pronunciation, $part_of_speech

$local_word $definition

'''

METADATA_TEMPLATE = '''
---
title: $title
subtitle: $subtitle
author: $author
year: $year
papersize: $papersize
geometry: $geometry
fontsize: $fontsize
dictionary: $dictionary
---
'''

def generate(markdown_file_strings, lexicon_file, settings):
    print('Generate called!')
    concatenated_markdown = '\n'.join(markdown_file_strings)

    lexicon_columns = read_lexicon_columns(settings)

    print('LEXICON COLUMNS:')
    print(lexicon_columns)

    if settings['format'] == 'HTML':
        filename = generate_HTML(concatenated_markdown, lexicon_file,
                                 lexicon_columns=lexicon_columns,
                                 theme=settings['theme'],
                                 title=settings['grammarTitle'],
                                 subtitle=settings['grammarSubtitle'],
                                 author=settings['author'])
    elif settings['format'] == 'LaTeX PDF':
        filename = generate_latex(concatenated_markdown, lexicon_file,
                                  lexicon_columns=lexicon_columns,
                                  layout=settings['layout'],
                                  title=settings['grammarTitle'],
                                  subtitle=settings['grammarSubtitle'],
                                  author=settings['author'])

    return filename

def read_lexicon_columns(settings):
    '''Given a settings dictionary, return a lexicon columns dictionary.'''
    equivalents = {'csvColumnWord': 'word',
                   'csvColumnLocal': 'local',
                   'csvColumnDefinition': 'definition',
                   'csvColumnPronunciation': 'pronunciation',
                   'csvColumnPartOfSpeech': 'part_of_speech'}

    columns = {}

    # Add an entry to overrides for each column included in the request.
    for old, new in equivalents.items():
        if old in settings:
            columns[new] = int(settings[old]) - 1

    return columns

def generate_latex(markdown, lexicon, lexicon_columns=LEXICON_COLUMN_DEFAULTS,
                   title='My language', subtitle='A grammar',
                   author='An author', layout='A4'):
    '''Takes a markdown string, a lexicon CSV string, and a number of settings.
    Creates a PDF document and returns the filename.'''

    print('Generating LaTeX')
    template_directory = os.path.join(base_directory, 'themes', 'latex')
    image_path = os.path.join(template_directory, 'images')
    print('TEMPLATE DIRECTORY: ' + template_directory)
    # Create the lexicon as a LaTeX string.
    dictionary_string = create_latex_dictionary(lexicon, lexicon_columns)

    # Create a metadata block and add it to the beginning of the markdown
    # string.
    year = time.strftime('%Y')

    layouts = {'A4': {'papersize': 'a4paper',
                      'geometry':
                      'top=3cm,bottom=3cm,left=3cm,right=3cm,headsep=10pt,',
                      'fontsize': '11pt'},

               'A5': {'papersize': 'a5paper',
                      'geometry':
                      'top=1.5cm,bottom=1.5cm,left=1.75cm,right=1.75cm,headsep=10pt,',
                      'fontsize': '12pt'}}

    paper = layouts[layout]['papersize']
    font = layouts[layout]['fontsize']
    geometry = layouts[layout]['geometry']

    metadata = {'title': title, 'subtitle': subtitle, 'author': author, 'year':
                year, 'fontsize': font, 'papersize': paper, 'geometry':
                geometry, 'dictionary': dictionary_string,
                'imagepath': image_path}

    # Format metadata as YAML and add it before the rest of the file.
    markdown = '---\n' + yaml.dump(metadata) + '\n---\n' + markdown

    # Create list of pandoc settings, including template file
    pandoc_arguments = ['--standalone',
                        '--toc',
                        '--smart',
                        '--latex-engine=xelatex',
                        '--top-level-division=chapter']

    template_name = 'Default.tex'
    template_path = os.path.join(template_directory, template_name)
    pandoc_arguments.append('--template={0}'.format(template_path))
    print('TEMPLATE_PATH: ' +template_path)

    # Create temporary filename for output
    temp_filename = '{0}.pdf'.format(str(time.time()))
    temp_path = os.path.join(base_directory, 'temp', temp_filename)

    print('OUTPUT: ' + temp_filename)

    # Define the filters to use
    filter_path = os.path.join(base_directory, 'filters', 'LaTeX.py')

    print('Generating...')
    pypandoc.convert_text(markdown, format='md', to='pdf',
                          outputfile=temp_path,
                          extra_args=pandoc_arguments,
                          filters=[filter_path])
    print('Generated: ' + temp_filename)
    return temp_filename

def generate_HTML(markdown, lexicon, lexicon_columns=LEXICON_COLUMN_DEFAULTS,
                  theme='Default', title='My language', subtitle='A grammar',
                  author='An author'):
    '''Takes a markdown string, a lexicon CSV string, and a number of settings.
    Creates a full HTML document and returns the filename.'''

    # Create a metadata block and add it to the beginning of the markdown
    # string.
    metadata = {'title': title,
                'author': author,
                'date': time.strftime('%d/%m/%Y')}

    # Format metadata as YAML and add it before the rest of the file.
    markdown = '---\n' + yaml.dump(metadata) + '\n---\n' + markdown

    # Create the lexicon as a Markdown string and add it to the end of the
    # file.
    dictionary_string = create_html_dictionary(lexicon, lexicon_columns)
    markdown = markdown + dictionary_string

    # Create list of pandoc settings, including theme files
    pandoc_arguments = ['--standalone',
                        '--toc',
                        '--smart',
                        '--html-q-tags']

    html_name = '{0}.html'.format(theme)
    css_name = '{0}.css'.format(theme)

    theme_directory = os.path.join(base_directory, 'themes', 'html')

    header_files = [html_name, 'before.html', css_name, 'after.html']

    for filename in header_files:
        full_path = os.path.join(theme_directory, filename)
        pandoc_arguments.append('--include-in-header={0}'.format(full_path))

    # Define the filters to use
    filter_path = os.path.join(base_directory, 'filters', 'HTML.py')

    # Get the generated HTML as a string
    html = pypandoc.convert_text(markdown, format='md', to='html',
                                 extra_args=pandoc_arguments,
                                 filters=[filter_path])

    # Replace dictionary words in the HTML with their definitions
    html = load_words_from_lexicon(html, lexicon, lexicon_columns)

    # Save the HTML to a temporary file
    temp_filename = '{0}.html'.format(str(time.time()))

    with open(os.path.join(base_directory, 'temp', temp_filename), 'w') as f:
        f.write(html)

    return temp_filename

def create_html_dictionary(lexicon_string, lexicon_columns):
    '''Convert the given lexicon string to a Markdown dictionary string for use in
    HTML.'''
    definitions = ''

    # Group words by letter
    groups = get_lexicon_groups(lexicon_string, lexicon_columns)

    # If the lexicon is blank, don't include it
    if len(groups) == 0:
        return ''

    entry_template = string.Template(HTML_DICTIONARY_ENTRY_TEMPLATE)

    for group in groups:
        for word in group[1]:
            entry = entry_template.substitute(word)
            definitions += entry

    # Substitute the created string into the template.
    return string.Template(HTML_DICTIONARY_TEMPLATE).substitute(definitions=definitions)

def create_latex_dictionary(lexicon_string, lexicon_columns):
    '''Convert the given lexicon string to a LaTeX dictionary string.'''
    definitions = ''

    # Group words by letter
    groups = get_lexicon_groups(lexicon_string, lexicon_columns)

    # If the lexicon is blank, don't include it
    if len(groups) == 0:
        return ''

    entry_template = string.Template(DICTIONARY_ENTRY_TEMPLATE)

    for group in groups:
        # Add letter label
        definitions += '\\section*{' + group[0].upper() + '}'

        definitions += '\\begin{multicols*}{2}'

        for word in group[1]:
            entry = entry_template.substitute(word)
            definitions += entry

        definitions += '\\end{multicols*}'

    # Substitute the created string into the template.
    return string.Template(DICTIONARY_TEMPLATE).substitute(definitions=definitions)

def get_lexicon_groups(lexicon_string, lexicon_columns):
    '''Given a lexicon string, return a list. Each item is a tuple, where the first
    item is a letter and the second is a list of word dictionaries that begin with
    that letter.'''
    groups = []

    # Read the lexicon string as a CSV file, deleting the header row.
    lexicon_dicts = convert_lexicon(lexicon_string, lexicon_columns)

    # Convert to a list.
    lexicon = list(zip(lexicon_dicts.keys(), lexicon_dicts.values()))

    # Sort alphabetically
    lexicon = sorted(lexicon, key=lambda x: x[0])

    # Group by first letter
    for first_letter, words in groupby(lexicon, lambda x: x[0][0]):
        # Add the conlang word to each word dictionary
        modified_words = []
        for word in words:
            modified_word = word[1]
            modified_word['word'] = word[0]
            modified_words.append(modified_word)

        groups.append((first_letter, modified_words))

    return groups

def load_words_from_lexicon(html, lexicon_string, lexicon_columns):
    '''Replace all words surrounded by double curly braces in the HTML string
    (created by the filter) with their dictionary definition according to the
    given lexicon.'''

    # Read the lexicon string as a CSV file.
    lexicon = convert_lexicon(lexicon_string, lexicon_columns)

    match_list = re.findall(r'{{[a-z]*}}', html, re.I)

    for match in match_list:
        word = match[2:-2]
        try:
            local_word = lexicon[word]['local_word']
            definition = lexicon[word]['definition']
            part = lexicon[word]['part_of_speech']

            definition_block = string.Template(DEFINITION_TEMPLATE)
            definition_HTML = definition_block.substitute(word=word,
                                                          local_word=local_word,
                                                          definition=definition,
                                                          part=part)

            html = html.replace(match, definition_HTML)

        except KeyError:
            pass

    return html

def convert_lexicon(lexicon_string, lexicon_columns):
    '''Convert a lexicon string (CSV) to a dictionary. Each key is a word and
    each value is a dictionary containing information about the word.'''
    word_lines = list(csv.reader(lexicon_string.split('\n')))[1:]

    lexicon = {}
    for line in word_lines:
        try:
            word_data = {'local_word': line[lexicon_columns['local']],
                         'definition': line[lexicon_columns['definition']],
                         'pronunciation': line[lexicon_columns['pronunciation']],
                         'part_of_speech': line[lexicon_columns['part_of_speech']]}
            lexicon[line[lexicon_columns['word']]] = word_data

        except IndexError:
            # Ignore empty lines
            if len(line) != 0:
                error = ('Could not correctly read CSV file! '
                         'Check that your column numbers are correct. '
                         'The error appears in the line: ' + ','.join(line))
                raise Exception(error)

    return lexicon
<commit_msg>More debug<commit_after>import time
import pypandoc
import os
import re
import csv
import string
import copy
from itertools import groupby
import yaml

LEXICON_COLUMN_DEFAULTS = {'word': 0, 'local': 1, 'part_of_speech': 3,
                           'definition': 5, 'pronunciation': 2}

base_directory = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))

with open(os.path.join(base_directory, 'themes', 'latex', 'Dictionary.tex')) as f:
    DICTIONARY_TEMPLATE = f.read()

DEFINITION_TEMPLATE = '''
$word
    $local_word ($part)

        $definition

'''

DICTIONARY_ENTRY_TEMPLATE = '''
\entry{$word}{$pronunciation}{$part_of_speech}{$local_word: $definition}
'''

HTML_DICTIONARY_TEMPLATE = '''
# Lexicon
$definitions
'''

HTML_DICTIONARY_ENTRY_TEMPLATE = '''

$word

$pronunciation, $part_of_speech

$local_word $definition

'''

METADATA_TEMPLATE = '''
---
title: $title
subtitle: $subtitle
author: $author
year: $year
papersize: $papersize
geometry: $geometry
fontsize: $fontsize
dictionary: $dictionary
---
'''

def generate(markdown_file_strings, lexicon_file, settings):
    print('Generate called!')
    concatenated_markdown = '\n'.join(markdown_file_strings)

    lexicon_columns = read_lexicon_columns(settings)

    print('LEXICON COLUMNS:')
    print(lexicon_columns)

    if settings['format'] == 'HTML':
        filename = generate_HTML(concatenated_markdown, lexicon_file,
                                 lexicon_columns=lexicon_columns,
                                 theme=settings['theme'],
                                 title=settings['grammarTitle'],
                                 subtitle=settings['grammarSubtitle'],
                                 author=settings['author'])
    elif settings['format'] == 'LaTeX PDF':
        filename = generate_latex(concatenated_markdown, lexicon_file,
                                  lexicon_columns=lexicon_columns,
                                  layout=settings['layout'],
                                  title=settings['grammarTitle'],
                                  subtitle=settings['grammarSubtitle'],
                                  author=settings['author'])

    return filename

def read_lexicon_columns(settings):
    '''Given a settings dictionary, return a lexicon columns dictionary.'''
    equivalents = {'csvColumnWord': 'word',
                   'csvColumnLocal': 'local',
                   'csvColumnDefinition': 'definition',
                   'csvColumnPronunciation': 'pronunciation',
                   'csvColumnPartOfSpeech': 'part_of_speech'}

    columns = {}

    # Add an entry to overrides for each column included in the request.
    for old, new in equivalents.items():
        if old in settings:
            columns[new] = int(settings[old]) - 1

    return columns

def generate_latex(markdown, lexicon, lexicon_columns=LEXICON_COLUMN_DEFAULTS,
                   title='My language', subtitle='A grammar',
                   author='An author', layout='A4'):
    '''Takes a markdown string, a lexicon CSV string, and a number of settings.
    Creates a PDF document and returns the filename.'''

    print('Generating LaTeX')
    template_directory = os.path.join(base_directory, 'themes', 'latex')
    image_path = os.path.join(template_directory, 'images')
    print('TEMPLATE DIRECTORY: ' + template_directory)
    # Create the lexicon as a LaTeX string.
    dictionary_string = create_latex_dictionary(lexicon, lexicon_columns)

    # Create a metadata block and add it to the beginning of the markdown
    # string.
    year = time.strftime('%Y')

    layouts = {'A4': {'papersize': 'a4paper',
                      'geometry':
                      'top=3cm,bottom=3cm,left=3cm,right=3cm,headsep=10pt,',
                      'fontsize': '11pt'},

               'A5': {'papersize': 'a5paper',
                      'geometry':
                      'top=1.5cm,bottom=1.5cm,left=1.75cm,right=1.75cm,headsep=10pt,',
                      'fontsize': '12pt'}}

    paper = layouts[layout]['papersize']
    font = layouts[layout]['fontsize']
    geometry = layouts[layout]['geometry']

    metadata = {'title': title, 'subtitle': subtitle, 'author': author, 'year':
                year, 'fontsize': font, 'papersize': paper, 'geometry':
                geometry, 'dictionary': dictionary_string,
                'imagepath': image_path}

    # Format metadata as YAML and add it before the rest of the file.
    markdown = '---\n' + yaml.dump(metadata) + '\n---\n' + markdown

    # Create list of pandoc settings, including template file
    pandoc_arguments = ['--standalone',
                        '--toc',
                        '--smart',
                        '--latex-engine=xelatex',
                        '--top-level-division=chapter']

    template_name = 'Default.tex'
    template_path = os.path.join(template_directory, template_name)
    pandoc_arguments.append('--template={0}'.format(template_path))
    print('TEMPLATE_PATH: ' +template_path)

    # Create temporary filename for output
    temp_filename = '{0}.pdf'.format(str(time.time()))
    temp_path = os.path.join(base_directory, 'temp', temp_filename)

    print('OUTPUT: ' + temp_path)

    # Define the filters to use
    filter_path = os.path.join(base_directory, 'filters', 'LaTeX.py')

    print('Generating...')
    try:
        pypandoc.convert_text(markdown, format='md', to='pdf',
                            outputfile=temp_path,
                            extra_args=pandoc_arguments,
                            filters=[filter_path])
    except Exception as e:
        print(str(type(e).__name__) + ': ' + str(e))

    print('Generated: ' + temp_filename)
    return temp_filename

def generate_HTML(markdown, lexicon, lexicon_columns=LEXICON_COLUMN_DEFAULTS,
                  theme='Default', title='My language', subtitle='A grammar',
                  author='An author'):
    '''Takes a markdown string, a lexicon CSV string, and a number of settings.
    Creates a full HTML document and returns the filename.'''

    # Create a metadata block and add it to the beginning of the markdown
    # string.
    metadata = {'title': title,
                'author': author,
                'date': time.strftime('%d/%m/%Y')}

    # Format metadata as YAML and add it before the rest of the file.
    markdown = '---\n' + yaml.dump(metadata) + '\n---\n' + markdown

    # Create the lexicon as a Markdown string and add it to the end of the
    # file.
    dictionary_string = create_html_dictionary(lexicon, lexicon_columns)
    markdown = markdown + dictionary_string

    # Create list of pandoc settings, including theme files
    pandoc_arguments = ['--standalone',
                        '--toc',
                        '--smart',
                        '--html-q-tags']

    html_name = '{0}.html'.format(theme)
    css_name = '{0}.css'.format(theme)

    theme_directory = os.path.join(base_directory, 'themes', 'html')

    header_files = [html_name, 'before.html', css_name, 'after.html']

    for filename in header_files:
        full_path = os.path.join(theme_directory, filename)
        pandoc_arguments.append('--include-in-header={0}'.format(full_path))

    # Define the filters to use
    filter_path = os.path.join(base_directory, 'filters', 'HTML.py')

    # Get the generated HTML as a string
    html = pypandoc.convert_text(markdown, format='md', to='html',
                                 extra_args=pandoc_arguments,
                                 filters=[filter_path])

    # Replace dictionary words in the HTML with their definitions
    html = load_words_from_lexicon(html, lexicon, lexicon_columns)

    # Save the HTML to a temporary file
    temp_filename = '{0}.html'.format(str(time.time()))

    with open(os.path.join(base_directory, 'temp', temp_filename), 'w') as f:
        f.write(html)

    return temp_filename

def create_html_dictionary(lexicon_string, lexicon_columns):
    '''Convert the given lexicon string to a Markdown dictionary string for use in
    HTML.'''
    definitions = ''

    # Group words by letter
    groups = get_lexicon_groups(lexicon_string, lexicon_columns)

    # If the lexicon is blank, don't include it
    if len(groups) == 0:
        return ''

    entry_template = string.Template(HTML_DICTIONARY_ENTRY_TEMPLATE)

    for group in groups:
        for word in group[1]:
            entry = entry_template.substitute(word)
            definitions += entry

    # Substitute the created string into the template.
    return string.Template(HTML_DICTIONARY_TEMPLATE).substitute(definitions=definitions)

def create_latex_dictionary(lexicon_string, lexicon_columns):
    '''Convert the given lexicon string to a LaTeX dictionary string.'''
    definitions = ''

    # Group words by letter
    groups = get_lexicon_groups(lexicon_string, lexicon_columns)

    # If the lexicon is blank, don't include it
    if len(groups) == 0:
        return ''

    entry_template = string.Template(DICTIONARY_ENTRY_TEMPLATE)

    for group in groups:
        # Add letter label
        definitions += '\\section*{' + group[0].upper() + '}'

        definitions += '\\begin{multicols*}{2}'

        for word in group[1]:
            entry = entry_template.substitute(word)
            definitions += entry

        definitions += '\\end{multicols*}'

    # Substitute the created string into the template.
    return string.Template(DICTIONARY_TEMPLATE).substitute(definitions=definitions)

def get_lexicon_groups(lexicon_string, lexicon_columns):
    '''Given a lexicon string, return a list. Each item is a tuple, where the first
    item is a letter and the second is a list of word dictionaries that begin with
    that letter.'''
    groups = []

    # Read the lexicon string as a CSV file, deleting the header row.
    lexicon_dicts = convert_lexicon(lexicon_string, lexicon_columns)

    # Convert to a list.
    lexicon = list(zip(lexicon_dicts.keys(), lexicon_dicts.values()))

    # Sort alphabetically
    lexicon = sorted(lexicon, key=lambda x: x[0])

    # Group by first letter
    for first_letter, words in groupby(lexicon, lambda x: x[0][0]):
        # Add the conlang word to each word dictionary
        modified_words = []
        for word in words:
            modified_word = word[1]
            modified_word['word'] = word[0]
            modified_words.append(modified_word)

        groups.append((first_letter, modified_words))

    return groups

def load_words_from_lexicon(html, lexicon_string, lexicon_columns):
    '''Replace all words surrounded by double curly braces in the HTML string
    (created by the filter) with their dictionary definition according to the
    given lexicon.'''

    # Read the lexicon string as a CSV file.
    lexicon = convert_lexicon(lexicon_string, lexicon_columns)

    match_list = re.findall(r'{{[a-z]*}}', html, re.I)

    for match in match_list:
        word = match[2:-2]
        try:
            local_word = lexicon[word]['local_word']
            definition = lexicon[word]['definition']
            part = lexicon[word]['part_of_speech']

            definition_block = string.Template(DEFINITION_TEMPLATE)
            definition_HTML = definition_block.substitute(word=word,
                                                          local_word=local_word,
                                                          definition=definition,
                                                          part=part)

            html = html.replace(match, definition_HTML)

        except KeyError:
            pass

    return html

def convert_lexicon(lexicon_string, lexicon_columns):
    '''Convert a lexicon string (CSV) to a dictionary. Each key is a word and
    each value is a dictionary containing information about the word.'''
    word_lines = list(csv.reader(lexicon_string.split('\n')))[1:]

    lexicon = {}
    for line in word_lines:
        try:
            word_data = {'local_word': line[lexicon_columns['local']],
                         'definition': line[lexicon_columns['definition']],
                         'pronunciation': line[lexicon_columns['pronunciation']],
                         'part_of_speech': line[lexicon_columns['part_of_speech']]}
            lexicon[line[lexicon_columns['word']]] = word_data

        except IndexError:
            # Ignore empty lines
            if len(line) != 0:
                error = ('Could not correctly read CSV file! '
                         'Check that your column numbers are correct. '
                         'The error appears in the line: ' + ','.join(line))
                raise Exception(error)

    return lexicon
<|endoftext|>


<commit_before>from spack import *

class Boost(Package):
    """Boost provides free peer-reviewed portable C++ source
       libraries, emphasizing libraries that work well with the C++
       Standard Library.

       Boost libraries are intended to be widely useful, and usable
       across a broad spectrum of applications. The Boost license
       encourages both commercial and non-commercial use.
    """
    homepage = "http://www.boost.org"
    url      = "http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2"
    list_url = "http://sourceforge.net/projects/boost/files/boost/"
    list_depth = 2

    version('1.59.0', '6aa9a5c6a4ca1016edd0ed1178e3cb87')
    version('1.58.0', 'b8839650e61e9c1c0a89f371dd475546')
    version('1.57.0', '1be49befbdd9a5ce9def2983ba3e7b76')
    version('1.56.0', 'a744cf167b05d72335f27c88115f211d')
    version('1.55.0', 'd6eef4b4cacb2183f2bf265a5a03a354')
    version('1.54.0', '15cb8c0803064faef0c4ddf5bc5ca279')
    version('1.53.0', 'a00d22605d5dbcfb4c9936a9b35bc4c2')
    version('1.52.0', '3a855e0f919107e0ca4de4d84ad3f750')
    version('1.51.0', '4b6bd483b692fd138aef84ed2c8eb679')
    version('1.50.0', '52dd00be775e689f55a987baebccc462')
    version('1.49.0', '0d202cb811f934282dea64856a175698')
    version('1.48.0', 'd1e9a7a7f532bb031a3c175d86688d95')
    version('1.47.0', 'a2dc343f7bc7f83f8941e47ed4a18200')
    version('1.46.1', '7375679575f4c8db605d426fc721d506')
    version('1.46.0', '37b12f1702319b73876b0097982087e0')
    version('1.45.0', 'd405c606354789d0426bc07bea617e58')
    version('1.44.0', 'f02578f5218f217a9f20e9c30e119c6a')
    version('1.43.0', 'dd49767bfb726b0c774f7db0cef91ed1')
    version('1.42.0', '7bf3b4eb841b62ffb0ade2b82218ebe6')
    version('1.41.0', '8bb65e133907db727a2a825c5400d0a6')
    version('1.40.0', 'ec3875caeac8c52c7c129802a8483bd7')
    version('1.39.0', 'a17281fd88c48e0d866e1a12deecbcc0')
    version('1.38.0', '5eca2116d39d61382b8f8235915cb267')
    version('1.37.0', '8d9f990bfb7e83769fa5f1d6f065bc92')
    version('1.36.0', '328bfec66c312150e4c2a78dcecb504b')
    version('1.35.0', 'dce952a7214e72d6597516bcac84048b')
    version('1.34.1', '2d938467e8a448a2c9763e0a9f8ca7e5')
    version('1.34.0', 'ed5b9291ffad776f8757a916e1726ad0')

    variant('debug', default=False, description='Switch to the debug version of Boost')
    variant('python', default=False, description='Activate the component Boost.Python')
    variant('mpi', default=False, description='Activate the component Boost.MPI')
    variant('compression', default=True, description='Activate the compression Boost.iostreams')

    depends_on('mpi', when='+mpi')
    depends_on('python', when='+python')
    depends_on('zlib', when='+compression')
    depends_on('bzip2', when='+compression')

    def url_for_version(self, version):
        """Handle Boost's weird URLs, which write the version two different ways."""
        parts = [str(p) for p in Version(version)]
        dots = ".".join(parts)
        underscores = "_".join(parts)
        return "http://downloads.sourceforge.net/project/boost/boost/%s/boost_%s.tar.bz2" % (
            dots, underscores)

    def determine_toolset(self):
        toolsets = {'gcc': 'gcc',
                    'icpc': 'intel',
                    'clang++': 'clang'}

        for cc, toolset in toolsets.iteritems():
            if(cc in self.compiler.cxx_names):
                return toolset

        # fallback to gcc if no toolset found
        return 'gcc'

    def determine_bootstrap_options(self, spec, options):
        options.append('--with-toolset=%s' % self.determine_toolset())

        without_libs = []
        if '~mpi' in spec:
            without_libs.append('mpi')
        if '~python' in spec:
            without_libs.append('python')
        else:
            options.append('--with-python=%s' % (spec['python'].prefix.bin + '/python'))

        if without_libs:
            options.append('--without-libraries=%s' % ','.join(without_libs))

        with open('user-config.jam', 'w') as f:
            if '+mpi' in spec:
                f.write('using mpi : %s ;\n' % (spec['mpi'].prefix.bin + '/mpicxx'))
            if '+python' in spec:
                f.write('using python : %s : %s ;\n' % (spec['python'].version,
                                                      (spec['python'].prefix.bin + '/python')))

    def determine_b2_options(self, spec, options):
        if '+debug' in spec:
            options.append('variant=debug')
        else:
            options.append('variant=release')

        if '~compression' in spec:
            options.extend(['-s NO_BZIP2=1',
                            '-s NO_ZLIB=1',
            ])

        if '+compression' in spec:
            options.extend(['-s BZIP2_INCLUDE=%s' % spec['bzip2'].prefix.include,
                            '-s BZIP2_LIBPATH=%s' % spec['bzip2'].prefix.lib,
                            '-s ZLIB_INCLUDE=%s' % spec['zlib'].prefix.include,
                            '-s ZLIB_LIBPATH=%s' % spec['zlib'].prefix.lib])

        options.extend(['toolset=%s' % self.determine_toolset(),
                       'link=static,shared',
                       '--layout=tagged'])

    def install(self, spec, prefix):
        # to make him find the user-config.jam
        env['BOOST_BUILD_PATH'] = './'

        bootstrap = Executable('./bootstrap.sh')

        bootstrap_options = ['--prefix=%s' % prefix]
        self.determine_bootstrap_options(spec, bootstrap_options)

        bootstrap(*bootstrap_options)

        # b2 used to be called bjam, before 1.47 (sigh)
        b2name = './b2' if spec.satisfies('@1.47:') else './bjam'

        b2 = Executable(b2name)
        b2_options = ['-j %s' % make_jobs]

        self.determine_b2_options(spec, b2_options)

        b2('install', 'threading=single', *b2_options)
        b2('install', 'threading=multi', *b2_options)
<commit_msg>Support Darwin for Boost<commit_after>from spack import *

class Boost(Package):
    """Boost provides free peer-reviewed portable C++ source
       libraries, emphasizing libraries that work well with the C++
       Standard Library.

       Boost libraries are intended to be widely useful, and usable
       across a broad spectrum of applications. The Boost license
       encourages both commercial and non-commercial use.
    """
    homepage = "http://www.boost.org"
    url      = "http://downloads.sourceforge.net/project/boost/boost/1.55.0/boost_1_55_0.tar.bz2"
    list_url = "http://sourceforge.net/projects/boost/files/boost/"
    list_depth = 2

    version('1.60.0', '65a840e1a0b13a558ff19eeb2c4f0cbe')
    version('1.59.0', '6aa9a5c6a4ca1016edd0ed1178e3cb87')
    version('1.58.0', 'b8839650e61e9c1c0a89f371dd475546')
    version('1.57.0', '1be49befbdd9a5ce9def2983ba3e7b76')
    version('1.56.0', 'a744cf167b05d72335f27c88115f211d')
    version('1.55.0', 'd6eef4b4cacb2183f2bf265a5a03a354')
    version('1.54.0', '15cb8c0803064faef0c4ddf5bc5ca279')
    version('1.53.0', 'a00d22605d5dbcfb4c9936a9b35bc4c2')
    version('1.52.0', '3a855e0f919107e0ca4de4d84ad3f750')
    version('1.51.0', '4b6bd483b692fd138aef84ed2c8eb679')
    version('1.50.0', '52dd00be775e689f55a987baebccc462')
    version('1.49.0', '0d202cb811f934282dea64856a175698')
    version('1.48.0', 'd1e9a7a7f532bb031a3c175d86688d95')
    version('1.47.0', 'a2dc343f7bc7f83f8941e47ed4a18200')
    version('1.46.1', '7375679575f4c8db605d426fc721d506')
    version('1.46.0', '37b12f1702319b73876b0097982087e0')
    version('1.45.0', 'd405c606354789d0426bc07bea617e58')
    version('1.44.0', 'f02578f5218f217a9f20e9c30e119c6a')
    version('1.43.0', 'dd49767bfb726b0c774f7db0cef91ed1')
    version('1.42.0', '7bf3b4eb841b62ffb0ade2b82218ebe6')
    version('1.41.0', '8bb65e133907db727a2a825c5400d0a6')
    version('1.40.0', 'ec3875caeac8c52c7c129802a8483bd7')
    version('1.39.0', 'a17281fd88c48e0d866e1a12deecbcc0')
    version('1.38.0', '5eca2116d39d61382b8f8235915cb267')
    version('1.37.0', '8d9f990bfb7e83769fa5f1d6f065bc92')
    version('1.36.0', '328bfec66c312150e4c2a78dcecb504b')
    version('1.35.0', 'dce952a7214e72d6597516bcac84048b')
    version('1.34.1', '2d938467e8a448a2c9763e0a9f8ca7e5')
    version('1.34.0', 'ed5b9291ffad776f8757a916e1726ad0')

    variant('debug', default=False, description='Switch to the debug version of Boost')
    variant('python', default=False, description='Activate the component Boost.Python')
    variant('mpi', default=False, description='Activate the component Boost.MPI')
    variant('compression', default=True, description='Activate the compression Boost.iostreams')

    depends_on('python', when='+python')
    depends_on('mpi', when='+mpi')
    depends_on('bzip2', when='+compression')
    depends_on('zlib', when='+compression')

    def url_for_version(self, version):
        """Handle Boost's weird URLs, which write the version two different ways."""
        parts = [str(p) for p in Version(version)]
        dots = ".".join(parts)
        underscores = "_".join(parts)
        return "http://downloads.sourceforge.net/project/boost/boost/%s/boost_%s.tar.bz2" % (
            dots, underscores)

    def determine_toolset(self, spec):
        if spec.satisfies("=darwin-x86_64"):
            return 'darwin'

        toolsets = {'g++': 'gcc',
                    'icpc': 'intel',
                    'clang++': 'clang'}

        for cc, toolset in toolsets.iteritems():
            if cc in self.compiler.cxx_names:
                return toolset

        # fallback to gcc if no toolset found
        return 'gcc'

    def determine_bootstrap_options(self, spec, options):
        options.append('--with-toolset=%s' % self.determine_toolset(spec))

        without_libs = []
        if '~mpi' in spec:
            without_libs.append('mpi')
        if '~python' in spec:
            without_libs.append('python')
        else:
            options.append('--with-python=%s' %
                join_path(spec['python'].prefix.bin, 'python'))

        if without_libs:
            options.append('--without-libraries=%s' % ','.join(without_libs))

        with open('user-config.jam', 'w') as f:
            if '+mpi' in spec:
                f.write('using mpi : %s ;\n' %
                    joinpath(spec['mpi'].prefix.bin, 'mpicxx'))
            if '+python' in spec:
                f.write('using python : %s : %s ;\n' %
                    (spec['python'].version,
                    joinpath(spec['python'].prefix.bin, 'python')))

    def determine_b2_options(self, spec, options):
        if '+debug' in spec:
            options.append('variant=debug')
        else:
            options.append('variant=release')

        if '~compression' in spec:
            options.extend([
                '-s', 'NO_BZIP2=1',
                '-s', 'NO_ZLIB=1'])

        if '+compression' in spec:
            options.extend([
                '-s', 'BZIP2_INCLUDE=%s' % spec['bzip2'].prefix.include,
                '-s', 'BZIP2_LIBPATH=%s' % spec['bzip2'].prefix.lib,
                '-s', 'ZLIB_INCLUDE=%s' % spec['zlib'].prefix.include,
                '-s', 'ZLIB_LIBPATH=%s' % spec['zlib'].prefix.lib,
                ])

        options.extend([
            'toolset=%s' % self.determine_toolset(spec),
            'link=static,shared',
            'threading=single,multi',
            '--layout=tagged'])

    def install(self, spec, prefix):
        # to make Boost find the user-config.jam
        env['BOOST_BUILD_PATH'] = './'

        bootstrap = Executable('./bootstrap.sh')

        bootstrap_options = ['--prefix=%s' % prefix]
        self.determine_bootstrap_options(spec, bootstrap_options)

        bootstrap(*bootstrap_options)

        # b2 used to be called bjam, before 1.47 (sigh)
        b2name = './b2' if spec.satisfies('@1.47:') else './bjam'

        b2 = Executable(b2name)
        b2_options = ['-j', '%s' % make_jobs]

        self.determine_b2_options(spec, b2_options)

        b2('install', *b2_options)
<|endoftext|>


<commit_before>#!/usr/bin/python

import os
import csv

import sys
sys.path.append('../pynipap')
import pynipap

class Export:
	def __init__(self, xmlrpc_uri):
		self.xmlrpc_uri = xmlrpc_uri

	def write(self, output_file, schema_name):
		"""
		"""
		f = open(output_file, "w+")
		writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL)

		pynipap.xmlrpc_uri = xmlrpc_uri
		ao = pynipap.AuthOptions({ 'authoritative_source': 'nipap' })

		import socket,xmlrpclib
		try:
			schema = pynipap.Schema.list({ 'name': schema_name })[0]
		except socket.error:
			print >> sys.stderr, "Connection refused, please check hostname & port"
			sys.exit(1)
		except xmlrpclib.ProtocolError:
			print >> sys.stderr, "Authentication failed, please check your username / password"
			sys.exit(1)
		except IndexError:
			print >> sys.stderr, "Non existing schema (", schema_name, ")"
			sys.exit(1)

		res = pynipap.Prefix.smart_search(schema, ' ', { 'include_all_parents': True })
		for p in res['result']:
			writer.writerow([p.display_prefix, p.type, p.node, p.order_id, p.description])

if __name__ == '__main__':
	import optparse
	parser = optparse.OptionParser()
	parser.add_option('--username', default='', help="Username")
	parser.add_option('--password', default='', help="Password")
	parser.add_option('--host', help="NIPAP backend host")
	parser.add_option('--port', default=1337, help="NIPAP backend port")
	parser.add_option('--schema', help="Schema name")
	parser.add_option('--file', help="Output file")

	(options, args) = parser.parse_args()

	if options.host is None:
		print >> sys.stderr, "Please specify the NIPAP backend host to work with"
		sys.exit(1)

	if options.schema is None:
		print >> sys.stderr, "Please specify a schema to export"
		sys.exit(1)

	if options.file is None:
		print >> sys.stderr, "Please specify an output file"
		sys.exit(1)

	auth_uri = ''
	if options.username:
		auth_uri = "%s:%s@" % (options.username, options.password)

	xmlrpc_uri = "http://%(auth_uri)s%(host)s:%(port)s" % {
			'auth_uri'	: auth_uri,
			'host'		: options.host,
			'port'		: options.port
			}

	wr = Export(xmlrpc_uri)
	wr.write(options.file, options.schema)
<commit_msg>Freshen up example CSV export script<commit_after>#!/usr/bin/python

import os
import csv

import sys
sys.path.append('../pynipap')
import pynipap

class Export:
    def __init__(self, xmlrpc_uri):
        self.xmlrpc_uri = xmlrpc_uri

    def write(self, output_file, query):
        """
        """
        f = open(output_file, "w+")
        writer = csv.writer(f, quoting=csv.QUOTE_MINIMAL)

        pynipap.xmlrpc_uri = xmlrpc_uri
        ao = pynipap.AuthOptions({ 'authoritative_source': 'nipap' })

        import socket,xmlrpclib
        try:
            res = pynipap.Prefix.smart_search(query, {})
        except socket.error:
            print >> sys.stderr, "Connection refused, please check hostname & port"
            sys.exit(1)
        except xmlrpclib.ProtocolError:
            print >> sys.stderr, "Authentication failed, please check your username / password"
            sys.exit(1)

        for p in res['result']:
            print p.vrf.rt
            writer.writerow([p.vrf.rt, p.display_prefix, p.type, p.node, p.order_id, p.description])

if __name__ == '__main__':
    import optparse
    parser = optparse.OptionParser()
    parser.add_option('--username', default='', help="Username")
    parser.add_option('--password', default='', help="Password")
    parser.add_option('--host', help="NIPAP backend host")
    parser.add_option('--port', default=1337, help="NIPAP backend port")
    parser.add_option('--query', default = '', help="A prefix query string")
    parser.add_option('--file', help="Output file")

    (options, args) = parser.parse_args()

    if options.host is None:
        print >> sys.stderr, "Please specify the NIPAP backend host to work with"
        sys.exit(1)

    if options.file is None:
        print >> sys.stderr, "Please specify an output file"
        sys.exit(1)

    auth_uri = ''
    if options.username:
        auth_uri = "%s:%s@" % (options.username, options.password)

    xmlrpc_uri = "http://%(auth_uri)s%(host)s:%(port)s" % {
            'auth_uri'  : auth_uri,
            'host'      : options.host,
            'port'      : options.port
            }

    wr = Export(xmlrpc_uri)
    wr.write(options.file, options.query)
<|endoftext|>


<commit_before>"""
main script to run all analyses for MyConnectome paper
"""

import os,sys

try:
    import myconnectome
except:
    print 'you first need to install the myconnectome python package'
    sys.exit(0)

from myconnectome.utils import run_shell_cmd

good_to_go=True
# check for environment variables

## 1 for required, 0 for recommended
envvars={'MYCONNECTOME_DIR':1,'WORKBENCH_BIN_DIR':1,'DAVID_EMAIL':0}

messages=[]
for v in envvars.keys():
    try:
        os.environ[v]
    except:
        if envvars[v]:
            good_to_go=False
            messages.append('environment variable %s must be specified'%v)
        else:
            print 'environment variable %s recommended but not required'%v
if good_to_go:
    print 'all environment variables present'

# check for suitable version of R
whichR=run_shell_cmd.run_shell_cmd('which R 2> /dev/null')
if len(whichR)==0:
    good_to_go=False
    messages.append('you need to install R, version 3.0 or newer')
else:
    rver=run_shell_cmd.run_shell_cmd('R --version 2> /dev/null')
    rversion=rver[0].split(' ')[2]
    print 'Found R version',rversion
    if int(rversion.split('.')[0]) <3:
        good_to_go=False
        messages.append('you need to install R, version 3.0 or newer')

whichmatlab=run_shell_cmd.run_shell_cmd('which matlab 2> /dev/null')
if len(whichmatlab)==0:
    print 'MATLAB was not detected - precomputed results will be downloaded'

if not good_to_go:
    print 'Problems detected'
    for m in messages:
        print m

    sys.exit(0)

# otherwise, run all of the scripts
filepath=os.path.dirname(os.path.abspath(__file__))
basepath=os.path.dirname(filepath)

execfile('%s/rsfmri_analysis.py'%basepath)

<commit_msg>added other modules<commit_after>"""
main script to run all analyses for MyConnectome paper
"""

import os,sys

try:
    import myconnectome
except:
    print 'you first need to install the myconnectome python package'
    sys.exit(0)

from myconnectome.utils import run_shell_cmd

good_to_go=True
# check for environment variables

## 1 for required, 0 for recommended
envvars={'MYCONNECTOME_DIR':1,'WORKBENCH_BIN_DIR':1,'DAVID_EMAIL':0}

messages=[]
for v in envvars.keys():
    try:
        os.environ[v]
    except:
        if envvars[v]:
            good_to_go=False
            messages.append('environment variable %s must be specified'%v)
        else:
            print 'environment variable %s recommended but not required'%v
if good_to_go:
    print 'all environment variables present'

# check for suitable version of R
whichR=run_shell_cmd.run_shell_cmd('which R 2> /dev/null')
if len(whichR)==0:
    good_to_go=False
    messages.append('you need to install R, version 3.0 or newer')
else:
    rver=run_shell_cmd.run_shell_cmd('R --version 2> /dev/null')
    rversion=rver[0].split(' ')[2]
    print 'Found R version',rversion
    if int(rversion.split('.')[0]) <3:
        good_to_go=False
        messages.append('you need to install R, version 3.0 or newer')

whichmatlab=run_shell_cmd.run_shell_cmd('which matlab 2> /dev/null')
if len(whichmatlab)==0:
    print 'MATLAB was not detected - precomputed results will be downloaded'

if not good_to_go:
    print 'Problems detected'
    for m in messages:
        print m

    sys.exit(0)

# otherwise, run all of the scripts
filepath=os.path.dirname(os.path.abspath(__file__))
basepath=os.path.dirname(filepath)

execfile('%s/scripts/rsfmri_analysis.py'%basepath)

execfile('%s/scripts/rnaseq_analysis.py'%basepath)

execfile('%s/scripts/metabolomic_analysis.py'%basepath)

execfile('%s/scripts/timeseries_analysis.py'%basepath)
<|endoftext|>


<commit_before>import re

__all__ = (
    'Email', 'email', 'EqualTo', 'equal_to', 'IPAddress', 'ip_address',
    'Length', 'length', 'NumberRange', 'number_range', 'Optional', 'optional',
    'Required', 'required', 'Regexp', 'regexp', 'URL', 'url', 'AnyOf',
    'any_of', 'NoneOf', 'none_of'
)

class ValidationError(ValueError):
    """
    Raised when a validator fails to validate its input.
    """
    def __init__(self, message=u'', *args, **kwargs):
        ValueError.__init__(self, message, *args, **kwargs)

class StopValidation(Exception):
    """
    Causes the validation chain to stop.

    If StopValidation is raised, no more validators in the validation chain are
    called. If raised with a message, the message will be added to the errors
    list.
    """
    def __init__(self, message=u'', *args, **kwargs):
        Exception.__init__(self, message, *args, **kwargs)

class EqualTo(object):
    """
    Compares the values of two fields.

    :param fieldname:
        The name of the other field to compare to.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated with `%(other_label)s` and `%(other_name)s` to provide a
        more helpful error.
    """
    def __init__(self, fieldname, message=None):
        self.fieldname = fieldname
        self.message = message

    def __call__(self, form, field):
        try:
            other = form[self.fieldname]
        except KeyError:
            raise ValidationError(field.gettext(u"Invalid field name '%s'.") % self.fieldname)
        if field.data != other.data:
            d = {
                'other_label': hasattr(other, 'label') and other.label.text or self.fieldname,
                'other_name': self.fieldname
            }
            if self.message is None:
                self.message = field.gettext(u'Field must be equal to %(other_name)s.')

            raise ValidationError(self.message % d)

class Length(object):
    """
    Validates the length of a string.

    :param min:
        The minimum required length of the string. If not provided, minimum
        length will not be checked.
    :param max:
        The maximum length of the string. If not provided, maximum length
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)d` and `%(max)d` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """
    def __init__(self, min=-1, max=-1, message=None):
        assert min != -1 or max!=-1, 'At least one of `min` or `max` must be specified.'
        assert max == -1 or min <= max, '`min` cannot be more than `max`.'
        self.min = min
        self.max = max
        self.message = message

    def __call__(self, form, field):
        l = field.data and len(field.data) or 0
        if l < self.min or self.max != -1 and l > self.max:
            if self.message is None:
                if self.max == -1:
                    self.message = field.ngettext(u'Field must be at least %(min)d character long.',
                                                  u'Field must be at least %(min)d characters long.', self.min)
                elif self.min == -1:
                    self.message = field.ngettext(u'Field cannot be longer than %(max)d character.',
                                                  u'Field cannot be longer than %(max)d characters.', self.max)
                else:
                    self.message = field.gettext(u'Field must be between %(min)d and %(max)d characters long.')

            raise ValidationError(self.message % dict(min=self.min, max=self.max))

class NumberRange(object):
    """
    Validates that a number is of a minimum and/or maximum value, inclusive.
    This will work with any comparable number type, such as floats and
    decimals, not just integers.

    :param min:
        The minimum required value of the number. If not provided, minimum
        value will not be checked.
    :param max:
        The maximum value of the number. If not provided, maximum value
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)s` and `%(max)s` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """
    def __init__(self, min=None, max=None, message=None):
        self.min = min
        self.max = max
        self.message = message

    def __call__(self, form, field):
        data = field.data
        if data is None or (self.min is not None and data < self.min) or \
            (self.max is not None and data > self.max):
            if self.message is None:
                # we use %(min)s interpolation to support floats, None, and
                # Decimals without throwing a formatting exception.
                if self.max is None:
                    self.message = field.gettext(u'Number must be greater than %(min)s.')
                elif self.min is None:
                    self.message = field.gettext(u'Number must be less than %(max)s.')
                else:
                    self.message = field.gettext(u'Number must be between %(min)s and %(max)s.')

            raise ValidationError(self.message % dict(min=self.min, max=self.max))

class Optional(object):
    """
    Allows empty input and stops the validation chain from continuing.

    If input is empty, also removes prior errors (such as processing errors)
    from the field.
    """
    field_flags = ('optional', )

    def __call__(self, form, field):
        if not field.raw_data or isinstance(field.raw_data[0], basestring) and not field.raw_data[0].strip():
            field.errors[:] = []
            raise StopValidation()

class Required(object):
    """
    Validates that the field contains data. This validator will stop the
    validation chain on error.

    :param message:
        Error message to raise in case of a validation error.
    """
    field_flags = ('required', )

    def __init__(self, message=None):
        self.message = message

    def __call__(self, form, field):
        if not field.data or isinstance(field.data, basestring) and not field.data.strip():
            if self.message is None:
                self.message = field.gettext(u'This field is required.')

            field.errors[:] = []
            raise StopValidation(self.message)

class Regexp(object):
    """
    Validates the field against a user provided regexp.

    :param regex:
        The regular expression string to use. Can also be a compiled regular
        expression pattern.
    :param flags:
        The regexp flags to use, for example re.IGNORECASE. Ignored if
        `regex` is not a string.
    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, regex, flags=0, message=None):
        if isinstance(regex, basestring):
            regex = re.compile(regex, flags)
        self.regex = regex
        self.message = message

    def __call__(self, form, field):
        if not self.regex.match(field.data or u''):
            if self.message is None:
                self.message = field.gettext(u'Invalid input.')

            raise ValidationError(self.message)

class Email(Regexp):
    """
    Validates an email address. Note that this uses a very primitive regular
    expression and should only be used in instances where you later verify by
    other means, such as email activation or lookups.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):
        super(Email, self).__init__(r'^.+@[^.].*\.[a-z]{2,10}$', re.IGNORECASE, message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid email address.')

        super(Email, self).__call__(form, field)

class IPAddress(Regexp):
    """
    Validates an IP(v4) address.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):
        super(IPAddress, self).__init__(r'^([0-9]{1,3}\.){3}[0-9]{1,3}$', message=message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid IP address.')

        super(IPAddress, self).__call__(form, field)

class MacAddress(Regexp):
    """
    Validates a Mac address.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):

        super(MacAddress, self).__init__(
            r'^((?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2})\s+(.*)$', message=message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid Mac address.')

        super(MacAddress, self).__call__(form, field)

class URL(Regexp):
    """
    Simple regexp based url validation. Much like the email validator, you
    probably want to validate the url later by other means if the url must
    resolve.

    :param require_tld:
        If true, then the domain-name portion of the URL must contain a .tld
        suffix.  Set this to false if you want to allow domains like
        `localhost`.
    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, require_tld=True, message=None):
        tld_part = (require_tld and ur'\.[a-z]{2,10}' or u'')
        regex = ur'^[a-z]+://([^/:]+%s|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]+)?(\/.*)?$' % tld_part
        super(URL, self).__init__(regex, re.IGNORECASE, message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid URL.')

        super(URL, self).__call__(form, field)

class AnyOf(object):
    """
    Compares the incoming data to a sequence of valid inputs.

    :param values:
        A sequence of valid inputs.
    :param message:
        Error message to raise in case of a validation error. `%(values)s`
        contains the list of values.
    :param values_formatter:
        Function used to format the list of values in the error message.
    """
    def __init__(self, values, message=None, values_formatter=None):
        self.values = values
        self.message = message
        if values_formatter is None:
            values_formatter = lambda v: u', '.join(v)
        self.values_formatter = values_formatter

    def __call__(self, form, field):
        if field.data not in self.values:
            if self.message is None:
                self.message = field.gettext(u'Invalid value, must be one of: %(values)s.')

            raise ValueError(self.message % dict(values=self.values_formatter(self.values)))

class NoneOf(object):
    """
    Compares the incoming data to a sequence of invalid inputs.

    :param values:
        A sequence of invalid inputs.
    :param message:
        Error message to raise in case of a validation error. `%(values)s`
        contains the list of values.
    :param values_formatter:
        Function used to format the list of values in the error message.
    """
    def __init__(self, values, message=None, values_formatter=None):
        self.values = values
        self.message = message
        if values_formatter is None:
            values_formatter = lambda v: u', '.join(v)
        self.values_formatter = values_formatter

    def __call__(self, form, field):
        if field.data in self.values:
            if self.message is None:
                self.message = field.gettext(u'Invalid value, can\'t be any of: %(values)s.')

            raise ValueError(self.message % dict(values=self.values_formatter(self.values)))

email = Email
equal_to = EqualTo
ip_address = IPAddress
length = Length
number_range = NumberRange
optional = Optional
required = Required
regexp = Regexp
url = URL
any_of = AnyOf
none_of = NoneOf
<commit_msg>fixed regex for mac address.<commit_after>import re

__all__ = (
    'Email', 'email', 'EqualTo', 'equal_to', 'IPAddress', 'ip_address',
    'Length', 'length', 'NumberRange', 'number_range', 'Optional', 'optional',
    'Required', 'required', 'Regexp', 'regexp', 'URL', 'url', 'AnyOf',
    'any_of', 'NoneOf', 'none_of'
)

class ValidationError(ValueError):
    """
    Raised when a validator fails to validate its input.
    """
    def __init__(self, message=u'', *args, **kwargs):
        ValueError.__init__(self, message, *args, **kwargs)

class StopValidation(Exception):
    """
    Causes the validation chain to stop.

    If StopValidation is raised, no more validators in the validation chain are
    called. If raised with a message, the message will be added to the errors
    list.
    """
    def __init__(self, message=u'', *args, **kwargs):
        Exception.__init__(self, message, *args, **kwargs)

class EqualTo(object):
    """
    Compares the values of two fields.

    :param fieldname:
        The name of the other field to compare to.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated with `%(other_label)s` and `%(other_name)s` to provide a
        more helpful error.
    """
    def __init__(self, fieldname, message=None):
        self.fieldname = fieldname
        self.message = message

    def __call__(self, form, field):
        try:
            other = form[self.fieldname]
        except KeyError:
            raise ValidationError(field.gettext(u"Invalid field name '%s'.") % self.fieldname)
        if field.data != other.data:
            d = {
                'other_label': hasattr(other, 'label') and other.label.text or self.fieldname,
                'other_name': self.fieldname
            }
            if self.message is None:
                self.message = field.gettext(u'Field must be equal to %(other_name)s.')

            raise ValidationError(self.message % d)

class Length(object):
    """
    Validates the length of a string.

    :param min:
        The minimum required length of the string. If not provided, minimum
        length will not be checked.
    :param max:
        The maximum length of the string. If not provided, maximum length
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)d` and `%(max)d` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """
    def __init__(self, min=-1, max=-1, message=None):
        assert min != -1 or max!=-1, 'At least one of `min` or `max` must be specified.'
        assert max == -1 or min <= max, '`min` cannot be more than `max`.'
        self.min = min
        self.max = max
        self.message = message

    def __call__(self, form, field):
        l = field.data and len(field.data) or 0
        if l < self.min or self.max != -1 and l > self.max:
            if self.message is None:
                if self.max == -1:
                    self.message = field.ngettext(u'Field must be at least %(min)d character long.',
                                                  u'Field must be at least %(min)d characters long.', self.min)
                elif self.min == -1:
                    self.message = field.ngettext(u'Field cannot be longer than %(max)d character.',
                                                  u'Field cannot be longer than %(max)d characters.', self.max)
                else:
                    self.message = field.gettext(u'Field must be between %(min)d and %(max)d characters long.')

            raise ValidationError(self.message % dict(min=self.min, max=self.max))

class NumberRange(object):
    """
    Validates that a number is of a minimum and/or maximum value, inclusive.
    This will work with any comparable number type, such as floats and
    decimals, not just integers.

    :param min:
        The minimum required value of the number. If not provided, minimum
        value will not be checked.
    :param max:
        The maximum value of the number. If not provided, maximum value
        will not be checked.
    :param message:
        Error message to raise in case of a validation error. Can be
        interpolated using `%(min)s` and `%(max)s` if desired. Useful defaults
        are provided depending on the existence of min and max.
    """
    def __init__(self, min=None, max=None, message=None):
        self.min = min
        self.max = max
        self.message = message

    def __call__(self, form, field):
        data = field.data
        if data is None or (self.min is not None and data < self.min) or \
            (self.max is not None and data > self.max):
            if self.message is None:
                # we use %(min)s interpolation to support floats, None, and
                # Decimals without throwing a formatting exception.
                if self.max is None:
                    self.message = field.gettext(u'Number must be greater than %(min)s.')
                elif self.min is None:
                    self.message = field.gettext(u'Number must be less than %(max)s.')
                else:
                    self.message = field.gettext(u'Number must be between %(min)s and %(max)s.')

            raise ValidationError(self.message % dict(min=self.min, max=self.max))

class Optional(object):
    """
    Allows empty input and stops the validation chain from continuing.

    If input is empty, also removes prior errors (such as processing errors)
    from the field.
    """
    field_flags = ('optional', )

    def __call__(self, form, field):
        if not field.raw_data or isinstance(field.raw_data[0], basestring) and not field.raw_data[0].strip():
            field.errors[:] = []
            raise StopValidation()

class Required(object):
    """
    Validates that the field contains data. This validator will stop the
    validation chain on error.

    :param message:
        Error message to raise in case of a validation error.
    """
    field_flags = ('required', )

    def __init__(self, message=None):
        self.message = message

    def __call__(self, form, field):
        if not field.data or isinstance(field.data, basestring) and not field.data.strip():
            if self.message is None:
                self.message = field.gettext(u'This field is required.')

            field.errors[:] = []
            raise StopValidation(self.message)

class Regexp(object):
    """
    Validates the field against a user provided regexp.

    :param regex:
        The regular expression string to use. Can also be a compiled regular
        expression pattern.
    :param flags:
        The regexp flags to use, for example re.IGNORECASE. Ignored if
        `regex` is not a string.
    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, regex, flags=0, message=None):
        if isinstance(regex, basestring):
            regex = re.compile(regex, flags)
        self.regex = regex
        self.message = message

    def __call__(self, form, field):
        if not self.regex.match(field.data or u''):
            if self.message is None:
                self.message = field.gettext(u'Invalid input.')

            raise ValidationError(self.message)

class Email(Regexp):
    """
    Validates an email address. Note that this uses a very primitive regular
    expression and should only be used in instances where you later verify by
    other means, such as email activation or lookups.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):
        super(Email, self).__init__(r'^.+@[^.].*\.[a-z]{2,10}$', re.IGNORECASE, message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid email address.')

        super(Email, self).__call__(form, field)

class IPAddress(Regexp):
    """
    Validates an IP(v4) address.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):
        super(IPAddress, self).__init__(r'^([0-9]{1,3}\.){3}[0-9]{1,3}$', message=message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid IP address.')

        super(IPAddress, self).__call__(form, field)

class MacAddress(Regexp):
    """
    Validates a Mac address.

    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, message=None):

        super(MacAddress, self).__init__(
            r'^(?:[0-9a-fA-F]{2}:){5}[0-9a-fA-F]{2}$', message=message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid Mac address.')

        super(MacAddress, self).__call__(form, field)

class URL(Regexp):
    """
    Simple regexp based url validation. Much like the email validator, you
    probably want to validate the url later by other means if the url must
    resolve.

    :param require_tld:
        If true, then the domain-name portion of the URL must contain a .tld
        suffix.  Set this to false if you want to allow domains like
        `localhost`.
    :param message:
        Error message to raise in case of a validation error.
    """
    def __init__(self, require_tld=True, message=None):
        tld_part = (require_tld and ur'\.[a-z]{2,10}' or u'')
        regex = ur'^[a-z]+://([^/:]+%s|([0-9]{1,3}\.){3}[0-9]{1,3})(:[0-9]+)?(\/.*)?$' % tld_part
        super(URL, self).__init__(regex, re.IGNORECASE, message)

    def __call__(self, form, field):
        if self.message is None:
            self.message = field.gettext(u'Invalid URL.')

        super(URL, self).__call__(form, field)

class AnyOf(object):
    """
    Compares the incoming data to a sequence of valid inputs.

    :param values:
        A sequence of valid inputs.
    :param message:
        Error message to raise in case of a validation error. `%(values)s`
        contains the list of values.
    :param values_formatter:
        Function used to format the list of values in the error message.
    """
    def __init__(self, values, message=None, values_formatter=None):
        self.values = values
        self.message = message
        if values_formatter is None:
            values_formatter = lambda v: u', '.join(v)
        self.values_formatter = values_formatter

    def __call__(self, form, field):
        if field.data not in self.values:
            if self.message is None:
                self.message = field.gettext(u'Invalid value, must be one of: %(values)s.')

            raise ValueError(self.message % dict(values=self.values_formatter(self.values)))

class NoneOf(object):
    """
    Compares the incoming data to a sequence of invalid inputs.

    :param values:
        A sequence of invalid inputs.
    :param message:
        Error message to raise in case of a validation error. `%(values)s`
        contains the list of values.
    :param values_formatter:
        Function used to format the list of values in the error message.
    """
    def __init__(self, values, message=None, values_formatter=None):
        self.values = values
        self.message = message
        if values_formatter is None:
            values_formatter = lambda v: u', '.join(v)
        self.values_formatter = values_formatter

    def __call__(self, form, field):
        if field.data in self.values:
            if self.message is None:
                self.message = field.gettext(u'Invalid value, can\'t be any of: %(values)s.')

            raise ValueError(self.message % dict(values=self.values_formatter(self.values)))

email = Email
equal_to = EqualTo
ip_address = IPAddress
length = Length
number_range = NumberRange
optional = Optional
required = Required
regexp = Regexp
url = URL
any_of = AnyOf
none_of = NoneOf
<|endoftext|>


<commit_before>from django.db import models
from recipe.models import Recipe
from django.utils.translation import ugettext_lazy as _

class Ingredient(models.Model):
     title = models.CharField(_('title'), max_length=250)
     quantity =  models.IntegerField(_('quantity'))
     measurement = models.CharField(_('measurement'),max_length=200)
     preparation = models.CharField(_('preparation'),max_length=100, blank=True, null=True)
     recipe    = models.ForeignKey(Recipe, verbose_name=_('recipe'))

     class Meta:
         ordering = ['title']

     def __unicode__(self):
        return self.title
<commit_msg>Changed the quantity field for ingredients to be a varchar instead of an integer to allow users to put fractions and whole numbers in the quantity field.<commit_after>from django.db import models
from recipe.models import Recipe
from django.utils.translation import ugettext_lazy as _

class Ingredient(models.Model):
     title = models.CharField(_('title'), max_length=250)
     quantity =  models.CharField(_('quantity'), max_length=10)
     measurement = models.CharField(_('measurement'),max_length=200)
     preparation = models.CharField(_('preparation'),max_length=100, blank=True, null=True)
     recipe    = models.ForeignKey(Recipe, verbose_name=_('recipe'))

     class Meta:
         ordering = ['title']

     def __unicode__(self):
        return self.title
<|endoftext|>


<commit_before>from datetime import timedelta
import datetime
import logging
import mysite.search.models
import mysite.customs.models
from celery.task import Task, PeriodicTask
from celery.registry import tasks
import celery.decorators
import mysite.search.launchpad_crawl

def refresh_bugs_from_all_indexed_launchpad_projects():
    # Look, ma, a hard-coded table that maps to
    # OpenHatch project names from Launchpad.net project names.
    # TimBL would be proud.
    lpproj2ohproj = { 'lxml': 'lxml',
                      'do': 'GNOME-do',
                      'gwibber': 'Gwibber'}
    for launchpad_project_name in lpproj2ohproj:
        openhatch_project_name = lpproj2ohproj[launchpad_project_name]
        import_bugs_from_one_project(launchpad_project_name,
                                     openhatch_project_name)

@celery.decorators.task
def import_bugs_from_one_project(launchpad_project_name,
                                 openhatch_project_name):
    logging.info("Looking at bugs %s on Launchpad" % launchpad_project_name)
    url = "https://bugs.launchpad.net/%s/+bugs" % launchpad_project_name
    bug_filter = mysite.search.launchpad_crawl.URLBugListFilter()
    # no filtering; dump everything
    l = mysite.search.launchpad_crawl.TextBugList(bug_filter(url))
    # convert elements into Bug objects
    for bug in l:
        openhatch_bug_link = 'https://bugs.launchpad.net/bugs/%d' % (
            bug.bugnumber)
        refresh_one_launchpad_bug(
            canonical_bug_link=openhatch_bug_link,
            openhatch_project_name=openhatch_project_name)

def refresh_all_launchpad_bugs():
    logging.info("Refreshing all Launchpad bugs.")
    for lp_bug in mysite.search.models.Bug.all_bugs.filter(
        canonical_bug_link__startswith='https://bugs.launchpad.net/'):
        refresh_one_launchpad_bug.apply(
            canonical_bug_link=lp_bug.canonical_bug_link,
            openhatch_project_name=None)

@celery.decorators.task
def refresh_one_launchpad_bug(canonical_bug_link,
                              openhatch_project_name):
    logging.info("Checking on %s..." % canonical_bug_link)
    # Either we already have the bug...
    try:
        bug = mysite.search.models.Bug.all_bugs.get(
            canonical_bug_link=canonical_bug_link)
    # ...or we need to create it
    except mysite.search.models.Bug.DoesNotExist:
        bug = mysite.search.models.Bug()
        bug.canonical_bug_link = canonical_bug_link

    if bug.data_is_more_fresh_than_one_day():
        return

    # Okay, so it's stale. Refresh the sucker.
    logging.info("Refreshing %s." % canonical_bug_link)

    # Set the project, if necessary
    if openhatch_project_name is None:
        pass
    else:
        # Get or create the OpenHatch project
        openhatch_project, _ = mysite.search.models.Project.objects.get_or_create(name=openhatch_project_name)

        if bug.project_id != openhatch_project.id:
            bug.project = openhatch_project

    # FIXME: One day, look at the bug data to see what project to use.
    # This code incorrectly assumes bugs don't migrate from one project
    # to another.
    prefix = 'https://bugs.launchpad.net/bugs/'
    assert canonical_bug_link.startswith(prefix)
    bug_id_str = canonical_bug_link.split(prefix, 1)[1]
    bug_id = int(bug_id_str)
    tb = mysite.search.launchpad_crawl.TextBug(bug_id)
    data_dict = mysite.search.lpb2json.obj2serializable(tb)
    _, new_data = mysite.search.launchpad_crawl.clean_lp_data_dict(data_dict)
    for key in new_data:
        setattr(bug, key, new_data[key])
    bug.last_polled = datetime.datetime.utcnow()
    bug.save()
<commit_msg>Make launchpad_tasks.py stop referring to PeriodicTask.<commit_after>from datetime import timedelta
import datetime
import logging
import mysite.search.models
import mysite.customs.models
from celery.task import Task
from celery.registry import tasks
import celery.decorators
import mysite.search.launchpad_crawl

def refresh_bugs_from_all_indexed_launchpad_projects():
    # Look, ma, a hard-coded table that maps to
    # OpenHatch project names from Launchpad.net project names.
    # TimBL would be proud.
    lpproj2ohproj = { 'lxml': 'lxml',
                      'do': 'GNOME-do',
                      'gwibber': 'Gwibber'}
    for launchpad_project_name in lpproj2ohproj:
        openhatch_project_name = lpproj2ohproj[launchpad_project_name]
        import_bugs_from_one_project(launchpad_project_name,
                                     openhatch_project_name)

@celery.decorators.task
def import_bugs_from_one_project(launchpad_project_name,
                                 openhatch_project_name):
    logging.info("Looking at bugs %s on Launchpad" % launchpad_project_name)
    url = "https://bugs.launchpad.net/%s/+bugs" % launchpad_project_name
    bug_filter = mysite.search.launchpad_crawl.URLBugListFilter()
    # no filtering; dump everything
    l = mysite.search.launchpad_crawl.TextBugList(bug_filter(url))
    # convert elements into Bug objects
    for bug in l:
        openhatch_bug_link = 'https://bugs.launchpad.net/bugs/%d' % (
            bug.bugnumber)
        refresh_one_launchpad_bug(
            canonical_bug_link=openhatch_bug_link,
            openhatch_project_name=openhatch_project_name)

def refresh_all_launchpad_bugs():
    logging.info("Refreshing all Launchpad bugs.")
    for lp_bug in mysite.search.models.Bug.all_bugs.filter(
        canonical_bug_link__startswith='https://bugs.launchpad.net/'):
        refresh_one_launchpad_bug.apply(
            canonical_bug_link=lp_bug.canonical_bug_link,
            openhatch_project_name=None)

@celery.decorators.task
def refresh_one_launchpad_bug(canonical_bug_link,
                              openhatch_project_name):
    logging.info("Checking on %s..." % canonical_bug_link)
    # Either we already have the bug...
    try:
        bug = mysite.search.models.Bug.all_bugs.get(
            canonical_bug_link=canonical_bug_link)
    # ...or we need to create it
    except mysite.search.models.Bug.DoesNotExist:
        bug = mysite.search.models.Bug()
        bug.canonical_bug_link = canonical_bug_link

    if bug.data_is_more_fresh_than_one_day():
        return

    # Okay, so it's stale. Refresh the sucker.
    logging.info("Refreshing %s." % canonical_bug_link)

    # Set the project, if necessary
    if openhatch_project_name is None:
        pass
    else:
        # Get or create the OpenHatch project
        openhatch_project, _ = mysite.search.models.Project.objects.get_or_create(name=openhatch_project_name)

        if bug.project_id != openhatch_project.id:
            bug.project = openhatch_project

    # FIXME: One day, look at the bug data to see what project to use.
    # This code incorrectly assumes bugs don't migrate from one project
    # to another.
    prefix = 'https://bugs.launchpad.net/bugs/'
    assert canonical_bug_link.startswith(prefix)
    bug_id_str = canonical_bug_link.split(prefix, 1)[1]
    bug_id = int(bug_id_str)
    tb = mysite.search.launchpad_crawl.TextBug(bug_id)
    data_dict = mysite.search.lpb2json.obj2serializable(tb)
    _, new_data = mysite.search.launchpad_crawl.clean_lp_data_dict(data_dict)
    for key in new_data:
        setattr(bug, key, new_data[key])
    bug.last_polled = datetime.datetime.utcnow()
    bug.save()
<|endoftext|>


<commit_before>"""Segmentation, validation and annotation of images of museum specimens
"""
__version__ = '0.1.20'
# distutils/version.py and win32/lib/win32verstamp.py have different
# restrictions on the format of version numbers - both must be met.
# Three numbers separated by dots is a safe format.
<commit_msg>Bump version<commit_after>"""Segmentation, validation and annotation of images of museum specimens
"""
__version__ = '0.1.21'
# distutils/version.py and win32/lib/win32verstamp.py have different
# restrictions on the format of version numbers - both must be met.
# Three numbers separated by dots is a safe format.
<|endoftext|>


<commit_before>"""This module contains a representation of a smart contract's memory."""
from typing import cast, List, Union, overload

from z3 import Z3Exception

from mythril.laser.ethereum import util
from mythril.laser.smt import (
    BitVec,
    Bool,
    Concat,
    Extract,
    If,
    simplify,
    symbol_factory,
)

class Memory:
    """A class representing contract memory with random access."""

    def __init__(self):
        """"""
        self._memory = []  # type: List[Union[int, BitVec]]

    def __len__(self):
        """

        :return:
        """
        return len(self._memory)

    def __copy__(self):
        copy = Memory()
        copy._memory = self._memory[:]
        return copy

    def extend(self, size):
        """

        :param size:
        """
        self._memory.extend(bytearray(size))

    def get_word_at(self, index: int) -> Union[int, BitVec]:
        """Access a word from a specified memory index.

        :param index: integer representing the index to access
        :return: 32 byte word at the specified index
        """
        try:
            return symbol_factory.BitVecVal(
                util.concrete_int_from_bytes(
                    bytes([util.get_concrete_int(b) for b in self[index : index + 32]]),
                    0,
                ),
                256,
            )
        except TypeError:
            result = simplify(
                Concat(
                    [
                        b if isinstance(b, BitVec) else symbol_factory.BitVecVal(b, 8)
                        for b in cast(
                            List[Union[int, BitVec]], self[index : index + 32]
                        )
                    ]
                )
            )
            assert result.size() == 256
            return result

    def write_word_at(self, index: int, value: Union[int, BitVec, bool, Bool]) -> None:
        """Writes a 32 byte word to memory at the specified index`

        :param index: index to write to
        :param value: the value to write to memory
        """
        try:
            # Attempt to concretize value
            if isinstance(value, bool):
                _bytes = (
                    int(1).to_bytes(32, byteorder="big")
                    if value
                    else int(0).to_bytes(32, byteorder="big")
                )
            else:
                _bytes = util.concrete_int_to_bytes(value)
            assert len(_bytes) == 32
            self[index : index + 32] = list(bytearray(_bytes))
        except (Z3Exception, AttributeError):  # BitVector or BoolRef
            value = cast(Union[BitVec, Bool], value)
            if isinstance(value, Bool):
                value_to_write = If(
                    value,
                    symbol_factory.BitVecVal(1, 256),
                    symbol_factory.BitVecVal(0, 256),
                )
            else:
                value_to_write = value
            assert value_to_write.size() == 256

            for i in range(0, value_to_write.size(), 8):
                self[index + 31 - (i // 8)] = Extract(i + 7, i, value_to_write)

    @overload
    def __getitem__(self, item: int) -> Union[int, BitVec]:
        ...

    @overload
    def __getitem__(self, item: slice) -> List[Union[int, BitVec]]:
        ...

    def __getitem__(
        self, item: Union[int, slice]
    ) -> Union[BitVec, int, List[Union[int, BitVec]]]:
        """

        :param item:
        :return:
        """
        if isinstance(item, slice):
            start, step, stop = item.start, item.step, item.stop
            if start is None:
                start = 0
            if stop is None:  # 2**256 is just a bit too big
                raise IndexError("Invalid Memory Slice")
            if step is None:
                step = 1
            return [cast(Union[int, BitVec], self[i]) for i in range(start, stop, step)]

        try:
            return self._memory[item]
        except IndexError:
            return 0

    def __setitem__(
        self,
        key: Union[int, slice],
        value: Union[BitVec, int, List[Union[int, BitVec]]],
    ):
        """

        :param key:
        :param value:
        """
        if isinstance(key, slice):
            start, step, stop = key.start, key.step, key.stop

            if start is None:
                start = 0
            if stop is None:
                raise IndexError("Invalid Memory Slice")
            if step is None:
                step = 1
            assert type(value) == list
            for i in range(0, stop - start, step):
                self[start + i] = cast(List[Union[int, BitVec]], value)[i]

        else:
            if key >= self.__len__():
                return
            if isinstance(value, int):
                assert 0 <= value <= 0xFF
            if isinstance(value, BitVec):
                assert value.size() == 8
            self._memory[key] = cast(Union[int, BitVec], value)
<commit_msg>Update mythril/laser/ethereum/state/memory.py<commit_after>"""This module contains a representation of a smart contract's memory."""
from typing import cast, List, Union, overload

from z3 import Z3Exception

from mythril.laser.ethereum import util
from mythril.laser.smt import (
    BitVec,
    Bool,
    Concat,
    Extract,
    If,
    simplify,
    symbol_factory,
)

class Memory:
    """A class representing contract memory with random access."""

    def __init__(self):
        """"""
        self._memory = []  # type: List[Union[int, BitVec]]

    def __len__(self):
        """

        :return:
        """
        return len(self._memory)

    def __copy__(self):
        copy = Memory()
        copy._memory = self._memory[:]
        return copy

    def extend(self, size):
        """

        :param size:
        """
        self._memory.extend(bytearray(size))

    def get_word_at(self, index: int) -> Union[int, BitVec]:
        """Access a word from a specified memory index.

        :param index: integer representing the index to access
        :return: 32 byte word at the specified index
        """
        try:
            return symbol_factory.BitVecVal(
                util.concrete_int_from_bytes(
                    bytes([util.get_concrete_int(b) for b in self[index : index + 32]]),
                    0,
                ),
                256,
            )
        except TypeError:
            result = simplify(
                Concat(
                    [
                        b if isinstance(b, BitVec) else symbol_factory.BitVecVal(b, 8)
                        for b in cast(
                            List[Union[int, BitVec]], self[index : index + 32]
                        )
                    ]
                )
            )
            assert result.size() == 256
            return result

    def write_word_at(self, index: int, value: Union[int, BitVec, bool, Bool]) -> None:
        """Writes a 32 byte word to memory at the specified index`

        :param index: index to write to
        :param value: the value to write to memory
        """
        try:
            # Attempt to concretize value
            if isinstance(value, bool):
                _bytes = (
                    int(1).to_bytes(32, byteorder="big")
                    if value
                    else int(0).to_bytes(32, byteorder="big")
                )
            else:
                _bytes = util.concrete_int_to_bytes(value)
            assert len(_bytes) == 32
            self[index : index + 32] = list(bytearray(_bytes))
        except (Z3Exception, AttributeError):  # BitVector or BoolRef
            value = cast(Union[BitVec, Bool], value)
            if isinstance(value, Bool):
                value_to_write = If(
                    value,
                    symbol_factory.BitVecVal(1, 256),
                    symbol_factory.BitVecVal(0, 256),
                )
            else:
                value_to_write = value
            assert value_to_write.size() == 256

            for i in range(0, value_to_write.size(), 8):
                self[index + 31 - (i // 8)] = Extract(i + 7, i, value_to_write)

    @overload
    def __getitem__(self, item: int) -> Union[int, BitVec]:
        ...

    @overload
    def __getitem__(self, item: slice) -> List[Union[int, BitVec]]:
        ...

    def __getitem__(
        self, item: Union[int, slice]
    ) -> Union[BitVec, int, List[Union[int, BitVec]]]:
        """

        :param item:
        :return:
        """
        if isinstance(item, slice):
            start, step, stop = item.start, item.step, item.stop
            if start is None:
                start = 0
            if stop is None:  # 2**256 is just a bit too big
                raise IndexError("Invalid Memory Slice")
            if step is None:
                step = 1
            return [cast(Union[int, BitVec], self[i]) for i in range(start, stop, step)]

        try:
            return self._memory[item]
        except IndexError:
            return 0

    def __setitem__(
        self,
        key: Union[int, slice],
        value: Union[BitVec, int, List[Union[int, BitVec]]],
    ):
        """

        :param key:
        :param value:
        """
        if isinstance(key, slice):
            start, step, stop = key.start, key.step, key.stop

            if start is None:
                start = 0
            if stop is None:
                raise IndexError("Invalid Memory Slice")
            if step is None:
                step = 1
            assert type(value) == list
            for i in range(0, stop - start, step):
                self[start + i] = cast(List[Union[int, BitVec]], value)[i]

        else:
            if key >= len(self):
                return
            if isinstance(value, int):
                assert 0 <= value <= 0xFF
            if isinstance(value, BitVec):
                assert value.size() == 8
            self._memory[key] = cast(Union[int, BitVec], value)
<|endoftext|>