text:
"""
Copyright © 2015 by Mengxue Cao

PyRecorder is a sound recorder written in Python.
The audio module is based on PyAduio.
The GUI is based on Tkinter.

The goal of this programme is to help phoneticians do easy recording.

"""
from __future__ import division
from pyaudio import PyAudio, paInt16
from Tkinter import *
import wave
import os

#####################
#                   #
#    Declaration    #
#                   #
#####################
# default parameters to be passed to setting window
parameters = {'CHUNK':1024, 'FORMAT':16, 'RATE':44100, 'CHANNELS':1, 'WAV_PATH':'', 'SCRIPT_FILE':''}

#####################
#                   #
#    READ SCRIPT    #
#                   #
#####################

# read data from file
def read_file(filename):
    f = open(filename)  # open the file and read
    s = f.read()        # convert the content into string
    f.close()           # close the file
    l = s.split("\n")   # get each sentence and store them into a list

    return l

##################
#                #
#   RECORDING    #
#                #
##################

# record sound
def record_wav():
    global state, ave_buffer, stream_in

    # as long as the state is "recording", keep recording sounds
    if state == 1:
        string_audio_data = stream_in.read(CHUNK)
        save_buffer.append(string_audio_data)

        # call the function once per millisecond
        # this enables Tkinter to handel other button-click events while recording
        root.after(1, record_wav)

# save waveform into wav file
def save_wave_file(filename, data_in, sampwidth):
    wf = wave.open(filename, 'wb')
    wf.setnchannels(CHANNELS)
    wf.setsampwidth(sampwidth)
    wf.setframerate(RATE)
    wf.writeframes("".join(data_in))
    wf.close()

##################
#                #
#    PLAYING     #
#                #
##################

# play the audio
def play_wave():
    global state, data_out, stream_out, wav_out, wave_form, script_count, script_list

    # if reaches EOF, stop playing
    if len(data_out) == 0:
        state == 0  # change the state flag to "stopepd"
        echo_text.configure(text = "Stopped", bg = 'white', fg = 'black', font = ("Helvetica", 50))
        stream_out.stop_stream()
        stream_out.close()
        wav_out.terminate()

        # update button states
        button_stop.configure(state = DISABLED)
        button_record.configure(state = NORMAL)
        button_play.configure(state = NORMAL)
        if script_count > 0:
            button_back.configure(state = NORMAL)
        if script_count < len(script_list) - 1:
            button_next.configure(state = NORMAL)

    # else, play the sound, as long as the state is "playing"
    elif state == 2:
        stream_out.write(data_out)
        data_out = wave_form.readframes(CHUNK)

        # call the function once a millisecond
        # this enables Tkinter to handel other button-click events while playing
        root.after(1, play_wave)

#######################
#                     #
#    BUTTON CLICK     #
#                     #
#######################

def button_record_Click():
    global sampwidth, wav_in, stream_in, state

    state = 1   # change the state flag into "recording"

    # update button states
    button_stop.configure(state = NORMAL)
    button_play.configure(state = DISABLED)
    button_back.configure(state = DISABLED)
    button_next.configure(state = DISABLED)
    button_record.configure(state = DISABLED)

    wav_in = PyAudio()
    stream_in = wav_in.open(format = FORMAT, channels = CHANNELS, rate = RATE, input = True, frames_per_buffer = CHUNK)
    sampwidth = wav_in.get_sample_size(FORMAT)
    echo_text.configure(text = "Recording...", bg = 'red', fg = 'white', font = ("Helvetica", 50))
    record_wav()

def button_play_Click():
    global state, wav_out, stream_out, data_out, wave_form, wavefile_name, script_count, script_list

    state = 2   # change the state flag into "playing"

    # update button states
    button_stop.configure(state = NORMAL)
    button_record.configure(state = DISABLED)
    button_back.configure(state = DISABLED)
    button_next.configure(state = DISABLED)
    button_play.configure(state = DISABLED)

    wav_out = PyAudio()
    wave_form = wave.open(wavefile_name, 'rb')
    stream_out = wav_out.open(format = wav_out.get_format_from_width(wave_form.getsampwidth()),
                channels = wave_form.getnchannels(),
                rate = wave_form.getframerate(),
                output = True)

    data_out = wave_form.readframes(CHUNK)
    echo_text.configure(text = "Playing...", bg = 'blue', fg = 'white', font = ("Helvetica", 50))
    play_wave()

def button_stop_Click():
    global state, save_buffer, wav_in, wav_out, stream_in, stream_out, data_out, wavefile_name, script_count, script_list

    echo_text.configure(text = "Stopped", bg = 'white', fg = 'black', font = ("Helvetica", 50))

    # stop from recording
    if state == 1:
        state = 0   # change the state flag into "stopped"
        save_wave_file(wavefile_name, save_buffer, sampwidth)

        # clean up
        save_buffer = []
        stream_in.stop_stream()
        stream_in.close()
        wav_in.terminate()

        # update button states
        button_stop.configure(state = DISABLED)
        button_play.configure(state = NORMAL)
        button_record.configure(state = NORMAL)
        if script_count > 0:
            button_back.configure(state = NORMAL)
        if script_count < len(script_list) - 1:
            button_next.configure(state = NORMAL)

    # stop from playing
    elif state == 2:
        state = 0   # change the state flag into "stopped"

        # clean up
        stream_out.stop_stream()
        stream_out.close()
        wav_out.terminate()
        data_out = []

        # update button states
        button_stop.configure(state = DISABLED)
        button_play.configure(state = NORMAL)
        button_record.configure(state = NORMAL)
        if script_count > 0:
            button_back.configure(state = NORMAL)
        if script_count < len(script_list) - 1:
            button_next.configure(state = NORMAL)

def button_back_Click():
    global script_count, script_list, script_line, filename_format, wavefile_name, WAV_PATH

    if script_count > 1:
        script_count = script_count - 1
        script_line.set(script_list[script_count])
        wavefile_name = filename_format.format(WAV_PATH, script_count + 1, '.wav')
        button_next.configure(state = NORMAL)

        # if file exists, enable play button
        if os.path.isfile(wavefile_name):
            button_play.configure(state = NORMAL)
        else:
            button_play.configure(state = DISABLED)

    elif script_count == 1:
        script_count = script_count - 1
        script_line.set(script_list[script_count])
        wavefile_name = filename_format.format(WAV_PATH, script_count + 1, '.wav')

        # update button states
        button_back.configure(state = DISABLED)
        button_next.configure(state = NORMAL)

def button_next_Click():
    global script_count, script_list, script_line, filename_format, wavefile_name, WAV_PATH

    if script_count < len(script_list) - 2:
        script_count = script_count + 1
        script_line.set(script_list[script_count])
        wavefile_name = filename_format.format(WAV_PATH, script_count + 1, '.wav')
        button_back.configure(state = NORMAL)

        # if file exists, enable play button
        if os.path.isfile(wavefile_name):
            button_play.configure(state = NORMAL)
        else:
            button_play.configure(state = DISABLED)

    elif script_count == len(script_list) - 2:
        script_count = script_count + 1
        script_line.set(script_list[script_count])
        wavefile_name = filename_format.format(WAV_PATH, script_count + 1, '.wav')

        # update button states
        button_back.configure(state = NORMAL)
        button_next.configure(state = DISABLED)

        # if file exists, enable play button
        if os.path.isfile(wavefile_name):
            button_play.configure(state = NORMAL)
        else:
            button_play.configure(state = DISABLED)

def button_quit_Click():
    root.destroy()

def button_settings_Click():
    Setting_window(parameters)

def show_about():
    About_window()

def maximise ():
    global window_width, window_height

    w, h = root.winfo_screenwidth(), root.winfo_screenheight()
    window_width = w * 0.6
    window_height = h * 0.6
    left_blank = (w - window_width) / 2
    top_blank = (h - window_height) / 2
    root.geometry("%dx%d+%d+%d" % (window_width, window_height, left_blank, top_blank))

def help_info():
    Help_window()

##################
#                #
#      GUI       #
#                #
##################
root = Tk()

# create a manu bar for the application
menubar = Menu(root)

# modify the about menu in apple menu bar
appmenu = Menu(menubar, name='apple')

menubar.add_cascade(menu = appmenu)
appmenu.add_command(label = 'About PyRecorder', command = show_about)
appmenu.add_separator()

# add window menu
windowmenu = Menu(menubar, name='window')
menubar.add_cascade(menu=windowmenu, label='Window')

# add help menu
helpmenu = Menu(menubar, name = 'help')
menubar.add_cascade(menu = helpmenu, label = 'Help')
root.createcommand('tk::mac::ShowHelp', help_info)

# apply menu
root.config(menu = menubar)

# constants for controlling layout
button_width = 8

button_padx = "2m"
button_pady = "1m"

buttons_frame_padx =  "3m"
buttons_frame_pady =  "2m"
buttons_frame_ipadx = "3m"
buttons_frame_ipady = "1m"

# set window size
maximise()

# create main frame
PyRecorder = Frame(root)
PyRecorder.pack(expand = YES, fill = BOTH)

#########################
#      text frame       #
#########################
text_frame_height = int(0.5 * window_height)
text_frame_width = int(0.9 * window_width)

text_frame = Frame(PyRecorder, borderwidth = 4,  relief = RIDGE, height = text_frame_height, width = text_frame_width, background = "white")
text_frame.pack(side = TOP, fill = BOTH, expand = YES, padx = 10, pady = 10, ipadx = 5, ipady = 5)
text_frame.pack_propagate(0)    # enable frame-size editing

script_line = StringVar()

# use "wraplength" option to set auto warping
script_text = Label(text_frame, textvariable = script_line, font = ("Helvetica", 50), justify = LEFT, height = text_frame_height, width = text_frame_width, wraplength = text_frame_width)
script_line.set('')
script_text.pack()

###########################
#      button frame       #
###########################
buttons_frame = Frame(PyRecorder)
buttons_frame.pack(side = TOP, ipadx = buttons_frame_ipadx, ipady = buttons_frame_ipady, padx = buttons_frame_padx, pady = buttons_frame_pady)

# back button
button_back = Button(buttons_frame, command = button_back_Click)
button_back.configure(text = "Back", font = ("Helvetica", 15))
button_back.configure(width = button_width, padx = button_padx, pady = button_pady)
button_back.configure(state = DISABLED)
button_back.pack(side = LEFT)

# next button
button_next = Button(buttons_frame, command = button_next_Click)
button_next.configure(text = "Next", font = ("Helvetica", 15))
button_next.configure(width = button_width, padx = button_padx, pady = button_pady)
button_next.configure(state = DISABLED)
button_next.pack(side = LEFT, padx = 4)

# record button
button_record = Button(buttons_frame, command = button_record_Click)
button_record.configure(text = "Record", font = ("Helvetica", 15))
button_record.configure(width = button_width, padx = button_padx, pady = button_pady)
button_record.configure(state = DISABLED)
button_record.pack(side = LEFT, padx = 4)

# stop button
button_stop = Button(buttons_frame, command = button_stop_Click)
button_stop.configure(text = "Stop", font = ("Helvetica", 15))
button_stop.configure(width = button_width, padx = button_padx, pady = button_pady)
button_stop.configure(state = DISABLED)
button_stop.pack(side = LEFT, padx = 4)

# play button
button_play = Button(buttons_frame, command = button_play_Click)
button_play.configure(text = "Play", font = ("Helvetica", 15))
button_play.configure(width = button_width, padx = button_padx, pady = button_pady)
button_play.configure(state = DISABLED)
button_play.pack(side = LEFT, padx = 4)

