def freq_plan(self, min_freq, max_freq, bins, overlap=<NUM_LIT:0>, quiet=False):

bin_size = self.bins_to_bin_size(bins)<EOL>bins_crop = round((<NUM_LIT:1> - overlap) * bins)<EOL>sample_rate_crop = (<NUM_LIT:1> - overlap) * self.device.sample_rate<EOL>freq_range = max_freq - min_freq<EOL>hopping = True if freq_range >= sample_rate_crop else False<EOL>hop_size = self.nearest_freq(sample_rate_crop, bin_size)<EOL>hops = math.ceil(freq_range / hop_size) if hopping else <NUM_LIT:1><EOL>min_center_freq = min_freq + (hop_size / <NUM_LIT:2>) if hopping else min_freq + (freq_range / <NUM_LIT:2>)<EOL>max_center_freq = min_center_freq + ((hops - <NUM_LIT:1>) * hop_size)<EOL>freq_list = [min_center_freq + (i * hop_size) for i in range(hops)]<EOL>if not quiet:<EOL><INDENT>logger.info('<STR_LIT>'.format(overlap))<EOL>logger.info('<STR_LIT>'.format(bin_size))<EOL>logger.info('<STR_LIT>'.format(bins))<EOL>logger.info('<STR_LIT>'.format(bins_crop))<EOL>logger.info('<STR_LIT>'.format(self.device.sample_rate / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format(sample_rate_crop / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format(freq_range / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format('<STR_LIT>' if hopping else '<STR_LIT>'))<EOL>logger.info('<STR_LIT>'.format(hop_size / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format(hops))<EOL>logger.info('<STR_LIT>'.format(min_center_freq / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format(max_center_freq / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format((min_center_freq - (hop_size / <NUM_LIT:2>)) / <NUM_LIT>))<EOL>logger.info('<STR_LIT>'.format((max_center_freq + (hop_size / <NUM_LIT:2>)) / <NUM_LIT>))<EOL>logger.debug('<STR_LIT>')<EOL>logger.debug('<STR_LIT>'.format('<STR_LIT>', '<STR_LIT>', '<STR_LIT>'))<EOL>for f in freq_list:<EOL><INDENT>logger.debug('<STR_LIT>'.format(<EOL>(f - (self.device.sample_rate / <NUM_LIT:2>)) / <NUM_LIT>,<EOL>f / <NUM_LIT>,<EOL>(f + (self.device.sample_rate / <NUM_LIT:2>)) / <NUM_LIT>,<EOL>))<EOL><DEDENT><DEDENT>return freq_list<EOL>

Returns list of frequencies for frequency hopping


def create_buffer(self, bins, repeats, base_buffer_size, max_buffer_size=<NUM_LIT:0>):

samples = bins * repeats<EOL>buffer_repeats = <NUM_LIT:1><EOL>buffer_size = math.ceil(samples / base_buffer_size) * base_buffer_size<EOL>if not max_buffer_size:<EOL><INDENT>max_buffer_size = (<NUM_LIT:100> * <NUM_LIT>**<NUM_LIT:2>) / <NUM_LIT:8><EOL><DEDENT>if max_buffer_size > <NUM_LIT:0>:<EOL><INDENT>max_buffer_size = math.ceil(max_buffer_size / base_buffer_size) * base_buffer_size<EOL>if buffer_size > max_buffer_size:<EOL><INDENT>logger.warning('<STR_LIT>'.format(<EOL>buffer_size, max_buffer_size<EOL>))<EOL>buffer_repeats = math.ceil(buffer_size / max_buffer_size)<EOL>buffer_size = max_buffer_size<EOL><DEDENT><DEDENT>logger.info('<STR_LIT>'.format(repeats))<EOL>logger.info('<STR_LIT>'.format(samples, samples / self.device.sample_rate))<EOL>if max_buffer_size > <NUM_LIT:0>:<EOL><INDENT>logger.info('<STR_LIT>'.format(<EOL>max_buffer_size, max_buffer_size / bins, max_buffer_size / self.device.sample_rate<EOL>))<EOL><DEDENT>else:<EOL><INDENT>logger.info('<STR_LIT>')<EOL><DEDENT>logger.info('<STR_LIT>'.format(<EOL>buffer_size, buffer_size / bins, buffer_size / self.device.sample_rate<EOL>))<EOL>logger.info('<STR_LIT>'.format(buffer_repeats))<EOL>return (buffer_repeats, zeros(buffer_size, numpy.complex64))<EOL>


def setup(self, bins, repeats, base_buffer_size=<NUM_LIT:0>, max_buffer_size=<NUM_LIT:0>, fft_window='<STR_LIT>',<EOL>fft_overlap=<NUM_LIT:0.5>, crop_factor=<NUM_LIT:0>, log_scale=True, remove_dc=False, detrend=None,<EOL>lnb_lo=<NUM_LIT:0>, tune_delay=<NUM_LIT:0>, reset_stream=False, max_threads=<NUM_LIT:0>, max_queue_size=<NUM_LIT:0>):

if self.device.is_streaming:<EOL><INDENT>self.device.stop_stream()<EOL><DEDENT>base_buffer = self.device.start_stream(buffer_size=base_buffer_size)<EOL>self._bins = bins<EOL>self._repeats = repeats<EOL>self._base_buffer_size = len(base_buffer)<EOL>self._max_buffer_size = max_buffer_size<EOL>self._buffer_repeats, self._buffer = self.create_buffer(<EOL>bins, repeats, self._base_buffer_size, self._max_buffer_size<EOL>)<EOL>self._tune_delay = tune_delay<EOL>self._reset_stream = reset_stream<EOL>self._psd = psd.PSD(bins, self.device.sample_rate, fft_window=fft_window, fft_overlap=fft_overlap,<EOL>crop_factor=crop_factor, log_scale=log_scale, remove_dc=remove_dc, detrend=detrend,<EOL>lnb_lo=lnb_lo, max_threads=max_threads, max_queue_size=max_queue_size)<EOL>self._writer = writer.formats[self._output_format](self._output)<EOL>

Prepare samples buffer and start streaming samples from device


if not self.device.is_streaming:<EOL><INDENT>return<EOL><DEDENT>self.device.stop_stream()<EOL>self._writer.close()<EOL>self._bins = None<EOL>self._repeats = None<EOL>self._base_buffer_size = None<EOL>self._max_buffer_size = None<EOL>self._buffer_repeats = None<EOL>self._buffer = None<EOL>self._tune_delay = None<EOL>self._reset_stream = None<EOL>self._psd = None<EOL>self._writer = None<EOL>

Stop streaming samples from device and delete samples buffer


if not self.device.is_streaming:<EOL><INDENT>raise RuntimeError('<STR_LIT>')<EOL><DEDENT>logger.debug('<STR_LIT>'.format(freq))<EOL>t_freq = time.time()<EOL>if self.device.freq != freq:<EOL><INDENT>if self._reset_stream:<EOL><INDENT>self.device.device.deactivateStream(self.device.stream)<EOL><DEDENT>self.device.freq = freq<EOL>if self._reset_stream:<EOL><INDENT>self.device.device.activateStream(self.device.stream)<EOL><DEDENT>if self._tune_delay:<EOL><INDENT>t_delay = time.time()<EOL>while True:<EOL><INDENT>self.device.read_stream()<EOL>t_delay_end = time.time()<EOL>if t_delay_end - t_delay >= self._tune_delay:<EOL><INDENT>break<EOL><DEDENT><DEDENT>logger.debug('<STR_LIT>'.format(t_delay_end - t_delay))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>logger.debug('<STR_LIT>')<EOL><DEDENT>psd_state = self._psd.set_center_freq(freq)<EOL>t_freq_end = time.time()<EOL>logger.debug('<STR_LIT>'.format(t_freq_end - t_freq))<EOL>for repeat in range(self._buffer_repeats):<EOL><INDENT>logger.debug('<STR_LIT>'.format(repeat + <NUM_LIT:1>))<EOL>t_acq = time.time()<EOL>acq_time_start = datetime.datetime.utcnow()<EOL>self.device.read_stream_into_buffer(self._buffer)<EOL>acq_time_stop = datetime.datetime.utcnow()<EOL>t_acq_end = time.time()<EOL>logger.debug('<STR_LIT>'.format(t_acq_end - t_acq))<EOL>self._psd.update_async(psd_state, numpy.copy(self._buffer))<EOL>t_final = time.time()<EOL>if _shutdown:<EOL><INDENT>break<EOL><DEDENT><DEDENT>psd_future = self._psd.result_async(psd_state)<EOL>logger.debug('<STR_LIT>'.format(t_final - t_freq))<EOL>return (psd_future, acq_time_start, acq_time_stop)<EOL>

Tune to specified center frequency and compute Power Spectral Density


def sweep(self, min_freq, max_freq, bins, repeats, runs=<NUM_LIT:0>, time_limit=<NUM_LIT:0>, overlap=<NUM_LIT:0>,<EOL>fft_window='<STR_LIT>', fft_overlap=<NUM_LIT:0.5>, crop=False, log_scale=True, remove_dc=False, detrend=None, lnb_lo=<NUM_LIT:0>,<EOL>tune_delay=<NUM_LIT:0>, reset_stream=False, base_buffer_size=<NUM_LIT:0>, max_buffer_size=<NUM_LIT:0>, max_threads=<NUM_LIT:0>, max_queue_size=<NUM_LIT:0>):

self.setup(<EOL>bins, repeats, base_buffer_size, max_buffer_size,<EOL>fft_window=fft_window, fft_overlap=fft_overlap, crop_factor=overlap if crop else <NUM_LIT:0>,<EOL>log_scale=log_scale, remove_dc=remove_dc, detrend=detrend, lnb_lo=lnb_lo, tune_delay=tune_delay,<EOL>reset_stream=reset_stream, max_threads=max_threads, max_queue_size=max_queue_size<EOL>)<EOL>try:<EOL><INDENT>freq_list = self.freq_plan(min_freq - lnb_lo, max_freq - lnb_lo, bins, overlap)<EOL>t_start = time.time()<EOL>run = <NUM_LIT:0><EOL>while not _shutdown and (runs == <NUM_LIT:0> or run < runs):<EOL><INDENT>run += <NUM_LIT:1><EOL>t_run_start = time.time()<EOL>logger.debug('<STR_LIT>'.format(run))<EOL>for freq in freq_list:<EOL><INDENT>psd_future, acq_time_start, acq_time_stop = self.psd(freq)<EOL>self._writer.write_async(psd_future, acq_time_start, acq_time_stop,<EOL>len(self._buffer) * self._buffer_repeats)<EOL>if _shutdown:<EOL><INDENT>break<EOL><DEDENT><DEDENT>write_next_future = self._writer.write_next_async()<EOL>t_run = time.time()<EOL>logger.debug('<STR_LIT>'.format(t_run - t_run_start))<EOL>if time_limit and (time.time() - t_start) >= time_limit:<EOL><INDENT>logger.info('<STR_LIT>'.format(time_limit, run))<EOL>break<EOL><DEDENT><DEDENT>write_next_future.result()<EOL>logging.debug('<STR_LIT>'.format(self.device.buffer_overflow_count))<EOL>logging.debug('<STR_LIT>'.format(self._psd._executor._max_workers))<EOL>logging.debug('<STR_LIT>'.format(self._psd._executor.max_queue_size_reached,<EOL>self._psd._executor.max_queue_size))<EOL>logging.debug('<STR_LIT>'.format(self._writer._executor._max_workers))<EOL>logging.debug('<STR_LIT>'.format(self._writer._executor.max_queue_size_reached,<EOL>self._writer._executor.max_queue_size))<EOL><DEDENT>finally:<EOL><INDENT>self.stop()<EOL>t_stop = time.time()<EOL>logger.info('<STR_LIT>'.format(t_stop - t_start))<EOL><DEDENT>


psd_state = {<EOL>'<STR_LIT>': <NUM_LIT:0>,<EOL>'<STR_LIT>': self._base_freq_array + self._lnb_lo + center_freq,<EOL>'<STR_LIT>': None,<EOL>'<STR_LIT>': threading.Lock(),<EOL>'<STR_LIT>': [],<EOL>}<EOL>return psd_state<EOL>

Set center frequency and clear averaged PSD data


freq_array = numpy.fft.fftshift(psd_state['<STR_LIT>'])<EOL>pwr_array = numpy.fft.fftshift(psd_state['<STR_LIT>'])<EOL>if self._crop_factor:<EOL><INDENT>crop_bins_half = round((self._crop_factor * self._bins) / <NUM_LIT:2>)<EOL>freq_array = freq_array[crop_bins_half:-crop_bins_half]<EOL>pwr_array = pwr_array[crop_bins_half:-crop_bins_half]<EOL><DEDENT>if psd_state['<STR_LIT>'] > <NUM_LIT:1>:<EOL><INDENT>pwr_array = pwr_array / psd_state['<STR_LIT>']<EOL><DEDENT>if self._log_scale:<EOL><INDENT>pwr_array = <NUM_LIT:10> * numpy.log10(pwr_array)<EOL><DEDENT>return (freq_array, pwr_array)<EOL>

Return freqs and averaged PSD for given center frequency


if len(psd_state['<STR_LIT>']) > <NUM_LIT:1>:<EOL><INDENT>concurrent.futures.wait(psd_state['<STR_LIT>'])<EOL><DEDENT>elif psd_state['<STR_LIT>']:<EOL><INDENT>psd_state['<STR_LIT>'][<NUM_LIT:0>].result()<EOL><DEDENT>return self.result(psd_state)<EOL>

Wait for all PSD threads to finish and return result


return self._executor.submit(self.wait_for_result, psd_state)<EOL>

Return freqs and averaged PSD for given center frequency (asynchronously in another thread)


future._result = None<EOL>

Remove result from future to release memory


def update(self, psd_state, samples_array):

freq_array, pwr_array = simplespectral.welch(samples_array, self._sample_rate, nperseg=self._bins,<EOL>window=self._fft_window, noverlap=self._fft_overlap_bins,<EOL>detrend=self._detrend)<EOL>if self._remove_dc:<EOL><INDENT>pwr_array[<NUM_LIT:0>] = (pwr_array[<NUM_LIT:1>] + pwr_array[-<NUM_LIT:1>]) / <NUM_LIT:2><EOL><DEDENT>with psd_state['<STR_LIT>']:<EOL><INDENT>psd_state['<STR_LIT>'] += <NUM_LIT:1><EOL>if psd_state['<STR_LIT>'] is None:<EOL><INDENT>psd_state['<STR_LIT>'] = pwr_array<EOL><DEDENT>else:<EOL><INDENT>psd_state['<STR_LIT>'] += pwr_array<EOL><DEDENT><DEDENT>

Compute PSD from samples and update average for given center frequency


def update_async(self, psd_state, samples_array):

future = self._executor.submit(self.update, psd_state, samples_array)<EOL>future.add_done_callback(self._release_future_memory)<EOL>psd_state['<STR_LIT>'].append(future)<EOL>return future<EOL>

Compute PSD from samples and update average for given center frequency (asynchronously in another thread)


match = re_float_with_multiplier.search(string)<EOL>if not match or not match.group('<STR_LIT>'):<EOL><INDENT>raise ValueError('<STR_LIT>'.format(string))<EOL><DEDENT>num = float(match.group('<STR_LIT>'))<EOL>multi = match.group('<STR_LIT>')<EOL>if multi:<EOL><INDENT>try:<EOL><INDENT>num *= multipliers[multi]<EOL><DEDENT>except KeyError:<EOL><INDENT>raise ValueError('<STR_LIT>'.format(multi))<EOL><DEDENT><DEDENT>return num<EOL>

Convert string with optional k, M, G, T multiplier to float


return [float_with_multiplier(f) for f in string.split('<STR_LIT::>')]<EOL>

Convert string with freq. or freq. range to list of floats


if not string:<EOL><INDENT>return {}<EOL><DEDENT>gains = {}<EOL>for gain in string.split('<STR_LIT:U+002C>'):<EOL><INDENT>amp_name, value = gain.split('<STR_LIT:=>')<EOL>gains[amp_name.strip()] = float(value.strip())<EOL><DEDENT>return gains<EOL>

Convert string with gains of individual amplification elements to dict


if not string:<EOL><INDENT>return {}<EOL><DEDENT>settings = {}<EOL>for setting in string.split('<STR_LIT:U+002C>'):<EOL><INDENT>setting_name, value = setting.split('<STR_LIT:=>')<EOL>settings[setting_name.strip()] = value.strip()<EOL><DEDENT>return settings<EOL>

Convert string with SoapySDR device settings to dict


wrapper = textwrap.TextWrapper(<EOL>width=int(os.environ.get('<STR_LIT>', <NUM_LIT>)),<EOL>initial_indent=indent,<EOL>subsequent_indent=indent<EOL>)<EOL>return '<STR_LIT:\n>'.join(wrapper.wrap(text))<EOL>

Wrap text to terminal width with default indentation


devices = simplesoapy.detect_devices(soapy_args, as_string=True)<EOL>text = []<EOL>text.append('<STR_LIT>')<EOL>if devices:<EOL><INDENT>for i, d in enumerate(devices):<EOL><INDENT>text.append('<STR_LIT>'.format(d))<EOL><DEDENT><DEDENT>else:<EOL><INDENT>text.append('<STR_LIT>')<EOL><DEDENT>return (devices, '<STR_LIT:\n>'.join(text))<EOL>


text = []<EOL>try:<EOL><INDENT>device = simplesoapy.SoapyDevice(soapy_args)<EOL>text.append('<STR_LIT>'.format(device.hardware))<EOL>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(str(x) for x in device.list_channels())))<EOL>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(device.list_antennas())))<EOL>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(device.list_frequencies())))<EOL>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(device.list_gains())))<EOL>text.append('<STR_LIT>')<EOL>for key, s in device.list_settings().items():<EOL><INDENT>text.append(wrap('<STR_LIT>'.format(key, s['<STR_LIT:name>'], s['<STR_LIT:description>'], s['<STR_LIT:value>'])))<EOL><DEDENT>text.append('<STR_LIT>')<EOL>for key, s in device.list_stream_args().items():<EOL><INDENT>text.append(wrap('<STR_LIT>'.format(key, s['<STR_LIT:name>'], s['<STR_LIT:description>'], s['<STR_LIT:value>'])))<EOL><DEDENT>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format(*device.get_gain_range()))<EOL>text.append('<STR_LIT>')<EOL>text.append('<STR_LIT>'.format(*[x / <NUM_LIT> for x in device.get_frequency_range()]))<EOL>text.append('<STR_LIT>')<EOL>rates = []<EOL>for r in device.list_sample_rates():<EOL><INDENT>if r[<NUM_LIT:0>] == r[<NUM_LIT:1>]:<EOL><INDENT>rates.append('<STR_LIT>'.format(r[<NUM_LIT:0>] / <NUM_LIT>))<EOL><DEDENT>else:<EOL><INDENT>rates.append('<STR_LIT>'.format(r[<NUM_LIT:0>] / <NUM_LIT>, r[<NUM_LIT:1>] / <NUM_LIT>))<EOL><DEDENT><DEDENT>text.append(wrap('<STR_LIT:U+002CU+0020>'.join(rates)))<EOL>text.append('<STR_LIT>')<EOL>bandwidths = []<EOL>for b in device.list_bandwidths():<EOL><INDENT>if b[<NUM_LIT:0>] == b[<NUM_LIT:1>]:<EOL><INDENT>bandwidths.append('<STR_LIT>'.format(b[<NUM_LIT:0>] / <NUM_LIT>))<EOL><DEDENT>else:<EOL><INDENT>bandwidths.append('<STR_LIT>'.format(b[<NUM_LIT:0>] / <NUM_LIT>, b[<NUM_LIT:1>] / <NUM_LIT>))<EOL><DEDENT><DEDENT>if bandwidths:<EOL><INDENT>text.append(wrap('<STR_LIT:U+002CU+0020>'.join(bandwidths)))<EOL><DEDENT>else:<EOL><INDENT>text.append('<STR_LIT>')<EOL><DEDENT><DEDENT>except RuntimeError:<EOL><INDENT>device = None<EOL>text.append('<STR_LIT>')<EOL><DEDENT>return (device, '<STR_LIT:\n>'.join(text))<EOL>

Returns info about selected SoapySDR device


<EOL>if '<STR_LIT>' not in os.environ:<EOL><INDENT>os.environ['<STR_LIT>'] = str(shutil.get_terminal_size().columns)<EOL><DEDENT>parser = argparse.ArgumentParser(<EOL>prog='<STR_LIT>',<EOL>formatter_class=argparse.RawDescriptionHelpFormatter,<EOL>description='<STR_LIT>',<EOL>add_help=False<EOL>)<EOL>parser._negative_number_matcher = re_float_with_multiplier_negative<EOL>main_title = parser.add_argument_group('<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=freq_or_freq_range, default='<STR_LIT>',<EOL>help='<STR_LIT>'<EOL>'<STR_LIT>')<EOL>output_group = main_title.add_mutually_exclusive_group()<EOL>output_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=argparse.FileType('<STR_LIT:w>'), default=sys.stdout,<EOL>help='<STR_LIT>')<EOL>output_group.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=int, default=None,<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', '<STR_LIT>', choices=sorted(writer.formats.keys()), default='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>main_title.add_argument('<STR_LIT>', action='<STR_LIT:version>',<EOL>version='<STR_LIT>'.format(__version__))<EOL>bins_title = parser.add_argument_group('<STR_LIT>')<EOL>bins_group = bins_title.add_mutually_exclusive_group()<EOL>bins_group.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT>,<EOL>help='<STR_LIT>')<EOL>bins_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float_with_multiplier,<EOL>help='<STR_LIT>')<EOL>spectra_title = parser.add_argument_group('<STR_LIT>')<EOL>spectra_group = spectra_title.add_mutually_exclusive_group()<EOL>spectra_group.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT>,<EOL>help='<STR_LIT>')<EOL>spectra_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float,<EOL>help='<STR_LIT>')<EOL>spectra_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float,<EOL>help='<STR_LIT>')<EOL>runs_title = parser.add_argument_group('<STR_LIT>')<EOL>runs_group = runs_title.add_mutually_exclusive_group()<EOL>runs_group.add_argument('<STR_LIT:-c>', '<STR_LIT>', dest='<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>runs_group.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT:1>,<EOL>help='<STR_LIT>')<EOL>runs_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float,<EOL>help='<STR_LIT>')<EOL>device_title = parser.add_argument_group('<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', default='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', default='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float_with_multiplier, default=<NUM_LIT>,<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float_with_multiplier, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>gain_group = device_title.add_mutually_exclusive_group()<EOL>gain_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float, default=<NUM_LIT>,<EOL>help='<STR_LIT>')<EOL>gain_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=specific_gains, default='<STR_LIT>',<EOL>help='<STR_LIT>'<EOL>'<STR_LIT>')<EOL>gain_group.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=float_with_multiplier, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=device_settings, default='<STR_LIT>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=float, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>device_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>crop_title = parser.add_argument_group('<STR_LIT>')<EOL>crop_group = crop_title.add_mutually_exclusive_group()<EOL>crop_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>crop_group.add_argument('<STR_LIT>', '<STR_LIT>', metavar='<STR_LIT>', type=float, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>perf_title = parser.add_argument_group('<STR_LIT>')<EOL>perf_title.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>perf_title.add_argument('<STR_LIT>', '<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>fft_rules_group = perf_title.add_mutually_exclusive_group()<EOL>fft_rules_group.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>fft_rules_group.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>perf_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>perf_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=int, default=<NUM_LIT:0>,<EOL>help='<STR_LIT>')<EOL>perf_title.add_argument('<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>other_title = parser.add_argument_group('<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT:store_true>',<EOL>help='<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', '<STR_LIT>', choices=['<STR_LIT:none>', '<STR_LIT>'], default='<STR_LIT:none>',<EOL>help='<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', choices=['<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>', '<STR_LIT>'],<EOL>default='<STR_LIT>', help='<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=float, default=None,<EOL>help='<STR_LIT>')<EOL>other_title.add_argument('<STR_LIT>', metavar='<STR_LIT>', type=float, default=<NUM_LIT:50>,<EOL>help='<STR_LIT>')<EOL>return parser<EOL>


def write(self, psd_data_or_future, time_start, time_stop, samples):

raise NotImplementedError<EOL>


def write_async(self, psd_data_or_future, time_start, time_stop, samples):

return self._executor.submit(self.write, psd_data_or_future, time_start, time_stop, samples)<EOL>

Write PSD of one frequncy hop (asynchronously in another thread)


raise NotImplementedError<EOL>

Write marker for next run of measurement


return self._executor.submit(self.write_next)<EOL>

Write marker for next run of measurement (asynchronously in another thread)


if self._close_output:<EOL><INDENT>self.output.close()<EOL><DEDENT>

Close output (only if it has been opened by writer)


magic = f.read(len(self.magic))<EOL>if not magic:<EOL><INDENT>return None<EOL><DEDENT>if magic != self.magic:<EOL><INDENT>raise ValueError('<STR_LIT>'.format(magic))<EOL><DEDENT>header = self.header._make(<EOL>self.header_struct.unpack(f.read(self.header_struct.size))<EOL>)<EOL>pwr_array = numpy.fromstring(f.read(header.size), dtype='<STR_LIT>')<EOL>return (header, pwr_array)<EOL>


def write(self, f, time_start, time_stop, start, stop, step, samples, pwr_array):

f.write(self.magic)<EOL>f.write(self.header_struct.pack(<EOL>self.version, time_start, time_stop, start, stop, step, samples, pwr_array.nbytes<EOL>))<EOL>f.write(pwr_array.tobytes())<EOL>f.flush()<EOL>


return len(self.magic) + self.header_struct.size<EOL>


try:<EOL><INDENT>f_array, pwr_array = psd_data_or_future.result()<EOL><DEDENT>except AttributeError:<EOL><INDENT>f_array, pwr_array = psd_data_or_future<EOL><DEDENT>try:<EOL><INDENT>step = f_array[<NUM_LIT:1>] - f_array[<NUM_LIT:0>]<EOL>self.formatter.write(<EOL>self.output,<EOL>time_start.timestamp(),<EOL>time_stop.timestamp(),<EOL>f_array[<NUM_LIT:0>],<EOL>f_array[-<NUM_LIT:1>] + step,<EOL>step,<EOL>samples,<EOL>pwr_array<EOL>)<EOL><DEDENT>except Exception as e:<EOL><INDENT>logging.exception('<STR_LIT>'.format(e))<EOL><DEDENT>


pass<EOL>


try:<EOL><INDENT>f_array, pwr_array = psd_data_or_future.result()<EOL><DEDENT>except AttributeError:<EOL><INDENT>f_array, pwr_array = psd_data_or_future<EOL><DEDENT>self.output.write('<STR_LIT>')<EOL>self.output.write('<STR_LIT>'.format(time_start))<EOL>self.output.write('<STR_LIT>'.format(time_stop))<EOL>self.output.write('<STR_LIT>')<EOL>self.output.write('<STR_LIT>')<EOL>for f, pwr in zip(f_array, pwr_array):<EOL><INDENT>self.output.write('<STR_LIT>'.format(f, pwr))<EOL><DEDENT>self.output.write('<STR_LIT:\n>')<EOL>self.output.flush()<EOL>


self.output.write('<STR_LIT:\n>')<EOL>self.output.flush()<EOL>


try:<EOL><INDENT>f_array, pwr_array = psd_data_or_future.result()<EOL><DEDENT>except AttributeError:<EOL><INDENT>f_array, pwr_array = psd_data_or_future<EOL><DEDENT>try:<EOL><INDENT>step = f_array[<NUM_LIT:1>] - f_array[<NUM_LIT:0>]<EOL>row = [<EOL>time_stop.strftime('<STR_LIT>'), time_stop.strftime('<STR_LIT>'),<EOL>f_array[<NUM_LIT:0>], f_array[-<NUM_LIT:1>] + step, step, samples<EOL>]<EOL>row += list(pwr_array)<EOL>self.output.write('<STR_LIT>'.format('<STR_LIT:U+002CU+0020>'.join(str(x) for x in row)))<EOL>self.output.flush()<EOL><DEDENT>except Exception as e:<EOL><INDENT>logging.exception('<STR_LIT>')<EOL><DEDENT>


future = super().submit(fn, *args, **kwargs)<EOL>work_queue_size = self._work_queue.qsize()<EOL>if work_queue_size > self.max_queue_size_reached:<EOL><INDENT>self.max_queue_size_reached = work_queue_size<EOL><DEDENT>return future<EOL>

Submits a callable to be executed with the given arguments.

        Count maximum reached work queue size in ThreadPoolExecutor.max_queue_size_reached.


if not prerequisites_ok():<EOL><INDENT>return<EOL><DEDENT>subprocess.call(['<STR_LIT>', '<STR_LIT>'])<EOL>for zipfile in glob.glob('<STR_LIT>'):<EOL><INDENT>first_part = zipfile.split('<STR_LIT:.>')[<NUM_LIT:0>]<EOL>new_name = "<STR_LIT>" % (first_part, context['<STR_LIT:version>'])<EOL>target = os.path.join(context['<STR_LIT>'], new_name)<EOL>shutil.copy(zipfile, target)<EOL>print("<STR_LIT>" % (zipfile, target))<EOL><DEDENT>

This is the actual zest.releaser entry point

    Relevant items in the context dict:

    name
        Name of the project being released

    tagdir
        Directory where the tag checkout is placed (*if* a tag
        checkout has been made)

    version
        Version we're releasing

    workingdir
        Original working directory


if not prerequisites_ok():<EOL><INDENT>return<EOL><DEDENT>lines = codecs.open('<STR_LIT>', '<STR_LIT>', '<STR_LIT:utf-8>').readlines()<EOL>for index, line in enumerate(lines):<EOL><INDENT>if line.startswith('<STR_LIT:version>'):<EOL><INDENT>new_line = '<STR_LIT>' % context['<STR_LIT>']<EOL>lines[index] = new_line<EOL><DEDENT><DEDENT>time.sleep(<NUM_LIT:1>)<EOL>codecs.open('<STR_LIT>', '<STR_LIT:w>', '<STR_LIT:utf-8>').writelines(lines)<EOL>

Fix the version in metadata.txt

    Relevant context dict item for both prerelease and postrelease:
    ``new_version``.


return '<STR_LIT>'.format('<STR_LIT>', width, string)<EOL>

Helper function to indent lines in printouts


self.params = self.defaults<EOL>self._init_properties()<EOL>self.set_attributes(**kwargs)<EOL>self._cache()<EOL>

C'tor.  Build from a set of keyword arguments.


<EOL>if name in self._params or name in self._mapping:<EOL><INDENT>try:<EOL><INDENT>return self.getp(name).value<EOL><DEDENT>except AttributeError as err:<EOL><INDENT>msg = str(err)<EOL>msg += "<STR_LIT>" % name<EOL>raise AttributeError(msg)<EOL><DEDENT>except TypeError as err:<EOL><INDENT>msg = str(err)<EOL>msg += "<STR_LIT>" % name<EOL>raise TypeError(msg)<EOL><DEDENT><DEDENT>return object.__getattribute__(self, name)<EOL>


<EOL>if name in self._params or name in self._mapping:<EOL><INDENT>self.setp(name, value=value)<EOL><DEDENT>else:<EOL><INDENT>object.__setattr__(self, name, value)<EOL><DEDENT>


try:<EOL><INDENT>ret = '<STR_LIT>'.format('<STR_LIT>', self.name, indent)<EOL><DEDENT>except AttributeError:<EOL><INDENT>ret = "<STR_LIT:%s>" % (type(self))<EOL><DEDENT>if not self.params:<EOL><INDENT>pass<EOL><DEDENT>else:<EOL><INDENT>ret += '<STR_LIT>'.format('<STR_LIT>', '<STR_LIT>', indent + <NUM_LIT:2>)<EOL>width = len(max(self.params.keys(), key=len))<EOL>for name, value in self.params.items():<EOL><INDENT>par = '<STR_LIT>'.format(name, value, width=width)<EOL>ret += '<STR_LIT>'.format('<STR_LIT>', par, indent + <NUM_LIT:4>)<EOL><DEDENT><DEDENT>return ret<EOL>


<EOL>return copy.deepcopy(self._params)<EOL>

Ordered dictionary of default parameters.


return copy.deepcopy(self._mapping)<EOL>

Ordered dictionary of mapping of names.

        This can be used to assign multiple names to a single parameter


name = self._mapping.get(name, name)<EOL>return self.params[name]<EOL>

Get the named `Property`.

Parameters
----------
name : str
    The property name.

Returns
-------
param : `Property`
    The parameter object.


def setp(self, name, clear_derived=True, value=None,<EOL>bounds=None, free=None, errors=None):

name = self._mapping.get(name, name)<EOL>try:<EOL><INDENT>self.params[name].set(<EOL>value=value,<EOL>bounds=bounds,<EOL>free=free,<EOL>errors=errors)<EOL><DEDENT>except TypeError as msg:<EOL><INDENT>print(msg, name)<EOL><DEDENT>if clear_derived:<EOL><INDENT>self.clear_derived()<EOL><DEDENT>self._cache(name)<EOL>

Set the value (and bounds) of the named parameter.

Parameters
----------

name : str
    The parameter name.
clear_derived : bool
    Flag to clear derived objects in this model
value:
    The value of the parameter, if None, it is not changed
bounds: tuple or None
    The bounds on the parameter, if None, they are not set
free : bool or None
    Flag to say if parameter is fixed or free in fitting, if None, it is not changed
errors : tuple or None
    Uncertainties on the parameter, if None, they are not changed


self.clear_derived()<EOL>kwargs = dict(kwargs)<EOL>for name, value in kwargs.items():<EOL><INDENT>try:<EOL><INDENT>self.getp(name)<EOL><DEDENT>except KeyError:<EOL><INDENT>print ("<STR_LIT>" %<EOL>(type(self), name))<EOL><DEDENT>try:<EOL><INDENT>self.setp(name, clear_derived=False, **value)<EOL><DEDENT>except TypeError:<EOL><INDENT>try:<EOL><INDENT>self.setp(name, clear_derived=False, *value)<EOL><DEDENT>except (TypeError, KeyError):<EOL><INDENT>try:<EOL><INDENT>self.setp(name, clear_derived=False, value=value)<EOL><DEDENT>except (TypeError, KeyError):<EOL><INDENT>self.__setattr__(name, value)<EOL><DEDENT><DEDENT><DEDENT>self._missing.pop(name, None)<EOL><DEDENT>if self._missing:<EOL><INDENT>raise ValueError(<EOL>"<STR_LIT>",<EOL>self._missing.keys())<EOL><DEDENT>

Set a group of attributes (parameters and members).  Calls
`setp` directly, so kwargs can include more than just the
parameter value (e.g., bounds, free, etc.).


self._missing = {}<EOL>for k, p in self.params.items():<EOL><INDENT>if p.required:<EOL><INDENT>self._missing[k] = p<EOL><DEDENT>if isinstance(p, Derived):<EOL><INDENT>if p.loader is None:<EOL><INDENT>p.loader = self.__getattribute__("<STR_LIT>" % k)<EOL><DEDENT>elif isinstance(p.loader, str):<EOL><INDENT>p.loader = self.__getattribute__(p.loader)<EOL><DEDENT><DEDENT><DEDENT>

Loop through the list of Properties,
        extract the derived and required properties and do the
        appropriate book-keeping


l = []<EOL>if pnames is None:<EOL><INDENT>pnames = self.params.keys()<EOL><DEDENT>for pname in pnames:<EOL><INDENT>p = self.params[pname]<EOL>if isinstance(p, Parameter):<EOL><INDENT>l.append(p)<EOL><DEDENT><DEDENT>return l<EOL>

Return a list of Parameter objects

        Parameters
        ----------

        pname : list or None
           If a list get the Parameter objects with those names

           If none, get all the Parameter objects

        Returns
        -------

        params : list
            list of Parameters


l = self.get_params(pnames)<EOL>v = [p.value for p in l]<EOL>return np.array(v)<EOL>

Return an array with the parameter values

        Parameters
        ----------

        pname : list or None
           If a list, get the values of the `Parameter` objects with those names

           If none, get all values of all the `Parameter` objects

        Returns
        -------

        values : `np.array`
            Parameter values


l = self.get_params(pnames)<EOL>v = [p.errors for p in l]<EOL>return np.array(v)<EOL>

Return an array with the parameter errors

        Parameters
        ----------
        pname : list of string or none
           If a list of strings, get the Parameter objects with those names

           If none, get all the Parameter objects

        Returns
        -------
        ~numpy.array of parameter errors

        Note that this is a N x 2 array.


for p in self.params.values():<EOL><INDENT>if isinstance(p, Derived):<EOL><INDENT>p.clear_value()<EOL><DEDENT><DEDENT>

Reset the value of all Derived properties to None

        This is called by setp (and by extension __setattr__)


ret = odict(name=self.__class__.__name__)<EOL>ret.update(self.params)<EOL>return ret<EOL>

Return self cast as an '~collections.OrderedDict' object


return yaml.dump(self.todict())<EOL>


pass<EOL>

Method called in _setp to cache any computationally
intensive properties after updating the parameters.

Parameters
----------
name : string
   The parameter name.

Returns
-------
None


try:<EOL><INDENT>return a.item()<EOL><DEDENT>except AttributeError:<EOL><INDENT>return np.asarray(a).item()<EOL><DEDENT>

Convert single-item lists and numpy arrays to scalars. Does
    not care about the type of the elements (i.e., will work fine on
    strings, etc.)

    https://github.com/numpy/numpy/issues/4701
    https://github.com/numpy/numpy/pull/5126


def defaults_docstring(defaults, header=None, indent=None, footer=None):

if indent is None:<EOL><INDENT>indent = '<STR_LIT>'<EOL><DEDENT>if header is None:<EOL><INDENT>header = '<STR_LIT>'<EOL><DEDENT>if footer is None:<EOL><INDENT>footer = '<STR_LIT>'<EOL><DEDENT>width = <NUM_LIT><EOL>hbar = '<STR_LIT:\n>'<EOL>s = hbar + (header) + hbar<EOL>for key, value, desc in defaults:<EOL><INDENT>if isinstance(value, basestring):<EOL><INDENT>value = "<STR_LIT:'>" + value + "<STR_LIT:'>"<EOL><DEDENT>if hasattr(value, '<STR_LIT>'):<EOL><INDENT>value = "<STR_LIT:<>" + value.__name__ + "<STR_LIT:>>"<EOL><DEDENT>s += indent +'<STR_LIT>' % ("<STR_LIT>" % key)<EOL>s += indent + indent + (indent + <NUM_LIT> * '<STR_LIT:U+0020>').join(desc.split('<STR_LIT:\n>'))<EOL>s += '<STR_LIT>' % str(value)<EOL><DEDENT>s += hbar<EOL>s += footer<EOL>return s<EOL>

Return a docstring from a list of defaults.


def decorator(func):<EOL><INDENT>"""<STR_LIT>"""<EOL>kwargs = dict(header='<STR_LIT>', <EOL>indent='<STR_LIT:U+0020>',<EOL>footer='<STR_LIT:\n>')<EOL>doc = defaults_docstring(defaults, **kwargs)<EOL>if func.__doc__ is None:<EOL><INDENT>func.__doc__ = '<STR_LIT>'<EOL><DEDENT>func.__doc__ += doc<EOL>return func<EOL><DEDENT>return decorator<EOL>

Decorator to append default kwargs to a function.


<EOL>return dumper.represent_mapping(<EOL>yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG, data.items())<EOL>


defaults = dict([(d[<NUM_LIT:0>], d[<NUM_LIT:1>]) for d in self.defaults])<EOL>for k in kwargs:<EOL><INDENT>if k not in defaults:<EOL><INDENT>msg = "<STR_LIT>" % (<EOL>self.__class__.__name__, k)<EOL>raise AttributeError(msg)<EOL><DEDENT><DEDENT>defaults.update(kwargs)<EOL>self.__dict__.update(defaults)<EOL>self.check_type(self.__dict__['<STR_LIT:default>'])<EOL>self.set(**defaults)<EOL>

Load kwargs key,value pairs into __dict__


@classmethod<EOL><INDENT>def defaults_docstring(cls, header=None, indent=None, footer=None):<DEDENT>

return defaults_docstring(cls.defaults, header=header,<EOL>indent=indent, footer=footer)<EOL>

Add the default values to the class docstring


return self.__value__<EOL>

Return the current value

        This may be modified by sub-classes to do additional
        operations (such as caching the results of
        complicated operations needed to compute the value)


return type(self.__value__)<EOL>


return self.value<EOL>

__call__ will return the current value

        By default this invokes `self.value`
        so, any additional functionality that sub-classes implement,
        (such as caching the results of
        complicated operations needed to compute the value)
        will also be invoked


if '<STR_LIT:value>' in kwargs:<EOL><INDENT>self.set_value(kwargs.pop('<STR_LIT:value>', None))<EOL><DEDENT>

Set the value to kwargs['value']

        The invokes hooks for type-checking and bounds-checking that
        may be implemented by sub-classes.


self.check_bounds(value)<EOL>self.check_type(value)<EOL>self.__value__ = value<EOL>

Set the value

        This invokes hooks for type-checking and bounds-checking that
        may be implemented by sub-classes.


Set the value to None

        This can be useful for sub-classes that use None
        to indicate an un-initialized value.

        Note that this invokes hooks for type-checking and
        bounds-checking that may be implemented by sub-classes, so it
        should will need to be re-implemented if those checks do note
        accept None as a valid value.


return odict(value=self.value)<EOL>

Convert to a '~collections.OrderedDict' object.

        By default this only assigns {'value':self.value}


return yaml.dump(self)<EOL>


pass<EOL>

Hook for bounds-checking, invoked during assignment.

        Sub-classes can raise an exception for out-of-bounds input values.


if self.__dict__['<STR_LIT>'] is None:<EOL><INDENT>return<EOL><DEDENT>elif value is None:<EOL><INDENT>return<EOL><DEDENT>elif isinstance(value, self.__dict__['<STR_LIT>']):<EOL><INDENT>return<EOL><DEDENT>msg = "<STR_LIT>" % (<EOL>type(value), self.__dict__['<STR_LIT>'])<EOL>raise TypeError(msg)<EOL>

Hook for type-checking, invoked during assignment.

        raises TypeError if neither value nor self.dtype are None and they
        do not match.

        will not raise an exception if either value or self.dtype is None


if self.__value__ is None:<EOL><INDENT>try: <EOL><INDENT>loader = self.__dict__['<STR_LIT>']<EOL><DEDENT>except KeyError:<EOL><INDENT>raise AttributeError("<STR_LIT>")<EOL><DEDENT>val = loader()<EOL>try:<EOL><INDENT>self.set_value(val)<EOL><DEDENT>except TypeError:<EOL><INDENT>msg = "<STR_LIT>" % (self.__dict__['<STR_LIT>'], type(val))<EOL>raise TypeError(msg)<EOL><DEDENT><DEDENT>return self.__value__<EOL>

Return the current value.

        This first checks if the value is cached (i.e., if
        `self.__value__` is not None)

        If it is not cached then it invokes the `loader` function to
        compute the value, and caches the computed value


try:<EOL><INDENT>scalar = asscalar(value)<EOL><DEDENT>except ValueError as e:<EOL><INDENT>raise TypeError(e)<EOL><DEDENT>super(Parameter, self).check_type(scalar)<EOL>

Hook for type-checking, invoked during assignment. Allows size 1
        numpy arrays and lists, but raises TypeError if value can not
        be cast to a scalar.


return self.__bounds__<EOL>

Return the parameter bounds.

        None implies unbounded.


return self.__free__<EOL>


return self.__errors__<EOL>

Return the parameter uncertainties.

        None implies no error estimate.
        Single value implies symmetric errors.
        Two values implies low,high asymmetric errors.


<EOL>if self.__errors__ is None:<EOL><INDENT>return <NUM_LIT:0.><EOL><DEDENT>if np.isscalar(self.__errors__):<EOL><INDENT>return self.__errors__<EOL><DEDENT>return <NUM_LIT:0.5> * (self.__errors__[<NUM_LIT:0>] + self.__errors__[<NUM_LIT:1>])<EOL>

Return the symmertic error

        Similar to above, but zero implies no error estimate,
        and otherwise this will either be the symmetric error,
        or the average of the low,high asymmetric errors.


return self.value<EOL>


if self.__bounds__ is None:<EOL><INDENT>return<EOL><DEDENT>if not self.__bounds__[<NUM_LIT:0>] <= value <= self.__bounds__[<NUM_LIT:1>]:<EOL><INDENT>msg = "<STR_LIT>"<EOL>msg = msg % (value, self.__bounds__[<NUM_LIT:0>], self.__bounds__[<NUM_LIT:1>])<EOL>raise ValueError(msg)<EOL><DEDENT>

Hook for bounds-checking, invoked during assignment.

        raises ValueError if value is outside of bounds.
        does nothing if bounds is set to None.


if bounds is None:<EOL><INDENT>self.__bounds__ = None<EOL>return<EOL><DEDENT>self.__bounds__ = [asscalar(b) for b in bounds]<EOL>


if free is None:<EOL><INDENT>self.__free__ = False<EOL>return<EOL><DEDENT>self.__free__ = bool(free)<EOL>


if errors is None:<EOL><INDENT>self.__errors__ = None<EOL>return<EOL><DEDENT>self.__errors__ = [asscalar(e) for e in errors]<EOL>


<EOL>if '<STR_LIT>' in kwargs:<EOL><INDENT>self.set_bounds(kwargs.pop('<STR_LIT>'))<EOL><DEDENT>if '<STR_LIT>' in kwargs:<EOL><INDENT>self.set_free(kwargs.pop('<STR_LIT>'))<EOL><DEDENT>if '<STR_LIT>' in kwargs:<EOL><INDENT>self.set_errors(kwargs.pop('<STR_LIT>'))<EOL><DEDENT>if '<STR_LIT:value>' in kwargs:<EOL><INDENT>self.set_value(kwargs.pop('<STR_LIT:value>'))<EOL><DEDENT>

Set the value,bounds,free,errors based on corresponding kwargs

        The invokes hooks for type-checking and bounds-checking that
        may be implemented by sub-classes.


return odict(value=self.value, bounds=self.bounds,<EOL>free=self.free, errors=self.errors)<EOL>

Convert to a '~collections.OrderedDict' object.

        This assigns {'value':self.value,'bounds'=self.bounds,
                      'free'=self.free,'errors'=self.errors}


tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG<EOL>return dumper.represent_mapping(<EOL>tag, data.todict().items(), flow_style=True)<EOL>


def check_dates(self, event, valid_dates):

for year, dates in valid_dates.items():<EOL><INDENT>for month, days in dates.items():<EOL><INDENT>response = self.client.get(reverse(<EOL>'<STR_LIT>', kwargs={'<STR_LIT>': year, '<STR_LIT>': month}<EOL>))<EOL>self.clean_whitespace(response)<EOL>if days:<EOL><INDENT>self.assertContains(response, event.title)<EOL><DEDENT>else:<EOL><INDENT>self.assertNotContains(response, event.title)<EOL><DEDENT>for day in days:<EOL><INDENT>self.assertContains(response, self.cal_str(day))<EOL><DEDENT>[self.assertNotContains(response, self.cal_str(day)) for<EOL>day in xrange(<NUM_LIT:1>, monthrange(<NUM_LIT>, int(month))[<NUM_LIT:1>] + <NUM_LIT:1>)<EOL>if day not in days]<EOL><DEDENT><DEDENT>


def check_dates_yearly(self, event, valid_dates):

A DRY helper function for yearly repeat tests.


def check_dates(self, valid_dates, title, one_year=True):

for year, dates in valid_dates.items():<EOL><INDENT>for month, days in dates.items():<EOL><INDENT>response = self.client.get(reverse(<EOL>'<STR_LIT>', kwargs={'<STR_LIT>': year, '<STR_LIT>': month}<EOL>))<EOL>self.clean_whitespace(response)<EOL>if days:<EOL><INDENT>self.assertContains(response, title)<EOL><DEDENT>else:<EOL><INDENT>self.assertNotContains(response, title)<EOL><DEDENT>for day in days:<EOL><INDENT>[self.assertContains(response, self.cal_str(day)) for<EOL>day in days]<EOL>[self.assertNotContains(response, self.cal_str(day)) for<EOL>day in xrange(<NUM_LIT:1>, monthrange(<NUM_LIT>, int(month))[<NUM_LIT:1>] + <NUM_LIT:1>)<EOL>if day not in days]<EOL><DEDENT>if one_year:<EOL><INDENT>response = self.client.get(reverse(<EOL>'<STR_LIT>', kwargs={<EOL>'<STR_LIT>': str(int(year) + <NUM_LIT:1>), '<STR_LIT>': month<EOL>}<EOL>))<EOL>self.clean_whitespace(response)<EOL>self.assertNotContains(response, title)<EOL><DEDENT><DEDENT><DEDENT>

Checks the dates in the given valid_dates dict. Also check that the
event title appears on the page when it's supposed to.


for month, days in valid_dates.items():<EOL><INDENT>response = self.client.get(reverse(<EOL>'<STR_LIT>', kwargs={'<STR_LIT>': '<STR_LIT>', '<STR_LIT>': month}<EOL>))<EOL>self.clean_whitespace(response)<EOL>self.assertContains(response, event.title)<EOL>for day in days:<EOL><INDENT>self.assertContains(response, self.cal_str(day))<EOL><DEDENT>[self.assertNotContains(response, self.cal_str(day)) for<EOL>day in range(<NUM_LIT:1>, monthrange(<NUM_LIT>, int(month))[<NUM_LIT:1>] + <NUM_LIT:1>)<EOL>if day not in days]<EOL><DEDENT>


def create_event(created_by, title, description, all_day=False,<EOL>start_date=None, end_date=None, categories=None, tags=None,<EOL>repeat='<STR_LIT>', end_repeat=None, full=True, utc=False):

if start_date and end_date:<EOL><INDENT>if utc:<EOL><INDENT>val = timezone.utc<EOL><DEDENT>else:<EOL><INDENT>val = timezone.get_default_timezone()<EOL><DEDENT>start_date = timezone.make_aware(datetime.datetime(*start_date), val)<EOL>end_date = timezone.make_aware(datetime.datetime(*end_date), val)<EOL><DEDENT>elif start_date and not end_date or end_date and not start_date:<EOL><INDENT>raise ValueError("<STR_LIT>"<EOL>"<STR_LIT>")<EOL><DEDENT>else:<EOL><INDENT>start_date = timezone.now()<EOL>end_date = timezone.now()<EOL><DEDENT>event = Event.objects.create(<EOL>start_date=start_date,<EOL>end_date=end_date,<EOL>all_day=all_day,<EOL>created_by=created_by,<EOL>title=title,<EOL>description=description,<EOL>repeat=repeat,<EOL>end_repeat=end_repeat<EOL>)<EOL>if categories:<EOL><INDENT>for category in categories:<EOL><INDENT>event.categories.create(title=category)<EOL><DEDENT><DEDENT>if tags:<EOL><INDENT>for tag in tags:<EOL><INDENT>event.tags.create(name=tag)<EOL><DEDENT><DEDENT>if full:<EOL><INDENT>event.full_clean()<EOL>event.save()<EOL><DEDENT>return event<EOL>

A factory method for creating events. If start_date is supplied,
end_date must also be supplied, and they must both be either lists
or tuples e.g. start_date=[2014, 2, 2], end_date=[2014, 2, 3].


if hasattr(response, '<STR_LIT:content>'):<EOL><INDENT>is_response = True<EOL>content = response.content<EOL><DEDENT>else:<EOL><INDENT>is_response = False<EOL>content = response<EOL><DEDENT>if isinstance(content, six.text_type):<EOL><INDENT>content = content.encode('<STR_LIT:utf-8>')<EOL><DEDENT>content = content.replace(b'<STR_LIT:\n>', b'<STR_LIT>')<EOL>for num_spaces in range(<NUM_LIT:7>, <NUM_LIT:2>, -<NUM_LIT:1>):<EOL><INDENT>while content.find(b'<STR_LIT:U+0020>'*num_spaces) >= <NUM_LIT:0>:<EOL><INDENT>content = content.replace(b'<STR_LIT:U+0020>'*num_spaces, b'<STR_LIT:U+0020>'*<NUM_LIT:2>)<EOL><DEDENT><DEDENT>content = content.replace(b'<STR_LIT:U+0020>'*<NUM_LIT:2>, b'<STR_LIT>')<EOL>if is_response:<EOL><INDENT>response.content = content<EOL><DEDENT>else:<EOL><INDENT>content = content.decode('<STR_LIT:utf-8>')<EOL><DEDENT>return content<EOL>

Remove all newlines and all occurances of multiple spaces.


def assertContentBefore(self, response, text1, text2):

failing_msg = "<STR_LIT>" % (text1, text2)<EOL>self.assertEqual(response.status_code, <NUM_LIT:200>)<EOL>self.assertTrue(<EOL>response.content.index(force_bytes(text1)) <<EOL>response.content.index(force_bytes(text2)),<EOL>failing_msg)<EOL>

Testing utility asserting that text1 appears before text2 in response
content. Modified from:
https://github.com/django/django/blob/master/tests/admin_views/tests.py


@register.simple_tag<EOL>def weekday(year_or_num, month=None, day=None, full=False):

if any([month, day]) and not all([month, day]):<EOL><INDENT>raise TemplateSyntaxError("<STR_LIT>")<EOL><DEDENT>try:<EOL><INDENT>if all([year_or_num, month, day]):<EOL><INDENT>weekday_num = date(*map(int, (year_or_num, month, day))).weekday()<EOL><DEDENT>else:<EOL><INDENT>weekday_num = year_or_num<EOL><DEDENT>if full:<EOL><INDENT>return WEEKDAYS[weekday_num]<EOL><DEDENT>else:<EOL><INDENT>return WEEKDAYS_ABBR[weekday_num]<EOL><DEDENT><DEDENT>except Exception:<EOL><INDENT>return<EOL><DEDENT>

Simple tag - returns the weekday of the given (year, month, day) or of given (weekday_number).

    Usage (in template):

    {% weekday 2014 3 3 %}

    Result: Mon

    Return abbreviation by default. To return full name: pass full=True

    {% weekday 2014 3 3 full=True %}

    Result: Monday

    When only number of weekday is given then 0 is considered as "Monday"

    {% weekday 0 full=True %}

    Result: Monday


def get_year_and_month(self, net, qs, **kwargs):

now = c.get_now()<EOL>year = now.year<EOL>month = now.month + net<EOL>month_orig = None<EOL>if '<STR_LIT>' not in qs:<EOL><INDENT>if '<STR_LIT>' and '<STR_LIT>' in self.kwargs:  <EOL><INDENT>year, month_orig = map(<EOL>int, (self.kwargs['<STR_LIT>'], self.kwargs['<STR_LIT>'])<EOL>)<EOL>month = month_orig + net<EOL><DEDENT>else:<EOL><INDENT>try:  <EOL><INDENT>year = int(self.request.GET['<STR_LIT>'])<EOL>month_orig = int(self.request.GET['<STR_LIT>'])<EOL>month = month_orig + net<EOL><DEDENT>except Exception:<EOL><INDENT>pass<EOL><DEDENT><DEDENT><DEDENT>return c.clean_year_month(year, month, month_orig)<EOL>

Get the year and month. First tries from kwargs, then from
querystrings. If none, or if cal_ignore qs is specified,
sets year and month to this year and this month.


for event in self.events:<EOL><INDENT>for cn in event.cancellations.all():<EOL><INDENT>if cn.date == d:<EOL><INDENT>event.title += '<STR_LIT>'<EOL><DEDENT><DEDENT><DEDENT>

Check if any events are cancelled on the given date 'd'.


vals = {<EOL>'<STR_LIT>': category,<EOL>'<STR_LIT>': tag<EOL>}<EOL>kwargs = {}<EOL>for k, v in vals.items():<EOL><INDENT>if v:<EOL><INDENT>kwargs[k] = v<EOL><DEDENT><DEDENT>return kwargs<EOL>

Helper function for getting category/tag kwargs.


ym_first = make_aware(<EOL>datetime.datetime(year, month, <NUM_LIT:1>),<EOL>get_default_timezone()<EOL>)<EOL>ym_last = make_aware(<EOL>datetime.datetime(year, month, monthrange(year, month)[<NUM_LIT:1>], <NUM_LIT>, <NUM_LIT>, <NUM_LIT>, <NUM_LIT>-<NUM_LIT:1>),<EOL>get_default_timezone()<EOL>)<EOL>return ym_first, ym_last<EOL>

Returns two datetimes: first day and last day of given year&month


def all_month_events(self, year, month, category=None, tag=None,<EOL>loc=False, cncl=False):

kwargs = self._get_kwargs(category, tag)<EOL>ym_first, ym_last = self.get_first_and_last(year, month)<EOL>pref = []<EOL>if loc:<EOL><INDENT>pref.append("<STR_LIT:location>")<EOL><DEDENT>if cncl:<EOL><INDENT>pref.append("<STR_LIT>")<EOL><DEDENT>r = Q(repeat="<STR_LIT>")<EOL>dstart_mo = Q(start_date__month=month)<EOL>dend_mo = Q(end_date__month=month)<EOL>dstart_yr = Q(start_date__year=year)<EOL>dend_yr = Q(end_date__year=year)<EOL>return self.model.objects.filter(<EOL>r & (dstart_mo | dend_mo) |  <EOL>(~Q(repeat="<STR_LIT>")) |  <EOL>((dstart_yr | dend_yr) & (dstart_mo | dend_yr)),  <EOL>Q(end_repeat=None) | Q(end_repeat__gte=ym_first),<EOL>start_date__lte=ym_last  <EOL>).filter(**kwargs).prefetch_related(*pref).order_by('<STR_LIT>').distinct()<EOL>

Returns all events that have an occurrence within the given
month & year.


return self.model.objects.filter(<EOL>Q(end_repeat=None) | Q(end_repeat__gte=now) |<EOL>Q(start_date__gte=now) | Q(end_date__gte=now)<EOL>).exclude(  <EOL>start_date__lt=now, end_date__lt=now,<EOL>repeat="<STR_LIT>", end_repeat=None,<EOL>).prefetch_related('<STR_LIT>')<EOL>

Returns a queryset of events that will occur again after 'now'.
Used to help generate a list of upcoming events.


def render_to_json_response(self, context, **kwargs):

return HttpResponse(<EOL>self.convert_context_to_json(context),<EOL>content_type='<STR_LIT:application/json>',<EOL>**kwargs<EOL>)<EOL>

Returns a JSON response, transforming 'context' to make the payload.


if '<STR_LIT>' in self.request.path:  <EOL><INDENT>return dumps(self.get_month_calendar_dict(context))<EOL><DEDENT>elif '<STR_LIT>' in self.request.path:  <EOL><INDENT>return dumps(self.get_month_event_list_dict(context))<EOL><DEDENT>elif '<STR_LIT>' in self.request.path:<EOL><INDENT>cal = self.get_month_calendar_dict(context)<EOL>l = self.get_month_event_list_dict(context)<EOL>cal.update(l)<EOL>return dumps(cal)<EOL><DEDENT>else:  <EOL><INDENT>for key, val in context.items():<EOL><INDENT>if isinstance(val, Promise):<EOL><INDENT>context[key] = force_text(val)<EOL><DEDENT><DEDENT>return dumps(self.get_day_context_dict(context))<EOL><DEDENT>

Get what we want out of the context dict and convert that to a JSON
object. Note that this does no object serialization b/c we're
not sending any objects.


year = now.year<EOL>month = now.month<EOL>day = now.day<EOL>e_day = event[<NUM_LIT:0>].l_start_date.day<EOL>e_end_day = event[<NUM_LIT:0>].l_end_date.day<EOL>good_today = True if event[<NUM_LIT:0>].l_start_date.time() >= now.time() else False<EOL>if event[<NUM_LIT:0>].starts_same_year_month_as(year, month) ande_day <= now.day <= e_end_day:<EOL><INDENT>occurrences = CountHandler(year, month, event).get_count()<EOL>future_dates = (x for x in occurrences if x >= now.day)<EOL>day = min(future_dates, key=lambda x: abs(x - now.day))<EOL><DEDENT>else:<EOL><INDENT>e_year = event[<NUM_LIT:0>].l_start_date.year<EOL>e_month = event[<NUM_LIT:0>].l_start_date.month<EOL>if date(e_year, e_month, e_day) > date(now.year, now.month, now.day):<EOL><INDENT>year = e_year<EOL>month = e_month<EOL>day = e_day<EOL><DEDENT>else:<EOL><INDENT>occurrences = CountHandler(year, month, event).get_count()<EOL>future_dates = [x for x in occurrences if x >= now.day]<EOL>e_end_month = event[<NUM_LIT:0>].l_end_date.month<EOL>if future_dates and future_dates[<NUM_LIT:0>] is day and not good_today:<EOL><INDENT>future_dates.pop(<NUM_LIT:0>)<EOL><DEDENT>while not future_dates:<EOL><INDENT>month, year = inc_month(month, year)<EOL>if event[<NUM_LIT:0>].repeats('<STR_LIT>') and(month != e_month or month != e_end_month):<EOL><INDENT>continue<EOL><DEDENT>occurrences = CountHandler(year, month, event).get_count()<EOL>future_dates = [x for x in occurrences]<EOL><DEDENT>day = min(future_dates)<EOL><DEDENT><DEDENT>if event[<NUM_LIT:0>].repeats('<STR_LIT>'):<EOL><INDENT>return check_weekday(year, month, day)<EOL><DEDENT>return year, month, day<EOL>

Returns the next occurrence of a given event, relative to 'now'.
The 'event' arg should be an iterable containing one element,
namely the event we'd like to find the occurrence of.
The reason for this is b/c the get_count() function of CountHandler,
which this func makes use of, expects an iterable.
CHANGED: The 'now' arg must be an instance of datetime.datetime()
to allow time comparison (used to accept datetime.date() as well)


def formatmonth(self, theyear, themonth, withyear=True, net=None, qs=None, template='<STR_LIT>'):

context = self.get_context()<EOL>context['<STR_LIT>'] = date(self.yr, self.mo, <NUM_LIT:1>)<EOL>context['<STR_LIT>'] = []<EOL>for week in self.monthdays2calendar(theyear, themonth):<EOL><INDENT>week_row = []<EOL>for day, weekday in week:<EOL><INDENT>week_row.append(self.formatday(day, weekday))<EOL><DEDENT>context['<STR_LIT>'].append(week_row)<EOL><DEDENT>nxt, prev = get_next_and_prev(net)<EOL>extra_qs = ('<STR_LIT:&>' + '<STR_LIT:&>'.join(qs)) if qs else '<STR_LIT>'<EOL>context['<STR_LIT>'] = mark_safe('<STR_LIT>' % (prev, extra_qs))<EOL>context['<STR_LIT>'] = mark_safe('<STR_LIT>' % (nxt, extra_qs))<EOL>context['<STR_LIT>'] = withyear<EOL>return render_to_string(template, context)<EOL>


super(EventCalendar, self).formatday(day, weekday)<EOL>now = get_now()<EOL>context = self.get_context()<EOL>context['<STR_LIT>'] = []<EOL>context['<STR_LIT>'] = day<EOL>context['<STR_LIT>'] = self.get_day_url(day)<EOL>context['<STR_LIT>'] = date(self.yr, self.mo, <NUM_LIT:1>)<EOL>context['<STR_LIT>'] = weekday<EOL>context['<STR_LIT>'] = self.cssclasses[weekday]<EOL>context['<STR_LIT>'] = popover_template<EOL>context['<STR_LIT>'] = len(self.count.get(day, [])),<EOL>try:<EOL><INDENT>processed_date = date(self.yr, self.mo, day)<EOL><DEDENT>except ValueError:<EOL><INDENT>processed_date = None<EOL><DEDENT>context['<STR_LIT>'] = date(self.yr, self.mo, <NUM_LIT:1>)<EOL>if day == <NUM_LIT:0>:<EOL><INDENT>template = noday_template<EOL><DEDENT>else:<EOL><INDENT>template = day_template<EOL><DEDENT>if now.date() == processed_date:<EOL><INDENT>context['<STR_LIT>'] = True<EOL><DEDENT>if processed_date and (day in self.count):<EOL><INDENT>for item in self.count[day]:<EOL><INDENT>self.pk = item[<NUM_LIT:1>]<EOL>self.title = item[<NUM_LIT:0>]<EOL>for event in self.events:<EOL><INDENT>if event.pk == self.pk:<EOL><INDENT>event.check_if_cancelled(processed_date)<EOL>context['<STR_LIT>'].append(event)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>return render_to_string(template, context)<EOL>


return super(MiniEventCalendar, self).formatday(<EOL>day, weekday,<EOL>day_template='<STR_LIT>',<EOL>popover_template='<STR_LIT>',<EOL>)<EOL>


self.wkday_not_today = '<STR_LIT>' % (<EOL>self.cssclasses[weekday])<EOL>self.wkday_today = (<EOL>'<STR_LIT>' % (<EOL>self.cssclasses[weekday])<EOL>)<EOL>if URLS_NAMESPACE:<EOL><INDENT>url_name = '<STR_LIT>' % (URLS_NAMESPACE)<EOL><DEDENT>else:<EOL><INDENT>url_name = '<STR_LIT>'<EOL><DEDENT>self.day_url = reverse(url_name, args=(self.yr, self.mo, day))<EOL>self.day = day<EOL>self.anch = '<STR_LIT>' % (<EOL>self.day_url, day<EOL>)<EOL>self.end = '<STR_LIT>'<EOL>


def formatmonthname(self, theyear, themonth, withyear=True):

display_month = month_name[themonth]<EOL>if isinstance(display_month, six.binary_type) and self.encoding:<EOL><INDENT>display_month = display_month.decode(self.encoding)<EOL><DEDENT>if withyear:<EOL><INDENT>s = u'<STR_LIT>' % (display_month, theyear)<EOL><DEDENT>else:<EOL><INDENT>s = u'<STR_LIT:%s>' % display_month<EOL><DEDENT>return ('<STR_LIT>'<EOL>'<STR_LIT>'<EOL>'<STR_LIT>' % s)<EOL>

Change colspan to "5", add "today" button, and return a month
name as a table row.


<EOL>display_month = month_name[self.mo]<EOL>if isinstance(display_month, six.binary_type) and self.encoding:<EOL><INDENT>display_month = display_month.decode('<STR_LIT:utf-8>')<EOL><DEDENT>self.when = ('<STR_LIT>' + display_month + '<STR_LIT:U+0020>' +<EOL>str(self.day) + '<STR_LIT:U+002CU+0020>' + self.event.l_start_date.strftime(<EOL>LEGACY_CALENDAR_TIME_FORMAT).lstrip('<STR_LIT:0>') + '<STR_LIT>' +<EOL>self.event.l_end_date.strftime(LEGACY_CALENDAR_TIME_FORMAT).lstrip('<STR_LIT:0>') +<EOL>'<STR_LIT>')<EOL>if self.event.location.exists():  <EOL><INDENT>self.where = '<STR_LIT>'<EOL>for l in self.event.location.all():<EOL><INDENT>self.where += l.name<EOL><DEDENT>self.where += '<STR_LIT>'<EOL><DEDENT>else:<EOL><INDENT>self.where = '<STR_LIT>'<EOL><DEDENT>self.desc = '<STR_LIT>' + self.event.description[:<NUM_LIT:100>]<EOL>self.desc += ('<STR_LIT>' if len(self.event.description) > <NUM_LIT:100><EOL>else '<STR_LIT>')<EOL>self.event_url = self.event.get_absolute_url()  <EOL>t = LEGACY_CALENDAR_TIME_FORMAT if self.event.l_start_date.minute else LEGACY_CALENDAR_HOUR_FORMAT<EOL>self.title2 = (self.event.l_start_date.strftime(t).lstrip('<STR_LIT:0>') +<EOL>'<STR_LIT:U+0020>' + self.title)<EOL>

Populate variables used to build popovers.


super(EventCalendar, self).formatday(day, weekday)<EOL>now = get_now()<EOL>self.day = day<EOL>out = '<STR_LIT>'<EOL>if day == <NUM_LIT:0>:<EOL><INDENT>return '<STR_LIT>'  <EOL><DEDENT>elif now.month == self.mo and now.year == self.yr and day == now.day:<EOL><INDENT>if day in self.count:<EOL><INDENT>out = self.wkday_today + self.anch<EOL><DEDENT>else:<EOL><INDENT>return self.wkday_today + self.anch + self.end<EOL><DEDENT><DEDENT>elif day in self.count:<EOL><INDENT>out = self.wkday_not_today + self.anch<EOL><DEDENT>else:<EOL><INDENT>return self.wkday_not_today + self.anch + self.end<EOL><DEDENT>detail = "<STR_LIT>"<EOL>extras = ('<STR_LIT>'<EOL>'<STR_LIT>')<EOL>common = '<STR_LIT>'<EOL>for item in self.count[day]:<EOL><INDENT>self.pk = item[<NUM_LIT:1>]<EOL>self.title = item[<NUM_LIT:0>]<EOL>for event in self.events:<EOL><INDENT>if event.pk == self.pk:<EOL><INDENT>self.event = event<EOL>self.check_if_cancelled()<EOL>self.popover_helper()<EOL>bg, fnt = self.event.get_colors()<EOL><DEDENT><DEDENT>out += ('<STR_LIT>' + self.event_url + '<STR_LIT>' +<EOL>extras % (<EOL>self.title,<EOL>detail % (<EOL>self.when, self.where, self.desc, self.event_url<EOL>),<EOL>common % (bg, fnt)<EOL>) +<EOL>self.title2 + '<STR_LIT>')<EOL><DEDENT>return out + self.end<EOL>


super(MiniEventCalendar, self).formatday(day, weekday)<EOL>now = get_now()<EOL>self.day = day<EOL>if day == <NUM_LIT:0>:<EOL><INDENT>return '<STR_LIT>'  <EOL><DEDENT>elif now.month == self.mo and now.year == self.yr and day == now.day:<EOL><INDENT>if day in self.count:<EOL><INDENT>self.popover_helper()<EOL>return self.wkday_today + self.anch + self.cal_event + self.end<EOL><DEDENT>else:<EOL><INDENT>return self.wkday_today + self.anch + self.end<EOL><DEDENT><DEDENT>elif day in self.count:<EOL><INDENT>self.popover_helper()<EOL>return self.wkday_not_today + self.anch + self.cal_event + self.end<EOL><DEDENT>else:<EOL><INDENT>return self.wkday_not_today + self.anch + self.end<EOL><DEDENT>


month += <NUM_LIT:1><EOL>if month > <NUM_LIT:12>:<EOL><INDENT>month = <NUM_LIT:1><EOL>year += <NUM_LIT:1><EOL><DEDENT>return month, year<EOL>

Increment the month and, if neccessary, the year.
Both month and year should be ints.


d = date(year, month, day)<EOL>new_d = d + timezone.timedelta(days=net)<EOL>return new_d.year, new_d.month, new_d.day<EOL>

Increments the day by converting to a datetime.date().


try:<EOL><INDENT>nxt, prev = map(<EOL>int, (req.GET.get('<STR_LIT>', <NUM_LIT:0>), req.GET.get('<STR_LIT>', <NUM_LIT:0>))<EOL>)<EOL>net = nxt - prev<EOL><DEDENT>except Exception:<EOL><INDENT>net = <NUM_LIT:0><EOL><DEDENT>return net<EOL>

Get the net of any 'next' and 'prev' querystrings.


return req.GET.get('<STR_LIT>', None), req.GET.get('<STR_LIT>', None)<EOL>

Get value of any category and/or tag querystrings


ordered_events = {}<EOL>for event in events:<EOL><INDENT>try:<EOL><INDENT>for occ in event.occurrence:<EOL><INDENT>try:<EOL><INDENT>ordered_events[occ].append(event)<EOL><DEDENT>except Exception:<EOL><INDENT>ordered_events[occ] = [event]<EOL><DEDENT><DEDENT><DEDENT>except AttributeError:  <EOL><INDENT>pass<EOL><DEDENT><DEDENT>if d:<EOL><INDENT>return ordered_events<EOL><DEDENT>else:<EOL><INDENT>return sorted(ordered_events.items())<EOL><DEDENT>

Group events that occur on the same day, then sort them alphabetically
by title, then sort by day. Returns a list of tuples that looks like
[(day: [events])], where day is the day of the event(s), and [events]
is an alphabetically sorted list of the events for the day.


if net == <NUM_LIT:0>:<EOL><INDENT>nxt = prev = <NUM_LIT:1><EOL><DEDENT>elif net > <NUM_LIT:0>:<EOL><INDENT>nxt = net + <NUM_LIT:1><EOL>prev = -(net - <NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>nxt = net + <NUM_LIT:1><EOL>prev = abs(net) + <NUM_LIT:1><EOL><DEDENT>return nxt, prev<EOL>

Returns what the next and prev querystrings should be.


def _check_year(year, month, error, error_msg):

if year not in xrange((now.year - <NUM_LIT:50>), (now.year + <NUM_LIT>)):<EOL><INDENT>year = now.year<EOL>month = now.month<EOL>error = error_msg<EOL><DEDENT>return year, month, error<EOL>

Checks that the year is within 50 years from now.


def clean_year_month(year, month, month_orig):

error = False<EOL>error_msg = "<STR_LIT>"<EOL>if month_orig not in xrange(<NUM_LIT:1>, <NUM_LIT>) and month_orig is not None:<EOL><INDENT>month = now.month<EOL>error = error_msg<EOL><DEDENT>while month > <NUM_LIT:12>:<EOL><INDENT>month -= <NUM_LIT:12><EOL>year += <NUM_LIT:1><EOL><DEDENT>while month < <NUM_LIT:1>:<EOL><INDENT>month += <NUM_LIT:12><EOL>year -= <NUM_LIT:1><EOL><DEDENT>year, month, error = _check_year(year, month, error, error_msg)<EOL>return year, month, error<EOL>

If 'month_orig', which is the month given in the url BEFORE any next/prev
query strings have been applied, is out of range, sets month to the
current month and returns an error message. Also Returns an error
message if the year given is +/- 50 years from now.
If 'month', which is the month given in the url AFTER any next/prev
query strings have been applied, is out of range, adjusts it to be
in range (by also adjusting the year).


def check_weekday(year, month, day, reverse=False):

d = date(year, month, day)<EOL>while d.weekday() in (<NUM_LIT:5>, <NUM_LIT:6>):<EOL><INDENT>if reverse:<EOL><INDENT>d -= timedelta(days=<NUM_LIT:1>)<EOL><DEDENT>else:<EOL><INDENT>d += timedelta(days=<NUM_LIT:1>)<EOL><DEDENT><DEDENT>return d.year, d.month, d.day<EOL>

Make sure any event day we send back for weekday repeating
events is not a weekend.


while weekday != d.weekday():<EOL><INDENT>d += timedelta(days=<NUM_LIT:1>)<EOL><DEDENT>return d<EOL>

Given a weekday and a date, will increment the date until it's
weekday matches that of the given weekday, then that date is returned.


def _chunk_fill_out_first_week(year, month, count, event, diff):

first_of_the_month = date(year, month, <NUM_LIT:1>)<EOL>d = _first_weekday(event.l_end_date.weekday(), first_of_the_month)<EOL>d2 = _first_weekday(event.l_start_date.weekday(), first_of_the_month)<EOL>diff_weekdays = d.day - d2.day<EOL>day = first_of_the_month.day<EOL>start = event.l_start_date.weekday()<EOL>first = first_of_the_month.weekday()<EOL>if start == first or diff_weekdays == diff:<EOL><INDENT>return count<EOL><DEDENT>elif start > first:<EOL><INDENT>end = event.l_end_date.weekday()<EOL>diff = end - first + <NUM_LIT:1><EOL><DEDENT>elif start < first:<EOL><INDENT>diff = d.day<EOL><DEDENT>for i in xrange(diff):<EOL><INDENT>if event.end_repeat is not None anddate(year, month, day) >= event.end_repeat:<EOL><INDENT>break<EOL><DEDENT>count[day].append((event.title, event.pk))<EOL>day += <NUM_LIT:1><EOL><DEDENT>return count<EOL>

If a repeating chunk event exists in a particular month, but didn't
start that month, it may be neccessary to fill out the first week.
Five cases:
    1. event starts repeating on the 1st day of month
    2. event starts repeating past the 1st day of month
    3. event starts repeating before the 1st day of month, and continues
    through it.
    4. event starts repeating before the 1st day of month, and finishes
    repeating before it.
    5. event starts repeating before the 1st day of month, and finishes
    on it.


if day is None:<EOL><INDENT>day = self.day<EOL><DEDENT>try:<EOL><INDENT>d = date(self.year, self.month, day)<EOL><DEDENT>except ValueError:  <EOL><INDENT>return self.count<EOL><DEDENT>if self.count_first and d <= self.end_repeat:<EOL><INDENT>self.count_it(d.day)<EOL><DEDENT>d += timedelta(days=self.num)<EOL>if self.end_on is not None:<EOL><INDENT>while d.month == self.month andd <= self.end_repeat andd.day <= self.end_on:<EOL><INDENT>self.count_it(d.day)<EOL>d += timedelta(days=self.num)<EOL><DEDENT><DEDENT>else:<EOL><INDENT>while d.month == self.month and d <= self.end_repeat:<EOL><INDENT>self.count_it(d.day)<EOL>d += timedelta(days=self.num)<EOL><DEDENT><DEDENT>

Add 'num' to the day and count that day until we reach end_repeat, or
until we're outside of the current month, counting the days
as we go along.


try:<EOL><INDENT>d = date(self.year, self.month, self.day)<EOL><DEDENT>except ValueError:  <EOL><INDENT>return self.count<EOL><DEDENT>if self.count_first andd <= self.end_repeat andd.weekday() not in (<NUM_LIT:5>, <NUM_LIT:6>):<EOL><INDENT>self.count_it(d.day)<EOL><DEDENT>d += timedelta(days=<NUM_LIT:1>)<EOL>while d.month == self.month and d <= self.end_repeat:<EOL><INDENT>if d.weekday() not in (<NUM_LIT:5>, <NUM_LIT:6>):<EOL><INDENT>self.count_it(d.day)<EOL><DEDENT>d += timedelta(days=<NUM_LIT:1>)<EOL><DEDENT>

Like self.repeat(), but used to repeat every weekday.


day = start<EOL>diff = start - end<EOL>try:<EOL><INDENT>if date(self.year, self.month, day) <= self.end_repeat:<EOL><INDENT>self.count_it(day)<EOL><DEDENT><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT>for i in xrange(diff):<EOL><INDENT>day -= <NUM_LIT:1><EOL>try:<EOL><INDENT>if date(self.year, self.month, day) <= self.end_repeat:<EOL><INDENT>self.count_it(day)<EOL><DEDENT><DEDENT>except ValueError:<EOL><INDENT>pass<EOL><DEDENT><DEDENT>

Starts from 'start' day and counts backwards until 'end' day.
'start' should be >= 'end'. If it's equal to, does nothing.
If a day falls outside of end_repeat, it won't be counted.


mycount = defaultdict(list)<EOL>d = self.event.l_start_date<EOL>while d.year != self.year or d.month != self.month:<EOL><INDENT>d += timedelta(days=<NUM_LIT>)<EOL><DEDENT>r = self.__class__(<EOL>mycount, self.year, self.month, d.day, self.event.end_repeat,<EOL>self.event, num=self.num, count_first=True<EOL>)<EOL>r.repeat()<EOL>if self.event.is_chunk() and r.count:<EOL><INDENT>r.day = min(r.count)<EOL>r.repeat_chunk(self.event.start_end_diff)<EOL><DEDENT>return r.count<EOL>

This function is unique b/c it creates an empty defaultdict,
adds in the event occurrences by creating an instance of Repeater,
then returns the defaultdict, likely to be merged into the 'main'
defaultdict (the one holding all event occurrences for this month).


<EOL>if self.event.l_start_date.month == self.month andself.event.l_start_date.year != self.year:<EOL><INDENT>self.count_it(self.event.l_start_date.day)<EOL><DEDENT>if self.event.is_chunk() and notself.event.starts_same_year_month_as(self.year, self.month):<EOL><INDENT>self._repeat_chunk()<EOL><DEDENT>return self.count<EOL>

Events that repeat every year should be shown every year
on the same date they started e.g. an event that starts on March 23rd
would appear on March 23rd every year it is scheduled to repeat.
If the event is a chunk event, hand it over to _repeat_chunk().


start_day = self.event.l_start_date.day<EOL>if not self.event.starts_same_month_as(self.month):<EOL><INDENT>self.count_it(start_day)<EOL><DEDENT>elif self.event.starts_same_month_not_year_as(self.month, self.year):<EOL><INDENT>self.count_it(start_day)<EOL><DEDENT>if self.event.is_chunk():<EOL><INDENT>self._repeat_chunk()<EOL><DEDENT>return self.count<EOL>

Events that repeat every month should be shown every month
on the same date they started e.g. an event that starts on the 23rd
would appear on the 23rd every month it is scheduled to repeat.


self.num = <NUM_LIT><EOL>mycount = self.repeat_biweekly()<EOL>if mycount:<EOL><INDENT>if self.event.is_chunk() and min(mycount) not in xrange(<NUM_LIT:1>, <NUM_LIT:8>):<EOL><INDENT>mycount = _chunk_fill_out_first_week(<EOL>self.year, self.month, mycount, self.event,<EOL>diff=self.event.start_end_diff,<EOL>)<EOL><DEDENT>for k, v in mycount.items():<EOL><INDENT>for item in v:<EOL><INDENT>self.count[k].append(item)<EOL><DEDENT><DEDENT><DEDENT>

Created to take some of the load off of _handle_weekly_repeat_out


start_d = _first_weekday(<EOL>self.event.l_start_date.weekday(), date(self.year, self.month, <NUM_LIT:1>)<EOL>)<EOL>self.day = start_d.day<EOL>self.count_first = True<EOL>if self.event.repeats('<STR_LIT>'):<EOL><INDENT>self._biweekly_helper()<EOL><DEDENT>elif self.event.repeats('<STR_LIT>'):<EOL><INDENT>self.repeat()<EOL>if self.event.is_chunk():<EOL><INDENT>diff = self.event.start_end_diff<EOL>self.count = _chunk_fill_out_first_week(<EOL>self.year, self.month, self.count, self.event, diff<EOL>)<EOL>for i in xrange(diff):<EOL><INDENT>self.day = start_d.day + i + <NUM_LIT:1><EOL>self.repeat()<EOL><DEDENT><DEDENT><DEDENT>

Handles repeating an event weekly (or biweekly) if the current
year and month are outside of its start year and month.
It takes care of cases 3 and 4 in _handle_weekly_repeat_in() comments.


self.day = self.event.l_start_date.day<EOL>self.count_first = False<EOL>repeats = {'<STR_LIT>': <NUM_LIT:7>, '<STR_LIT>': <NUM_LIT>}<EOL>if self.event.starts_same_year_month_as(self.year, self.month):<EOL><INDENT>for repeat, num in repeats.items():<EOL><INDENT>self.num = num<EOL>if self.event.repeats(repeat):<EOL><INDENT>self.repeat()<EOL>if self.event.is_chunk():<EOL><INDENT>self.repeat_chunk(diff=self.event.start_end_diff)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

Handles repeating both weekly and biweekly events, if the
current year and month are inside it's l_start_date and l_end_date.
Four possibilites:
    1. The event starts this month and ends repeating this month.
    2. The event starts this month and doesn't finish repeating
    this month.
    3. The event didn't start this month but ends repeating this month.
    4. The event didn't start this month and doesn't end repeating
    this month.


if not event.starts_same_month_as(self.month) and notevent.repeats('<STR_LIT>'):<EOL><INDENT>return<EOL><DEDENT>mycount = defaultdict(list)<EOL>r = Repeater(<EOL>mycount, self.year, self.month, day=event.l_start_date.day,<EOL>end_repeat=event.end_repeat, event=event, count_first=True,<EOL>end_on=event.l_end_date.day, num=<NUM_LIT:1><EOL>)<EOL>if event.starts_same_month_as(self.month):<EOL><INDENT>if not event.ends_same_month_as(self.month):<EOL><INDENT>r.end_on = None<EOL><DEDENT><DEDENT>else:<EOL><INDENT>r.day = <NUM_LIT:1><EOL><DEDENT>r.repeat()<EOL>for k, v in r.count.items():<EOL><INDENT>self.count[k].extend(v)<EOL><DEDENT>

This handles either a non-repeating event chunk, or the first
month of a repeating event chunk.


for day in count:<EOL><INDENT>for item in count[day]:<EOL><INDENT>for event in events:<EOL><INDENT>if event.pk == item[<NUM_LIT:1>]:<EOL><INDENT>try:<EOL><INDENT>event.occurrence.append(day)<EOL><DEDENT>except AttributeError:<EOL><INDENT>event.occurrence = []<EOL>event.occurrence.append(day)<EOL><DEDENT><DEDENT><DEDENT><DEDENT><DEDENT>

Adds an occurrence key to the event object w/ a list of occurrences
and adds a popover (for use with twitter bootstrap).
The occurrence is added so that each event can be aware of what
day(s) it occurs in the month.


def month_display(year, month, all_month_events,<EOL>start_day, net, qs, mini=False, request=None, context=None):

<EOL>count = CountHandler(year, month, all_month_events).get_count()<EOL>for event in all_month_events[::-<NUM_LIT:1>]:<EOL><INDENT>for l in count.values():<EOL><INDENT>for item in l:<EOL><INDENT>if item[<NUM_LIT:1>] == event.pk:<EOL><INDENT>l.insert(<NUM_LIT:0>, l.pop(l.index(item)))<EOL><DEDENT><DEDENT><DEDENT><DEDENT>args = (year, month, count, all_month_events, start_day)<EOL>if not mini:<EOL><INDENT>html_cal = EventCalendar(request=request, context=context, *args).formatmonth(year, month, net=net, qs=qs)<EOL><DEDENT>else:<EOL><INDENT>html_cal = MiniEventCalendar(request=request, context=context, *args).formatmonth(year, month, net=net, qs=qs)<EOL><DEDENT>nxt, prev = get_next_and_prev(net)<EOL>extra_qs = ('<STR_LIT:&>' + '<STR_LIT:&>'.join(qs)) if qs else '<STR_LIT>'<EOL>html_cal = html_cal.replace(<EOL>'<STR_LIT>',<EOL>'<STR_LIT>' % (prev, extra_qs)<EOL>).replace(<EOL>'<STR_LIT>' % year,<EOL>'<STR_LIT>' % (year, nxt, extra_qs)<EOL>)<EOL>add_occurrences(all_month_events, count)<EOL>return html_cal<EOL>

A function that returns an html calendar for the given
month in the given year, with the number of events for that month
shown on the generated calendar. Start_day is the day the calendar
should start on (default is Monday).


def day_display(year, month, all_month_events, day):

<EOL>count = CountHandler(year, month, all_month_events).get_count()<EOL>pks = [x[<NUM_LIT:1>] for x in count[day]]  <EOL>day_events = list(Event.objects.filter(pk__in=pks).order_by(<EOL>'<STR_LIT>').prefetch_related('<STR_LIT>'))<EOL>day_events.sort(key=lambda x: x.l_start_date.hour)<EOL>return day_events<EOL>

Returns the events that occur on the given day.
Works by getting all occurrences for the month, then drilling
down to only those occurring on the given day.


if self.event.repeats('<STR_LIT>'):<EOL><INDENT>has_ended = False<EOL>now_gt_start = self.now > self.event.l_start_date<EOL>now_gt_end = self.now > self.event.end_date<EOL>if now_gt_end or now_gt_start:<EOL><INDENT>has_ended = True<EOL><DEDENT>has_not_started = self.event.l_start_date > self.finish<EOL>if has_ended or has_not_started:<EOL><INDENT>return self.events<EOL><DEDENT>self.events.append((self.event.l_start_date, self.event))<EOL>return self.events<EOL><DEDENT>if self.event.repeats('<STR_LIT>'):<EOL><INDENT>self._weekday()<EOL><DEDENT>elif self.event.repeats('<STR_LIT>'):<EOL><INDENT>self._monthly()<EOL><DEDENT>elif self.event.repeats('<STR_LIT>'):<EOL><INDENT>self._yearly()<EOL><DEDENT>else:<EOL><INDENT>self._others()<EOL><DEDENT>return self.events<EOL>

Repeats an event and returns 'num' (or fewer)
upcoming events from 'now'.


def we_should_stop(self, start, start_):

if start > self.finish orself.event.end_repeat is not None andstart_ > self.event.end_repeat:<EOL><INDENT>return True<EOL><DEDENT>else:<EOL><INDENT>return False<EOL><DEDENT>

Checks 'start' to see if we should stop collecting upcoming events.
'start' should be a datetime.datetime, 'start_' should be the same
as 'start', but it should be a datetime.date to allow comparison
w/ end_repeat.


return timezone.localtime(self.start_date)<EOL>


return timezone.localtime(self.end_date)<EOL>


start = self.l_start_date<EOL>end = self.l_end_date<EOL>happening = False<EOL>if (now >= start) and (start.time() <= now.time() <= end.time()):<EOL><INDENT>if self.repeats('<STR_LIT>'):<EOL><INDENT>if not now.weekday() > <NUM_LIT:4>:  <EOL><INDENT>happening = True<EOL><DEDENT><DEDENT>elif self.repeats('<STR_LIT>') or self.repeats('<STR_LIT>'):<EOL><INDENT>happening = True<EOL><DEDENT>elif self.repeats('<STR_LIT>'):<EOL><INDENT>if start.day <= now.day <= end.day:<EOL><INDENT>happening = True<EOL><DEDENT><DEDENT>elif self.repeats('<STR_LIT>'):<EOL><INDENT>if (start.month <= now.month <= end.month) and(start.day <= now.day <= end.day):<EOL><INDENT>happening = True<EOL><DEDENT><DEDENT>else:<EOL><INDENT>repeat = {'<STR_LIT>': <NUM_LIT:7>, '<STR_LIT>': <NUM_LIT>}<EOL>while end <= now:<EOL><INDENT>start += datetime.timedelta(days=repeat[self.repeat])<EOL>end += datetime.timedelta(days=repeat[self.repeat])<EOL><DEDENT>if start <= now <= end:<EOL><INDENT>happening = True<EOL><DEDENT><DEDENT><DEDENT>return happening<EOL>

Return True if the event is happening 'now', False if not.


s = self.l_start_date<EOL>e = self.l_end_date<EOL>start = datetime.date(s.year, s.month, s.day)<EOL>end = datetime.date(e.year, e.month, e.day)<EOL>diff = start - end<EOL>return abs(diff.days)<EOL>

Return the difference between start and end dates.


return (<EOL>self.end_repeat is None<EOL>or<EOL>self.end_repeat >= after_time.date()<EOL>or<EOL>self.l_start_date >= after_time<EOL>or<EOL>self.l_end_date >= after_time<EOL>)<EOL>

Return True if the event will occur again after 'after_date'.


result = self._check_if_cancelled_cache.get(date, None)<EOL>if result is None:<EOL><INDENT>try:<EOL><INDENT>self._prefetched_objects_cache[Event.cancellations.related.field.related_query_name()]<EOL>result = any(<EOL>((cancellation.date == date) for cancellation in self.cancellations.all())<EOL>)<EOL><DEDENT>except (AttributeError, KeyError):<EOL><INDENT>result = False<EOL>result = self.cancellations.filter(date=date).exists()<EOL><DEDENT>self._check_if_cancelled_cache[date] = result<EOL><DEDENT>if result:<EOL><INDENT>self.title_extra = _("<STR_LIT>")<EOL><DEDENT>self._last_check_if_cancelled = result<EOL>return result<EOL>

Return True if event was in cancelled state at 'date'. Also set self.title_extra to ' (CANCELLED)' if it was so.

        Warning! Results are memoized on instance level. If you need to reset "cache" of results then set ``instance._prefetched_objects_cache = {}``


err = _("<STR_LIT>")<EOL>colors = ['<STR_LIT>', '<STR_LIT>']<EOL>colors2 = colors + ['<STR_LIT>', '<STR_LIT>']<EOL>if len(self.COLORS) > <NUM_LIT:6>:<EOL><INDENT>colors = colors2<EOL><DEDENT>for color in colors:<EOL><INDENT>c = getattr(self, color)<EOL>l = len(c)<EOL>if l:<EOL><INDENT>if l != <NUM_LIT:6>:<EOL><INDENT>raise ValidationError(err)<EOL><DEDENT>else:<EOL><INDENT>try:<EOL><INDENT>int(c, <NUM_LIT:16>)<EOL><DEDENT>except ValueError:<EOL><INDENT>raise ValidationError(err)<EOL><DEDENT><DEDENT><DEDENT><DEDENT>

Makes sure that if a custom color is supplied, it's valid.


def call(args, stdout=None, stderr=None, stdin=None, daemonize=False,<EOL>preexec_fn=None, shell=False, cwd=None, env=None):

stream = lambda s, m: s is None and os.open(os.devnull, m) or s<EOL>stdout = stream(stdout, os.O_WRONLY)<EOL>stderr = stream(stderr, os.O_WRONLY)<EOL>stdin = stream(stdin, os.O_RDONLY)<EOL>shared_pid = Value('<STR_LIT:i>', <NUM_LIT:0>)<EOL>pid = os.fork()<EOL>if pid > <NUM_LIT:0>:<EOL><INDENT>os.waitpid(pid, <NUM_LIT:0>)<EOL>child_pid = shared_pid.value<EOL>del shared_pid<EOL>if daemonize:<EOL><INDENT>sys.exit(<NUM_LIT:0>)<EOL><DEDENT>return child_pid<EOL><DEDENT>else:<EOL><INDENT>os.setsid()<EOL>proc = subprocess.Popen(args, stdout=stdout, stderr=stderr, stdin=stdin, close_fds=True,<EOL>preexec_fn=preexec_fn, shell=shell, cwd=cwd, env=env)<EOL>shared_pid.value = proc.pid<EOL>os._exit(<NUM_LIT:0>)<EOL><DEDENT>

Run an external command in a separate process and detach it from the current process. Excepting
`stdout`, `stderr`, and `stdin` all file descriptors are closed after forking. If `daemonize`
is True then the parent process exits. All stdio is redirected to `os.devnull` unless
specified. The `preexec_fn`, `shell`, `cwd`, and `env` parameters are the same as their `Popen`
counterparts. Return the PID of the child process if not daemonized.


def __init__(self, stdout=None, stderr=None, stdin=None, close_fds=False, exclude_fds=None,<EOL>daemonize=False):

self.stdout = stdout<EOL>self.stderr = stderr<EOL>self.stdin = stdin<EOL>self.close_fds = close_fds<EOL>self.exclude_fds = set()<EOL>self.daemonize = daemonize<EOL>self.pid = None<EOL>self.shared_pid = Value('<STR_LIT:i>', <NUM_LIT:0>)<EOL>for item in list(exclude_fds or []) + [stdout, stderr, stdin]:<EOL><INDENT>if hasattr(item, '<STR_LIT>'):<EOL><INDENT>item = item.fileno()<EOL><DEDENT>self.exclude_fds.add(item)<EOL><DEDENT>

Fork and detach a process. The stdio streams of the child default to /dev/null but may be
overridden with the `stdout`, `stderr`, and `stdin` parameters. If `close_fds` is True then
all open file descriptors (except those passed as overrides for stdio) are closed by the
child process. File descriptors in `exclude_fds` will not be closed. If `daemonize` is True
then the parent process exits.


limits = resource.getrlimit(resource.RLIMIT_NOFILE)<EOL>result = limits[<NUM_LIT:1>]<EOL>if result == resource.RLIM_INFINITY:<EOL><INDENT>result = maxfd<EOL><DEDENT>return result<EOL>

Return the maximum file descriptor value.


try:<EOL><INDENT>os.close(fd)<EOL><DEDENT>except OSError as exc:<EOL><INDENT>if exc.errno != errno.EBADF:<EOL><INDENT>msg = "<STR_LIT>".format(fd, exc)<EOL>raise Error(msg)<EOL><DEDENT><DEDENT>


maxfd = self._get_max_fd()<EOL>for fd in reversed(list(range(maxfd))):<EOL><INDENT>if fd not in self.exclude_fds:<EOL><INDENT>self._close_fd(fd)<EOL><DEDENT><DEDENT>


if target is None:<EOL><INDENT>target_fd = os.open(os.devnull, os.O_RDWR)<EOL><DEDENT>else:<EOL><INDENT>target_fd = target.fileno()<EOL><DEDENT>os.dup2(target_fd, stream.fileno())<EOL>

Redirect a system stream to the provided target.


pid = os.fork()<EOL>if pid > <NUM_LIT:0>:<EOL><INDENT>os.waitpid(pid, <NUM_LIT:0>)<EOL>self.pid = self.shared_pid.value<EOL><DEDENT>else:<EOL><INDENT>os.setsid()<EOL>pid = os.fork()<EOL>if pid > <NUM_LIT:0>:<EOL><INDENT>self.shared_pid.value = pid<EOL>os._exit(<NUM_LIT:0>)<EOL><DEDENT>else:<EOL><INDENT>if self.close_fds:<EOL><INDENT>self._close_open_fds()<EOL><DEDENT>self._redirect(sys.stdout, self.stdout)<EOL>self._redirect(sys.stderr, self.stderr)<EOL>self._redirect(sys.stdin, self.stdin)<EOL><DEDENT><DEDENT>return self<EOL>


def __exit__(self, exc_cls, exc_val, exc_tb):

if self.daemonize or not self.pid:<EOL><INDENT>if exc_val:<EOL><INDENT>traceback.print_exception(exc_cls, exc_val, exc_tb)<EOL><DEDENT>os._exit(<NUM_LIT:0>)<EOL><DEDENT>


def wrapper(*args, **kwargs):<EOL><INDENT>pid = os.getpid()<EOL>if pid == parent_pid:<EOL><INDENT>return func(*args, **kwargs)<EOL><DEDENT><DEDENT>wrapper.__name__ = func.__name__<EOL>return wrapper<EOL>

Only execute the decorated function in the parent thread.


Add arguments to the parser for collection in app.args.

        Args:
            parser:
                `argparse.ArgumentParser`. Parser.
                Arguments added here are server on
                self.args.


def apply_tasks_to_issue(self, issue, tasks, issue_body=None):

issue_body = issue_body or issue.body<EOL>task_numbers = transport.format_task_numbers_with_links(tasks)<EOL>if task_numbers:<EOL><INDENT>new_body = transport.ASANA_SECTION_RE.sub('<STR_LIT>', issue_body)<EOL>new_body = new_body + "<STR_LIT>" % task_numbers<EOL>transport.issue_edit(issue,<EOL>body=new_body)<EOL>return new_body<EOL><DEDENT>return issue_body<EOL>


logging.info("<STR_LIT>")<EOL>ltm = self.app.data.get("<STR_LIT>", {})<EOL>for label in repo.get_labels():<EOL><INDENT>tag_id = ltm.get(label.name, None)<EOL>if tag_id is None:<EOL><INDENT>tag = self.app.asana.tags.create(name=label.name,<EOL>workspace=self.asana_ws_id,<EOL>notes="<STR_LIT>" % label.url<EOL>)<EOL>logging.info("<STR_LIT>", label.name, tag['<STR_LIT:id>'])<EOL>ltm[label.name] = tag['<STR_LIT:id>']<EOL><DEDENT><DEDENT>for ms in repo.get_milestones(state="<STR_LIT:all>"):<EOL><INDENT>tag_id = ltm.get(_ms_label(ms.id), None)<EOL>if tag_id is None:<EOL><INDENT>tag = self.app.asana.tags.create(name=ms.title,<EOL>workspace=self.asana_ws_id,<EOL>notes="<STR_LIT>" % ms.url<EOL>)<EOL>logging.info("<STR_LIT>", ms.title, tag['<STR_LIT:id>'])<EOL>ltm[_ms_label(ms.id)] = tag['<STR_LIT:id>']<EOL><DEDENT><DEDENT>self.app.data['<STR_LIT>'] = ltm<EOL>return ltm<EOL>

Creates a local map of github labels/milestones to asana tags.


def __init__(self, filename, args, version):

self.args = args<EOL>self.version = version<EOL>self.filename = filename<EOL>try:<EOL><INDENT>with open(self.filename, '<STR_LIT:rb>') as file:<EOL><INDENT>self.data = json.load(file)<EOL><DEDENT><DEDENT>except IOError:<EOL><INDENT>self.data = {}<EOL><DEDENT>

Args:
    filename:
        Filename for database.
    args:
        Program arguments.
    version:
        Version of file.


if not self.has_key('<STR_LIT:version>'):<EOL><INDENT>raise Exception("<STR_LIT>")<EOL><DEDENT>self.data['<STR_LIT:version>'] = self.version<EOL>

Asserts that the version and data file exists.


with open(self.filename, '<STR_LIT:wb>') as file:<EOL><INDENT>self.prune()<EOL>self.data['<STR_LIT:version>'] = self.version<EOL>json.dump(self.data,<EOL>file,<EOL>sort_keys=True, indent=<NUM_LIT:2>)<EOL><DEDENT>


self.data[key] = value<EOL>


return self.data[key]<EOL>


def apply(self, key, value, prompt=None,<EOL>on_load=lambda a: a, on_save=lambda a: a):

<EOL>if value == '<STR_LIT>':<EOL><INDENT>value = None<EOL>if key and self.data.has_key(key): del self.data[key]<EOL><DEDENT>if value is not None:<EOL><INDENT>value = on_load(value)<EOL>if key: self.data[key] = on_save(value)<EOL>return value<EOL><DEDENT>elif not key or not self.has_key(key):<EOL><INDENT>if callable(prompt):<EOL><INDENT>value = prompt()<EOL><DEDENT>elif prompt is not None:<EOL><INDENT>value = raw_input(prompt + "<STR_LIT>")<EOL><DEDENT>if value is None:<EOL><INDENT>if self.data.has_key(key): del self.data[key]<EOL>return None<EOL><DEDENT>self.data[key] = on_save(value)<EOL>return value<EOL><DEDENT>return on_load(self.data[key])<EOL>

Applies a setting value to a key, if the value is not `None`.

        Returns without prompting if either of the following:
            * `value` is not `None`
            * already present in the dictionary

        Args:
            prompt:
                May either be a string to prompt via `raw_input` or a
                method (callable) that returns the value.

            on_load:
                lambda. Value is passed through here after loaded.

            on_save:
                lambda. Value is saved as this value.


seen = set()<EOL>seen_add = seen.add<EOL>return [ x for x in seq if x not in seen and not seen_add(x)]<EOL>


if self.oauth:<EOL><INDENT>return False<EOL><DEDENT>self.settings.apply('<STR_LIT>', self.args.asana_api,<EOL>"<STR_LIT>")<EOL>self.settings.apply('<STR_LIT>', self.args.github_api,<EOL>"<STR_LIT>")<EOL>logging.debug("<STR_LIT>")<EOL>self.asana = Client.basic_auth(self.settings['<STR_LIT>'])<EOL>self.asana_errors = asana_errors<EOL>self.asana_me = self.asana.users.me()<EOL>logging.debug("<STR_LIT>")<EOL>self.github = Github(self.settings['<STR_LIT>'])<EOL>self.github_user = self.github.get_user()<EOL>self.oauth = True<EOL>

Connects to Github and Asana and authenticates via OAuth.


@classmethod<EOL><INDENT>def _list_select(cls, lst, prompt, offset=<NUM_LIT:0>):<DEDENT>

inp = input("<STR_LIT>" % prompt)<EOL>assert inp, "<STR_LIT>"<EOL>try:<EOL><INDENT>return lst[int(inp)+offset]<EOL><DEDENT>except ValueError:<EOL><INDENT>return inp<EOL><DEDENT>except IndexError:<EOL><INDENT>assert False, "<STR_LIT>"<EOL><DEDENT>

Given a list of values and names, accepts the index value or name.


@classmethod<EOL><INDENT>def make_asana_url(cls, project_id, task_id):<DEDENT>

return "<STR_LIT>" % (project_id, task_id)<EOL>


return '<STR_LIT>' % namespace<EOL>


def save_issue_data_task(self, issue, task_id, namespace='<STR_LIT>'):

issue_data = self.get_saved_issue_data(issue, namespace)<EOL>if '<STR_LIT>' not in issue_data:<EOL><INDENT>issue_data['<STR_LIT>'] = [task_id]<EOL><DEDENT>elif task_id not in issue_data['<STR_LIT>']:<EOL><INDENT>issue_data['<STR_LIT>'].append(task_id)<EOL><DEDENT>

Saves a issue data (tasks, etc.) to local data.

        Args:
            issue:
                `int`. Github issue number.
            task:
                `int`. Asana task ID.
            namespace:
                `str`. Namespace for storing this issue.


def get_saved_issue_data(self, issue, namespace='<STR_LIT>'):

if isinstance(issue, int):<EOL><INDENT>issue_number = str(issue)<EOL><DEDENT>elif isinstance(issue, str):<EOL><INDENT>issue_number = issue<EOL><DEDENT>else:<EOL><INDENT>issue_number = issue.number<EOL><DEDENT>issue_data_key = self._issue_data_key(namespace)<EOL>issue_data = self.data.get(issue_data_key,<EOL>{})<EOL>_data = issue_data.get(str(issue_number), {})<EOL>issue_data[str(issue_number)] = _data<EOL>return _data<EOL>

Returns issue data from local data.

        Args:
            issue:
                `int`. Github issue number.
            namespace:
                `str`. Namespace for storing this issue.


def move_saved_issue_data(self, issue, ns, other_ns):

if isinstance(issue, int):<EOL><INDENT>issue_number = str(issue)<EOL><DEDENT>elif isinstance(issue, str):<EOL><INDENT>issue_number = issue<EOL><DEDENT>else:<EOL><INDENT>issue_number = issue.number<EOL><DEDENT>issue_data_key = self._issue_data_key(ns)<EOL>other_issue_data_key = self._issue_data_key(other_ns)<EOL>issue_data = self.data.get(issue_data_key,<EOL>{})<EOL>other_issue_data = self.data.get(other_issue_data_key,<EOL>{})<EOL>_id = issue_data.pop(issue_number, None)<EOL>if _id:<EOL><INDENT>other_issue_data[issue_number] = _id<EOL><DEDENT>self.data[other_issue_data_key] = other_issue_data<EOL>self.data[issue_data_key] = issue_data<EOL>

Moves an issue_data from one namespace to another.


return '<STR_LIT>'<EOL>


if isinstance(task, int):<EOL><INDENT>task_number = str(task)<EOL><DEDENT>elif isinstance(task, str):<EOL><INDENT>task_number = task<EOL><DEDENT>else:<EOL><INDENT>task_number = task['<STR_LIT:id>']<EOL><DEDENT>task_data_key = self._task_data_key()<EOL>task_data = self.data.get(task_data_key, {})<EOL>_data = task_data.get(str(task_number), {})<EOL>task_data[str(task_number)] = _data<EOL>return _data<EOL>

Returns task data from local data.

        Args:
            task:
                `int`. Asana task number.


try:<EOL><INDENT>return self.asana.tasks.find_by_id(asana_task_id)<EOL><DEDENT>except asana_errors.NotFoundError:<EOL><INDENT>return None<EOL><DEDENT>except asana_errors.ForbiddenError:<EOL><INDENT>return None<EOL><DEDENT>


<EOL>self.version = version<EOL>self.exit_code = <NUM_LIT><EOL>self.oauth = False<EOL>self.logger = logging.getLogger()<EOL>formatter = logging.Formatter("<STR_LIT>")<EOL>self.logger.setLevel(logging.DEBUG)<EOL>self.logger.propagate = False<EOL>self.logger.handlers = []<EOL>ch = logging.StreamHandler()<EOL>ch.setLevel(logging.INFO)<EOL>ch.setFormatter(formatter)<EOL>self.logger.addHandler(ch)<EOL>parser = argparse.ArgumentParser(description='<STR_LIT>')<EOL>def_settings_file = os.path.join(<EOL>os.path.expanduser("<STR_LIT>"),<EOL>'<STR_LIT>',<EOL>)<EOL>def_data_file = os.path.expanduser("<STR_LIT>")<EOL>actions = {}<EOL>choices = []<EOL>help_msgs = '<STR_LIT>'<EOL>for action in Action.iter_actions():<EOL><INDENT>actions[action.name] = action<EOL>choices.append(action.name)<EOL>help_msgs += '<STR_LIT>' % (action.name, action.__doc__)<EOL><DEDENT>help_msgs += '<STR_LIT:\n>'<EOL>parser.add_argument(<EOL>'<STR_LIT:action>',<EOL>action='<STR_LIT:store>',<EOL>nargs=<NUM_LIT:1>,<EOL>help=help_msgs,<EOL>choices=choices,<EOL>)<EOL>parser.add_argument(<EOL>'<STR_LIT>', '<STR_LIT>',<EOL>action='<STR_LIT:store_true>',<EOL>dest='<STR_LIT>',<EOL>help="<STR_LIT>",<EOL>)<EOL>parser.add_argument(<EOL>'<STR_LIT>', '<STR_LIT>',<EOL>action='<STR_LIT:store>',<EOL>nargs='<STR_LIT:?>',<EOL>dest='<STR_LIT>',<EOL>default=def_settings_file,<EOL>help="<STR_LIT>",<EOL>)<EOL>parser.add_argument(<EOL>'<STR_LIT>', '<STR_LIT>',<EOL>action='<STR_LIT:store>',<EOL>nargs='<STR_LIT:?>',<EOL>dest='<STR_LIT>',<EOL>default=def_data_file,<EOL>help="<STR_LIT>",<EOL>)<EOL>for action in list(actions.values()):<EOL><INDENT>action.add_arguments(parser)<EOL><DEDENT>Action.add_arguments(parser)<EOL>parser.add_argument('<STR_LIT>', '<STR_LIT>', action='<STR_LIT:version>',<EOL>version='<STR_LIT>' + '<STR_LIT:%s>' % version)<EOL>self.args = parser.parse_args()<EOL>if len(sys.argv) < <NUM_LIT:2>:<EOL><INDENT>parser.print_help()<EOL>self.exit_code = <NUM_LIT:1><EOL>return<EOL><DEDENT>if self.args.verbose:<EOL><INDENT>ch.setLevel(logging.DEBUG)<EOL><DEDENT>logging.debug("<STR_LIT>")<EOL>self.settings = JSONData(filename=self.args.settings_file,<EOL>args=self.args, version=version)<EOL>self.data = JSONData(filename=self.args.data_file,<EOL>args=self.args, version=version)<EOL>try:<EOL><INDENT>action_name = self.args.action[<NUM_LIT:0>]<EOL>action_class = actions.get(action_name)<EOL>if not action_class:<EOL><INDENT>raise NotImplementedError(<EOL>"<STR_LIT>" % action_name)<EOL><DEDENT>action = action_class(app=self, args=self.args)<EOL>self.authenticate()<EOL>transport.start(self)<EOL>action.run()<EOL>transport.flush(callback=self.flush_settings)<EOL>logging.debug("<STR_LIT>")<EOL>self.flush_settings()<EOL><DEDENT>except AssertionError as exc:<EOL><INDENT>logging.error("<STR_LIT>", str(exc))<EOL>logging.debug("<STR_LIT:%s>", traceback.format_exc())<EOL>self.exit_code = <NUM_LIT:1><EOL>return<EOL><DEDENT>except Exception as exc:<EOL><INDENT>logging.exception("<STR_LIT>", exc)<EOL>self.exit_code = <NUM_LIT><EOL>return<EOL><DEDENT>finally:<EOL><INDENT>transport.shutdown()<EOL>self.settings.save()<EOL>self.data.save()<EOL><DEDENT>self.exit_code = <NUM_LIT:0><EOL>


app = ToolApp(version=__VERSION__)<EOL>exit(app.exit_code)<EOL>


def wrapped_func(*args, **kwargs):<EOL><INDENT>tries = <NUM_LIT:0><EOL>while True:<EOL><INDENT>try:<EOL><INDENT>try:<EOL><INDENT>return func(*args, **kwargs)<EOL><DEDENT>except (asana_errors.InvalidRequestError,<EOL>asana_errors.NotFoundError) as exc:<EOL><INDENT>logging.warn("<STR_LIT>", exc)<EOL><DEDENT>except asana_errors.ForbiddenError as exc:<EOL><INDENT>logging.warn("<STR_LIT>", exc)<EOL><DEDENT>except asana_errors.NotFoundError as exc:<EOL><INDENT>logging.warn("<STR_LIT>", exc)<EOL><DEDENT>return None<EOL><DEDENT>except asana_errors.RetryableAsanaError as retry_exc:<EOL><INDENT>tries += <NUM_LIT:1><EOL>logging.warn("<STR_LIT>", retry_exc, tries)<EOL>if tries >= <NUM_LIT:3>:<EOL><INDENT>raise<EOL><DEDENT><DEDENT>except Exception as exc:<EOL><INDENT>logging.exception("<STR_LIT>")<EOL>return<EOL><DEDENT><DEDENT><DEDENT>return wrapped_func<EOL>

Decorator for retrying tasks with special cases.


kwargs['<STR_LIT>'] = task<EOL>settings_queue.put(kwargs)<EOL>


while True:<EOL><INDENT>if shutdown_event.is_set():<EOL><INDENT>return<EOL><DEDENT>if callable(callback):<EOL><INDENT>callback()<EOL><DEDENT>try:<EOL><INDENT>item = queue.get(timeout=<NUM_LIT:1>)<EOL>queue.put(item)  <EOL><DEDENT>except queue.Empty:<EOL><INDENT>return<EOL><DEDENT><DEDENT>


put("<STR_LIT>",<EOL>issue_number=issue.number,<EOL>**kwargs)<EOL>


def task_create(asana_workspace_id, name, notes, assignee, projects,<EOL>completed, **kwargs):

put("<STR_LIT>",<EOL>asana_workspace_id=asana_workspace_id,<EOL>name=name,<EOL>notes=notes,<EOL>assignee=assignee,<EOL>projects=projects,<EOL>completed=completed,<EOL>**kwargs)<EOL>


return shutdown_event.is_set()<EOL>

Returns True if the app is requesting a global shutdown.


while True:<EOL><INDENT>try:<EOL><INDENT>item = settings_queue.get(timeout=<NUM_LIT:1>)<EOL>yield item<EOL><DEDENT>except queue.Empty:<EOL><INDENT>return<EOL><DEDENT><DEDENT>


project_id = data.get('<STR_LIT>', None)<EOL>def _task_format(task_id):<EOL><INDENT>if project_id:<EOL><INDENT>asana_url = tool.ToolApp.make_asana_url(project_id, task_id)<EOL>return "<STR_LIT>" % (task_id, asana_url)<EOL><DEDENT>else:<EOL><INDENT>return "<STR_LIT>" % task_id<EOL><DEDENT><DEDENT>return "<STR_LIT:\n>".join([_task_format(tid) for tid in tasks])<EOL>

Returns formatting for the tasks section of asana.


@transport_task<EOL><INDENT>def apply_tasks_to_issue(self, tasks, issue_number, issue_body):<DEDENT>

issue_body = issue_body<EOL>task_numbers = format_task_numbers_with_links(tasks)<EOL>if task_numbers:<EOL><INDENT>new_body = ASANA_SECTION_RE.sub('<STR_LIT>', issue_body)<EOL>new_body = new_body + "<STR_LIT>" % task_numbers<EOL>put("<STR_LIT>",<EOL>issue_number=issue_number,<EOL>body=new_body)<EOL>return new_body<EOL><DEDENT>return issue_body<EOL>


subclasses = c.__subclasses__()<EOL>for d in list(subclasses):<EOL><INDENT>subclasses.extend(get_subclasses(d))<EOL><DEDENT>return subclasses<EOL>


app = self.app<EOL>repo = app.data.apply('<STR_LIT>', app.args.github_repo,<EOL>app.prompt_repo,<EOL>on_load=app.github.get_repo,<EOL>on_save=lambda r: r.id<EOL>)<EOL>assert repo, "<STR_LIT>"<EOL>project = app.data.apply('<STR_LIT>', app.args.asana_project,<EOL>app.prompt_project,<EOL>on_load=app.asana.projects.find_by_id,<EOL>on_save=lambda p: p['<STR_LIT:id>']<EOL>)<EOL>assert project, "<STR_LIT>"<EOL>first_issue = app.data.apply('<STR_LIT>', app.args.first_issue,<EOL>"<STR_LIT>",<EOL>on_save=int)<EOL>assert first_issue<EOL>assert first_issue >= <NUM_LIT:0>, "<STR_LIT>"<EOL>app.sync_data()<EOL>return repo, project<EOL>


for sub_class in get_subclasses(cls):<EOL><INDENT>yield sub_class<EOL><DEDENT>


def either(val):<EOL><INDENT>for func in funcs:<EOL><INDENT>result = val.apply(func)<EOL>if result:<EOL><INDENT>return result<EOL><DEDENT><DEDENT>return Null()<EOL><DEDENT>return either<EOL>

A utility function for selecting the first non-null query.

Parameters:

  funcs: One or more functions

Returns:

   A function that, when called with a :class:`Node`, will
   pass the input to each `func`, and return the first non-Falsey
   result.

Examples:

   >>> s = Soupy("
hi
")
   >>> s.apply(either(Q.find('a'), Q.find('p').text))
   Scalar('hi')