pseek 3.7.0__tar.gz → 3.7.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pseek
3
- Version: 3.7.0
3
+ Version: 3.7.1
4
4
  Classifier: Development Status :: 5 - Production/Stable
5
5
  Classifier: Environment :: Console
6
6
  Classifier: Intended Audience :: Developers
@@ -273,6 +273,8 @@ psk backup --directory
273
273
  psk TODO --content
274
274
  ```
275
275
 
276
+ > **Note:** When searching through file contents, binary files are automatically ignored, and this behavior cannot be changed. If null bytes are present within the first 8 KiB of a file, it is identified as a binary file (The entire file is not examined, in order to increase speed).
277
+
276
278
  ### Search Everywhere
277
279
 
278
280
  ```bash
@@ -757,12 +759,12 @@ Controls how deep the search goes inside directories.
757
759
  A depth of `0` means that only base path's immediate contents are searched; subdirectories are not entered.
758
760
 
759
761
  ```text
760
- project/ ← base directory
761
- ├── file.txt ← depth 0
762
- ├── folder1/ ← depth 0
763
- │ ├── file.txt ← depth 1
764
- │ └── folder2/ ← depth 1
765
- │ └── file.txt ← depth 2
762
+ project/ <- base directory
763
+ ├── file.txt <- depth 0
764
+ ├── folder1/ <- depth 0
765
+ │ ├── file.txt <- depth 1
766
+ │ └── folder2/ <- depth 1
767
+ │ └── file.txt <- depth 2
766
768
  ```
767
769
 
768
770
  `--depth` can be specified multiple times to search non-contiguous depth ranges:
@@ -965,7 +967,7 @@ If the search exceeds the limit, it will be terminated. Results found before the
965
967
  Display a summary of the search, including result counts, scanned paths, archive information, and search time.
966
968
 
967
969
  ```bash
968
- pseek config --stats
970
+ pseek config --archive --stats
969
971
  ```
970
972
 
971
973
  Example output:
@@ -974,7 +976,7 @@ Example output:
974
976
  Statistics
975
977
  ────────────────
976
978
  Results
977
- Files: 12
979
+ Files matched: 12
978
980
  Directories matched: 3
979
981
  Files with matched content: 8
980
982
  Lines matched: 24
@@ -245,6 +245,8 @@ psk backup --directory
245
245
  psk TODO --content
246
246
  ```
247
247
 
248
+ > **Note:** When searching through file contents, binary files are automatically ignored, and this behavior cannot be changed. If null bytes are present within the first 8 KiB of a file, it is identified as a binary file (The entire file is not examined, in order to increase speed).
249
+
248
250
  ### Search Everywhere
249
251
 
250
252
  ```bash
@@ -729,12 +731,12 @@ Controls how deep the search goes inside directories.
729
731
  A depth of `0` means that only base path's immediate contents are searched; subdirectories are not entered.
730
732
 
731
733
  ```text
732
- project/ ← base directory
733
- ├── file.txt ← depth 0
734
- ├── folder1/ ← depth 0
735
- │ ├── file.txt ← depth 1
736
- │ └── folder2/ ← depth 1
737
- │ └── file.txt ← depth 2
734
+ project/ <- base directory
735
+ ├── file.txt <- depth 0
736
+ ├── folder1/ <- depth 0
737
+ │ ├── file.txt <- depth 1
738
+ │ └── folder2/ <- depth 1
739
+ │ └── file.txt <- depth 2
738
740
  ```
739
741
 
740
742
  `--depth` can be specified multiple times to search non-contiguous depth ranges:
@@ -937,7 +939,7 @@ If the search exceeds the limit, it will be terminated. Results found before the
937
939
  Display a summary of the search, including result counts, scanned paths, archive information, and search time.
938
940
 
939
941
  ```bash
940
- pseek config --stats
942
+ pseek config --archive --stats
941
943
  ```
942
944
 
943
945
  Example output:
@@ -946,7 +948,7 @@ Example output:
946
948
  Statistics
947
949
  ────────────────
948
950
  Results
949
- Files: 12
951
+ Files matched: 12
950
952
  Directories matched: 3
951
953
  Files with matched content: 8
952
954
  Lines matched: 24
@@ -49,7 +49,7 @@ def build_highlight(text, matches):
49
49
  return ''.join(parts)
50
50
 
51
51
 
52
- def echo(results: dict, context: bool):
52
+ def echo(results: dict, context: tuple[int, int]):
53
53
  """Display results with a specific format and color scheme"""
54
54
  for match_type, datas in results.items():
55
55
  if datas:
@@ -258,7 +258,7 @@ def search_with_timeout(config):
258
258
  time.sleep(0.0005)
259
259
 
260
260
 
261
- def check_rar_backend(archive_enabled: bool, tool_path: str, backend: str):
261
+ def check_rar_backend(archive_enabled: bool, tool_path: str | None, backend: str):
262
262
  """Check for the existence of rar backend or save and set it for rarfile"""
263
263
 
264
264
  # Save backend path for later executions
@@ -7,6 +7,8 @@ from itertools import islice
7
7
  from pathlib import Path
8
8
  from threading import RLock
9
9
 
10
+ import click
11
+
10
12
  from pseek import _pignore
11
13
 
12
14
  from .archive import ARCHIVE_EXTS, extract_names_from_archive, extract_text_from_archive
@@ -378,6 +380,20 @@ def is_symlink_valid(entry):
378
380
  return True
379
381
 
380
382
 