#########################
#      echo frame      #
#########################
welcome_message = "Please define the saving path and locate the recording script file\n by clicking the \"Settings\" button below!"
echo_frame = Frame(PyRecorder)
echo_frame.pack(side = TOP, fill = BOTH, expand = YES)
echo_text = Label(echo_frame, text = welcome_message, font=("Helvetica", 20), fg = 'blue')
echo_text.pack(fill = BOTH, expand = YES)

#########################
#      foot frame       #
#########################
foot_frame = Frame(PyRecorder)
foot_frame.pack(side = BOTTOM, fill = BOTH, expand = YES, ipadx = buttons_frame_ipadx, padx = buttons_frame_padx)

# settings button
button_settings = Button(foot_frame, command = button_settings_Click)
button_settings.configure(text = "Settings", font = ("Helvetica", 15))
button_settings.configure(width = button_width, padx = button_padx, pady = button_pady)
button_settings.pack(side = RIGHT)

# quit button
button_quit = Button(foot_frame, command = button_quit_Click)
button_quit.configure(text = "Quit", font = ("Helvetica", 15))
button_quit.configure(width = button_width, padx = button_padx, pady = button_pady)
button_quit.pack(side = RIGHT, padx = 4)

############################
#     Dialog window for    #
#     programme about      #
############################
class About_window(object):

    root = None

    def __init__(self):

        self.top = Toplevel(About_window.root)
        self.resize_about()     # resize the window
        self.top.wm_title('About')

        # disable inputs in the main window while setting window is open
        self.top.grab_set()

        #########################
        #      text frame       #
        #########################
        text_frame = Frame(self.top)
        text_frame.pack(expand = YES, fill = BOTH)

        m_name = 'PyRecorder'

        message_name = Label(text_frame, text = m_name, font = ("Papyrus", 30, "bold"), justify = LEFT, fg = 'RoyalBlue')
        message_name.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        m_intro = 'helps phoneticians do easy recording'
        message_intro = Label(text_frame, text = m_intro, font = ("Papyrus", 20), justify = LEFT, fg = 'RoyalBlue')
        message_intro.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        m_version = 'version 1.0.1'
        message_version = Label(text_frame, text = m_version, font = ("Papyrus", 20), justify = LEFT, fg = 'RoyalBlue')
        message_version.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        m_url = 'https://github.com/smilett/PyRecorder'
        message_url = Label(text_frame, text = m_url, font = ("Helvetica", 15), justify = LEFT, fg = 'RoyalBlue')
        message_url.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        m_author = 'Copyright © 2015 by Mengxue Cao'
        message_author = Label(text_frame, text = m_author, font = ("Helvetica", 15), justify = LEFT, fg = 'black')
        message_author.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

    def resize_about(self):
        about_w, about_h = self.top.winfo_screenwidth(), self.top.winfo_screenheight()
        about_window_width = about_w * 0.3
        about_window_height = about_h * 0.4
        about_left_blank = (about_w - about_window_width) / 2
        about_top_blank = (about_h - about_window_height) / 2
        self.top.geometry("%dx%d+%d+%d" % (about_window_width, about_window_height, about_left_blank, about_top_blank))

############################
#     Dialog window for    #
#     programme help       #
############################
class Help_window(object):

    root = None

    def __init__(self):

        self.top = Toplevel(Help_window.root)
        self.resize_help()     # resize the window
        self.top.wm_title('Help')

        text_frame_width = int(0.9 * window_width)

        # disable inputs in the main window while setting window is open
        self.top.grab_set()

        #########################
        #      text frame       #
        #########################
        text_frame = Frame(self.top)
        text_frame.pack(expand = YES, fill = BOTH, ipadx = 10, padx = 10)

        intro_info = 'Get started by the following steps!'
        message_intro = Label(text_frame, text = intro_info, font = ("Helvetica", 15, "bold"), justify = LEFT, wraplength = text_frame_width)
        message_intro.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        help_info_1 = '1. Prepare a file contains recording scripts, where each line contains only one sentence (or word).'
        message_help_1 = Label(text_frame, text = help_info_1, font = ("Helvetica", 15), anchor = W, justify = LEFT, wraplength = text_frame_width)
        message_help_1.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        help_info_2 = '2. Set parameters by clicking the \"Setting\" button.'
        message_help_2 = Label(text_frame, text = help_info_2, font = ("Helvetica", 15), anchor = W, justify = LEFT, wraplength = text_frame_width)
        message_help_2.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        help_info_3 = '3. Click \"Record\" to start recording, and click \"Stop\" to stop.'
        message_help_3 = Label(text_frame, text = help_info_3, font = ("Helvetica", 15), anchor = W, justify = LEFT, wraplength = text_frame_width)
        message_help_3.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        help_info_4 = '4. Click \"Play\" to play back.'
        message_help_4 = Label(text_frame, text = help_info_4, font = ("Helvetica", 15), anchor = W, justify = LEFT, wraplength = text_frame_width)
        message_help_4.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        help_info_5 = '5. Click \"Back\" and \"Next\" to navigate.'
        message_help_5 = Label(text_frame, text = help_info_5, font = ("Helvetica", 15), anchor = W, justify = LEFT, wraplength = text_frame_width)
        message_help_5.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        url_info = 'Find the README file on project homepage'
        url_link = r'https://github.com/smilett/PyRecorder'
        button_url = Button(text_frame, text = url_info, font = ("Helvetica", 15), command = lambda: self.openurl(url_link))
        button_url.pack(side = TOP, ipady = 5, pady = 5)

    def openurl(self, url):
        import webbrowser
        webbrowser.open_new(url)

    def resize_help(self):
        help_w, help_h = self.top.winfo_screenwidth(), self.top.winfo_screenheight()
        help_window_width = help_w * 0.55
        help_window_height = help_h * 0.4
        help_left_blank = (help_w - help_window_width) / 2
        help_top_blank = (help_h - help_window_height) / 2
        self.top.geometry("%dx%d+%d+%d" % (help_window_width, help_window_height, help_left_blank, help_top_blank))

############################
#     Dialog window for    #
#     programme settings   #
############################
class Setting_window(object):

    root = None

    def __init__(self, parameters):

        self.top = Toplevel(Setting_window.root)
        self.resize()     # resize the window
        self.top.wm_title('Settings')

        # disable inputs in the main window while setting window is open
        self.top.grab_set()

        #########################
        #      text frame       #
        #########################
        text_frame = Frame(self.top)
        text_frame.pack(expand = YES, fill = BOTH, ipadx = 10, padx = 10)

        msg = 'Please enter seting parameters!'

        message = Label(text_frame, text = msg, font = ("Helvetica", 15), justify = LEFT)
        message.pack(side = TOP, padx = 4, pady = 4, expand = YES, fill = BOTH)

        ##########################
        #      setting frame       #
        ##########################
        setting_frame = Frame(self.top)
        setting_frame.pack(expand = YES, fill = X, ipadx = 10, padx = 10)

        # CHUNK
        chunk_frame = Frame(setting_frame)
        chunk_frame.pack(expand = YES, fill = X)

        text_CHUNK = Label(chunk_frame, text = "Frames per buffer:", font = ("Helvetica", 15), justify = LEFT)
        text_CHUNK.pack(side = LEFT, padx = 4, pady = 4)

        v_chunk = IntVar()
        radiobutton_chunk_1 = Radiobutton(chunk_frame, text = "1024", variable = v_chunk, value = 1024)
        radiobutton_chunk_1.pack(side = LEFT)

        radiobutton_chunk_2 = Radiobutton(chunk_frame, text = "2048", variable = v_chunk, value = 2048)
        radiobutton_chunk_2.pack(side = LEFT)
        v_chunk.set(parameters['CHUNK'])

        # FORMAT
        format_frame = Frame(setting_frame)
        format_frame.pack(expand = YES, fill = X)

        text_FORMAT = Label(format_frame, text = "Bit rate:", font = ("Helvetica", 15), justify = LEFT)
        text_FORMAT.pack(side = LEFT,padx = 4, pady = 4)

        v_format = IntVar()
        radiobutton_format_1 = Radiobutton(format_frame, text = "16-bit", variable = v_format, value = 16)
        radiobutton_format_1.pack(side = LEFT)
        v_format.set(parameters['FORMAT'])

        # RATE
        rate_frame = Frame(setting_frame)
        rate_frame.pack(expand = YES, fill = X)

        text_RATE = Label(rate_frame, text = "Sampling rate:", font = ("Helvetica", 15), justify = LEFT)
        text_RATE.pack(side = LEFT,padx = 4, pady = 4)

        v_rate = IntVar()
        radiobutton_rate_1 = Radiobutton(rate_frame, text = "16 KHz", variable = v_rate, value = 16000)
        radiobutton_rate_1.pack(side = LEFT)

        radiobutton_rate_2 = Radiobutton(rate_frame, text = "22.05 KHz", variable = v_rate, value = 22050)
        radiobutton_rate_2.pack(side = LEFT)

        radiobutton_rate_3 = Radiobutton(rate_frame, text = "44.1 KHz", variable = v_rate, value = 44100)
        radiobutton_rate_3.pack(side = LEFT)
        v_rate.set(parameters['RATE'])

        # CHANNELS
        channels_frame = Frame(setting_frame)
        channels_frame.pack(expand = YES, fill = X)

        text_CHANNELS = Label(channels_frame, text = "Number of recording channels:", font = ("Helvetica", 15), justify = LEFT)
        text_CHANNELS.pack(side = LEFT,padx = 4, pady = 4)

        v_channels = IntVar()
        radiobutton_channels_1 = Radiobutton(channels_frame, text = "1", variable = v_channels, value = 1)
        radiobutton_channels_1.pack(side = LEFT)

        radiobutton_channels_2 = Radiobutton(channels_frame, text = "2", variable = v_channels, value = 2)
        radiobutton_channels_2.pack(side = LEFT)
        v_channels.set(parameters['CHANNELS'])

        # WAV_PATH
        wav_path_frame = Frame(setting_frame)
        wav_path_frame.pack(expand = YES, fill = X)

        text_WAV_PATH = Label(wav_path_frame, text = "Saving path:", font = ("Helvetica", 15), justify = LEFT)
        text_WAV_PATH.pack(side = LEFT,padx = 4, pady = 4)

        entry_WAV_PATH = Entry(wav_path_frame)
        entry_WAV_PATH.pack(side = LEFT, padx = 4, pady = 4, expand = YES, fill = BOTH)
        entry_WAV_PATH.insert(0, parameters['WAV_PATH'])

        # SCRIPT_FILE
        script_file_frame = Frame(setting_frame)
        script_file_frame.pack(expand = YES, fill = X)

        text_SCRIPT_FILE = Label(script_file_frame, text = "Recording script file:", font = ("Helvetica", 15), justify = LEFT)
        text_SCRIPT_FILE.pack(side = LEFT, padx = 4, pady = 4)

        entry_SCRIPT_FILE = Entry(script_file_frame)
        entry_SCRIPT_FILE.pack(side = LEFT, padx = 4, pady = 4, expand = YES, fill = BOTH)
        entry_SCRIPT_FILE.insert(0, parameters['SCRIPT_FILE'])

        enteries = [v_chunk, v_format, v_rate, v_channels, entry_WAV_PATH, entry_SCRIPT_FILE]

        ###########################
        #      button frame       #
        ###########################
        button_frame = Frame(self.top)
        button_frame.pack(expand = YES, fill = BOTH, ipadx = 10, padx = 10)

        button_submit = Button(button_frame, text = 'Submit')
        button_submit['command'] = lambda: self.submit(enteries)
        button_submit.pack(side = RIGHT, padx = 4)

        button_cancel = Button(button_frame, text = 'Cancel')
        button_cancel['command'] = self.top.destroy
        button_cancel.pack(side = RIGHT, padx = 4)

    def submit(self, enteries):

        # get parameter values from settings
        p_CHUNK = enteries[0].get()         # frames per buffer
        p_FORMAT = enteries[1].get()        # bit rate: 16-bit use "paInt16", 32-bit use "paInt32"
        p_RATE = enteries[2].get()          # sampling rate
        p_CHANNELS = enteries[3].get()      # number of recording channels
        p_WAV_PATH = enteries[4].get()      # saving path for wave files
        p_SCRIPT_FILE = enteries[5].get()   # file of recording script

        # close seeting window
        self.top.destroy()

        # check wav path and script file
        if p_WAV_PATH == '':
            echo_text.configure(text = "Please set \"Saving path\"!\n", bg = 'white', fg = 'red', font = ("Helvetica", 20))

        elif p_SCRIPT_FILE == '':
            echo_text.configure(text = "Please set \"Recording script file\"!\n", bg = 'white', fg = 'red', font = ("Helvetica", 20))

        elif not os.path.exists(p_WAV_PATH):
            echo_text.configure(text = "Saving path does not exist!\n", bg = 'white', fg = 'red', font = ("Helvetica", 20))

        elif not os.path.isfile(p_SCRIPT_FILE):
            echo_text.configure(text = "Recording script file does not exist!\n", bg = 'white', fg = 'red', font = ("Helvetica", 20))

        else:
            # pass parameter value to global parameter record
            parameters['CHUNK'] = p_CHUNK
            parameters['FORMAT'] = p_FORMAT
            parameters['RATE'] = p_RATE
            parameters['CHANNELS'] = p_CHANNELS
            parameters['SCRIPT_FILE'] = p_SCRIPT_FILE

            # fix wav path
            if p_WAV_PATH[-1] != os.path.sep:
                parameters['WAV_PATH'] = p_WAV_PATH + os.path.sep
            else:
                parameters['WAV_PATH'] = p_WAV_PATH

            # set echo window to default
            echo_text.configure(text = "Stopped", bg = 'white', fg = 'black', font = ("Helvetica", 50))

            # set parameters into correct formart, and pass them to global values
            self.get_parameters(parameters)

            global wavefile_name, script_list, filename_format

            # read in script list
            script_list = read_file(SCRIPT_FILE)

            # define wavefile name dynamically based on file counts
            if len(script_list) >= 10 and len(script_list) < 100:
                filename_format = '{0:s}{1:02d}{2:s}'

            elif len(script_list) >= 100 and len(script_list) < 1000:
                filename_format = '{0:s}{1:03d}{2:s}'

            elif len(script_list) >= 1000 and len(script_list) < 10000:
                filename_format = '{0:s}{1:04d}{2:s}'
            else:
                filename_format = '{0:s}{1:d}{2:s}'

            wavefile_name = filename_format.format(WAV_PATH, script_count + 1, '.wav')

            # if file exists, enable play button
            if os.path.isfile(wavefile_name):
                button_play.configure(state = NORMAL)
            else:
                button_play.configure(state = DISABLED)

            # print script in the recording script window
            script_line.set(script_list[script_count])

            # update button states
            button_record.configure(state = NORMAL)
            button_next.configure(state = NORMAL)

    def get_parameters(self, parameters):
        global CHUNK, FORMAT, RATE, CHANNELS, WAV_PATH, SCRIPT_FILE

        CHUNK = parameters['CHUNK']
        RATE = parameters['RATE']
        CHANNELS = parameters['CHANNELS']
        WAV_PATH = parameters['WAV_PATH']
        SCRIPT_FILE = parameters['SCRIPT_FILE']

        if parameters['FORMAT'] == 16:
            FORMAT = paInt16

    def resize(self):
        w, h = self.top.winfo_screenwidth(), self.top.winfo_screenheight()
        window_width = w * 0.4
        window_height = h * 0.4
        left_blank = (w - window_width) / 2
        top_blank = (h - window_height) / 2
        self.top.geometry("%dx%d+%d+%d" % (window_width, window_height, left_blank, top_blank))

##################
#                #
#      MAIN      #
#                #
##################
def main():
    global state, save_buffer, script_count

    state = 0
    script_count = 0
    save_buffer = []

    root.wm_title('PyRecorder')
    Setting_window.root = root
    About_window.root = root
    root.mainloop()

if __name__ == "__main__":
    main()


text:
<?php
 #############################################################################
 # IMDBPHP                              (c) Giorgos Giagas & Itzchak Rehberg #
 # written by Giorgos Giagas                                                 #
 # extended & maintained by Itzchak Rehberg <izzysoft AT qumran DOT org>     #
 # http://www.izzysoft.de/                                                   #
 # ------------------------------------------------------------------------- #
 # This program is free software; you can redistribute and/or modify it      #
 # under the terms of the GNU General Public License (see doc/LICENSE)       #
 #############################################################################

 /* $Id$ */

#===============================================[ optional URL Parameters ]===
# check: only check the specified class (movie, name, charts, nowplay, trail)
#        default: Check them all
# skip : skip the test for the specified, comma-separated classes. Has
#        priority over "check"
# cron : enable cron-mode (cron=1) - i.e. output plain text, and on errors only
# cache: enable (1|on|true) or disable (0|off|false) caching. Overrides config.

require_once(dirname(__FILE__)."/helpers.inc");
#=====================================[ Make sure it works out-of-the-box ]===
$os = php_uname('s');
$path = ini_get('include_path');
if (strtolower(substr($os,0,3))=="win") ini_set('include_path',".;..;$path");
else ini_set('include_path',".:..:$path");

#====================================================[ Output HTML Header ]===
if (!CRON) {
  echo "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN'>\n";
  echo "\n"
     . " <TITLE>IMDBAPI Checks</TITLE>\n"
     . " \n"
     . "\n";
}
#==========================================[ Define what should be tested ]===
$check_movie   = false;
$check_name    = false;
$check_charts  = false;
$check_nowplay = false;
$check_budget  = false;
$check_poster  = false;
$uri = $_SERVER['REQUEST_URI'];
if ( strpos($uri,'?')>0 ) $uri .= '&';
else $uri .= '?';
raw("IMDB\n");
#if ( empty($_REQUEST['api']) && !in_array($_REQUEST['api'],array('imdb','pilot')) ) {
#  if (CRON) {
    $api = 'imdb';
#  } else {
#    raw("\n");
#    exit;
#  }
#} else {
#  $api = $_REQUEST['api'];
#}
(isset($_REQUEST["check"])) ? $check = $_REQUEST["check"] : $check = '';
(isset($_REQUEST["cache"])) ? $cache = $_REQUEST["cache"] : $cache = '0';
switch ($check) {
  case "movie"   : $check_movie   = true; break;
  case "name"    : $check_name    = true; break;
  case "charts"  : $check_charts  = true; break;
  case "nowplay" : $check_nowplay = true; break;
  case "budget"  : $check_budget  = true; break;
  case "poster"  : $check_poster  = true; break;
  default:
    $check_movie   = true;
    $check_name    = true;
    $check_charts  = true;
    $check_nowplay = true;
    $check_budget  = true;
    $check_poster  = true;
}
if (!empty($_REQUEST["skip"])) {
  $skips = explode(",",$_REQUEST["skip"]);
  $segments = array("movie","name","charts","nowplay");
  foreach($skips as $skip) ${"check_$skip"} = FALSE;
}

#=========================================================[ Run the tests ]===
if ($check_movie)   { if ($api=='imdb') require('imdb.inc'); else require('pilot.inc'); }
if ($check_name)    { if ($api=='imdb') require('imdb_person.inc'); else require ('pilot_person.inc'); }
if ($check_charts)  { if ($api=='imdb') require ("imdb_charts.inc"); }
if ($check_nowplay) { if ($api=='imdb') require ("imdb_nowplaying.inc"); }
if ($check_budget)  { if ($api=='imdb') require ("imdb_budget.inc"); }
if ($check_poster)  { if ($api=='imdb') require ("movieposters.inc"); }

#===============================================[ Summary and HTML footer ]===
$passed  = $methods - $failures;
$percent = round(100*$passed/$methods)."%";
if (CRON) {
  if ($failures>0 || !empty($failed)) {
    echo "Some methods failed the automated tests:\n"
       . "========================================\n\n";
    foreach ($failed as $fail) echo "* $fail\n";
    echo "\nOverall results:\n\n"
       . "Success: $passed/$methods ($percent)\n";
  }
} else {
  headline("Test Results:");
  raw("

Methods: $methods

Passed: $passed

Failures: $failures

Success: $percent

\n");
  if ($percent == "100%") raw("Congratulations! Looks like the complete API is working perfectly.");
  raw("\n");
}
?>

redpajama_set_name: RedPajamaGithub


text:
package org.jclouds.concurrent.config;
import static com.google.common.base.Throwables.getStackTraceAsString;
import static com.google.inject.name.Names.named;
import static java.lang.String.format;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.jclouds.Constants.PROPERTY_SCHEDULER_THREADS;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.assertTraceHasSubmission;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.incrementInitialElement;
import static org.jclouds.concurrent.config.ExecutorServiceModuleTest.runnableThrowsRTE;
import static org.testng.Assert.assertTrue;

import java.io.IOException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;

import org.jclouds.lifecycle.Closer;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;

import com.google.common.collect.ImmutableList;
import com.google.common.util.concurrent.ListeningScheduledExecutorService;
import com.google.inject.Guice;
import com.google.inject.Injector;
import com.google.inject.Key;

@Test
public class ScheduledExecutorServiceModuleTest {
   private static final String LINE_SEPARATOR = System.getProperty("line.separator");

   private Injector injector;

   @BeforeClass
   private void setupExecutorModule() {
      ScheduledExecutorServiceModule module = new ScheduledExecutorServiceModule() {
         @Override
         protected void configure() {
            bindConstant().annotatedWith(named(PROPERTY_SCHEDULER_THREADS)).to(1);
            super.configure();
         }
      };

      injector = Guice.createInjector(module);
   }

   @AfterClass
   private void close() throws IOException {
      ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
            named(PROPERTY_SCHEDULER_THREADS)));
      injector.getInstance(Closer.class).close();
      assertTrue(sched.isShutdown());
   }

   @Test
   public void testShutdownOnClose() throws IOException {
      Injector i = Guice.createInjector();

      Closer closer = i.getInstance(Closer.class);
      ListeningScheduledExecutorService executor = createMock(ListeningScheduledExecutorService.class);
      ExecutorServiceModule.shutdownOnClose(executor, closer);

      expect(executor.shutdownNow()).andReturn(ImmutableList.<Runnable> of()).atLeastOnce();

      replay(executor);
      closer.close();

      verify(executor);
   }

   @Test(timeOut = 5000)
   public void testExceptionInSubmitRunnableIncludesSubmissionTrace() throws Exception {
      ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
            named(PROPERTY_SCHEDULER_THREADS)));
      String submission = null;
      try {
         // this is sensitive to formatting as we are looking for the stack traces to match. if you wrap the below
         // line again, you'll need to change incrementInitialElement to 3 line numbers instead of 2.
         submission = getStackTraceAsString(incrementInitialElement(new RuntimeException(), 2))
               .replaceFirst(format(".*%s", LINE_SEPARATOR), "");
         sched.submit(runnableThrowsRTE()).get();
      } catch (ExecutionException e) {
         assertTraceHasSubmission(getStackTraceAsString(e), submission);
         assertTraceHasSubmission(getStackTraceAsString(e.getCause()), submission);
      }
   }

   @Test(timeOut = 5000)
   public void testExceptionInScheduleWithFixedDelayRunnableIncludesSubmissionTrace() throws Exception {
      ListeningScheduledExecutorService sched = injector.getInstance(Key.get(ListeningScheduledExecutorService.class,
            named(PROPERTY_SCHEDULER_THREADS)));
      String submission = null;
      try {
         // this is sensitive to formatting as we are looking for the stack traces to match. if you wrap the below
         // line again, you'll need to change incrementInitialElement to 3 line numbers instead of 2.
         submission = getStackTraceAsString(incrementInitialElement(new RuntimeException(), 2))
               .replaceFirst(format(".*%s", LINE_SEPARATOR), "");
         sched.scheduleWithFixedDelay(runnableThrowsRTE(), 0, 1, TimeUnit.MICROSECONDS).get();
      } catch (ExecutionException e) {
         assertTraceHasSubmission(getStackTraceAsString(e), submission);
         assertTraceHasSubmission(getStackTraceAsString(e.getCause()), submission);
      }
   }
}


text:
package com.querydsl.jpa.support;

import java.util.Arrays;
import java.util.List;

import org.hibernate.dialect.DerbyDialect;
import org.hibernate.dialect.function.CastFunction;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.type.Type;

import com.querydsl.core.types.Ops;
import com.querydsl.sql.DerbyTemplates;
import com.querydsl.sql.SQLTemplates;

/**
 * {@code QDerbyDialect} extends {@code DerbyDialect} with additional functions
 */
public class QDerbyDialect extends DerbyDialect {

    private static final CastFunction castFunction = new CastFunction() {
        @Override
        public String render(Type columnType, List args, SessionFactoryImplementor factory) {
            if (args.get(1).equals("string")) {
                return super.render(columnType, Arrays.asList("char(" + args.get(0) + ")", args.get(1)), factory);
            } else {
                return super.render(columnType, args, factory);
            }
        }
    };

    public QDerbyDialect() {
        SQLTemplates templates = DerbyTemplates.DEFAULT;
        getFunctions().putAll(DialectSupport.createFunctions(templates));
        registerFunction("concat", DialectSupport.createFunction(templates, Ops.CONCAT));
        registerFunction("cast", castFunction);
    }

}


text:
#import <Foundation/Foundation.h>
#import "KrollContext.h"

@class TiHost;

@protocol TiEvaluator <NSObject>

- (TiHost*)host;

- (NSString*)basename;

@property(nonatomic,readwrite,retain)	NSURL * currentURL;

- (void)evalJSWithoutResult:(NSString*)code;

- (void)evalFile:(NSString*)file;

- (BOOL)evaluationError;

// NOTE: this must only be called on a thread JS thread or an exception will occur
- (id)evalJSAndWait:(NSString*)code;

- (void)fireEvent:(id)listener withObject:(id)obj remove:(BOOL)yn thisObject:(id)thisObject_;

- (id)preloadForKey:(id)key name:(id)key;

- (KrollContext*)krollContext;

//Creates a kroll object to be used with the proxy.
- (id)registerProxy:(id)proxy;

//Removes the kroll object and the proxy.
- (void)unregisterProxy:(id)proxy;

//Returns YES if and only iff the proxy has been registered.
- (BOOL)usesProxy:(id)proxy;

//Returns the kroll object created iff the proxy has been registered. Otherwise, returns nil.
- (id)krollObjectForProxy:(id)proxy;

@end


text:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xmlns:task="http://www.springframework.org/schema/task"

	xsi:schemaLocation="
		http://www.springframework.org/schema/beans
		http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context-3.2.xsd
        http://www.springframework.org/schema/tx
        http://www.springframework.org/schema/tx/spring-tx-3.2.xsd
        http://www.springframework.org/schema/task
		http://www.springframework.org/schema/task/spring-task-3.2.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc-3.2.xsd">

	<!-- defines shared resources visible to all other web components -->
	<bean id="propertyConfigurer" class="com.qycloud.oatos.server.security.SecurityPropertyConfigurer">
		<property name="locations">
			<list>
				<value>classpath:*property/jdbc.properties</value>
			</list>
		</property>
	</bean>

	<!--后台服务数据源 -->
	<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
		<property name="driverClassName" value="${jdbc.driverClassName}" />
		<property name="url" value="${jdbc.url}" />
		<property name="username" value="${jdbc.username}" />
		<property name="password" value="${jdbc.password}" />
	</bean>

    <!-- transaction manager, use JtaTransactionManager for global tx -->
    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource" />
    </bean>

    <!-- enable component scanning (beware that this does not enable mapper scanning!) -->
    <context:component-scan base-package="com.qycloud.oatos.server" />

    <!-- enable autowire -->
    <context:annotation-config />

    <!-- enable transaction demarcation with annotations -->
    <tx:annotation-driven />

    <!-- define the SqlSessionFactory -->
    <bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="typeAliasesPackage" value="com.qycloud.oatos.server.domain.entity" />
    </bean>

    <!-- scan for mappers and let them be autowired -->
    <bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
        <property name="basePackage" value="com.qycloud.oatos.server.dao" />
    </bean>

	<!-- @ResponseBody string set  charset utf-8 -->
	<bean id="stringHttpMessageConverter" class="org.springframework.http.converter.StringHttpMessageConverter">
		<property name="supportedMediaTypes">
			<list>
				<value>text/plain;charset=UTF-8</value>
			</list>
		</property>
	</bean>

	<!-- @ResponseBody message converters must set before mvc:annotation-driven -->
	<bean id="requestMappingHandlerAdapter" class="org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter">
		<property name="messageConverters">
			<list>
				<ref bean="stringHttpMessageConverter"/>
				<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter"/>
			</list>
		</property>
	</bean>

	<!-- Enables the Spring MVC @Controller programming model -->
	<mvc:annotation-driven />

	<!-- tasks -->
	<task:scheduled-tasks>
		<task:scheduled ref="MessageTask" method="execute" cron="0 0/3 * * * *"/>
<!--		<task:scheduled ref="EnterpriseModuleTask" method="execute" cron="0 30 23 * * *"/>-->
	</task:scheduled-tasks>

</beans>


text:
<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="wrap_content">

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical">

        <View
            android:id="@+id/resultColorStrip"
            android:layout_width="match_parent"
            android:layout_height="7dp" />

        <TextView
            android:id="@+id/textGroupHeading"
            android:layout_width="match_parent"
            android:layout_height="30dp"
            android:gravity="center_vertical"
            android:paddingLeft="40dp"
            android:text="Text"
            android:textStyle="bold" />

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/textLabel3"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:gravity="center_vertical"
                android:paddingBottom="5dp"
                android:paddingLeft="40dp"
                android:text="@string/race_position"
                android:textColor="@color/colorPrimary"
                android:textSize="12sp"
                android:textStyle="bold" />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="7">

                <TextView
                    android:id="@+id/textPosition"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="2"
                    android:gravity="center_vertical"
                    android:textColor="@color/colorPrimary"
                    android:textSize="12sp"
                    android:textStyle="bold"
                    tools:text="1" />

                <LinearLayout
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="7">

                    <TextView
                        android:id="@+id/textLabel0"
                        android:layout_width="wrap_content"
                        android:layout_height="wrap_content"
                        android:gravity="center_vertical"
                        android:text="@string/race_time"
                        android:textSize="12sp" />

                    <TextView
                        android:id="@+id/textTotalRaceTime"
                        android:layout_width="0dp"
                        android:layout_height="wrap_content"
                        android:layout_weight="1"
                        android:gravity="center_vertical"
                        android:textSize="12sp"
                        tools:text="2:12" />
                </LinearLayout>

            </LinearLayout>
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/textLabel1"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:gravity="center_vertical"
                android:paddingBottom="5dp"
                android:paddingLeft="40dp"
                android:text="@string/last_lap"
                android:textSize="12sp" />

            <TextView
                android:id="@+id/textLastLap"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="7"
                android:gravity="center_vertical"
                android:textSize="12sp"
                tools:text="0:12" />
        </LinearLayout>

        <LinearLayout
            android:layout_width="match_parent"
            android:layout_height="wrap_content">

            <TextView
                android:id="@+id/textLabel2"
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="3"
                android:gravity="center_vertical"
                android:paddingBottom="10dp"
                android:paddingLeft="40dp"
                android:text="@string/best_lap"
                android:textColor="@color/colorPrimary"
                android:textSize="12sp" />

            <LinearLayout
                android:layout_width="0dp"
                android:layout_height="wrap_content"
                android:layout_weight="7">

                <TextView
                    android:id="@+id/textBestLap"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:gravity="center_vertical"
                    android:textColor="@color/colorPrimary"
                    android:textSize="12sp"
                    tools:text="1:15" />

                <TextView
                    android:id="@+id/textPositionByBestLap"
                    android:layout_width="0dp"
                    android:layout_height="wrap_content"
                    android:layout_weight="1"
                    android:gravity="center_vertical"
                    android:text="@string/best_lap_position"
                    android:textColor="@color/colorPrimary"
                    android:textSize="12sp" />

            </LinearLayout>
        </LinearLayout>
    </LinearLayout>

</LinearLayout>


text:
/***************************************************************************\
    KneeBoard.h
    Scott Randolph
    September 4, 1998

    This class provides the pilots knee board notepad and map.
\***************************************************************************/
#ifndef _KNEEBOARD_H_
#define _KNEEBOARD_H_

//#include "Graphics/Include/Render2d.h"
#include "Graphics/Include/image.h"

class SimVehicleClass;
class WayPointClass;
class DisplayDevice;
class CImageFileMemory;

class KneeBoard
{
public:
    KneeBoard();
    virtual ~KneeBoard();
    void KneeBoard::DrawMissionText(Render2D *renderer, SimVehicleClass *platform);
    // loads and cleanup kneeboard resources
    virtual void Setup(/*DisplayDevice *device, int top, int left, int bottom, int right*/);
    virtual void Cleanup(void);

    // sfr: page information functions and variables
    enum Page {BRIEF, MAP, STEERPOINT};
    void SetPage(Page p)
    {
        page = p;
    };
    Page GetPage(void)
    {
        return page;
    };

    // map stuff
    CImageFileMemory &GetImageFile()
    {
        return mapImageFile;
    }
    /*float GetVcenter()   const { return wsVcenter;   }
    float GetHcenter()   const { return wsHcenter;   }
    float GetHsize()     const { return wsHsize;     }
    float GetVsize()     const { return wsVsize;  }
    int   GetPixelMag()  const { return pixelMag;    }
    float GetPixel2nmX() const { return m_pixel2nmX; }
    float GetPixel2nmY() const { return m_pixel2nmY; }*/

    //void UpdateMapDimensions( SimVehicleClass *platform );

private:
    // reference counters (views using us)
    unsigned int refCount;

    // sfr: non sense using an internal parameter to a private function
    void LoadKneeImage(/*CImageFileMemory &imagefile*/);
    // Which page we're displaying
    Page page;
    /*
     // Real world map dimensions (R/O externally)
     float wsVcenter; //vertical center
     float wsHcenter; //horizontal center
     float wsHsize; //horizontal size
     float wsVsize; //vertical size
     int pixelMag;
     float m_pixel2nmX, m_pixel2nmY;
    */
    // Map image surface and Blt rectangles
    bool imageLoaded;
    CImageFileMemory  mapImageFile;

};

#endif // _KNEEBOARD_H_


text:
<?php

namespace RedKiteCms\Block\SocialBlockBundle\Tests\Unit\Core\SdkCollection;

use RedKiteLabs\RedKiteCms\RedKiteCmsBundle\Tests\TestCase;
use RedKiteCms\Block\SocialBlockBundle\Core\SdkCollection\SdkCollection;

/**
 * LanguagesFormTest
 *
 * @author RedKite Labs <info@redkite-labs.com>
 */
class RenderSdkListenerTest extends TestCase
{
    public function testAddSkd()
    {
        $sdk = $this->getMock('RedKiteCms\Block\SocialBlockBundle\Core\Sdk\SdkInterface');

        $collection = new SdkCollection();
        $collection->addSdk($sdk);

        $this->assertCount(1, $collection);
        $this->assertEquals($sdk, $collection->current());
        $this->assertEquals(0, $collection->key());
        $this->assertTrue($collection->valid());
        $collection->next();
        $this->assertFalse($collection->valid());
    }
}


text:
@interface ARExternalWebBrowserViewController : UIViewController <WKNavigationDelegate>

@property (readonly, nonatomic, strong) WKWebView *webView;
@property (readonly, nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, readonly, strong) NSURL *initialURL;
@property (nonatomic, assign) UIStatusBarStyle statusBarStyle;

- (instancetype)initWithURL:(NSURL *)url;

- (NSURL *)currentURL;
- (void)loadURL:(NSURL *)URL;
- (void)reload;

// This hook is exposed for subclasses to be able to make decisions as to how to handle the navigation action.
- (WKNavigationActionPolicy)shouldLoadNavigationAction:(WKNavigationAction *)navigationAction;
- (WKNavigationResponsePolicy)shouldLoadNavigationResponse:(WKNavigationResponse *)navigationResponse;

@end


text:
package org.broadinstitute.dsde.workbench.sam.db.tables

import org.broadinstitute.dsde.workbench.sam.db.{DatabaseKey, SamTypeBinders}
import org.broadinstitute.dsde.workbench.sam.model.{ResourceRoleName, ResourceTypeName}
import org.broadinstitute.dsde.workbench.sam.db.SamParameterBinderFactory.SqlInterpolationWithSamBinders
import scalikejdbc._

final case class ResourceTypePK(value: Long) extends DatabaseKey
final case class ResourceTypeRecord(id: ResourceTypePK, name: ResourceTypeName, ownerRoleName: ResourceRoleName, reuseIds: Boolean, allowLeaving: Boolean)

object ResourceTypeTable extends SQLSyntaxSupportWithDefaultSamDB[ResourceTypeRecord] {
  override def tableName: String = "SAM_RESOURCE_TYPE"

  import SamTypeBinders._
  def apply(e: ResultName[ResourceTypeRecord])(rs: WrappedResultSet): ResourceTypeRecord = ResourceTypeRecord(
    rs.get(e.id),
    rs.get(e.name),
    rs.get(e.ownerRoleName),
    rs.get(e.reuseIds),
    rs.get(e.allowLeaving)
  )

  def pkQuery(resourceTypeName: ResourceTypeName, resourceTypeTableAlias: String = "rtt"): SQLSyntax = {
    val rtt = ResourceTypeTable.syntax(resourceTypeTableAlias)
    samsqls"select ${rtt.id} from ${ResourceTypeTable as rtt} where ${rtt.name} = ${resourceTypeName}"
  }
}


text:
<?xml version="1.0" encoding="UTF-8"?>
<sem:triples uri="http://www.lds.org/vrl/publications-and-documents/missionary-work/new-and-returning-member-progress-form" xmlns:sem="http://marklogic.com/semantics">
  <sem:triple>
    <sem:subject>http://www.lds.org/vrl/publications-and-documents/missionary-work/new-and-returning-member-progress-form</sem:subject>
    <sem:predicate>http://www.w3.org/2004/02/skos/core#prefLabel</sem:predicate>
    <sem:object datatype="xsd:string" xml:lang="eng">New and Returning Member Progress (Form)</sem:object>
  </sem:triple>
  <sem:triple>
    <sem:subject>http://www.lds.org/vrl/publications-and-documents/missionary-work/new-and-returning-member-progress-form</sem:subject>
    <sem:predicate>http://www.w3.org/2004/02/skos/core#inScheme</sem:predicate>
    <sem:object datatype="sem:iri">http://www.lds.org/concept-scheme/vrl</sem:object>
  </sem:triple>
  <sem:triple>
    <sem:subject>http://www.lds.org/vrl/publications-and-documents/missionary-work/new-and-returning-member-progress-form</sem:subject>
    <sem:predicate>http://www.lds.org/core#entityType</sem:predicate>
    <sem:object datatype="sem:iri">http://www.lds.org/Topic</sem:object>
  </sem:triple>
</sem:triples>


text:
/*
 * apitrigeom.h - header for functions to generate triangle tesselated
 *                geometry for use with OpenGL, XGL, etc.
 *
 */

void rt_tri_fcylinder(SceneHandle, void *, apivector, apivector, apiflt);
void rt_tri_cylinder(SceneHandle, void *, apivector, apivector, apiflt);
void rt_tri_ring(SceneHandle, void *, apivector, apivector, apiflt, apiflt);
void rt_tri_plane(SceneHandle, void *, apivector, apivector);
void rt_tri_box(SceneHandle, void *, apivector, apivector);


text:
package org.apache.camel.model;

import javax.xml.bind.annotation.XmlRootElement;

import org.apache.camel.Exchange;
import org.apache.camel.Predicate;
import org.apache.camel.model.language.ExpressionDefinition;
import org.apache.camel.spi.AsPredicate;
import org.apache.camel.spi.Metadata;
import org.apache.camel.spi.RouteContext;

/**
 * Predicate to determine if the message should be sent or not to the endpoint, when using interceptSentToEndpoint.
 */
@Metadata(label = "configuration") @AsPredicate
@XmlRootElement(name = "whenSkipSendToEndpoint")
public class WhenSkipSendToEndpointDefinition extends WhenDefinition {
    @Override
    public String getShortName() {
        return "whenSkipSendToEndpoint";
    }

    @Override
    protected Predicate createPredicate(RouteContext routeContext) {
        // we need to keep track whether the when matches or not, so delegate
        // the predicate and add the matches result as a property on the exchange
        final Predicate delegate = super.createPredicate(routeContext);
        return new Predicate() {
            @Override
            public boolean matches(Exchange exchange) {
                boolean matches = delegate.matches(exchange);
                exchange.setProperty(Exchange.INTERCEPT_SEND_TO_ENDPOINT_WHEN_MATCHED, matches);
                return matches;
            }

            @Override
            public String toString() {
                return delegate.toString();
            }
        };
    }

    /**
     * Expression used as the predicate to evaluate whether the message should be sent or not to the endpoint
     */
    @Override
    public void setExpression(ExpressionDefinition expression) {
        // override to include javadoc what the expression is used for
        super.setExpression(expression);
    }

}


text:
package ad

import (
	"go2o/core/domain/interface/ad"
	"sort"
)

var _ ad.IAd = new(GalleryAd)
var _ ad.IGalleryAd = new(GalleryAd)

type GalleryAd struct {
	*adImpl
	_adValue ad.ValueGallery
}

// 获取广告数据
func (this *GalleryAd) GetAdValue() ad.ValueGallery {
	if this._adValue == nil {
		if this.GetDomainId() > 0 {
			this._adValue = this._rep.GetValueGallery(this.GetDomainId())
			sort.Sort(this._adValue)
		} else {
			this._adValue = []*ad.Image{}
		}
	}
	return this._adValue
}

// 获取可用的广告数据
func (this *GalleryAd) GetEnabledAdValue() ad.ValueGallery {
	val := this.GetAdValue()
	newVal := ad.ValueGallery{}
	for _, v := range val {
		if v.Enabled == 1 {
			newVal = append(newVal, v)
		}
	}
	return newVal
}

// 保存广告图片
func (this *GalleryAd) SaveImage(v *ad.Image) (int, error) {
	v.AdId = this.GetDomainId()
	return this._rep.SaveAdImageValue(v)
}

// 获取图片项
func (this *GalleryAd) GetImage(id int) *ad.Image {
	return this._rep.GetValueAdImage(this.GetDomainId(), id)
}

// 删除图片项
func (this *GalleryAd) DelImage(id int) error {
	return this._rep.DelAdImage(this.GetDomainId(), id)
}

// 转换为数据传输对象
func (this *GalleryAd) Dto() *ad.AdDto {
	return &ad.AdDto{
		Id:   this.adImpl.GetDomainId(),
		Type: this.adImpl.Type(),
		Data: this.GetEnabledAdValue(),
	}
}


text:
---
title: Запуск инструкций сборки
permalink: advanced/building_images_with_stapel/assembly_instructions.html
directive_summary: shell_and_ansible
---

## Пользовательские стадии

***Пользовательские стадии*** — это [_стадии_]({{ "internals/stages_and_storage.html" | true_relative_url }}) со сборочными инструкциями из [конфигурации]({{ "reference/werf_yaml.html#секция-image" | true_relative_url }}). Другими словами, — это стадии, конфигурируемые пользователем (существуют также служебные стадии, которые пользователь конфигурировать не может). В настоящее время существует два вида сборочных инструкций: _shell_ и _ansible_.

werf поддерживает четыре _пользовательские стадии_, которые выполняются последовательно, в следующем порядке: _beforeInstall_, _install_, _beforeSetup_ и _setup_. В результате выполнения инструкций пользовательской стадии, создается один Docker-слой. Т.е. по одному слою на каждую стадию, в независимости от количества инструкций.

## Обоснование использования

### Своя концепция организации сборки (opinionated software)

Шаблон и механизм работы _пользовательских стадий_ основан на анализе сборки реальных приложений. В результате мы пришли к выводу, что для того, чтобы качественно улучшить сборку большинства приложений, достаточно разбить инструкции сборки на 4 группы (эти группы и есть _пользовательские стадии_), подчиняющиеся определенным правилам. Такая группировка уменьшает количество слоев и ускоряет сборку.

### Четкая структура сборочного процесса

Наличие _пользовательских стадий_ определяет структуру процесса сборки и, таким образом, устанавливает некоторые рамки для разработчика. Несмотря на дополнительное ограничение по сравнению с неструктурированными инструкциями Docker-файла, это наоборот дает выигрыш в скорости, т.к. разработчик знает, какие инструкции на каком этапе должны быть.

### Запуск инструкций сборки при изменениях в git-репозитории

werf может использовать как локальные, так и удаленные git-репозитории, при сборке. Любой _пользовательской стадии_ можно определить зависимость от изменения конкретных файлов или папок в одном или нескольких git-репозиториях. Это дает возможность принудительно пересобирать _пользовательскую стадию_ если в локальном или удаленном репозитории (или репозиториях) изменяются какие-либо файлы.

### Больше инструментов сборки: shell, ansible, ...

_Shell_ — знакомый и хорошо известный инструмент сборки.
_Ansible_ — более молодой инструмент, требующий чуть больше времени на изучение.

Если вам нужен быстрый результат с минимальными затратами времени и как можно быстрее, то использование _shell_ может быть вполне достаточно — все работает аналогично директиве `RUN` в Dockerfile.

В случае с _Ansible_ применяется декларативный подход и подразумевается идемпотентность операций. Такой подход дает более предсказуемый результат, особенно в случае проектов большого жизненного цикла.

Архитектура werf позволяет добавлять поддержку и других инструментов сборки в будущем.

## Использование пользовательских стадий

werf позволяет определять до четырех _пользовательских стадий_ с инструкциями сборки. На содержание самих инструкций сборки werf не накладывает каких-либо ограничений, т.е. вы можете указывать все те же инструкции, которые указывали в Dockerfile в директиве `RUN`. Однако важно не просто перенести инструкции из Dockerfile, а правильно разбить их на _пользовательские стадии_. Исходя из опыта работы с реальными приложениями, мы пришли к заключению, что сборка большинства приложений проходит следующие этапы:

- установка системных пакетов
- установка системных зависимостей
- установка зависимостей приложения
- настройка системных пакетов
- настройка приложения

Какая может быть наилучшая стратегия выполнения этих этапов?

Первая мысль — лучше выполнять эти этапы последовательно, кэшируя промежуточные результаты, а с другой стороны разбивать инструкции по файловым зависимостям.

Подход с _пользовательскими стадиями_ предлагает следующую стратегию:
- использовать стадию _beforeInstall_ для инсталляции системных пакетов;
- использовать стадию _install_ для инсталляции системных зависимостей и зависимостей приложения;
- использовать стадию _beforeSetup_ для настройки системных параметров и установки приложения;
- использовать стадию _setup_ для настройки приложения.

### beforeInstall

Данная стадия предназначена для выполнения инструкций перед установкой приложения.
Этот этап предназначен для системных приложений, которые редко изменяются, но требуют много времени для установки.
Примером таких приложений могут быть языковые пакеты, инструменты сборки, такие как composer, java, gradle и т.д.
Также сюда можно добавлять инструкции настройки системы, которые редко изменяются.
Например, языковые настройки, настройки часового пояса, добавление пользователей и групп.

Поскольку эти компоненты меняются редко, они будут кэшироваться в рамках стадии _beforeInstall_ на длительный период.

### install

Данная стадия предназначена для установки приложения и его зависимостей, а также выполнения базовых настроек.

На данной стадии появляется доступ к исходному коду используемых git-репозиториев (директива git) и появляется возможность установки зависимостей на основе manifest-файлов с использованием таких инструментов, как composer, gradle, npm и т.д. Поскольку сборка стадии зависит от manifest-файла, для достижения наилучшего результата важно добавить зависимость от изменений в manifest-файлах репозитория для этой стадии. Например, если в проекте используется composer, то добавление файла composer.lock в зависимости стадии _beforeInstall_ позволит пересобирать стадию при изменении файла composer.lock.

### beforeSetup

Данная стадия предназначена для подготовки приложения перед настройкой.

На данной стадии рекомендуется выполнять разного рода компиляцию и обработку.
Например, компиляция jar-файлов, бинарных файлов, файлов библиотек, создание ассетов web-приложений, минификация, шифрование и т.п.
Перечисленные операции, как правило, зависят от изменений в исходном коде и на данной стадии также важно определить достаточные зависимости от изменений в репозитории. Логично, что стадия будет зависеть от большего числа файлов в репозитории, чем на предыдущей стадии, и, соответственно, ее пересборка будет выполняться чаще.

При правильно определенных зависимостях, изменения в коде приложения должны приводить к пересборке стадии _beforeSetup_, а изменение manifest-файла к стадии _install_ и последующих стадий.

### setup

Данная стадия предназначена для настройки приложения.

Обычно на данной стадии выполняется копирование файлов конфигурации (например, в папку `/etc`), создание файлов текущей версии приложения и т.д.
Такого рода операции не должны быть затратными по времени, т.к. они скорее всего будут выполняться в большинстве сборок.

### Пользовательская стратегия

Несмотря на изложенную четкую стратегию шаблона _пользовательских стадий_ и функции каждой стадии, по сути для пользователя нет никаких ограничений. Предложенное использование стадий является лишь рекомендацией, которая основана на нашем опыте с реальными приложениями. Вы можете использовать только одну пользовательскую стадию, либо определить свою стратегию группировки инструкций, чтобы получить преимущества кэширования и зависимостей от изменений в git-репозиториях с учетом особенностей сборки вашего приложения.

## Синтаксис

Пользовательские стадии и инструкции сборки определяются внутри двух взаимоисключающих директив — `shell` и `ansible`. Каждый образ может собираться либо используя сборочные инструкции ***shell***, либо задачи ***ansible***, описанные в соответствующих директивах.

В каждой директиве можно описывать инструкции для _пользовательских стадий_, соответственно:
- `beforeInstall`
- `install`
- `beforeSetup`
- `setup`

Также можно указывать директивы версий кэша (***cacheVersion***), которые по сути являются частью дайджеста каждой _пользовательской стадии_. Более подробно в [соответствующем разделе](#зависимость-от-значения-cacheversion).

## Shell

Синтаксис описания _пользовательских стадий_ при использовании сборочных инструкций _shell_:

```yaml
shell:
  beforeInstall:
  - <bash_command 1>
  - <bash_command 2>
  ...
  - <bash_command N>
  install:
  - bash command
  ...
  beforeSetup:
  - bash command
  ...
  setup:
  - bash command
  ...
  cacheVersion: <version>
  beforeInstallCacheVersion: <version>
  installCacheVersion: <version>
  beforeSetupCacheVersion: <version>
  setupCacheVersion: <version>
```

Сборочные инструкции _shell_ — это массив bash-команд для соответствующей _пользовательской стадии_. Все команды одной стадии выполняются как одна инструкция `RUN` в Dockerfile, т.е. в результате создается один слой на каждую _пользовательскую стадию_.

werf при сборке использует собственный исполняемый файл bash и вам не нужно отдельно добавлять его в образ (или [базовый образ]({{ "advanced/building_images_with_stapel/base_image.html" | true_relative_url }})) при сборке.

Пример описания стадии _beforeInstall_ содержащей команды `apt-get update` и `apt-get install`:

```yaml
beforeInstall:
- apt-get update
- apt-get install -y build-essential g++ libcurl4
```

werf выполнит команды стадии следующим образом::
- на хост-машине сгенерируется временный скрипт:

    ```shell
    #!/.werf/stapel/embedded/bin/bash -e

    apt-get update
    apt-get install -y build-essential g++ libcurl4
    ```

- скрипт смонтируется в _сборочный контейнер_ как `/.werf/shell/script.sh`
- скрипт выполнится.

> Исполняемый файл `bash` находится внутри Docker-тома _stapel_. Подробнее про эту концепцию можно узнать в этой [статье](https://habr.com/company/flant/blog/352432/) (упоминаемый в статье `dappdeps` был переименован в `stapel`, но принцип сохранился)

## Ansible

Синтаксис описания _пользовательских стадий_ при использовании сборочных инструкций _ansible_:

```yaml
ansible:
  beforeInstall:
  - <ansible task 1>
  - <ansible task 2>
  ...
  - <ansible task N>
  install:
  - ansible task
  ...
  beforeSetup:
  - ansible task
  ...
  setup:
  - ansible task
  ...
  cacheVersion: <version>
  beforeInstallCacheVersion: <version>
  installCacheVersion: <version>
  beforeSetupCacheVersion: <version>
  setupCacheVersion: <version>
```

### Ansible config и stage playbook

Сборочные инструкции _ansible_ — это массив Ansible-заданий для соответствующей _пользовательской стадии_. Для запуска этих заданий с помощью `ansible-playbook` werf монтирует следующую структуру папок в _сборочный контейнер_:

```shell
/.werf/ansible-workdir
├── ansible.cfg
├── hosts
└── playbook.yml
```

`ansible.cfg` содержит настройки для Ansible:
- использование локального транспорта (transport = local)
- подключение callback плагина werf для удобного логирования (stdout_callback = werf)
- включение режима цвета (force_color = 1)
- установка использования `sudo` для повышения привилегий (чтобы не было необходимости использовать `become` в Ansible-заданиях)

`hosts` — inventory-файл, содержит только localhost и некоторые `ansible_*` параметры.

`playbook.yml` — playbook, содержащий все задания соответствующей _пользовательской стадии_. Пример `werf.yaml` с описанием стадии _install_:

```yaml
ansible:
  install:
  - debug: msg='Start install'
  - file: path=/etc mode=0777
  - copy:
      src: /bin/sh
      dest: /bin/sh.orig
  - apk:
      name: curl
      update_cache: yes
  ...
```

В приведенном примере, werf сгенерирует следующий `playbook.yml` для стадии _install_:
```yaml
- hosts: all
  gather_facts: 'no'
  tasks:
  - debug: msg='Start install'  \
  - file: path=/etc mode=0777   |
  - copy:                        > эти строки будут скопированы из werf.yaml
      src: /bin/sh              |
      dest: /bin/sh.orig        |
  - apk:                        |
      name: curl                |
      update_cache: yes         /
  ...
```

werf выполняет playbook _пользовательской стадии_ в сборочном контейнере стадии с помощью команды `playbook-ansible`:

```shell
$ export ANSIBLE_CONFIG="/.werf/ansible-workdir/ansible.cfg"
$ ansible-playbook /.werf/ansible-workdir/playbook.yml
```

> Исполняемые файлы и библиотеки `ansible` и `python` находятся внутри Docker-тома _stapel_. Подробнее про эту концепцию можно узнать в этой [статье](https://habr.com/company/flant/blog/352432/) (упоминаемый в статье `dappdeps` был переименован в `stapel`, но принцип сохранился)

### Поддерживаемые модули

Одной из концепций, которую использует werf, является идемпотентность сборки. Это значит что если "ничего не изменилось", то werf при повторном и последующих запусках сборки должен создавать бинарно идентичные образы. В werf эта задача решается с помощью подсчета _дайджестов стадий_.

Многие модули Ansible не являются идемпотентными, т.е. они могут давать разный результат запусков при неизменных входных параметрах. Это, конечно, не дает возможность корректно высчитывать _дайджест_ стадии, чтобы определять реальную необходимость её пересборки из-за изменений. Это привело к тому, что список поддерживаемых модулей был ограничен.

На текущий момент, список поддерживаемых модулей Ansible следующий:

- [Commands modules](https://docs.ansible.com/ansible/2.5/modules/list_of_commands_modules.html): command, shell, raw, script.
- [Crypto modules](https://docs.ansible.com/ansible/2.5/modules/list_of_crypto_modules.html): openssl_certificate и другие.
- [Files modules](https://docs.ansible.com/ansible/2.5/modules/list_of_files_modules.html): acl, archive, copy, stat, tempfile и другие.
- [Net Tools Modules](https://docs.ansible.com/ansible/2.5/modules/list_of_net_tools_modules.html): get_url, slurp, uri.
- [Packaging/Language modules](https://docs.ansible.com/ansible/2.5/modules/list_of_packaging_modules.html#language): composer, gem, npm, pip и другие.
- [Packaging/OS modules](https://docs.ansible.com/ansible/2.5/modules/list_of_packaging_modules.html#os): apt, apk, yum и другие.
- [System modules](https://docs.ansible.com/ansible/2.5/modules/list_of_system_modules.html): user, group, getent, locale_gen, timezone, cron и другие.
- [Utilities modules](https://docs.ansible.com/ansible/2.5/modules/list_of_utilities_modules.html): assert, debug, set_fact, wait_for.

При указании в _конфигурации сборки_ модуля отсутствующего в приведенном списке, сборка прервется с ошибкой. Не стесняйтесь [сообщать](https://github.com/werf/werf/issues/new) нам, если вы считаете что какой-либо модуль должен быть включен в список поддерживаемых.

### Копирование файлов

Предпочтительный способ копирования файлов в образ — использование [_git mapping_]({{ "advanced/building_images_with_stapel/git_directive.html" | true_relative_url }}).
werf не может определять изменения в копируемых файлах при использовании модуля `copy`.
Единственный вариант копирования внешнего файла в образ на текущий момент — использовать метод `.Files.Get` Go-шаблона.
Данный метод возвращает содержимое файла как строку, что дает возможность использовать содержимое как часть _пользовательской стадии_.
Таким образом, при изменении содержимого файла изменится дайджест соответствующей стадии, что приведет к пересборке всей стадии.

Пример копирования файла `nginx.conf` в образ:

{% raw %}
```yaml
ansible:
  install:
  - copy:
      content: |
{{ .Files.Get "/conf/etc/nginx.conf" | indent 8}}
      dest: /etc/nginx/nginx.conf
```
{% endraw %}

В результате получится подобный `playbook.yml`:

```yaml
- hosts: all
  gather_facts: no
  tasks:
    install:
    - copy:
        content: |
          http {
            sendfile on;
            tcp_nopush on;
            tcp_nodelay on;
            ...
```

### Шаблоны Jinja

В Ansible реализована поддержка шаблонов [Jinja](https://docs.ansible.com/ansible/2.5/user_guide/playbooks_templating.html) в playbook'ах. Однако у Go-шаблонов и Jinja-шаблонов одинаковый разделитель: {% raw %}`{{` и `}}`{% endraw %}. Чтобы использовать Jinja-шаблоны в конфигурации werf, их нужно экранировать. Для этого есть два варианта: экранировать только {% raw %}`{{`{% endraw %}, либо экранировать все выражение шаблона Jinja.

Например, у вас есть следующая задача Ansible:

{% raw %}
```yaml
- copy:
    src: {{item}}
    dest: /etc/nginx
    with_files:
    - /app/conf/etc/nginx.conf
    - /app/conf/etc/server.conf
```
{% endraw %}

{% raw %}
Тогда, выражение Jinja-шаблона `{{item}}` должно быть экранировано:
{% endraw %}

{% raw %}
```yaml
# экранируем только {{
src: {{"{{"}} item }}
```
либо
```yaml
# экранируем все выражение
src: {{`{{item}}`}}
```
{% endraw %}

### Проблемы с Ansible

- Live-вывод реализован только для модулей `raw` и `command`. Остальные модули отображают вывод каналов `stdout` и `stderr` после выполнения, что приводит к задержкам, скачкообразному выводу.
- Модуль `apt` подвисает на некоторых версиях Debian и Ubuntu. Проявляется также на наследуемых образах([issue #645](https://github.com/werf/werf/issues/645)).

## Зависимости пользовательских стадий

Одна из особенностей werf — возможность определять зависимости, при которых происходит пересборка _стадии_.
Как указано в [статье]({{ "internals/stages_and_storage.html" | true_relative_url }}), сборка _стадий_ выполняется последовательно, одна за другой, и для каждой _стадии_ высчитывается _дайджест стадии_. У _дайджестов_ есть ряд зависимостей, при изменении которых _дайджест стадии_ меняется, что служит для werf сигналом для пересборки стадии с измененным _дайджестом_. Поскольку каждая следующая _стадия_ имеет зависимость, в том числе и от предыдущей _стадии_ согласно _конвейеру стадий_, при изменении дайджеста какой-либо _стадии_, произойдет пересборка и _стадии_ с изменённым дайджестом и всех последующих _стадий_.

_Дайджест пользовательских стадий_ и соответственно пересборка _пользовательских стадий_ зависит от изменений:
- в инструкциях сборки
- в директивах семейства _cacheVersion_
- в git-репозитории (или git-репозиториях)
- в файлах, импортируемых из [артефактов]({{ "advanced/building_images_with_stapel/artifacts.html" | true_relative_url }})

Первые три описанных варианта зависимостей, рассматриваются подробно далее.

## Зависимость от изменений в инструкциях сборки

_Дайджест пользовательской стадии_ зависит от итогового текста инструкций, т.е. после применения шаблонизатора. Любые изменения в тексте инструкций с учетом применения шаблонизатора Go или Jinja (в случае Ansible) в _пользовательской стадии_ приводят к пересборке _стадии_. Например, вы используете следующие _shell-инструкции_:

```yaml
shell:
  beforeInstall:
  - echo "Commands on the Before Install stage"
  install:
  - echo "Commands on the Install stage"
  beforeSetup:
  - echo "Commands on the Before Setup stage"
  setup:
  - echo "Commands on the Setup stage"
```

При первой сборке этого образа будут выполнены инструкции всех четырех _пользовательских стадий_.
В данной конфигурации нет _git mapping_, так что последующие сборки не приведут к повторному выполнению инструкций — _дайджест пользовательских стадий_ не изменилась, сборочный кэш содержит актуальную информацию.

Изменим инструкцию сборки для стадии _install_:

```yaml
shell:
  beforeInstall:
  - echo "Commands on the Before Install stage"
  install:
  - echo "Commands on the Install stage"
  - echo "Installing ..."
  beforeSetup:
  - echo "Commands on the Before Setup stage"
  setup:
  - echo "Commands on the Setup stage"
```

Дайджест стадии _install_ изменилась, и запуск werf для сборки приведет к выполнению всех инструкций стадии _install_ и инструкций последующих _стадий_, т.е. _beforeSetup_ и _setup_.

Дайджест стадии может меняться также из-за использования переменных окружения и Go-шаблонов.
Если не уделять этому достаточное внимание при написании конфигурации, можно столкнуться с неожиданными пересборками стадий. Например:

{% raw %}
```yaml
shell:
  beforeInstall:
  - echo "Commands on the Before Install stage for {{ env "CI_COMMIT_SHA" }}"
  install:
  - echo "Commands on the Install stage"
  ...
```
{% endraw %}

Первая сборка высчитает дайджест стадии _beforeInstall_ на основе команды (хэш коммита, конечно, будет другой):
```shell
echo "Commands on the Before Install stage for 0a8463e2ed7e7f1aa015f55a8e8730752206311b"
```

После очередного коммита, при сборке дайджест стадии _beforeInstall_ уже будет другой (с других хешем коммита):

```shell
echo "Commands on the Before Install stage for 36e907f8b6a639bd99b4ea812dae7a290e84df27"
```

Соответственно, используя переменную `CI_COMMIT_SHA` дайджест стадии _beforeInstall_ будет меняться после каждого коммита, что будет приводить к пересборке.

## Зависимость от изменений в git-репозитории

<a class="google-drawings" href="{{ "images/configuration/assembly_instructions3.png" | true_relative_url }}" data-featherlight="image">
    <img src="{{ "images/configuration/assembly_instructions3_preview.png" | true_relative_url }}" alt="Зависимость от изменений в git-репозитории">
  </a>

Как описывалось в статье про [_git mapping_]({{ "advanced/building_images_with_stapel/git_directive.html" | true_relative_url }}), существуют специальные стадии _gitArchive_ и _gitLatestPatch_.
Стадия _gitArchive_ выполняется после пользовательской стадии _beforeInstall_, а стадия _gitLatestPatch_ после пользовательской стадии _setup_, если в локальном git-репозитории есть изменения.
Таким образом, чтобы выполнить сборку с последней версией исходного кода, можно пересобрать стадию _beforeInstall_, изменив значение директивы _cacheVersion_ либо изменив сами инструкции стадии _beforeInstall_.

Пользовательские стадии _install_, _beforeSetup_ и _setup_ также могут зависеть от изменений в git-репозитории. В этом случае (если такая зависимость определена) git-патч применяется перед выполнением инструкций _пользовательской стадии_, чтобы сборочные инструкции выполнялись с актуальной версией кода приложения.

> Во время процесса сборки исходный код обновляется **только в рамках одной стадии**, последующие стадии, зависящие последовательно друг от друга, будут использовать также обновленную версию файлов.
> Первая сборка добавляет файлы из git-репозитория на стадии _gitArchive_. Все последующие сборки обновляют файлы на стадии _gitCache_, _gitLatestPatch_ или на одной из следующих пользовательских стадий: _install_, _beforeSetup_, _setup_.
<br />
<br />
Пример этого этапа (фаза подсчета дайджестов, _calculating digests_):
![git files actualized on specific stage]({{ "images/build/git_mapping_updated_on_stage.png" | true_relative_url }})

Зависимость _пользовательской стадии_ от изменений в git-репозитории указывается с помощью параметра `git.stageDependencies`. Синтаксис:

```yaml
git:
- ...
  stageDependencies:
    install:
    - <mask 1>
    ...
    - <mask N>
    beforeSetup:
    - <mask>
    ...
    setup:
    - <mask>
```

У параметра `git.stageDependencies` возможно указывать 3 ключа: `install`, `beforeSetup` и `setup`.
Значение каждого ключа — массив масок файлов, относящихся к соответствующей стадии. Соответствующая _пользовательская стадия_ пересобирается, если в git-репозитории происходят изменения подпадающие под указанную маску.

Для каждой _пользовательской стадии_ werf создает список подпадающих под маску файлов и вычисляет контрольную сумму каждого файла с учетом его аттрибутов и содержимого. Эти контрольные суммы являются частью _дайджеста стадии_, поэтому любое изменение файлов в репозитории, подпадающее под маску, приводит к изменениям _дайджеста стадии_. К этим изменениям относятся: изменение атрибутов файла, изменение содержимого файла, добавление или удаление подпадающего под маску файла и т.п.

При применении маски указанной в `git.stageDependencies` учитываются значения параметров `git.includePaths` и `git.excludePaths` (смотри подробнее про них в соответствующем [разделе]({{ "advanced/building_images_with_stapel/git_directive.html#использование-фильтров" | true_relative_url }})). werf считает подпадающими под маску только файлы удовлетворяющие фильтру `includePaths` и подпадающие под маску `stageDependencies`. Аналогично, werf считает подпадающими под маску только файлы не удовлетворяющие фильтру `excludePaths` и не подпадающие под маску `stageDependencies`.

Правила описания маски в параметре `stageDependencies` аналогичны описанию параметров `includePaths` и `excludePaths`. Маска определяет шаблон для файлов и путей, и может содержать следующие шаблоны:

- `*` — Удовлетворяет любому файлу. Шаблон включает `.` и исключает `/`.
- `**` — Удовлетворяет директории со всем ее содержимым, рекурсивно.
- `?` — Удовлетворяет любому одному символу в имени файла (аналогично regexp-шаблону `/.{1}/`).
- `[set]` — Удовлетворяет любому символу из указанного набора символов. Аналогично использованию в regexp-шаблонах, включая указание диапазонов типа `[^a-z]`.
- `\` — Экранирует следующий символ.

Маска, которая начинается с шаблона `*` или `**`, должна быть взята в одинарные или двойные кавычки в `werf.yaml`:

```
# * в начале маски, используем двойные кавычки
- "*.rb"
# одинарные также работают
- '**/*'
# нет * в начале, можно не использовать кавычки
- src/**/*.js
```

Факт изменения файлов в git-репозитории werf определяет, подсчитывая их контрольные суммы. Для _пользовательской стадии_ и для каждой маски применяется следующий алгоритм:

- werf создает список всех файлов согласно пути определенному в параметре `add`, и применяет фильтры `excludePaths` и `includePaths`;
- К каждому файлу с учетом его пути применяется маска, согласно правилам применения шаблонов;
- Если под маску подпадает папка, то все содержимое папки считается подпадающей под маску рекурсивно;
- У получившегося списка файлов werf подсчитывает контрольные суммы, с учетом аттрибутов файлов и их содержимого.

Контрольные суммы подсчитываются вначале сборочного процесса, перед запуском какой-либо стадии.

Пример:

```yaml
image: app
git:
- add: /src
  to: /app
  stageDependencies:
    beforeSetup:
    - "*"
shell:
  install:
  - echo "install stage"
  beforeSetup:
  - echo "beforeSetup stage"
  setup:
  - echo "setup stage"
```

В приведенном файле конфигурации `werf.yaml` указан _git mapping_, согласно которому содержимое папки `/src` локального git-репозитория копируется в папку `/app` собираемого образа.
Во время первой сборки, файлы кэшируются в стадии _gitArchive_ и выполняются сборочные инструкции стадий _install_, _beforeSetup_ и _setup_.

Сборка следующего коммита, в котором будут только изменения файлов за пределами папки `/src` не приведет к выполнению инструкций каких-либо стадий. Если коммит будет содержать изменение внутри папки `/src`, контрольные суммы файлов подпадающих под маску изменятся, werf применит git-патч и пересоберёт все пользовательские стадии, начиная со стадии _beforeSetup_, а именно — _beforeSetup_ и _setup_. Применение git-патча будет выполнено один раз на стадии _beforeSetup_.

## Зависимость от значения CacheVersion

Существуют ситуации, когда необходимо принудительно пересобрать все или какую-то конкретную _пользовательскую стадию_. Этого можно достичь, изменяя параметры `cacheVersion` или `<user stage name>CacheVersion`.

Дайджест пользовательской стадии _install_ зависит от значения параметра `installCacheVersion`. Чтобы пересобрать пользовательскую стадию _install_ (и все последующие стадии), можно изменить значение параметра `installCacheVersion`.

> Обратите внимание, что параметры `cacheVersion` и `beforeInstallCacheVersion` имеют одинаковый эффект, — при изменении этих параметров возникает пересборка стадии _beforeInstall_ и всех последующих стадий.

### Пример: Общий образ для нескольких приложений

Вы можете определить образ, содержащий общие системные пакеты в отдельном файле `werf.yaml`. Изменение параметра `cacheVersion` может быть использовано для пересборки этого образа, чтобы обновить версии системных пакетов.

```yaml
image: ~
from: ubuntu:latest
shell:
  beforeInstallCacheVersion: 2
  beforeInstall:
  - apt update
  - apt install ...
```

Этот образ может быть использован как базовый образ для нескольких приложений (например, если образ с hub.docker.com не удовлетворяет вашим требованиям).

### Пример использования внешних зависимостей

Параметры _CacheVersion_ можно использовать совместно с [шаблонами Go-шаблонизатора]({{ "reference/werf_yaml_template_engine.html" | true_relative_url }}), чтобы определить зависимость _пользовательской стадии_ от файлов, не находящихся в git-репозитории.

{% raw %}
```yaml
image: ~
from: ubuntu:latest
shell:
  installCacheVersion: {{.Files.Get "some-library-latest.tar.gz" | sha256sum}}
  install:
  - tar zxf some-library-latest.tar.gz
  - <build application>
```
{% endraw %}

Если использовать, например, скрипт загрузки файла `some-library-latest.tar.gz` и запускать werf для сборки уже после скачивания файла, то пересборка пользовательской стадии _install_ (и всех последующих) будет происходить в случае если скачан новый (измененный) файл.


text:
import { defineConfig } from 'vite';
import solidPlugin from 'vite-plugin-solid';

export default defineConfig({
  plugins: [solidPlugin()],
  server: {
    port: 3000,
  },
  build: {
    target: 'esnext',
  },
});


text:
declare module "@malept/flatpak-bundler" {
  // See https://docs.flatpak.org/en/latest/flatpak-builder-command-reference.html#flatpak-manifest
  export interface FlatpakManifest {
    id: string
    branch?: string
    defaultBranch?: string
    collectionId?: string
    extensionTag?: string
    tokenType?: number
    runtime: string
    runtimeVersion: string
    sdk: string
    var?: string
    metadata?: string
    command: string
    buildRuntime?: boolean
    buildExtension?: boolean
    separateLocales?: boolean
    idPlatform?: string
    metadataPlatform?: string
    writableSdk?: boolean
    appstreamCompose?: boolean
    sdkExtensions?: string[]
    platformExtensions?: string[]
    base?: string
    baseVersion?: string
    baseExtensions?: string[]
    inheritExtensions?: string[]
    inheritSdkExtensions?: string[]
    tags?: string[]
    buildOptions?: any
    modules?: (any | string)[]
    addExtensions?: any
    addBuildExtensions?: any
    cleanup?: string[]
    cleanupCommands?: string[]
    cleanupPlatform?: string[]
    cleanupPlatformCommands?: string[]
    preparePlatformCommands?: string[]
    finishArgs?: string[]
    renameDesktopFile?: string
    renameAppdataFile?: string
    renameIcon?: string
    appdataLicense?: string
    copyIcon?: boolean
    desktopFileNamePrefix?: string
    desktopFileNameSuffix?: string
  }

  export interface FlatpakBundlerBuildOptions {
    bundlePath: string
    arch: "i386" | "x86_64" | "aarch64"| "arm"
    workingDir?: string
    buildDir?: string
    repoDir?: string
    cleanTmpdirs?: boolean
    autoInstallRuntime?: boolean
    autoInstallSdk?: boolean
    autoInstallBase?: boolean
    gpgSign?: string
    gpgHomedir?: string
    subject?: string
    body?: string
    files?: [string, string][]
    symlinks?: [string, string][]
    extraExports?: any
    runtimeFlatpakref?: string
    sdkFlatpakref?: string
    baseFlatpakref?: string
    bundleRepoUrl?: string
    extraFlatpakBuilderArgs?: any
    extraFlatpakBuildExportArgs?: any
    extraFlatpakBuildBundleArgs?: any
  }

  export function bundle(manifest: FlatpakManifest, options: FlatpakBundlerBuildOptions): Promise<void>
  export function translateArch(arch: string): string
}


text:
module Devise
  module Strategies
    class JsonWebToken < Base
      def valid?
        request.headers['Authorization'].present?
      end

      def authenticate!
        return fail! unless claims
        return fail! unless claims.has_key?('user_id')

        success! User.find_by_id claims['user_id']
      end

      protected

      def claims
        strategy, token = request.headers['Authorization'].split(' ')

        return nil if (strategy || '').downcase != 'bearer'

        JWTWrapper.decode(token) rescue nil
      end
    end
  end
end


text:
layout: page
title: Stone Motors Dinner
date: 2016-05-24
author: Jane Donovan
tags: weekly links, java
status: published
summary: Duis scelerisque bibendum tellus vel.
banner: images/banner/wedding.jpg
booking:
  startDate: 10/29/2019
  endDate: 11/01/2019
  ctyhocn: PDLCAHX
  groupCode: SMD
published: true
---
Phasellus laoreet, eros in vulputate dignissim, magna justo suscipit libero, at dapibus neque nulla eget libero. Nunc semper mauris at erat auctor, ut posuere eros volutpat. Proin interdum sagittis fermentum. Nulla ullamcorper ligula at elit eleifend, at consectetur sapien tincidunt. Morbi a posuere tortor. Nam et urna et dolor pulvinar pulvinar eu varius metus. Pellentesque quis diam ac risus tristique fermentum in vel enim. Sed faucibus posuere volutpat.
Pellentesque eu quam nisi. Fusce volutpat molestie neque, sit amet rhoncus nisi laoreet quis. Sed a ligula diam. Maecenas non nisi ut nibh semper tincidunt quis vel enim. In imperdiet odio non nibh pulvinar sollicitudin. Suspendisse potenti. Sed nisl sapien, vehicula nec bibendum in, aliquet non purus. Morbi hendrerit lorem a velit feugiat blandit. Mauris id elit sed tellus consequat bibendum. Maecenas sed urna ligula.

1 Praesent eget sem ut nisl ultrices egestas in sed dolor
1 Vivamus tempor diam vitae ullamcorper vestibulum
1 Integer ultricies arcu ac est tempus, eget porta est bibendum
1 Praesent facilisis dui et massa laoreet, ac porttitor sem dapibus.

Proin a purus hendrerit libero tempor convallis id at purus. In ut iaculis lacus. Aliquam accumsan est non tortor lacinia placerat. Donec quis dolor euismod ante rutrum aliquet. Mauris et tincidunt metus, at hendrerit sem. Nulla dignissim augue ut enim auctor, vehicula lacinia quam ullamcorper. Donec faucibus dapibus arcu quis mollis. Phasellus a quam blandit, fermentum leo mollis, mattis felis. Nulla non elit sit amet libero volutpat ornare vel id tortor. Sed ornare sit amet leo rutrum sollicitudin. Aenean viverra vehicula facilisis. In hac habitasse platea dictumst. Nullam sagittis, dolor a blandit aliquam, urna enim viverra ipsum, sed maximus elit sem sed nisl. Donec cursus nisi ligula, in cursus risus vestibulum eu.


text:
package monix

import cats.Contravariant

import scala.concurrent.ExecutionContext

package object execution {

  /** Returns the associated Cats type class instances for the
    * [[CancelableFuture]] data type.
    *
    * @param ec is the
    *        [[scala.concurrent.ExecutionContext ExecutionContext]]
    *        needed in order to create the needed type class instances,
    *        since future transformations rely on an `ExecutionContext`
    *        passed explicitly (by means of an implicit parameter)
    *        on each operation
    */
  implicit def cancelableFutureCatsInstances(implicit ec: ExecutionContext): CancelableFutureCatsInstances =
    new CancelableFutureCatsInstances()

  /** Contravariant type class instance of [[Callback]] for Cats. */
  implicit def contravariantCallback[E]: Contravariant[Callback[E, ?]] =
    contravariantRef.asInstanceOf[Contravariant[Callback[E, ?]]]

  private[this] val contravariantRef: Contravariant[Callback[Any, ?]] =
    new Contravariant[Callback[Any, ?]] {
      override def contramap[A, B](cb: Callback[Any, A])(f: B => A): Callback[Any, B] =
        cb.contramap(f)
    }
}


text:
package ru.stqa.pft.addressbook.generators;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import com.beust.jcommander.ParameterException;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.thoughtworks.xstream.XStream;
import ru.stqa.pft.addressbook.model.ContactData;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.ArrayList;
import java.util.List;

public class ContactDataGenetator {

  @Parameter(names = "-c", description = "Contact count")
  public int count;

  @Parameter(names = "-f", description = "Target contact file")
  public String file;

  @Parameter(names = "-d", description = "Data format")
  public String format;

  public static void main(String[] args) throws IOException {
    System.out.println(new File(".").getAbsolutePath());
    ContactDataGenetator genetator = new ContactDataGenetator();
    JCommander jCommander = new JCommander(genetator);
    try {
      jCommander.parse(args);
    } catch (ParameterException ex) {
      jCommander.usage();
      return;
    }
    genetator.run();

  }

  private void run() throws IOException {
    List<ContactData> contacts = generateContacts(count);
    if (format.equals("csv")) {
      saveAsCsv(contacts, new File(file));
    } else if (format.equals("xml")) {
      saveAsXml(contacts, new File(file));
    } else if (format.equals("json")) {
      saveAsJson(contacts, new File(file));
    } else {
      System.out.println("Unrecognized format " + format);
    }
  }

  private void saveAsJson(List<ContactData> contacts, File file) throws IOException {
    Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().setPrettyPrinting().create();
    String json = gson.toJson(contacts);
    Writer writer = new FileWriter(file);
    writer.write(json);
    writer.close();
  }

  private void saveAsXml(List<ContactData> contacts, File file) throws IOException {
    XStream xstream = new XStream();
    xstream.processAnnotations(ContactData.class);
    //xstream.alias("group", GroupData.class);
    String xml = xstream.toXML(contacts);
    Writer writer = new FileWriter(file);
    writer.write(xml);
    writer.close();
  }

  private void saveAsCsv(List<ContactData> contacts, File file) throws IOException {
    System.out.println(new File(".").getAbsolutePath());
    Writer writer = new FileWriter(file);
    for (ContactData contact : contacts) {
      writer.write(String.format("%s;%s;%s;%s;%s\n", contact.getFirstname(), contact.getMiddlename(), contact.getLastname(), contact.getAddress(), contact.getEmail(), contact.getMobile()));
    }
    writer.close();

  }

  private List<ContactData> generateContacts(int count) {
    List<ContactData> contacts = new ArrayList<ContactData>();
    for (int i = 0; i <count; i++) {
      contacts.add(new ContactData()
              .withFirstname((String.format("First %s", i))).withMiddlename(String.format("Middle %s", i)).withLastname(String.format("Last %s", i))
              .withAddress(String.format("Address %s", i))
              .withEmail(String.format("Email%s@test.com", i)).withMobile(String.format("+7901000%s", i)));
    }
    return contacts;
  }
}