Python Cmdparser Module

Sometimes, we have to write commands using the command prompt terminal, and this terminal which interprets the inline commands written for various purposes, is called command interpreters. We can write and build a framework which we will use to write line-oriented command interpreters, and for achieving this task, sometimes we have to use classes. A class that provides a framework for command interpreters so that we can write line-oriented commands is known as the cmd class. Now, many of us wonder what the uses of cmd class and how it is helpful to us are. A cmd class is very useful for creating prototypes, test harnesses that will be later wrapped, and administrative tools present in a more sophisticated manner. Therefore, to perform all these tasks and create these tools, we have to use a command-line interface, and this can be easily built using a cmd class.

The use of command-line interpreters has become very rare because Graphical User Interface (GUI) in most applications has been increased nowadays. Therefore, users are more attracted to using these applications only instead of using a simple line-oriented command interpreter but using a command-line interface has its own advantages.

Following are the several advantages of using a command-line interface or interpreter:

  • These command-line interpreters don't have any GUI-based interfaces; that's why CPU and memory resources far from cheaper computers are also available.
  • Creating a text-oriented document with the command-line interpreter is very easy, and we can create it very fastly.
  • As the command line interpreters are portable, therefore, we can run them anywhere on any device.
  • It is very easy to open a file in the command line interpreter, and this method is way faster than getting into drivers and searching into the menu for files.

These are some major advantages of command-line interpreters, and that's why most users even today prefer them over many GUI-based applications whose interfaces are way more attractive. After seeing these advantages, we can understand and conclude that it is how much useful to build a command-line interpreter with the cmd class. It will not only help us in our professional life and professional tasks, but it will also be helpful in our personal projects. Many of us would be surprised to hear that the cmd class is also present in the Python packages, and therefore it is possible to create a framework for command-line interface using a Python program. We are going to learn about the Cmdparser module in Python in which we will see the use of cmd class, and we will build a framework for command line interpreter using this module.

Cmdparser Module in Python

Cmdparser Module is a Python package that comes with two sub-modules in it which are very useful for us to write text command parsers and create a framework for the command-line interface. Cmdparser Module also uses the cmd class & functions of this in it, and we will use these functions in the programs to build a parse tree to perform name matching operation. Cmdparser Module in Python uses the built-in cmd module of Python and calls it for creating a framework for the command-line interface.

The Cmdparser Module of Python contains the two sub-modules or Python packages that are following:

  • datetimeparse
  • cmdparser

In this tutorial, we will learn about the implementation and working of both sub-modules of the Cmdparser package and use them in a Python program to create a simple parse tree.

Cmdparser Module: Installation

If we want to use functions and sub-modules of the Cmdparser Module in a Python program, we should ensure that this module is present in our system because it is not an in-built module of Python. Therefore, if the Cmdparser Module is not already present in our system, we have to install it to move further with the implementation part of its sub-modules. We can install the Cmdparser Module through various installation processes, but here we will use the pip installer to perform this task because it is the easiest and simplest way to do it.

Write the following command in the terminal shell to install the Cmdparser Module in our system through pip installer:

After writing the command given above, we have to press the enter key and wait for some time as it will take a while to install this module successfully.

Python Cmdparser Module

The Cmdparser Module is now successfully installed in our system as we can see that, and now, we can work with it and its sub-modules by importing it into the program. We will first look at the overview and implementation of the cmdparser sub-module of the Cmdparser package, and then we will go through the overview of the datetimeparser sub-module.

Cmdparser Module: Overview of cmdparser sub-module:

cmdparser sub-module from the Cmdparser package of Python allows us to create parse tree structure with the help of textual command specifications like the one given below:

We can check this particular command string using the parse tree structures. The cmdparser sub-module also allows us to validate partial command strings' completion to be listed for the parse tree. Let's understand this concept by making a parse tree from a Python program using the textual command specification we have listed above.

Example: Look at the following Python program where we have created a parse tree from the cmdparser sub-module and then matched tokens with the parse tree:

Output:

"command invalid somewhere in: 'uvwx'"
{'efgh', 'ijkl'}

Python Cmdparser Module

Explanation:

We have first imported the cmdparser sub-module from the cmdparser package to create a parse tree with tokens in the program. After that, we have created a sample parse tree in the parseTree variable using the parse_spec() function from the cmdparser package. Inside the parse tree, we have only defined static tokens and used them later for matching. After that, we used the parse_match() of the cmdparser package to match the tokens from the parse tree we defined. In the second matching, the parse tree will throw an error as "uvwx" is not a static token defined in the package. In last, we used the parse_completions() function to complete the rest of the tokens from the parse tree. This function will print the rest of the static tokens of the parse tree in the output.

Now, as we can see in the output, the rest of the static tokens from the parse is printed, and before that, an error for the "uvwx" token is also printed.

We used static tokens in the parse, which we have created in the example given above, but we can also create parse trees with the help of dynamic tokens using the Cmdparser Module. While we are creating a parse tree having dynamic tokens in it, we can set up the dynamic tokens where the list of strings is accepted, and this list of strings in the dynamic tokens changes over time. We can also use dynamic tokens where the arbitrary string or list of strings can be accepted while we are dealing with a fixed token string. If we want to look at the specifications of all the classes available in the Cmdparser Module for setting up dynamic tokens, we can check the docstrings of the module. Here, we will understand this by creating a parse tree with dynamic tokens using the Cmdparser Module classes. Look at the following example where we created a parse tree using dynamic tokens from the Cmdparser Module.

Example 2: Look at the following Python program where we created a parse tree with dynamic tokens to accept a dynamic list of strings:

Output:

"'all' is not a valid "
{'apple',
 'banana',
 'grapes',
 'greenapple',
 'guava',
 'lichi',
 'mango',
 'melon',
 'orange',
 'strawberry',
 'watermelon'}

Python Cmdparser Module

Explanation:

After importing the cmdparser sub-module package from the Cmdparser Module, we created a class with fruit names as tokens of the parse tree in the program. The fruit names we defined inside the 'tokenOfFurits' class will work as the static tokens of the parse tree, and for retrieving the values of fruit names from the class, we have defined a default function inside the class. Then, we have defined another function (myIdentificationFactory) that will accept dynamic tokens in the parse tree, and it will accept numeric values (numbers) as matching values. To set up dynamic tokens with a numeric value, we used IntegerToken() function from the Cmdparser package, and thus it will make this a dynamic token that will accept any integer value as a matching value from the parse tree. After that, we used parse_spec() function to create the parse tree having number and fruit as dynamic tokens and "keep" & "packet" as static tokens. Then, we used the check_match() function and gave token values in it to perform the matching operation from the parse tree. We can see in the output that when we haven't provided a number, it will throw a matching error. In last, when we used the get_completions() function with the parse tree, all the fruit values used as a token is printed in the output.

Classes in the cmdparser sub-module:

Following are the four classes available inside the cmdparser sub-package that are suitable as base classes for creating user-derived tokens (static as well as dynamic):

  • Token: Token is the base class from the cmdparser sub-package, and it is useful when one of the sets of fixed values is suitable in the parse tree we are creating. In the parse tree, where the list of string values can be static or dynamic, this class can be used to create and accept tokens. We have to override the get_values() method if we want to return a list of valid tokens as a list of strings from the parse tree in the result.
  • AnyToken: This base class is similar to the Token class of the sub-package, but any string is to be expected in the result while using the AnyToken base class. If we want to perform validation of the tokens, we can do this via the validate() method available in the sub-module. But, before using the validate() method, we should note that validate() method doesn't allow the tab-completion because it is called only during the entire command is parsed. AnyToken base class also requires the convert() method while calling the list of strings (both static and dynamic).
  • AnyTokenString: The AnyTokenString base class is very similar to the AnyToken class in terms of the function performed by both base classes. But, in the AnyTokenString class, all the remaining items from the values we defined on the command line are consumed during the parsing.
  • Subtree: The subtree base class from the cmdparser sub-package matches the entire command from the parse tree we created and stores the result of the matching process against the specified token in the dictionary fields. While using the subtree class, we have to pass the command specification string to the class's constructor, and then type classes will override the convert() method to interpret the command.

Cmdparser Module: Overview of datetimeparser Sub-Module:

Datetimeparser sub-module from the Cmdparser package adds some specific token types in the creation of parse tree, which will help to parse human-readable specifications related to date and time format. In the datetimeparser sub-module, both absolute and relative types of dates are specified, and these types can be converted to other instances also whenever required and as appropriate.

Following are the examples of types of dates in the datetimeparser sub-module:

  • 02 November 2020
  • 01: 28 on Thursday last week etc.

Classes in the datetimeparser Sub-Module:

Following are the five classes available inside the datetimeparser sub-package of the Cmdparser Module that is suitable as base classes for creating user-derived tokens (static as well as dynamic):

  • TimeSubtree: TimeSubtree class of the datetimeparser sub-module is used to parse the time of a day given in 12 or 24-hour format inside a parse tree. The returned value after parsing the time given is as returned with the help of time.localtime() function.
  • DateSubtree: DateSubtree class from the datetimeparser sub-module acts similar to the TimeSubtree class. DateSubtree class includes literals for the different date formats, i.e., days from a week related to the current day (Monday last week), literal date (01-11-2021), descriptive date version (01-November-2021), as well as today, yesterday, and tomorrow along with parse calendar dates. The return value in the case of DateSubtree class is the datetime.date instance from the parse tree.
  • DateTimeSubtree: After reading the description of the first two base classes of the datetimeparser sub-module, we can get a basic idea of DateTimeSubtree class by its name. DateTimeSubtree class parses specifications from both date and time given in the parse tree. DateTimeSubtree accepts a combination of TimeSubtree and DateSubtree phrases or a phrase of RelativeTimeSubtree class (We will read next about this class) to parse the specifications of both date and time. In the case of a phrase is from RelativeTimeSubtree class, the time is taken in the relative format according to the time given. The returned value for the DateTimeSubtree class is the datetime.datetime instance value.
  • RelativeTimeSubtree: The RelativeTimeSubtree base class from the datetimeparser sub-module returns from the wrapper class as its return value. The RelativeTimeSubtree class is used to parse phrases given in the format, which indicates a time offset from the present time, such as two days ago, three hours ago, etc. The returned value in the case of RelativeTimeSubtree class is an instance of cmdparser.DateDelta class (A wrapper class from the datetimeparser sub-module) contains a datetime.timedelta instance.
  • CLassCalenderPeriodSubtree: The CLassCalenderPeriodSubtree is the last base class from the datetimeparser sub-module, and it parses the specification of calender periods given from the past. The return value in the case of this class is 2-tuple of instances from the datetime.date, which represents the following in the return value format: ranges of date specified from the calendar, where the first date from the range is inclusive and the second date from the range is exclusive etc.

Conclusion

We read about Cmdparser Module in this tutorial, and we learned how we could create an interface of cmdparser using the packages of this Module. We learned about both cmdparser and datetimeparser sub-modules of the Cmdparser package in Python and how these are helpful in creating tokens for the parse tree. In last, we looked at the base classes of both sub-modules of the Cmdparser package and learned how these classes are helpful in parsing the specifications given for a token of the parse tree.