<gh_stars>1-10

from datetime import timedelta, datetime
import os
import struct

from tqdm import tqdm

# Allow for explicit parser selection, or else use pychapter10 by default.
from chapter10 import C10
if os.environ.get('LIBRARY', 'c10') == 'i106':
    try:
        from i106 import C10
    except ImportError:
        print('Could not import libirig106-python, reverting to pychapter10')


# Format a number nicely with commas for thousands, etc.
fmt_number = '{0:,}'.format


def swap_word(word):
    return struct.unpack('<H', struct.pack('>H', word))[0]


def find_c10(paths):
    """Take a list of paths and yield paths to Chapter 10 files found at
    those locations or subdirectories. Any files in the original list are
    returned as-is.
    """

    for path in paths:
        path = os.path.abspath(path)
        if os.path.isdir(path):
            for dirname, dirnames, filenames in os.walk(path):
                for f in filenames:
                    if os.path.splitext(f)[1].lower() in ('.c10', '.ch10'):
                        yield os.path.join(dirname, f)
        else:
            yield path


def fmt_table(table):
    """Print tabular data to stdout. Numeric fields justified right, others
    left.
    """

    # Make a list of columns (instead of a list of rows) and find max widths.
    columns = len(table[0])
    tmp = [r for r in table if len(r) == columns]
    col_widths = [max(len(x) for x in col) for col in zip(*tmp)]

    # Width is the sum of the column widths + ~3 padding characters per column.
    width = sum(col_widths) + (len(table[0]) * 3) + 1

    # Header row
    s = ('-' * width) + '\n|'
    for i, x in enumerate(table[0]):
        s += ' ' + x.ljust(col_widths[i]) + ' |'
    s += '\n{}\n'.format('-' * width)

    # Data rows
    size_suffix = (' kb', ' mb', ' gb', '  b')
    for row in table[1:]:
        s += '|'
        if len(row) < columns:
            s += ' ' + row[0] + '|'.rjust(width - len(row[0]) - 2)
        else:
            for i, x in enumerate(row):
                if x.replace(',', '').isdigit() or x[-3:] in size_suffix:
                    s += ' {} |'.format(x.rjust(col_widths[i]))
                else:
                    s += ' {} |'.format(x.ljust(col_widths[i]))
        s += '\n'

    return s + ('-' * width)


def get_time(rtc, time_packet):
    """Get a datetime object based on last time packet and an RTC value."""

    # TODO: this is here because the event sample file has no time
    if time_packet is None:
        return datetime.now()

    rtc -= time_packet.rtc
    mask = 0xffffffffffff
    while rtc > mask:
        rtc -= mask
    return time_packet.time + timedelta(seconds=rtc / 10_000_000)


def fmt_size(size):
    """Convert byte size to a more readable format (mb, etc.)."""

    unit, units = ' b', ['gb', 'mb', 'kb']
    while size > 1024 and units:
        size /= 1024.0
        unit = units.pop()
    return '{} {}'.format(round(size, 2), unit)


def walk_packets(c10, args={}, include_time=True):
    """Walk a chapter 10 file based on sys.argv (type, channel, etc.)."""

    # Apply defaults.
    args['--type'] = args.get('--type') or ''
    args['--channel'] = args.get('--channel') or ''
    args['--exclude'] = args.get('--exclude') or ''

    # Parse types (if given) into ints.
    types = [t.strip() for t in args['--type'].split(',') if t.strip()]
    types = [int(t, 16) if t.startswith('0x') else int(t) for t in types]

    # Parse channel selection.
    channels = [c.strip() for c in args['--channel'].split(',') if c.strip()]
    exclude = [e.strip() for e in args['--exclude'].split(',') if e.strip()]

    # Filter packets (except time).
    for i, packet in enumerate(c10):
        if include_time and packet.data_type == 0x11:
            yield packet

        channel = str(packet.channel_id)
        if channels and channel not in channels:
            continue
        elif channel in exclude:
            continue
        elif types and packet.data_type not in types:
            continue

        yield packet


class FileProgress(tqdm):
    """Extend tqdm to show progress reading over a file based on f.tell()."""

    def __init__(self, filename=None, total=None, **kwargs):
        if total is None:
            total = os.stat(filename).st_size
        tqdm_kwargs = dict(
            dynamic_ncols=True,
            total=total,
            leave=False,
            unit='bytes',
            unit_scale=True)
        tqdm_kwargs.update(kwargs)
        tqdm.__init__(self, **tqdm_kwargs)
        self.last_tell = 0

    def update_from_tell(self, tell):
        self.update(tell - self.last_tell)
        self.last_tell = tell

from datetime import timedelta, datetime
import os
import struct

from tqdm import tqdm

# Allow for explicit parser selection, or else use pychapter10 by default.
from chapter10 import C10
if os.environ.get('LIBRARY', 'c10') == 'i106':
    try:
        from i106 import C10
    except ImportError:
        print('Could not import libirig106-python, reverting to pychapter10')


# Format a number nicely with commas for thousands, etc.
fmt_number = '{0:,}'.format


def swap_word(word):
    return struct.unpack('<H', struct.pack('>H', word))[0]


def find_c10(paths):
    """Take a list of paths and yield paths to Chapter 10 files found at
    those locations or subdirectories. Any files in the original list are
    returned as-is.
    """

    for path in paths:
        path = os.path.abspath(path)
        if os.path.isdir(path):
            for dirname, dirnames, filenames in os.walk(path):
                for f in filenames:
                    if os.path.splitext(f)[1].lower() in ('.c10', '.ch10'):
                        yield os.path.join(dirname, f)
        else:
            yield path


def fmt_table(table):
    """Print tabular data to stdout. Numeric fields justified right, others
    left.
    """

    # Make a list of columns (instead of a list of rows) and find max widths.
    columns = len(table[0])
    tmp = [r for r in table if len(r) == columns]
    col_widths = [max(len(x) for x in col) for col in zip(*tmp)]

    # Width is the sum of the column widths + ~3 padding characters per column.
    width = sum(col_widths) + (len(table[0]) * 3) + 1

    # Header row
    s = ('-' * width) + '\n|'
    for i, x in enumerate(table[0]):
        s += ' ' + x.ljust(col_widths[i]) + ' |'
    s += '\n{}\n'.format('-' * width)

    # Data rows
    size_suffix = (' kb', ' mb', ' gb', '  b')
    for row in table[1:]:
        s += '|'
        if len(row) < columns:
            s += ' ' + row[0] + '|'.rjust(width - len(row[0]) - 2)
        else:
            for i, x in enumerate(row):
                if x.replace(',', '').isdigit() or x[-3:] in size_suffix:
                    s += ' {} |'.format(x.rjust(col_widths[i]))
                else:
                    s += ' {} |'.format(x.ljust(col_widths[i]))
        s += '\n'

    return s + ('-' * width)


def get_time(rtc, time_packet):
    """Get a datetime object based on last time packet and an RTC value."""

    # TODO: this is here because the event sample file has no time
    if time_packet is None:
        return datetime.now()

    rtc -= time_packet.rtc
    mask = 0xffffffffffff
    while rtc > mask:
        rtc -= mask
    return time_packet.time + timedelta(seconds=rtc / 10_000_000)


def fmt_size(size):
    """Convert byte size to a more readable format (mb, etc.)."""

    unit, units = ' b', ['gb', 'mb', 'kb']
    while size > 1024 and units:
        size /= 1024.0
        unit = units.pop()
    return '{} {}'.format(round(size, 2), unit)


def walk_packets(c10, args={}, include_time=True):
    """Walk a chapter 10 file based on sys.argv (type, channel, etc.)."""

    # Apply defaults.
    args['--type'] = args.get('--type') or ''
    args['--channel'] = args.get('--channel') or ''
    args['--exclude'] = args.get('--exclude') or ''

    # Parse types (if given) into ints.
    types = [t.strip() for t in args['--type'].split(',') if t.strip()]
    types = [int(t, 16) if t.startswith('0x') else int(t) for t in types]

    # Parse channel selection.
    channels = [c.strip() for c in args['--channel'].split(',') if c.strip()]
    exclude = [e.strip() for e in args['--exclude'].split(',') if e.strip()]

    # Filter packets (except time).
    for i, packet in enumerate(c10):
        if include_time and packet.data_type == 0x11:
            yield packet

        channel = str(packet.channel_id)
        if channels and channel not in channels:
            continue
        elif channel in exclude:
            continue
        elif types and packet.data_type not in types:
            continue

        yield packet


class FileProgress(tqdm):
    """Extend tqdm to show progress reading over a file based on f.tell()."""

    def __init__(self, filename=None, total=None, **kwargs):
        if total is None:
            total = os.stat(filename).st_size
        tqdm_kwargs = dict(
            dynamic_ncols=True,
            total=total,
            leave=False,
            unit='bytes',
            unit_scale=True)
        tqdm_kwargs.update(kwargs)
        tqdm.__init__(self, **tqdm_kwargs)
        self.last_tell = 0

    def update_from_tell(self, tell):
        self.update(tell - self.last_tell)
        self.last_tell = tell
# Allow for explicit parser selection, or else use pychapter10 by default. # Format a number nicely with commas for thousands, etc. Take a list of paths and yield paths to Chapter 10 files found at     those locations or subdirectories. Any files in the original list are     returned as-is. Print tabular data to stdout. Numeric fields justified right, others     left. # Make a list of columns (instead of a list of rows) and find max widths. # Width is the sum of the column widths + ~3 padding characters per column. # Header row # Data rows Get a datetime object based on last time packet and an RTC value. # TODO: this is here because the event sample file has no time Convert byte size to a more readable format (mb, etc.). Walk a chapter 10 file based on sys.argv (type, channel, etc.). # Apply defaults. # Parse types (if given) into ints. # Parse channel selection. # Filter packets (except time). Extend tqdm to show progress reading over a file based on f.tell().