entangled-cli 2.0.2__tar.gz → 2.0.4__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.
Files changed (41) hide show
  1. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/PKG-INFO +6 -2
  2. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/README.md +3 -0
  3. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/new.py +1 -1
  4. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/status.py +3 -0
  5. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/config/language.py +2 -1
  6. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/construct.py +35 -10
  7. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/status.py +13 -2
  8. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/pyproject.toml +4 -2
  9. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/LICENSE +0 -0
  10. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/__init__.py +0 -0
  11. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/code_reader.py +0 -0
  12. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/__init__.py +0 -0
  13. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/brei.py +0 -0
  14. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/stitch.py +0 -0
  15. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/sync.py +0 -0
  16. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/tangle.py +0 -0
  17. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/commands/watch.py +0 -0
  18. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/config/__init__.py +0 -0
  19. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/config/templates.py +0 -0
  20. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/config/version.py +0 -0
  21. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/document.py +0 -0
  22. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/errors/__init__.py +0 -0
  23. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/errors/internal.py +0 -0
  24. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/errors/user.py +0 -0
  25. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/filedb.py +0 -0
  26. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/hooks/__init__.py +0 -0
  27. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/hooks/base.py +0 -0
  28. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/hooks/build.py +0 -0
  29. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/hooks/quarto_attributes.py +0 -0
  30. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/hooks/task.py +0 -0
  31. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/logging.py +0 -0
  32. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/main.py +0 -0
  33. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/markdown_reader.py +0 -0
  34. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/parsing.py +0 -0
  35. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/properties.py +0 -0
  36. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/py.typed +0 -0
  37. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/tangle.py +0 -0
  38. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/text_location.py +0 -0
  39. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/transaction.py +0 -0
  40. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/utility.py +0 -0
  41. {entangled_cli-2.0.2 → entangled_cli-2.0.4}/entangled/version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: entangled-cli
3
- Version: 2.0.2
3
+ Version: 2.0.4
4
4
  Summary: Literate Programming toolbox
5
5
  Home-page: https://entangled.github.io/
6
6
  License: Apache 2
@@ -13,9 +13,10 @@ Classifier: Programming Language :: Python :: 3.11
13
13
  Classifier: Programming Language :: Python :: 3.12
14
14
  Requires-Dist: argh (>=0.30,<0.31)
15
15
  Requires-Dist: brei (>=0.2.3,<0.3.0)
16
- Requires-Dist: copier (>=8.3.0,<9.0.0)
16
+ Requires-Dist: copier (>=9,<10)
17
17
  Requires-Dist: filelock (>=3.12.0,<4.0.0)
18
18
  Requires-Dist: mawk (>=0.1.4,<0.2.0)
19
+ Requires-Dist: pexpect (>=4.9.0,<5.0.0)
19
20
  Requires-Dist: rich (>=13.3.5,<14.0.0)
20
21
  Requires-Dist: rich-argparse (>=1.4.0,<2.0.0)
21
22
  Requires-Dist: tomlkit (>=0.12.1,<0.13.0)
@@ -122,6 +123,9 @@ version = "2.0"
122
123
 
123
124
  # default watch_list is ["**/*.md"]
124
125
  watch_list = ["docs/**/*.md"]
126
+
127
+ # default ignore_list is ["**/README.md"]
128
+ ignore_list = ["docs/**/examples.md"]
125
129
  ```
126
130
 
127
131
  You may add languages as follows:
@@ -97,6 +97,9 @@ version = "2.0"
97
97
 
98
98
  # default watch_list is ["**/*.md"]
99
99
  watch_list = ["docs/**/*.md"]
100
+
101
+ # default ignore_list is ["**/README.md"]
102
+ ignore_list = ["docs/**/examples.md"]
100
103
  ```
101
104
 
102
105
  You may add languages as follows:
@@ -123,7 +123,7 @@ def new(
123
123
  "Please supply both a [template] and a [project_path].\n", print_help
124
124
  )
125
125
 
126
- copy_this_template: Optional[str] = template
126
+ copy_this_template: str = template
127
127
  trust_this_template: bool = trust
128
128
 
129
129
  # Use an officially supported template, if available, and trust it
@@ -31,6 +31,9 @@ def rich_status():
31
31
  config_table.add_row(
32
32
  "Watch list", ", ".join(f"'{pat}'" for pat in config.watch_list)
33
33
  )
34
+ config_table.add_row(
35
+ "Ignore list", ", ".join(f"'{pat}'" for pat in config.ignore_list)
36
+ )
34
37
  config_table.add_row("Hooks enabled", ", ".join(config.hooks))
35
38
 
36
39
  console = Console(color_system="auto")
@@ -46,5 +46,6 @@ languages = [
46
46
  Language("F#", ["fsharp"], Comment("//")),
47
47
  Language("Javascript", ["javascript", "js", "ecma"], Comment("//")),
48
48
  Language("Go", ["go", "golang"], Comment("//")),
49
- Language("R", ["r", "rlang"], Comment("#"))
49
+ Language("R", ["r", "rlang"], Comment("#")),
50
+ Language("Nix", ["nix"], Comment("#"))
50
51
  ]
@@ -27,7 +27,7 @@ class FromStr:
27
27
  def construct(annot: Any, json: Any) -> Any:
28
28
  try:
29
29
  return _construct(annot, json)
30
- except (AssertionError, ValueError, KeyError) as e:
30
+ except (AssertionError, ValueError, KeyError, TypeError) as e:
31
31
  raise ConfigError(annot, json) from e
32
32
 
33
33
 
@@ -47,6 +47,10 @@ def is_optional_type(dtype: Type[Any]) -> TypeGuard[Type[Optional[Any]]]:
47
47
  )
48
48
 
49
49
 
50
+ def normalize_enum(x: str):
51
+ return x.upper().replace("-", "_")
52
+
53
+
50
54
  def _construct(annot: Type[T], json: Any) -> T:
51
55
  """Construct an object from a given type from a JSON stream.
52
56
 
@@ -70,14 +74,35 @@ def _construct(annot: Type[T], json: Any) -> T:
70
74
  )
71
75
  if annot is Any:
72
76
  return cast(T, json)
73
- # if annot is dict or isgeneric(annot) and typing.get_origin(annot) is dict:
74
- # assert isinstance(json, dict)
75
- # return json
76
- if annot is Path and isinstance(json, str):
77
- return cast(T, Path(json))
77
+
78
+ # dicts
79
+ if isgeneric(annot) and typing.get_origin(annot) is dict:
80
+ assert isinstance(json, dict)
81
+ return cast(T, {construct(typing.get_args(annot)[0], k): construct(typing.get_args(annot)[1], v)
82
+ for k, v in json.items()})
83
+ if annot is dict:
84
+ assert isinstance(json, dict)
85
+ return cast(T, json)
86
+
87
+ # lists
78
88
  if isgeneric(annot) and typing.get_origin(annot) is list:
79
89
  assert isinstance(json, list)
80
90
  return cast(T, [construct(typing.get_args(annot)[0], item) for item in json])
91
+ if annot is list:
92
+ assert isinstance(json, list)
93
+ return cast(T, json)
94
+
95
+ # sets
96
+ if isgeneric(annot) and typing.get_origin(annot) is set:
97
+ assert isinstance(json, list)
98
+ return cast(T, {construct(typing.get_args(annot)[0], item) for item in json})
99
+ if annot is set:
100
+ assert isinstance(json, list)
101
+ return cast(T, set(json))
102
+
103
+ if annot is Path and isinstance(json, str):
104
+ return cast(T, Path(json))
105
+
81
106
  if is_optional_type(annot):
82
107
  if json is None:
83
108
  return cast(T, None)
@@ -97,13 +122,13 @@ def _construct(annot: Type[T], json: Any) -> T:
97
122
  if is_dataclass(annot):
98
123
  assert isinstance(json, dict)
99
124
  arg_annot = typing.get_type_hints(annot)
100
- # assert all(k in json for k in arg_annot)
101
125
  args = {k: construct(arg_annot[k], json[k]) for k in json}
102
126
  return cast(T, annot(**args))
103
127
  if isinstance(json, str) and isinstance(annot, type) and issubclass(annot, Enum):
104
- options = {opt.name.lower(): opt for opt in annot}
105
- assert json.lower() in options
106
- return cast(T, options[json.lower()])
128
+ options = {normalize_enum(e.name): e for e in annot}
129
+ assert isinstance(json, str)
130
+ assert normalize_enum(json) in options
131
+ return cast(T, options[normalize_enum(json)])
107
132
  raise ValueError(f"Couldn't construct {annot} from {repr(json)}")
108
133
 
109
134
 
@@ -5,6 +5,17 @@ from itertools import chain
5
5
  from pathlib import Path
6
6
 
7
7
 
8
+ def safe_glob(pattern):
9
+ """The `glob` method of `Path` raises a FileNotFound error when
10
+ there are rapid changes in the filesystem.
11
+
12
+ `safe_glob` catches this error and returns an empty list instead."""
13
+ try:
14
+ return Path().glob(pattern)
15
+ except FileNotFoundError:
16
+ return []
17
+
18
+
8
19
  def find_watch_dirs():
9
20
  """List all directories that contain files that need watching."""
10
21
  input_file_list = list_input_files()
@@ -16,9 +27,9 @@ def find_watch_dirs():
16
27
 
17
28
  def list_input_files():
18
29
  """List all input files."""
19
- include_file_list = chain.from_iterable(map(Path(".").glob, config.watch_list))
30
+ include_file_list = chain.from_iterable(map(safe_glob, config.watch_list))
20
31
  exclude_file_list = list(
21
- chain.from_iterable(map(Path(".").glob, config.ignore_list))
32
+ chain.from_iterable(map(safe_glob, config.ignore_list))
22
33
  )
23
34
  return [path for path in include_file_list if not path in exclude_file_list]
24
35
 
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "entangled-cli"
3
- version = "2.0.2"
3
+ version = "2.0.4"
4
4
  description = "Literate Programming toolbox"
5
5
  repository = "https://github.com/entangled/entangled.py"
6
6
  homepage = "https://entangled.github.io/"
@@ -17,9 +17,10 @@ filelock = "^3.12.0" # file lock for json db
17
17
  argh = "^0.30" # easy argument parsing
18
18
  rich = "^13.3.5" # colourful output
19
19
  tomlkit = "^0.12.1" # read/write toml files
20
- copier = "^8.3.0" # project templates
20
+ copier = "^9" # project templates
21
21
  brei = "^0.2.3" # build system
22
22
  rich-argparse = "^1.4.0" # colourful help messages
23
+ pexpect = "^4.9.0"
23
24
 
24
25
  [tool.poetry.group.dev.dependencies]
25
26
  pytest = "^7.3.1"
@@ -31,6 +32,7 @@ mkdocs-material = "^9.1.13"
31
32
  mkdocstrings = { extras = ["python"], version = "^0.21.2" }
32
33
  twine = "^4.0.2"
33
34
  pytest-asyncio = "^0.21.1"
35
+ ruff = "^0.4.4"
34
36
 
35
37
  [build-system]
36
38
  requires = ["poetry-core"]
File without changes