csspin-python 2.1.0__py3-none-any.whl → 2.1.1__py3-none-any.whl

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.
csspin_python/behave.py CHANGED
@@ -20,7 +20,7 @@
20
20
 
21
21
  import contextlib
22
22
  import sys
23
- from typing import Generator
23
+ from typing import Generator, Iterable
24
24
 
25
25
  from csspin import config, die, info, option, rmtree, setenv, sh, task, writetext
26
26
  from csspin.tree import ConfigTree
@@ -67,16 +67,16 @@ def configure(cfg: ConfigTree) -> None:
67
67
  cfg.behave.opts.append("--tags=~windows")
68
68
 
69
69
 
70
- def create_coverage_pth(cfg: ConfigTree) -> str: # pylint: disable=unused-argument
70
+ def create_coverage_pth(cfg: ConfigTree) -> Path: # pylint: disable=unused-argument
71
71
  """Creating the coverage path file and returning its path"""
72
- coverage_pth_path = cfg.python.site_packages / "coverage.pth"
72
+ coverage_pth_path: Path = cfg.python.site_packages / "coverage.pth"
73
73
  info(f"Create {coverage_pth_path}")
74
74
  writetext(coverage_pth_path, "import coverage; coverage.process_startup()")
75
75
  return coverage_pth_path
76
76
 
77
77
 
78
78
  @contextlib.contextmanager
79
- def with_coverage(cfg: ConfigTree) -> Generator:
79
+ def with_coverage(cfg: ConfigTree) -> Generator[None, None, None]:
80
80
  """Context-manager enabling to run coverage"""
81
81
  coverage_pth = ""
82
82
  try:
@@ -95,28 +95,28 @@ def with_coverage(cfg: ConfigTree) -> Generator:
95
95
 
96
96
  @task(when="cept")
97
97
  def behave( # pylint: disable=too-many-arguments,too-many-positional-arguments
98
- cfg,
99
- instance: option(
98
+ cfg: ConfigTree,
99
+ instance: option( # type: ignore[valid-type]
100
100
  "-i", # noqa: F821
101
101
  "--instance", # noqa: F821
102
102
  help="Directory of the CONTACT Elements instance.", # noqa: F722
103
103
  ),
104
- coverage: option(
104
+ coverage: option( # type: ignore[valid-type]
105
105
  "-c", # noqa: F821
106
106
  "--coverage", # noqa: F821
107
107
  is_flag=True,
108
108
  help="Run the tests while collecting coverage.", # noqa: F722
109
109
  ),
110
- debug: option(
110
+ debug: option( # type: ignore[valid-type]
111
111
  "--debug", is_flag=True, help="Start debug server." # noqa: F722,F821
112
112
  ),
113
- with_test_report: option(
113
+ with_test_report: option( # type: ignore[valid-type]
114
114
  "--with-test-report", # noqa: F722
115
115
  is_flag=True,
116
116
  help="Create a test execution report.", # noqa: F722
117
117
  ),
118
- args,
119
- ):
118
+ args: Iterable[str],
119
+ ) -> None:
120
120
  """Run Gherkin tests using behave."""
121
121
  # pylint: disable=missing-function-docstring
122
122
  coverage_enabled = coverage or cfg.behave.coverage
csspin_python/devpi.py CHANGED
@@ -18,7 +18,10 @@
18
18
  """Module implementing the devpi plugin for spin"""
19
19
 
20
20
 
21
+ from typing import Iterable
22
+
21
23
  from csspin import Command, config, die, exists, readyaml, setenv, sh, task
24
+ from csspin.tree import ConfigTree
22
25
 
23
26
  defaults = config(
24
27
  formats=["bdist_wheel"],
@@ -34,13 +37,13 @@ defaults = config(
34
37
  )
35
38
 
36
39
 
37
- def init(cfg): # pylint: disable=unused-argument
40
+ def init(cfg: ConfigTree) -> None: # pylint: disable=unused-argument
38
41
  """Sets some environment variables"""
39
42
  setenv(DEVPI_VENV="{python.venv}", DEVPI_CLIENTDIR="{spin.spin_dir}/devpi")
40
43
 
41
44
 
42
45
  @task("devpi:upload")
43
- def upload(cfg):
46
+ def upload(cfg: ConfigTree) -> None:
44
47
  """Upload project wheel to a package server."""
45
48
  if not cfg.devpi.user:
46
49
  die("devpi.user is required!")
@@ -68,7 +71,7 @@ def upload(cfg):
68
71
 
69
72
 
70
73
  @task()
71
- def devpi(cfg, args):
74
+ def devpi(cfg: ConfigTree, args: Iterable[str]) -> None:
72
75
  """Run the 'devpi' command inside the project's virtual environment.
73
76
 
74
77
  All command line arguments are simply passed through to 'devpi'.
@@ -17,7 +17,10 @@
17
17
 
18
18
  """Module implementing the playwright plugin for spin"""
19
19
 
20
+ from typing import Iterable
21
+
20
22
  from csspin import Path, Verbosity, config, die, option, setenv, sh, task
23
+ from csspin.tree import ConfigTree
21
24
 
22
25
  defaults = config(
23
26
  browsers_path="{spin.data}/playwright_browsers",
@@ -50,29 +53,29 @@ defaults = config(
50
53
 
51
54
  @task(when="cept")
52
55
  def playwright( # pylint: disable=too-many-arguments,too-many-positional-arguments
53
- cfg,
54
- instance: option(
56
+ cfg: ConfigTree,
57
+ instance: option( # type: ignore[valid-type]
55
58
  "-i", # noqa: F821
56
59
  "--instance", # noqa: F821
57
60
  default=None,
58
61
  help="Directory of the CONTACT Elements instance.", # noqa: F722
59
62
  ),
60
- coverage: option(
63
+ coverage: option( # type: ignore[valid-type]
61
64
  "-c", # noqa: F821
62
65
  "--coverage", # noqa: F821
63
66
  is_flag=True,
64
67
  help="Run the tests while collecting coverage.", # noqa: F722
65
68
  ),
66
- debug: option(
69
+ debug: option( # type: ignore[valid-type]
67
70
  "--debug", is_flag=True, help="Start debug server." # noqa: F722,F821
68
71
  ),
69
- with_test_report: option(
72
+ with_test_report: option( # type: ignore[valid-type]
70
73
  "--with-test-report", # noqa: F722
71
74
  is_flag=True,
72
75
  help="Create a test execution report.", # noqa: F722
73
76
  ),
74
- args,
75
- ):
77
+ args: Iterable[str],
78
+ ) -> None:
76
79
  """Run the playwright tests with pytest."""
77
80
  setenv(
78
81
  PLAYWRIGHT_BROWSERS_PATH=cfg.playwright.browsers_path,
@@ -113,7 +116,7 @@ def playwright( # pylint: disable=too-many-arguments,too-many-positional-argume
113
116
  sh(*cmd, *opts, *args, *cfg.playwright.tests)
114
117
 
115
118
 
116
- def _download_playwright_browsers(cfg):
119
+ def _download_playwright_browsers(cfg: ConfigTree) -> None:
117
120
  """Let playwright install the browsers"""
118
121
  sh(
119
122
  f"playwright install {' '.join(cfg.playwright.browsers)}",
@@ -121,6 +124,6 @@ def _download_playwright_browsers(cfg):
121
124
  )
122
125
 
123
126
 
124
- def provision(cfg):
127
+ def provision(cfg: ConfigTree) -> None:
125
128
  """Install playwright browsers during provisioning"""
126
129
  _download_playwright_browsers(cfg)
csspin_python/pytest.py CHANGED
@@ -18,7 +18,10 @@
18
18
  """Module implementing the pytest plugin for spin"""
19
19
 
20
20
 
21
+ from typing import Iterable
22
+
21
23
  from csspin import Path, Verbosity, config, die, option, setenv, sh, task
24
+ from csspin.tree import ConfigTree
22
25
 
23
26
  defaults = config(
24
27
  coverage=False,
@@ -49,29 +52,29 @@ defaults = config(
49
52
 
50
53
  @task(when="test")
51
54
  def pytest( # pylint: disable=too-many-arguments,too-many-positional-arguments
52
- cfg,
53
- instance: option(
55
+ cfg: ConfigTree,
56
+ instance: option( # type: ignore[valid-type]
54
57
  "-i", # noqa: F821
55
58
  "--instance", # noqa: F821
56
59
  default=None,
57
60
  help="Directory of the CONTACT Elements instance.", # noqa: F722
58
61
  ),
59
- coverage: option(
62
+ coverage: option( # type: ignore[valid-type]
60
63
  "-c", # noqa: F821
61
64
  "--coverage", # noqa: F821
62
65
  is_flag=True,
63
66
  help="Run the tests while collecting coverage.", # noqa: F722
64
67
  ),
65
- debug: option(
68
+ debug: option( # type: ignore[valid-type]
66
69
  "--debug", is_flag=True, help="Start debug server." # noqa: F722,F821
67
70
  ),
68
- with_test_report: option(
71
+ with_test_report: option( # type: ignore[valid-type]
69
72
  "--with-test-report", # noqa: F722
70
73
  is_flag=True,
71
74
  help="Create a test execution report.", # noqa: F722
72
75
  ),
73
- args,
74
- ):
76
+ args: Iterable[str],
77
+ ) -> None:
75
78
  """Run the 'pytest' command."""
76
79
  opts = cfg.pytest.opts
77
80
  if cfg.verbosity == Verbosity.QUIET:
csspin_python/python.py CHANGED
@@ -75,6 +75,14 @@ import shutil
75
75
  import sys
76
76
  from subprocess import check_output
77
77
  from textwrap import dedent, indent
78
+ from typing import Iterable, Type, Union
79
+
80
+ try:
81
+ from typing import Self # type: ignore[attr-defined]
82
+ except ImportError:
83
+ from typing import TypeVar
84
+
85
+ Self = TypeVar("Self") # type: ignore[misc]
78
86
 
79
87
  from click.exceptions import Abort
80
88
  from csspin import (
@@ -185,16 +193,16 @@ defaults = config(
185
193
 
186
194
 
187
195
  @task()
188
- def python(args):
196
+ def python(args: Iterable[object]) -> None:
189
197
  """Run the Python interpreter used for this projects."""
190
198
  sh("python", *args)
191
199
 
192
200
 
193
201
  @task("python:wheel", when="package")
194
202
  def wheel(
195
- cfg,
196
- paths: argument(type=str, nargs=-1, required=False), # noqa: F722
197
- ):
203
+ cfg: ConfigTree,
204
+ paths: argument(type=str, nargs=-1, required=False), # type: ignore[valid-type]
205
+ ) -> None:
198
206
  """Build a wheel of the current project and any additional wheels."""
199
207
  setenv(PIP_INDEX_URL=cfg.python.index_url)
200
208
  search_paths = paths or cfg.python.build_wheels
@@ -226,8 +234,13 @@ def wheel(
226
234
 
227
235
 
228
236
  @task()
229
- def env():
230
- """Generate command to activate the virtual environment"""
237
+ def env() -> None:
238
+ """
239
+ Generate command to activate the virtual environment
240
+
241
+ NOTE: spin itself should not be run from within the activated virtual
242
+ environment!
243
+ """
231
244
  if sys.platform == "win32":
232
245
  # Don't care about cmd
233
246
  print(normpath("{python.scriptdir}", "activate.ps1"))
@@ -235,12 +248,12 @@ def env():
235
248
  print(f". {normpath('{python.scriptdir}', 'activate')}")
236
249
 
237
250
 
238
- def pyenv_install(cfg):
251
+ def pyenv_install(cfg: ConfigTree) -> None:
239
252
  """Install and setup the virtual environment using pyenv"""
240
253
  with namespaces(cfg.python):
241
254
  if cfg.python.user_pyenv:
242
255
  info("Using your existing pyenv installation ...")
243
- sh(f"pyenv install --skip-existing {cfg.python.version}")
256
+ sh("pyenv", "install", "--skip-existing", {cfg.python.version})
244
257
  cfg.python.interpreter = backtick("pyenv which python --nosystem").strip()
245
258
  else:
246
259
  info("Installing Python {version} to {inst_dir}")
@@ -248,16 +261,18 @@ def pyenv_install(cfg):
248
261
  # pyenv is by far the most robust way to install a
249
262
  # version of Python.
250
263
  if not exists("{pyenv.path}"):
251
- sh(f"git clone {cfg.python.pyenv.url} {cfg.python.pyenv.path}")
264
+ sh("git", "clone", cfg.python.pyenv.url, cfg.python.pyenv.path)
252
265
  else:
253
266
  with cd(cfg.python.pyenv.path):
254
- sh("git pull")
267
+ sh("git", "pull")
255
268
  # we should set
256
269
  setenv(PYTHON_BUILD_CACHE_PATH=mkdir(cfg.python.pyenv.cache))
257
270
  setenv(PYTHON_CFLAGS="-DOPENSSL_NO_COMP")
258
271
  try:
259
272
  sh(
260
- f"{cfg.python.pyenv.python_build} {cfg.python.version} {cfg.python.inst_dir}"
273
+ cfg.python.pyenv.python_build,
274
+ cfg.python.version,
275
+ cfg.python.inst_dir,
261
276
  )
262
277
  except Abort:
263
278
  error("Failed to build the Python interpreter - removing it")
@@ -265,7 +280,7 @@ def pyenv_install(cfg):
265
280
  raise
266
281
 
267
282
 
268
- def nuget_install(cfg):
283
+ def nuget_install(cfg: ConfigTree) -> None:
269
284
  """Install the virtual environment using nuget"""
270
285
  if not exists(cfg.python.nuget.exe):
271
286
  download(cfg.python.nuget.url, cfg.python.nuget.exe)
@@ -283,7 +298,7 @@ def nuget_install(cfg):
283
298
  "-source",
284
299
  cfg.python.nuget.source,
285
300
  )
286
- sh(f"{cfg.python.interpreter} -m ensurepip --upgrade")
301
+ sh(cfg.python.interpreter, "-m", "ensurepip", "--upgrade")
287
302
  sh(
288
303
  cfg.python.interpreter,
289
304
  "-mpip",
@@ -314,7 +329,7 @@ def provision(cfg: ConfigTree) -> None:
314
329
  cfg.python.site_packages = get_site_packages(interpreter=cfg.python.python)
315
330
 
316
331
 
317
- def configure(cfg):
332
+ def configure(cfg: ConfigTree) -> None:
318
333
  """Configure the python plugin"""
319
334
  if not cfg.python.version and not cfg.python.use:
320
335
  die(
@@ -348,7 +363,7 @@ def configure(cfg):
348
363
  _check_aws_token_validity(cfg)
349
364
 
350
365
 
351
- def init(cfg):
366
+ def init(cfg: ConfigTree) -> None:
352
367
  """Initialize the python plugin"""
353
368
  if not cfg.python.use:
354
369
  logging.debug("Checking for %s", cfg.python.interpreter)
@@ -365,7 +380,7 @@ def init(cfg):
365
380
  ACTIVATED = False
366
381
 
367
382
 
368
- def venv_init(cfg):
383
+ def venv_init(cfg: ConfigTree) -> None:
369
384
  """Activate the virtual environment"""
370
385
  global ACTIVATED # pylint: disable=global-statement
371
386
  if os.environ.get("VIRTUAL_ENV", "") != cfg.python.venv and not ACTIVATED:
@@ -386,7 +401,38 @@ def venv_init(cfg):
386
401
  ACTIVATED = True
387
402
 
388
403
 
389
- def patch_activate(schema):
404
+ class ActivateScriptPatcher(abc.ABC):
405
+ activatescript: Union[str, Path]
406
+ setpattern: str
407
+ resetpattern: str
408
+ old_env_pattern: str
409
+ patchmarker: str
410
+ replacements: list[tuple[str, str]]
411
+ script: str
412
+
413
+ @staticmethod
414
+ @abc.abstractmethod
415
+ def interpolate_environ_value(value: str) -> str:
416
+ """
417
+ Translate value so the script can handle uninterpolated "{ENVVAR}" literals in value
418
+
419
+ Example:
420
+ # Assume the following subset of os.environ
421
+ os.environ = {
422
+ "PATH": "/bin:/usr/bin",
423
+ "COMPILER_PATHS": "/compiler/A/bin:/compiler/B/bin",
424
+ }
425
+
426
+ # Now, setenv has been called with
427
+ # setenv(PATH="{python.scriptdir}:{COMPILER_PATHS}:{PATH}") thus the
428
+ # value of ``PATH`` in ``EXPORTS`` equals "/venv/bin:{COMPILER_PATHS}:{PATH}" as
429
+ # ``COMPILER_PATHS`` and ``PATH`` haven't been interpolated yet.
430
+ interpolate_environ_value(value) => /venv/bin:/compiler/A/bin:/compiler/B/bin:/bin:/usr/bin
431
+ """
432
+ return value
433
+
434
+
435
+ def patch_activate(schema: Type[ActivateScriptPatcher]) -> None:
390
436
  """Patch the activate script"""
391
437
  if exists(schema.activatescript):
392
438
  setters = []
@@ -397,9 +443,9 @@ def patch_activate(schema):
397
443
  setters.append(schema.setpattern.format(name=name, value=value))
398
444
  resetters.add(schema.resetpattern.format(name=name))
399
445
  old_value_setters.add(schema.old_env_pattern.format(name=name))
400
- resetters = "\n".join(resetters)
401
- setters = "\n".join(setters)
402
- old_value_setters = "\n".join(old_value_setters)
446
+ resetters_string = "\n".join(resetters)
447
+ setters_string = "\n".join(setters)
448
+ old_value_setters_string = "\n".join(old_value_setters)
403
449
  original = readtext(schema.activatescript)
404
450
  if schema.patchmarker not in original:
405
451
  shutil.copyfile(
@@ -418,36 +464,13 @@ def patch_activate(schema):
418
464
  newscript = schema.script.format(
419
465
  patchmarker=schema.patchmarker,
420
466
  original=original,
421
- resetters=resetters,
422
- old_value_setters=old_value_setters,
423
- setters=setters,
467
+ resetters=resetters_string,
468
+ old_value_setters=old_value_setters_string,
469
+ setters=setters_string,
424
470
  )
425
471
  writetext(f"{schema.activatescript}", newscript)
426
472
 
427
473
 
428
- class ActivateScriptPatcher(abc.ABC):
429
- @staticmethod
430
- @abc.abstractmethod
431
- def interpolate_environ_value(value):
432
- """
433
- Translate value so the script can handle uninterpolated "{ENVVAR}" literals in value
434
-
435
- Example:
436
- # Assume the following subset of os.environ
437
- os.environ = {
438
- "PATH": "/bin:/usr/bin",
439
- "COMPILER_PATHS": "/compiler/A/bin:/compiler/B/bin",
440
- }
441
-
442
- # Now, setenv has been called with
443
- # setenv(PATH="{python.scriptdir}:{COMPILER_PATHS}:{PATH}") thus the
444
- # value of ``PATH`` in ``EXPORTS`` equals "/venv/bin:{COMPILER_PATHS}:{PATH}" as
445
- # ``COMPILER_PATHS`` and ``PATH`` haven't been interpolated yet.
446
- interpolate_environ_value(value) => /venv/bin:/compiler/A/bin:/compiler/B/bin:/bin:/usr/bin
447
- """
448
- return value
449
-
450
-
451
474
  class BashActivate(ActivateScriptPatcher):
452
475
  patchmarker = "\n## Patched by csspin_python.python\n"
453
476
  activatescript = Path("{python.scriptdir}") / "activate"
@@ -510,7 +533,7 @@ class BashActivate(ActivateScriptPatcher):
510
533
  )
511
534
 
512
535
  @staticmethod
513
- def interpolate_environ_value(value):
536
+ def interpolate_environ_value(value: str) -> str:
514
537
  if not value:
515
538
  return ""
516
539
  keys = re.findall(r"{(?P<key>\w+?)}", value)
@@ -564,7 +587,7 @@ class PowershellActivate(ActivateScriptPatcher):
564
587
  )
565
588
 
566
589
  @staticmethod
567
- def interpolate_environ_value(value):
590
+ def interpolate_environ_value(value: str) -> str:
568
591
  if not value:
569
592
  return ""
570
593
  keys = re.findall(r"{(?P<key>\w+?)}", value)
@@ -577,7 +600,7 @@ class PowershellActivate(ActivateScriptPatcher):
577
600
  class BatchActivate(ActivateScriptPatcher):
578
601
  patchmarker = "\nREM Patched by csspin_python.python\n"
579
602
  activatescript = Path("{python.scriptdir}") / "activate.bat"
580
- replacements = ()
603
+ replacements = []
581
604
  old_env_pattern = dedent(
582
605
  """
583
606
  if defined _OLD_SPIN_VALUE_{name} goto ENDIFSPIN{name}1
@@ -614,7 +637,7 @@ class BatchActivate(ActivateScriptPatcher):
614
637
  )
615
638
 
616
639
  @staticmethod
617
- def interpolate_environ_value(value):
640
+ def interpolate_environ_value(value: str) -> str:
618
641
  if not value:
619
642
  return ""
620
643
  keys = re.findall(r"{(?P<key>\w+?)}", value)
@@ -627,7 +650,7 @@ class BatchActivate(ActivateScriptPatcher):
627
650
  class BatchDeactivate(ActivateScriptPatcher):
628
651
  patchmarker = "\nREM Patched by csspin_python.python\n"
629
652
  activatescript = Path("{python.scriptdir}") / "deactivate.bat"
630
- replacements = ()
653
+ replacements = []
631
654
  old_env_pattern = ""
632
655
  setpattern = ""
633
656
  resetpattern = dedent(
@@ -658,7 +681,7 @@ class BatchDeactivate(ActivateScriptPatcher):
658
681
  class PythonActivate(ActivateScriptPatcher):
659
682
  patchmarker = "# Patched by csspin_python.python\n"
660
683
  activatescript = Path("{python.scriptdir}") / "activate_this.py"
661
- replacements = ()
684
+ replacements = []
662
685
  old_env_pattern = ""
663
686
  setpattern = 'os.environ["{name}"] = fr"{value}"'
664
687
  resetpattern = ""
@@ -671,7 +694,7 @@ class PythonActivate(ActivateScriptPatcher):
671
694
  )
672
695
 
673
696
  @staticmethod
674
- def interpolate_environ_value(value):
697
+ def interpolate_environ_value(value: str) -> str:
675
698
  if not value:
676
699
  return ""
677
700
  keys = re.findall(r"{(?P<key>\w+?)}", value)
@@ -681,7 +704,7 @@ class PythonActivate(ActivateScriptPatcher):
681
704
  return value
682
705
 
683
706
 
684
- def get_site_packages(interpreter):
707
+ def get_site_packages(interpreter: Path) -> Path:
685
708
  """Return the path to the virtual environments site-packages."""
686
709
  return Path(
687
710
  check_output(
@@ -696,7 +719,7 @@ def get_site_packages(interpreter):
696
719
  )
697
720
 
698
721
 
699
- def finalize_provision(cfg):
722
+ def finalize_provision(cfg: ConfigTree) -> None:
700
723
  """Patching the activate scripts and preparing the site-packages"""
701
724
  cfg.python.provisioner.install(cfg)
702
725
 
@@ -732,8 +755,11 @@ class ProvisionerProtocol:
732
755
  The provisioner will be memoized, so make sure it works with ``pickle.dumps``.
733
756
  """
734
757
 
758
+ requirements: set[str]
759
+ devpackages: set[str]
760
+
735
761
  # noinspection PyMethodMayBeStatic
736
- def provision_python(self, cfg: ConfigTree) -> None:
762
+ def provision_python(self: Self, cfg: ConfigTree) -> None:
737
763
  """Provision the project's python interpreter"""
738
764
  if sys.platform == "win32":
739
765
  nuget_install(cfg)
@@ -742,7 +768,7 @@ class ProvisionerProtocol:
742
768
  pyenv_install(cfg)
743
769
 
744
770
  # noinspection PyMethodMayBeStatic
745
- def provision_venv(self, cfg: ConfigTree) -> None:
771
+ def provision_venv(self: Self, cfg: ConfigTree) -> None:
746
772
  """Provision the virtual environment of the project"""
747
773
  # virtualenv is guaranteed to be available like this
748
774
  # as we declared it as one of spin's dependencies
@@ -761,26 +787,26 @@ class ProvisionerProtocol:
761
787
  env={"PYTHONPATH": cfg.spin.spin_dir / "plugins"},
762
788
  )
763
789
 
764
- def prerequisites(self, cfg: ConfigTree) -> None:
790
+ def prerequisites(self: Self, cfg: ConfigTree) -> None:
765
791
  """Provide requirements for the provisioning strategy."""
766
792
 
767
- def lock(self, cfg: ConfigTree) -> None:
793
+ def lock(self: Self, cfg: ConfigTree) -> None:
768
794
  """Lock the project's dependencies."""
769
795
 
770
- def add(self, cfg: ConfigTree, req: str, devpackage: bool = False) -> None:
796
+ def add(self: Self, cfg: ConfigTree, req: str, devpackage: bool = False) -> None:
771
797
  """Add an extra dependency (incl. development ones)."""
772
798
 
773
- def lock_extras(self, cfg: ConfigTree) -> None:
799
+ def lock_extras(self: Self, cfg: ConfigTree) -> None:
774
800
  """Lock the extra dependencies."""
775
801
 
776
- def sync(self, cfg: ConfigTree) -> None:
802
+ def sync(self: Self, cfg: ConfigTree) -> None:
777
803
  """Synchronize the environment with the locked dependencies."""
778
804
 
779
- def install(self, cfg: ConfigTree) -> None:
805
+ def install(self: Self, cfg: ConfigTree) -> None:
780
806
  """Install the project itself."""
781
807
 
782
808
  # noinspection PyMethodMayBeStatic
783
- def cleanup(self, cfg: ConfigTree) -> None:
809
+ def cleanup(self: Self, cfg: ConfigTree) -> None:
784
810
  """Cleanup the provisioned environment"""
785
811
  rmtree(cfg.python.venv)
786
812
 
@@ -792,12 +818,12 @@ class SimpleProvisioner(ProvisionerProtocol):
792
818
  longer required.
793
819
  """
794
820
 
795
- def __init__(self):
821
+ def __init__(self: Self) -> None:
796
822
  self.requirements = set()
797
823
  self.devpackages = set()
798
824
  self.m = Memoizer("{python.memo}")
799
825
 
800
- def prerequisites(self, cfg):
826
+ def prerequisites(self: Self, cfg: ConfigTree) -> None:
801
827
  # We'll need pip
802
828
  sh(
803
829
  "python",
@@ -811,23 +837,23 @@ class SimpleProvisioner(ProvisionerProtocol):
811
837
  "pip",
812
838
  )
813
839
 
814
- def lock(self, cfg):
840
+ def lock(self: Self, cfg: ConfigTree) -> None:
815
841
  """Noop"""
816
842
 
817
- def add(self, cfg, req, devpackage=False):
843
+ def add(self: Self, cfg: ConfigTree, req: str, devpackage: bool = False) -> None:
818
844
  # Add the requirement or devpackage if not already there.
819
845
  if not self.m.check(req):
820
846
  lst = self.devpackages if devpackage else self.requirements
821
847
  lst.add(req)
822
848
 
823
- def sync(self, cfg):
849
+ def sync(self: Self, cfg: ConfigTree) -> None:
824
850
  self.__execute_installation(
825
851
  self.requirements,
826
852
  None if cfg.verbosity > Verbosity.NORMAL else "-q",
827
853
  cfg.python.index_url,
828
854
  )
829
855
 
830
- def install(self, cfg):
856
+ def install(self: Self, cfg: ConfigTree) -> None:
831
857
  quietflag = None if cfg.verbosity > Verbosity.NORMAL else "-q"
832
858
  self.__execute_installation(self.devpackages, quietflag, cfg.python.index_url)
833
859
 
@@ -862,14 +888,16 @@ class SimpleProvisioner(ProvisionerProtocol):
862
888
  if pip_check.returncode:
863
889
  die(pip_check.stdout)
864
890
 
865
- def _split(self, reqset):
891
+ def _split(self: Self, reqset: set[str]) -> list[str]:
866
892
  """to pass whitespace-less args to sh()"""
867
893
  reqlist = []
868
894
  for req in reqset:
869
895
  reqlist.extend(req.split())
870
896
  return reqlist
871
897
 
872
- def __execute_installation(self, packages, quietflag, index_url):
898
+ def __execute_installation(
899
+ self: Self, packages: set[str], quietflag: Union[str, None], index_url: str
900
+ ) -> None:
873
901
  """Install packages that are not yet memoized"""
874
902
  if to_install := {package for package in packages if not self.m.check(package)}:
875
903
  sh(
@@ -886,7 +914,9 @@ class SimpleProvisioner(ProvisionerProtocol):
886
914
  self.m.save()
887
915
 
888
916
 
889
- def venv_provision(cfg): # pylint: disable=too-many-branches,missing-function-docstring
917
+ def venv_provision( # pylint: disable=too-many-branches,missing-function-docstring
918
+ cfg: ConfigTree,
919
+ ) -> None:
890
920
  fresh_env = False
891
921
 
892
922
  info("Checking venv '{python.venv}'")
@@ -961,7 +991,7 @@ def cleanup(cfg: ConfigTree) -> None:
961
991
  rmtree(current_path / filename)
962
992
 
963
993
 
964
- def _get_pipconf(cfg):
994
+ def _get_pipconf(cfg: ConfigTree) -> Path:
965
995
  """Retrieve the pipconf configuration file path."""
966
996
  if sys.platform == "win32":
967
997
  pipconf = interpolate1(Path(cfg.python.venv)) / "pip.ini"
@@ -971,7 +1001,7 @@ def _get_pipconf(cfg):
971
1001
  return pipconf
972
1002
 
973
1003
 
974
- def _configure_pipconf(cfg, update=False):
1004
+ def _configure_pipconf(cfg: ConfigTree, update: bool = False) -> None:
975
1005
  """Configure the pip configuration file"""
976
1006
  config_parser = configparser.ConfigParser()
977
1007
  config_parser.read_string(cfg.python.pipconf)
@@ -985,7 +1015,7 @@ def _configure_pipconf(cfg, update=False):
985
1015
  config_parser.write(fd)
986
1016
 
987
1017
 
988
- def _obfuscate_index_url(index_url):
1018
+ def _obfuscate_index_url(index_url: str) -> None:
989
1019
  """Add the CodeArtifact token to the secrets."""
990
1020
 
991
1021
  from csspin import secrets
@@ -993,7 +1023,7 @@ def _obfuscate_index_url(index_url):
993
1023
  secrets.add(index_url.split(":")[2].split("@")[0]) # Codeartifact token
994
1024
 
995
1025
 
996
- def _check_aws_token_validity(cfg):
1026
+ def _check_aws_token_validity(cfg: ConfigTree) -> None:
997
1027
  """
998
1028
  If csspin-python[aws_auth] is installed, we can use csaccess to get the
999
1029
  CodeArtifact authentication token.
csspin_python/radon.py CHANGED
@@ -18,8 +18,10 @@
18
18
  """Module implementing the radon plugin for spin"""
19
19
 
20
20
  import logging
21
+ from typing import Iterable
21
22
 
22
23
  from csspin import config, info, option, sh, task
24
+ from csspin.tree import ConfigTree
23
25
 
24
26
  defaults = config(
25
27
  exe="radon",
@@ -36,20 +38,20 @@ defaults = config(
36
38
 
37
39
  @task()
38
40
  def radon(
39
- cfg,
40
- allsource: option(
41
+ cfg: ConfigTree,
42
+ allsource: option( # type: ignore[valid-type]
41
43
  "--all", # noqa: F821
42
44
  "allsource", # noqa: F821
43
45
  is_flag=True,
44
46
  help="Run for all src- and test-files.", # noqa: F722,F821
45
47
  ),
46
- args,
47
- ):
48
+ args: Iterable[str],
49
+ ) -> None:
48
50
  """Run radon to measure code complexity."""
49
51
  if allsource:
50
- files = ("{spin.project_root}/src", "{spin.project_root}/tests")
52
+ files = ["{spin.project_root}/src", "{spin.project_root}/tests"]
51
53
  else:
52
- files = args
54
+ files = list(args)
53
55
  if not files and hasattr(cfg, "vcs") and hasattr(cfg.vcs, "modified"):
54
56
  info("Found modified files.")
55
57
  files = cfg.vcs.modified
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: csspin-python
3
- Version: 2.1.0
3
+ Version: 2.1.1
4
4
  Summary: Plugin-package for csspin providing Python related plugins
5
5
  Author-email: CONTACT Software GmbH <info@contact-software.com>
6
6
  Maintainer-email: Waleri Enns <waleri.enns@contact-software.com>, Benjamin Thomas Schwertfeger <benjaminthomas.schwertfeger@contact-software.com>, Fabian Hafer <fabian.hafer@contact-software.com>
@@ -20,6 +20,7 @@ Classifier: Topic :: Software Development
20
20
  Requires-Python: >=3.9
21
21
  Description-Content-Type: text/x-rst
22
22
  License-File: LICENSE
23
+ Requires-Dist: platformdirs~=4.3.8
23
24
  Requires-Dist: virtualenv
24
25
  Provides-Extra: aws-auth
25
26
  Requires-Dist: csaccess>=0.1.0; extra == "aws-auth"
@@ -0,0 +1,19 @@
1
+ csspin_python/behave.py,sha256=iJZeyIqB7V_NzTdLTZldNY9W_GGwCWkXe6WY69wpDqs,4997
2
+ csspin_python/behave_schema.yaml,sha256=8qoOCK-uTmwgRRW29urgK0X_kgn0zO0X34v89bvii2w,1241
3
+ csspin_python/debugpy.py,sha256=v0ZZopv5TNoSaFf2kiePsw9OmhBpjfOBFh0u71jTcnQ,962
4
+ csspin_python/debugpy_schema.yaml,sha256=BeH30nSirDYctkdhS9xMXUG5htj3PED_ZjmxPG5WRUc,364
5
+ csspin_python/devpi.py,sha256=C-5O_vA06CwQR4uElOw-2VH2-m001SpxowM_X6RbRwo,2352
6
+ csspin_python/devpi_schema.yaml,sha256=2gPATWjVcfvCTrGZX2FK6wH8hh9KS0XzZ35JvZeJGEU,487
7
+ csspin_python/playwright.py,sha256=mzSsLcmewDZnZwdSyp5HytEMnXgkoJ9s1XXkd05eOwU,4254
8
+ csspin_python/playwright_schema.yaml,sha256=WFMok7dB7G6L8f8y_2_RKHjGe4ww1iUUS4tqCoUI1FE,1054
9
+ csspin_python/pytest.py,sha256=Mx6l4Cb28FjdZgL9Vd1zBbhcnYyc4QsqwkozksoKZJc,3189
10
+ csspin_python/pytest_schema.yaml,sha256=1bF8hNsJfV-LHUwGBBJ3GnQOZJiIQkG81DCBma2MalU,809
11
+ csspin_python/python.py,sha256=AbIX3r07c4tVAj0jIfjiRi7Vk9XFiap6AvS4xCYee48,34461
12
+ csspin_python/python_schema.yaml,sha256=F_PMK8D3KBvXK945b6-oRDoaxuDgxkBGqVPAJ-eFmv0,5970
13
+ csspin_python/radon.py,sha256=uFqm6FEi5oWj-_XVaAm3s9cam0cUmr1_FwRf40K6xWs,1876
14
+ csspin_python/radon_schema.yaml,sha256=rlRzXw5z4XbjOVznRiUxWGP4E9hx1Jm-gGw1iQiYzE0,548
15
+ csspin_python-2.1.1.dist-info/licenses/LICENSE,sha256=4MAecetnRTQw5DlHtiikDSzKWO1xVLwzM5_DsPMYlnE,10172
16
+ csspin_python-2.1.1.dist-info/METADATA,sha256=pIuulk5YG9JUQqORop0oV4GoX0DdHZoOOGktz8YkhYA,4209
17
+ csspin_python-2.1.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
+ csspin_python-2.1.1.dist-info/top_level.txt,sha256=QSeglMEGbFu1z4L6MCQYwo01NgL0KojWvC4rzgMQ8gU,14
19
+ csspin_python-2.1.1.dist-info/RECORD,,
@@ -1,19 +0,0 @@
1
- csspin_python/behave.py,sha256=iA5t-vwMDhmWoo-FHaeZ6JyIzj6k4r2WLyYa2AjXyp4,4815
2
- csspin_python/behave_schema.yaml,sha256=8qoOCK-uTmwgRRW29urgK0X_kgn0zO0X34v89bvii2w,1241
3
- csspin_python/debugpy.py,sha256=v0ZZopv5TNoSaFf2kiePsw9OmhBpjfOBFh0u71jTcnQ,962
4
- csspin_python/debugpy_schema.yaml,sha256=BeH30nSirDYctkdhS9xMXUG5htj3PED_ZjmxPG5WRUc,364
5
- csspin_python/devpi.py,sha256=2NhGYzq4aVzDa_d80uItUlYM9cA0uRFQ4rvnCryxL2k,2213
6
- csspin_python/devpi_schema.yaml,sha256=2gPATWjVcfvCTrGZX2FK6wH8hh9KS0XzZ35JvZeJGEU,487
7
- csspin_python/playwright.py,sha256=nYuPjuTfGx_6QPYsUpr-eAZARyXX_hZF8D4AxeI2u1s,4003
8
- csspin_python/playwright_schema.yaml,sha256=WFMok7dB7G6L8f8y_2_RKHjGe4ww1iUUS4tqCoUI1FE,1054
9
- csspin_python/pytest.py,sha256=EwxPynyPWS72NTtIah1jUGVa7fJYY8I2_NQz0y0U7Os,2978
10
- csspin_python/pytest_schema.yaml,sha256=1bF8hNsJfV-LHUwGBBJ3GnQOZJiIQkG81DCBma2MalU,809
11
- csspin_python/python.py,sha256=du1sFA6Uh8Wp5V6sN3_iSsQNEz-OZBAJG-FdgCyvsjM,33114
12
- csspin_python/python_schema.yaml,sha256=F_PMK8D3KBvXK945b6-oRDoaxuDgxkBGqVPAJ-eFmv0,5970
13
- csspin_python/radon.py,sha256=OSV0vTz7SMMHC82jUvWsBq6vtWolOjdiZ2bBdxplVJ4,1744
14
- csspin_python/radon_schema.yaml,sha256=rlRzXw5z4XbjOVznRiUxWGP4E9hx1Jm-gGw1iQiYzE0,548
15
- csspin_python-2.1.0.dist-info/licenses/LICENSE,sha256=4MAecetnRTQw5DlHtiikDSzKWO1xVLwzM5_DsPMYlnE,10172
16
- csspin_python-2.1.0.dist-info/METADATA,sha256=-cWwMdEo8x0I1_vcEAjiCO5DC79Y-ymGXro6Qig7Q4s,4174
17
- csspin_python-2.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
18
- csspin_python-2.1.0.dist-info/top_level.txt,sha256=QSeglMEGbFu1z4L6MCQYwo01NgL0KojWvC4rzgMQ8gU,14
19
- csspin_python-2.1.0.dist-info/RECORD,,