Skip to content

London | 26-SDC-Mar | Khilola Rustamova| Sprint 4 |Implement shell tools python#537

Open
HilolaRustam wants to merge 8 commits into
CodeYourFuture:mainfrom
HilolaRustam:implement-shell-tools-python
Open

London | 26-SDC-Mar | Khilola Rustamova| Sprint 4 |Implement shell tools python#537
HilolaRustam wants to merge 8 commits into
CodeYourFuture:mainfrom
HilolaRustam:implement-shell-tools-python

Conversation

@HilolaRustam

@HilolaRustam HilolaRustam commented Jun 10, 2026

Copy link
Copy Markdown

Learners, PR Template

Self checklist

  • I have titled my PR with Region | Cohort | FirstName LastName | Sprint | Assignment Title
  • My changes meet the requirements of the task
  • I have tested my changes
  • My changes follow the style guide

Changelist

implementation of cat, ls and wc with python

@HilolaRustam HilolaRustam added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. Module-Tools The name of the module. 📅 Sprint 3 Assigned during Sprint 3 of this module labels Jun 10, 2026
@illicitonion illicitonion added Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Jun 10, 2026

@illicitonion illicitonion left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is generally looking good, and like things work :) I left a few style comments, and many of my comments to one project apply to the others as well.

Comment thread implement-shell-tools/cat/mycat.py Outdated
return sorted(files)

def read_lines(file):
with open(file, "r", encoding="utf-8") as f:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This block is more indented than the others - why is that?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was an accident, i have aligned it.

try:
lines = read_lines(file)
except FileNotFoundError:
print(f"cat: {file}: No such file or directory", file=sys.stderr)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good job printing to stderr not stdout :)

However! If you ran into an issue here, I think your program will still exit with exit code 0. What exit code do you think it should exit with?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right. A missing file should result in a non-zero exit code to indicate an error. I've updated the code to exit with code 1 if any file cannot be read.

Comment thread implement-shell-tools/cat/mycat.py Outdated
sys.stdout.write(prefix + line)


def main():

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This all works, but often people will have their main function at the top of the file so it's the first thing you read, and allow you to scroll down to read details if needed. You don't need to follow this, but it can often make it easier to read/review code.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you, I've moved main() higher in the file to make the program flow easier to see.

Comment thread implement-shell-tools/cat/mycat.py Outdated
paths.append(a)

files = expand_paths(paths)
print_lines(files, number_all,number_nonempty)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've noticed your whitespace is a bit inconsistent (e.g. no space after this ,) - you may want investigate a tool like black to help automate fixing this.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for your suggestion. I've cleaned up the whitespace issues and I'll take a look at Black for automatic formatting

Comment thread implement-shell-tools/cat/mycat.py Outdated
number_all = True
elif a == "-b":
number_nonempty = True
number_all = False #-b overrides -n

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What would happen if -b appeared before -n in the command line?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've changed the flag handling so -b always takes precedence regardless of argument order.

Comment thread implement-shell-tools/cat/mycat.py Outdated
paths.append(a)

files = expand_paths(paths)
print_lines(files, number_all,number_nonempty)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We often used named arguments in Python when we have multiple arguments of the same type, to make sure we don't accidentally pass them in the wrong order. If you wrote print_lines(files, number_nonempty, number_all) here it wouldn't be obvious that the order was swapped. Instead we can write:

print_lines(files, number_all=number_all, number_nonempty=number_nonempty)

and if we swapped them by mistake it would be obvious.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That makes sense. I've updated the call to use named arguments

Comment thread implement-shell-tools/ls/my-ls.py Outdated
def list_dir(path, show_all=False, one_per_line = False):
try:
entries = os.listdir(path)
except FileNotFoundError:

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same question as above about exit codes.

@illicitonion illicitonion added Reviewed Volunteer to add when completing a review with trainee action still to take. and removed Review in progress This review is currently being reviewed. This label will be replaced by "Reviewed" soon. labels Jun 10, 2026
@HilolaRustam HilolaRustam added Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. and removed Reviewed Volunteer to add when completing a review with trainee action still to take. labels Jun 11, 2026

@illicitonion illicitonion left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks really good, well done!

Comment on lines +17 to +26
for a in args:
if a == "-n":
number_all = True
elif a == "-b":
number_nonempty = True
else:
paths.append(a)

if number_nonempty:
number_all = False

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This kind of relationship where different options/states are related but exclusive can be hard to follow. (Here, it should never be the case that number_all and number_nonempty are both True - it's an invalid state in the program).

Instead of this, we sometimes use enums for this (or can use strings as enums). Consider a single variable number_mode which could be set to either "none", "non_empty" or "all" - here we don't need to think about what both True mean - we just have one variable which could have one of three variables. What do you think about this?


return line_count, word_count, byte_count

def expand(paths):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general you shouldn't need to do this kind of glob expansion yourself - the shell should do this for you and expand the globs into different file names when calling your program. You can test this out by printing what sys.argv is when you run python3 my-wc.py some*glob - look at what arguments you actually get :)

try:
l, w, c = count_file(file)
except FileNotFoundError:
print(f"wc: {file}: No such file or directory", file=sys.stderr)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What exit code will you exit with if you failed to read one file?

@illicitonion illicitonion changed the title London | 26-SDC-Mar | Khilola Rustamova| Sprint 3 |Implement shell tools python London | 26-SDC-Mar | Khilola Rustamova| Sprint 4 |Implement shell tools python Jun 11, 2026
@illicitonion illicitonion added Reviewed Volunteer to add when completing a review with trainee action still to take. and removed Needs Review Trainee to add when requesting review. PRs without this label will not be reviewed. labels Jun 11, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Module-Tools The name of the module. Reviewed Volunteer to add when completing a review with trainee action still to take. 📅 Sprint 3 Assigned during Sprint 3 of this module

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants