Skip to content

Switch to using arg map for testing args #22076

Closed as not planned
Closed as not planned

Description

Connor Peet (@connor4312) has written a great way to handle command line args for js-debug here. This should be incorporated into how testing args are handled as it is cleaner and would be easier to then add and remove args as needed. (Yes we should no longer be manipulating args to the extent we were before but something like adding --collect-only or checking for --color=no are both still applicable)

Connor's code with annotation

/**
 * Converts an array of strings (with or without '=') into a map. 
 * If a string contains '=', it is split into a key-value pair, with the portion 
 * before the '=' as the key and the portion after the '=' as the value.
 * If no '=' is found in the string, the entire string becomes a key with a value of null.
 *
 * @param args - Readonly array of strings to be converted to a map.
 * @returns A map representation of the input strings.
 */
const argsToMap = (args: ReadonlyArray<string>) => {
  const map: { [key: string]: string | null } = {};
  for (const arg of args) {
    const delimiter = arg.indexOf('=');
    if (delimiter === -1) {
      map[arg] = null;
    } else {
      map[arg.slice(0, delimiter)] = arg.slice(delimiter + 1);
    }
  }

  return map;
};

/**
 * Converts a map into an array of strings. 
 * Each key-value pair in the map is transformed into a string.
 * If the value is null, only the key is represented in the string. 
 * If the value is defined (and not null), the string is in the format "key=value". 
 * If a value is undefined, the key-value pair is skipped.
 *
 * @param map - The map to be converted to an array of strings.
 * @returns An array of strings representation of the input map.
 */
const mapToArgs = (map: { [key: string]: string | null | undefined }) => {
  const out: string[] = [];
  for (const key of Object.keys(map)) {
    const value = map[key];
    if (value === undefined) {
      continue;
    }

    out.push(value === null ? key : `${key}=${value}`);
  }

  return out;
};

New method to add arg when not already present

/**
 * Adds an argument to the map only if it doesn't already exist.
 * 
 * @param map - The map of arguments.
 * @param argKey - The argument key to be checked and added.
 * @param argValue - The value to set for the argument if it's not already in the map.
 * @returns The updated map.
 */
function addArgIfNotExist(
    map: { [key: string]: string | null | undefined },
    argKey: string,
    argValue: string | null
): { [key: string]: string | null | undefined } {
    // Only add the argument if it doesn't exist in the map.
    if (map[argKey] === undefined) {
        map[argKey] = argValue;
    }

    return map;
}

Activity

  1. drothlis commented on Mar 12, 2024

    @drothlis

    This (merged in #22885) breaks legitimate arguments to pytest, e.g. #22999 (comment)).

    It simply isn't possible to parse unix command-line arguments unless you know what the program expects. For example:

    pytest --ignore file1 --ignore file2
    

    You have to know that (for pytest, specifically) --ignore consumes 1 parameter; you can't tell just from looking at the arguments.

  2. added 2 commits that reference this issue on Mar 28, 2024
  3. eleanorjboyd commented on Apr 25, 2024

    @eleanorjboyd
    MemberAuthor

    I reverted this in a previous commit- it was not a viable solution for the given use case

  4. locked as resolved and limited conversation to collaborators on May 26, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions