Example #1
0
    def _column_value_getter(self, obj):
        """Create callable that returns column values for given object types."""
        if is_namedtuple(obj):
            # Get values using properties
            def get(obj, column):
                return getattr(obj, column, None)

        elif is_dict_like(obj):
            # Get values using dictionary keys
            def get(obj, column):
                return obj.get(column)

        elif is_list_like(obj):
            # Get values using list indexes
            def get(obj, column):
                col = self.column_location(column)
                try:
                    return obj[col]
                except IndexError:
                    return None

        else:
            # Fallback to single column
            def get(obj, _):
                return obj

        return get
Example #2
0
    def __init__(self, data=None, columns=None, index=None):
        self._data = []
        self._columns = []
        self._index = []

        # Use public setters to validate data
        if columns is not None:
            self.columns = list(columns)
        if index is not None:
            self.index = list(index)

        if not data:
            self._init_empty()
        elif isinstance(data, Table):
            self._init_table(data)
        elif is_dict_like(data):
            self._init_dict(data)
        elif is_list_like(data):
            self._init_list(data)
        else:
            raise TypeError("Not a valid input format")

        if columns:
            self._sort_columns(columns)

        self._validate_self()
Example #3
0
def to_options(
    opts: Options, default: Optional[str] = None
) -> Tuple[List[str], Optional[str]]:
    """Convert keyword argument for multiple options into
    a list of strings.

    Also handles default option validation.
    """
    if isinstance(opts, str):
        opts = [opt.strip() for opt in opts.split(",")]
    elif is_list_like(opts):
        opts = [str(opt) for opt in opts]
    else:
        raise ValueError(f"Unsupported options type: {opts}")

    if not opts:
        return [], None

    if default is None:
        default = opts[0]

    if default not in opts:
        raise ValueError(f"Default '{default}' is not in available options")

    return opts, default
Example #4
0
    def _column_name_getter(self, obj):
        """Create callable that returns column names for given obj types."""
        if is_namedtuple(obj):
            # Use namedtuple fields as columns
            def get(obj):
                return list(obj._fields)

        elif is_dict_like(obj):
            # Use dictionary keys as columns
            def get(obj):
                return list(obj.keys())

        elif is_list_like(obj):
            # Use either predefined columns, or
            # generate range-based column values
            predefined = list(self._columns)

            def get(obj):
                count = len(obj)
                if predefined:
                    if count > len(predefined):
                        raise ValueError(
                            f"Data had more than defined {count} columns")
                    return predefined[:count]
                else:
                    return list(range(count))

        else:
            # Fallback to single column
            def get(_):
                return self._columns[:1] if self._columns else [0]

        return get
Example #5
0
def _driver_path(factory: Any, download: bool) -> Optional[Path]:
    if platform.system() != "Windows":
        manager = factory(link_path="/usr/bin")
    else:
        manager = factory()

    driver_names = manager.get_driver_filename()

    if driver_names is None:
        return None

    if not is_list_like(driver_names):
        driver_names = [driver_names]

    primary_path = Path(DRIVER_DIR) / driver_names[0]
    if download or primary_path.exists():
        return primary_path

    for name in driver_names:
        temp_path = Path(DRIVER_DIR) / name
        if temp_path.exists():
            return temp_path

        link_path = Path(manager.link_path) / name
        if link_path.exists():
            return link_path

    return Path(manager.link_path) / driver_names[0]
Example #6
0
    def _validate_index(self, names):
        """Validate that given index names can be used."""
        if not is_list_like(names):
            raise ValueError("Index should be list-like")

        if len(set(names)) != len(names):
            raise ValueError("Duplicate index names")

        if self._data and len(names) != len(self._data):
            raise ValueError("Invalid index length")
Example #7
0
    def _validate_columns(self, names):
        """Validate that given column names can be used."""
        if not is_list_like(names):
            raise ValueError("Columns should be list-like")

        if len(set(names)) != len(names):
            raise ValueError("Duplicate column names")

        if self._data and len(names) != len(self._data[0]):
            raise ValueError("Invalid columns length")
Example #8
0
def _link_paths(manager: Any):
    names = manager.get_driver_filename()

    if names is None:
        return []

    if not is_list_like(names):
        names = [names]

    return [Path(manager.download_root) / name for name in names]
Example #9
0
    def get(self, indexes=None, columns=None, as_list=False):
        """Get values from table. Return type depends on input dimensions.

        If `indexes` and `columns` are scalar, i.e. not lists:
            Returns single cell value

        If either `indexes` or `columns` is a list:
            Returns matching row or column

        If both `indexes` and `columns` are lists:
            Returns a new Table instance with matching cell values

        :param indexes: list of indexes, or all if not given
        :param columns: list of columns, or all if not given
        """
        indexes = if_none(indexes, self._index)
        columns = if_none(columns, self._columns)

        if is_list_like(indexes) and is_list_like(columns):
            return self.get_table(indexes, columns, as_list)
        elif not is_list_like(indexes) and is_list_like(columns):
            return self.get_row(indexes, columns, as_list)
        elif is_list_like(indexes) and not is_list_like(columns):
            return self.get_column(columns, indexes, as_list)
        else:
            return self.get_cell(indexes, columns)
Example #10
0
    def _sort_by(self, values, reverse=False):
        """Sort index and data by using `values` as sorting criteria."""
        assert is_list_like(values)
        assert len(values) == len(self._data)

        def sorter(row):
            """Sort table by given values, while allowing for disparate types.
            Order priority:
                - Values by typename
                - Numeric types
                - None values
            """
            criteria = []
            for value in row[1]:  # Ignore enumeration
                criteria.append(
                    (
                        value is not None,
                        "" if isinstance(value, Number) else type(value).__name__,
                        value,
                    )
                )
            return criteria

        # Store original index order using enumerate() before sort, and
        # use it to sort index/data later
        values = sorted(enumerate(values), key=sorter, reverse=reverse)
        idxs = [value[0] for value in values]

        # Re-order index, and update range-based values
        indexes = []
        for idx_new, idx_old in enumerate(idxs):
            index = self._index[idx_old]
            if isinstance(index, int):
                indexes.append(idx_new)
            else:
                indexes.append(index)

        # Re-order data
        self._data = [self._data[idx] for idx in idxs]
Example #11
0
def to_list(obj, size=1):
    """Convert (possibly scalar) value to list of `size`."""
    if not is_list_like(obj):
        return [obj] * int(size)
    else:
        return obj