383
+ def needs_ignore_matcher(config) -> bool:
384
+ # In cases where all paths must be searched and
385
+ # there are no filtering rules,
386
+ # there is no need to create matcher.
387
+ return (
388
+ not config.hidden
389
+ or not config.no_git_ignore
390
+ or not config.no_ignore_dot
391
+ or not config.no_ignore_exclude
392
+ or not config.no_ignore_global
393
+ or bool(config.glob)
394
+ )
395
+
396
+
381
397
  def walk_logic(path: Path, config, depth: int, matcher, ancestors: set):
382
398
  """Recursively walk a directory while pruning excluded subtrees"""
383
399
 
@@ -411,18 +427,27 @@ def walk_logic(path: Path, config, depth: int, matcher, ancestors: set):
411
427
  continue
412
428
  is_dir = False
413
429
 
414
- # Ignore rules / hidden filtering / glob logic
415
- absolute_entry = (
416
- Path(os.path.abspath(entry_path))
417
- if not config.absolute_path else entry_path
418
- ).as_posix()
419
- ignored, whitelisted, should_descend = (
420
- matcher.match_path(
421
- absolute_entry,
422
- # We don't need target of symlink; symlink itself is always a file
423
- is_dir if not entry.is_symlink() else False
424
- )
425
- )
430
+ if matcher is None:
431
+ ignored = False
432
+ whitelisted = False
433
+ should_descend = is_dir
434
+ else:
435
+ # Ignore rules / hidden filtering / glob logic
436
+
437
+ absolute_entry = (
438
+ Path(os.path.abspath(entry_path))
439
+ if not config.absolute_path
440
+ else entry_path
441
+ ).as_posix()
442
+
443
+ try:
444
+ ignored, whitelisted, should_descend = matcher.match_path(
445
+ absolute_entry,
446
+ # We don't need target of symlink; symlink itself is always a file
447
+ is_dir if not entry.is_symlink() else False,
448
+ )
449
+ except RuntimeError:
450
+ continue
426
451
 
427
452
  if ignored:
428
453
  continue
@@ -433,7 +458,12 @@ def walk_logic(path: Path, config, depth: int, matcher, ancestors: set):
433
458
  # This flag is used in seek func to indicate that this dir
434
459
  # doesn't need to be displayed, even though it must still
435
460
  # be included in metric calculation.
436
- metric_only = is_dir and matcher.has_positive_globs and not whitelisted
461
+ metric_only = (
462
+ is_dir
463
+ and matcher is not None
464
+ and matcher.has_positive_globs
465
+ and not whitelisted
466
+ )
437
467
 
438
468
  # A symlink may be a valid filename-search candidate even
439
469
  # when its target is not followed or cannot be resolved.
@@ -462,6 +492,7 @@ def walk(config):
462
492
  """Include paths define traversal roots, avoiding unnecessary traversal
463
493
  of unrelated parts of the tree"""
464
494
  roots = config.include or {config.path}
495
+ needs_matcher = needs_ignore_matcher(config)
465
496
 
466
497
  for root in roots:
467
498
  depth = len(root.relative_to(config.path).parts) - 1
@@ -473,18 +504,27 @@ def walk(config):
473
504
  yield root.resolve(), False
474
505
 
475
506
  if root.is_dir() and any(depth < d[1] for d in config.depth):
476
- matcher = _pignore.IgnoreMatcher(
477
- Path(os.path.abspath(root)).as_posix(),
478
- git_ignore=not config.no_git_ignore,
479
- ignore=not config.no_ignore_dot,
480
- git_exclude=not config.no_ignore_exclude,
481
- git_global=not config.no_ignore_global,
482
- parents=not config.no_ignore_parent,
483
- require_git=not config.no_require_git,
484
- hidden=not config.hidden,
485
- globs=list(config.glob) or None,
486
- glob_root=config.path.as_posix()
487
- )
507
+ matcher = None
508
+
509
+ if needs_matcher:
510
+ try:
511
+ matcher = _pignore.IgnoreMatcher(
512
+ Path(os.path.abspath(root)).as_posix(),
513
+ git_ignore=not config.no_git_ignore,
514
+ ignore=not config.no_ignore_dot,
515
+ git_exclude=not config.no_ignore_exclude,
516
+ git_global=not config.no_ignore_global,
517
+ parents=not config.no_ignore_parent,
518
+ require_git=not config.no_require_git,
519
+ hidden=not config.hidden,
520
+ globs=list(config.glob) or None,
521
+ glob_root=config.path.as_posix()
522
+ )
523
+ except ValueError as e:
524
+ raise click.BadParameter(e, param_hint='--glob')
525
+ except RuntimeError as e:
526
+ click.secho(e, fg='red')
527
+ raise click.exceptions.Exit(1)
488
528
 
489
529
  yield from walk_logic(root, config, depth, matcher, set())
490
530
 
@@ -24,7 +24,7 @@ def compile_regex(txt, flags=0) -> re.Pattern | None:
24
24
  raise click.exceptions.Exit(1)
25
25
 
26
26
 
27
- def get_path_suffix(path: Path | str, is_dir: bool | None = None) -> str:
27
+ def get_path_suffix(path: Path | str, is_dir: bool | None = None) -> str | None:
28
28
  """ If multiple file suffixes are valid, return them, otherwise return only the last suffix """
29
29
  if isinstance(path, str):
30
30
  path = Path(path)
@@ -4,7 +4,7 @@ build-backend = "maturin"
4
4
 
5
5
  [project]
6
6
  name = "pseek"
7
- version = "3.7.0"
7
+ version = "3.7.1"
8
8
  description = "Pseek is a Python CLI toolkit to search files, folders, and text"
9
9
  readme = "README.md"
10
10
  license = "MIT"
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes