poetry-plugin-ivcap 0.1.0__tar.gz → 0.2.2__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.3
2
2
  Name: poetry-plugin-ivcap
3
- Version: 0.1.0
3
+ Version: 0.2.2
4
4
  Summary: A custom Poetry command for IVCAP deployments
5
5
  License: MIT
6
6
  Author: Max Ott
@@ -27,9 +27,11 @@ Add to your `pyproject.toml`:
27
27
 
28
28
  ```toml
29
29
  [tool.poetry-plugin-ivcap]
30
- default_target = "docker"
31
- docker_tag = "myapp:dev"
32
- ```
30
+ service-file = "service.py"
31
+ service-id = "urn:ivcap:service:ac158a1f-dfb4-5dac-bf2e-9bf15e0f2cc7"
32
+ port = 8077
33
+ # docker
34
+ # docker-run-opts = { port = 8079 }```
33
35
 
34
36
  ## Installation
35
37
 
@@ -40,8 +42,44 @@ poetry self add poetry-plugin-ivcap
40
42
  ## Usage
41
43
 
42
44
  ```bash
43
- poetry ivcap
44
- poetry ivcap docker
45
+ poetry ivcap run
46
+ poetry ivcap docker-build
47
+ poetry ivcap docker-run
48
+ poetry ivcap docker-publish
49
+ poetry ivcap service-register
50
+ poetry ivcap create-service-id
51
+ poetry ivcap tool-register
52
+ ```
53
+
54
+ To get help on the currently installed version
55
+ ```
56
+ % poetry ivcap
57
+
58
+ IVCAP plugin
59
+
60
+ Supporting the development of services and tools for the IVCAP platform
61
+
62
+ Available subcommands:
63
+ run Run the service locally
64
+ docker-build Build the docker image for this service
65
+ docker-run Run the service's docker image locally
66
+ docker-publish Publish the service's docker image to IVCAP
67
+ service-register Register the service with IVCAP
68
+ create-service-id Create a unique service ID for the service
69
+ tool-register Register the service as an AI Tool with IVCAP
70
+
71
+ Example:
72
+ poetry ivcap run
73
+
74
+ Configurable optiosn in pyproject.toml:
75
+
76
+ [tool.poetry-plugin-ivcap]
77
+ service-file = "service.py" # The Python file that implements the service
78
+ service-file = "service.py"
79
+ service-id = "urn:ivcap:service:ac158a1f-dfb4-5dac-bf2e-9bf15e0f2cc7" # A unique identifier for the service
80
+
81
+ docker-build-template = "docker buildx build -t #DOCKER_NAME# ."
82
+ docker-run-template = "docker run -rm -p #PORT#:#PORT#"
45
83
  ```
46
84
 
47
85
  ## Development
@@ -0,0 +1,103 @@
1
+ # poetry-plugin-ivcap
2
+
3
+ A custom Poetry plugin that adds a `poetry ivcap` command for local and Docker-based deployments.
4
+
5
+ ## Example Configuration
6
+
7
+ Add to your `pyproject.toml`:
8
+
9
+ ```toml
10
+ [tool.poetry-plugin-ivcap]
11
+ service-file = "service.py"
12
+ service-id = "urn:ivcap:service:ac158a1f-dfb4-5dac-bf2e-9bf15e0f2cc7"
13
+ port = 8077
14
+ # docker
15
+ # docker-run-opts = { port = 8079 }```
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ poetry self add poetry-plugin-ivcap
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ ```bash
26
+ poetry ivcap run
27
+ poetry ivcap docker-build
28
+ poetry ivcap docker-run
29
+ poetry ivcap docker-publish
30
+ poetry ivcap service-register
31
+ poetry ivcap create-service-id
32
+ poetry ivcap tool-register
33
+ ```
34
+
35
+ To get help on the currently installed version
36
+ ```
37
+ % poetry ivcap
38
+
39
+ IVCAP plugin
40
+
41
+ Supporting the development of services and tools for the IVCAP platform
42
+
43
+ Available subcommands:
44
+ run Run the service locally
45
+ docker-build Build the docker image for this service
46
+ docker-run Run the service's docker image locally
47
+ docker-publish Publish the service's docker image to IVCAP
48
+ service-register Register the service with IVCAP
49
+ create-service-id Create a unique service ID for the service
50
+ tool-register Register the service as an AI Tool with IVCAP
51
+
52
+ Example:
53
+ poetry ivcap run
54
+
55
+ Configurable optiosn in pyproject.toml:
56
+
57
+ [tool.poetry-plugin-ivcap]
58
+ service-file = "service.py" # The Python file that implements the service
59
+ service-file = "service.py"
60
+ service-id = "urn:ivcap:service:ac158a1f-dfb4-5dac-bf2e-9bf15e0f2cc7" # A unique identifier for the service
61
+
62
+ docker-build-template = "docker buildx build -t #DOCKER_NAME# ."
63
+ docker-run-template = "docker run -rm -p #PORT#:#PORT#"
64
+ ```
65
+
66
+ ## Development
67
+
68
+ ### Build the Plugin Package
69
+
70
+ ```bash
71
+ poetry build
72
+ ```
73
+
74
+ This creates .whl and .tar.gz files in the dist/ directory.
75
+
76
+ ### Publish to PyPI
77
+
78
+ Create an account at https://pypi.org/account/register/
79
+
80
+ Add your credentials:
81
+ ```bash
82
+ poetry config pypi-token.pypi <your-token>
83
+ ```
84
+
85
+ Publish:
86
+ ```bash
87
+ poetry publish --build
88
+ ```
89
+
90
+ ### Optional: Test on TestPyPI First
91
+
92
+ To verify your setup without publishing to the real PyPI:
93
+
94
+ ```bash
95
+ poetry config repositories.test-pypi https://test.pypi.org/legacy/
96
+ poetry publish -r test-pypi --build
97
+ ```
98
+
99
+ Then test installing via:
100
+
101
+ ```bash
102
+ poetry self add --source test-pypi poetry-plugin-deploy
103
+ ```
@@ -3,15 +3,16 @@
3
3
  # Use of this source code is governed by a BSD-style license that can be
4
4
  # found in the LICENSE file. See the AUTHORS file for names of contributors.
5
5
  #
6
+ from datetime import datetime, timezone
6
7
  import os
7
8
  import re
8
9
  import sys
9
10
  import tempfile
10
- from typing import Dict, Optional
11
+ from typing import Dict, List, Optional
11
12
  from pydantic import BaseModel, Field
12
13
  import subprocess
13
14
 
14
- from .util import command_exists, get_name
15
+ from .util import command_exists, get_name, get_version
15
16
 
16
17
  DOCKER_BUILD_TEMPLATE = """
17
18
  docker buildx build
@@ -23,12 +24,20 @@ docker buildx build
23
24
  --load #PROJECT_DIR#
24
25
  """
25
26
 
26
- DOCKER_RUN_TEMPLATE = """
27
+ DOCKER_LAMBDA_RUN_TEMPLATE = """
27
28
  docker run -it
28
29
  -p #PORT#:#PORT#
29
30
  --platform=linux/#ARCH#
30
31
  --rm \
31
- #NAME#_#ARCH#:#TAG# --port #PORT#
32
+ #NAME#_#ARCH#:#TAG#
33
+ """
34
+
35
+ DOCKER_BATCH_RUN_TEMPLATE = """
36
+ docker run -it
37
+ --platform=linux/#ARCH#
38
+ -v #PROJECT_DIR#:/data
39
+ --rm \
40
+ #NAME#_#ARCH#:#TAG#
32
41
  """
33
42
 
34
43
  class DockerConfig(BaseModel):
@@ -37,7 +46,7 @@ class DockerConfig(BaseModel):
37
46
  arch: Optional[str] = Field(None)
38
47
  version: Optional[str] = Field(None)
39
48
  dockerfile: Optional[str] = Field("Dockerfile")
40
- project_dir: Optional[str] = Field(".")
49
+ project_dir: Optional[str] = Field(os.getcwd())
41
50
 
42
51
  @property
43
52
  def docker_name(self) -> str:
@@ -57,26 +66,61 @@ class DockerConfig(BaseModel):
57
66
  .split()
58
67
  return t
59
68
 
60
- def from_run_template(self, data) -> str:
69
+ def from_run_template(self, data, args, line) -> List[any]:
61
70
  pdata = data.get("tool", {}).get("poetry-plugin-ivcap", {})
62
- template = pdata.get("docker-run-template", DOCKER_RUN_TEMPLATE).strip()
63
- opts = pdata.get("docker-run-opts", {"port": 8080})
71
+ template = pdata.get("docker-run-template")
72
+ if template is None:
73
+ smode = pdata.get("service-type")
74
+ if smode is None:
75
+ line("<error>ERROR: 'service-type' is not defined in [poetry-plugin-ivcap]</error>")
76
+ sys.exit(1)
77
+ if smode == "lambda":
78
+ template = DOCKER_LAMBDA_RUN_TEMPLATE
79
+ elif smode == "batch":
80
+ template = DOCKER_BATCH_RUN_TEMPLATE
81
+ else:
82
+ line(f"<error>ERROR: Unknown service type '{smode}' in [poetry-plugin-ivcap]</error>")
83
+ sys.exit(1)
84
+
85
+ opts = pdata.get("docker-run-opts", [])
86
+ port = get_port_value(args)
87
+ port_in_args = True
88
+ if not port:
89
+ port = get_port_value(opts)
90
+ if not port:
91
+ port_in_args = False
92
+ port = str(pdata.get("port", 8000))
93
+
94
+ # elif opts.get('port') is not None:
95
+ # opts['port'] = opts.get('port')
96
+ # elif '--port' in template:
97
+ # # If the template has a port but no port is provided, use a default
98
+ # opts['port'] = '8000'
99
+
64
100
  t = template.strip()\
65
101
  .replace("#NAME#", self.name)\
66
102
  .replace("#TAG#", self.tag)\
103
+ .replace("#PORT#", port)\
67
104
  .replace("#ARCH#", self.arch)\
68
105
  .replace("#VERSION#", self.version)\
69
106
  .replace("#PROJECT_DIR#", self.project_dir)
70
107
 
71
- for key, value in opts.items():
72
- t = t.replace(f"#{key.upper()}#", str(value))
108
+ # for key, value in opts.items():
109
+ # if key != "port":
110
+ # t = t.replace(f"#{key.upper()}#", str(value))
73
111
 
74
- return t.split()
112
+
113
+ cmd = t.split()
114
+ cmd.extend(opts)
115
+ cmd.extend(args)
116
+ if smode == "lambda" and not port_in_args:
117
+ cmd.extend(["--port", port])
118
+ return cmd
75
119
 
76
120
 
77
121
  def docker_build(data: dict, line, arch = None) -> None:
78
122
  check_docker_cmd(line)
79
- config = _docker_cfg(data, line, arch)
123
+ config = docker_cfg(data, line, arch)
80
124
  build_cmd = config.from_build_template(data)
81
125
  line(f"<info>INFO: {' '.join(build_cmd)}</info>")
82
126
  process = subprocess.Popen(build_cmd, stdout=sys.stdout, stderr=sys.stderr)
@@ -87,10 +131,10 @@ def docker_build(data: dict, line, arch = None) -> None:
87
131
  line("<info>INFO: Docker build completed successfully</info>")
88
132
  return config.docker_name
89
133
 
90
- def docker_run(data: dict, line) -> None:
134
+ def docker_run(data: dict, args, line) -> None:
91
135
  check_docker_cmd(line)
92
- config = _docker_cfg(data, line)
93
- build_run = config.from_run_template(data)
136
+ config = docker_cfg(data, line)
137
+ build_run = config.from_run_template(data, args, line)
94
138
  line(f"<info>INFO: {' '.join(build_run)}</info>")
95
139
  process = subprocess.Popen(build_run, stdout=sys.stdout, stderr=sys.stderr)
96
140
  exit_code = process.wait()
@@ -99,24 +143,15 @@ def docker_run(data: dict, line) -> None:
99
143
  else:
100
144
  line("<info>INFO: Docker run completed successfully</info>")
101
145
 
102
- def _docker_cfg(data: dict, line, arch = None) -> DockerConfig:
103
- project_data = data.get("project", {})
146
+ def docker_cfg(data: dict, line, arch = None) -> DockerConfig:
104
147
  name = get_name(data)
105
- version = project_data.get("version", None)
106
148
 
107
149
  pdata = data.get("tool", {}).get("poetry-plugin-ivcap", {})
108
- config = DockerConfig(name=name, version=version, **pdata.get("docker", {}))
150
+ config = DockerConfig(name=name, **pdata.get("docker", {}))
109
151
  if arch:
110
152
  # override architecture if provided
111
153
  config.arch = arch
112
154
 
113
- if not config.version:
114
- try:
115
- config.version = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).decode().strip()
116
- except Exception as e:
117
- line(f"<error>Error retrieving latest tag: {e}</error>")
118
- config.version = "???"
119
-
120
155
  if not config.tag:
121
156
  try:
122
157
  config.tag = subprocess.check_output(['git', 'rev-parse', "--short", 'HEAD']).decode().strip()
@@ -124,6 +159,9 @@ def _docker_cfg(data: dict, line, arch = None) -> DockerConfig:
124
159
  line(f"<warning>WARN: retrieving commit hash: {e}</warning>")
125
160
  config.tag = "latest"
126
161
 
162
+ if not config.version:
163
+ config.version = get_version(data, config.tag, line)
164
+
127
165
  if not config.arch:
128
166
  try:
129
167
  config.arch = subprocess.check_output(['uname', '-m']).decode().strip()
@@ -183,3 +221,12 @@ def check_docker_cmd(line):
183
221
  if not command_exists("docker"):
184
222
  line("<error>'docker' command not found. Please install it first.</error>")
185
223
  sys.exit(1)
224
+
225
+ def get_port_value(arr):
226
+ try:
227
+ index = arr.index('--port')
228
+ return arr[index + 1]
229
+ except ValueError:
230
+ return None
231
+ except IndexError:
232
+ return None
@@ -11,14 +11,12 @@ import tempfile
11
11
  import uuid
12
12
  import humanize
13
13
 
14
- from .docker import _docker_cfg, docker_build, docker_push
14
+ from .docker import docker_cfg, docker_build, docker_push
15
15
  from .util import command_exists, execute_subprocess_and_capture_output, get_name, string_to_number
16
16
 
17
17
  def docker_publish(data, line):
18
18
  check_ivcap_cmd(line)
19
- #dname = docker_build(data, line, arch="amd64")
20
- dname = "gene_onology_term_mapper_amd64:9a9a7cc"
21
- print(dname)
19
+ dname = docker_build(data, line, arch="amd64")
22
20
 
23
21
  size_cmd = ["docker", "inspect", "--format='{{.Size}}'", dname]
24
22
  line(f"<debug>Running: {' '.join(size_cmd)} </debug>")
@@ -38,7 +36,7 @@ def service_register(data, line):
38
36
  line("<error>Missing 'service-file' in [tool.poetry-plugin-ivcap]</error>")
39
37
  return
40
38
 
41
- dcfg = _docker_cfg(data, line, "amd64")
39
+ dcfg = docker_cfg(data, line, "amd64")
42
40
  pkg_cmd = ["ivcap", "package", "list", dcfg.docker_name]
43
41
  line(f"<debug>Running: {' '.join(pkg_cmd)} </debug>")
44
42
  pkg = subprocess.check_output(pkg_cmd).decode()
@@ -0,0 +1,107 @@
1
+ #
2
+ # Copyright (c) 2025 Commonwealth Scientific and Industrial Research Organisation (CSIRO). All rights reserved.
3
+ # Use of this source code is governed by a BSD-style license that can be
4
+ # found in the LICENSE file. See the AUTHORS file for names of contributors.
5
+ #
6
+ import os
7
+ from poetry.plugins.application_plugin import ApplicationPlugin
8
+ from cleo.commands.command import Command
9
+ from cleo.helpers import argument
10
+ import subprocess
11
+
12
+ from poetry_plugin_ivcap.util import get_version
13
+
14
+ from .ivcap import create_service_id, service_register, tool_register
15
+ from .docker import docker_build, docker_run
16
+ from .ivcap import docker_publish
17
+
18
+ class IvcapCommand(Command):
19
+ name = "ivcap"
20
+ description = "IVCAP plugin `poetry ivcap <subcommand>`"
21
+ help = """\
22
+
23
+ IVCAP plugin
24
+
25
+ Supporting the development of services and tools for the IVCAP platform
26
+
27
+ Available subcommands:
28
+ run Run the service locally
29
+ docker-build Build the docker image for this service
30
+ docker-run Run the service's docker image locally
31
+ docker-publish Publish the service's docker image to IVCAP
32
+ service-register Register the service with IVCAP
33
+ create-service-id Create a unique service ID for the service
34
+ tool-register Register the service as an AI Tool with IVCAP
35
+
36
+ Example:
37
+ poetry ivcap run -- --port 8080
38
+
39
+ Configurable options in pyproject.toml:
40
+
41
+ [tool.poetry-plugin-ivcap]
42
+ service-file = "service.py" # The Python file that implements the service
43
+ service-file = "service.py"
44
+ service-id = "urn:ivcap:service:ac158a1f-dfb4-5dac-bf2e-9bf15e0f2cc7" # A unique identifier for the service
45
+
46
+ docker-build-template = "docker buildx build -t #DOCKER_NAME# ."
47
+ docker-run-template = "docker run -rm -p #PORT#:#PORT#"
48
+ """
49
+ arguments = [
50
+ argument("subcommand", optional=True, description="Subcommand: run, deploy, etc."),
51
+ argument("args", optional=True, multiple=True, description="Additional arguments for subcommand"),
52
+ ]
53
+
54
+ allow_extra_args = True
55
+ ignore_validation_errors = True
56
+
57
+ def handle(self):
58
+ poetry = self.application.poetry
59
+ data = poetry.pyproject.data
60
+
61
+ sub = self.argument("subcommand")
62
+ args = self.argument("args")
63
+
64
+ if sub == "run":
65
+ self.run_service(data, args, self.line)
66
+ elif sub == "docker-build":
67
+ docker_build(data, self.line)
68
+ elif sub == "docker-run":
69
+ docker_run(data, args, self.line)
70
+ elif sub == "docker-publish":
71
+ docker_publish(data, self.line)
72
+ elif sub == "service-register":
73
+ service_register(data, self.line)
74
+ elif sub == "create-service-id":
75
+ sid = create_service_id(data, self.line)
76
+ print(sid)
77
+ elif sub == "tool-register":
78
+ tool_register(data, self.line)
79
+ else:
80
+ if not (sub == None or sub == "help"):
81
+ self.line(f"<error>Unknown subcommand: {sub}</error>")
82
+ print(self.help)
83
+
84
+ def run_service(self, data, args, line):
85
+ config = data.get("tool", {}).get("poetry-plugin-ivcap", {})
86
+
87
+ service = config.get("service-file")
88
+ if not service:
89
+ self.line("<error>Missing 'service-file' in [tool.poetry-plugin-ivcap]</error>")
90
+ return
91
+
92
+ if not '--port' in args:
93
+ port = config.get("port")
94
+ if port:
95
+ args.extend(["--port", str(port)])
96
+
97
+ env = os.environ.copy()
98
+ env["VERSION"] = get_version(data, None, line)
99
+
100
+ cmd = ["poetry", "run", "python", service]
101
+ cmd.extend(args)
102
+ self.line(f"<info>Running: {' '.join(cmd)}</info>")
103
+ subprocess.run(cmd, env=env)
104
+
105
+ class IvcapPlugin(ApplicationPlugin):
106
+ def activate(self, application):
107
+ application.command_loader.register_factory("ivcap", lambda: IvcapCommand())
@@ -5,6 +5,7 @@
5
5
  #
6
6
  import subprocess
7
7
  import platform
8
+ from datetime import datetime, timezone
8
9
 
9
10
  def get_name(data) -> str:
10
11
  project_data = data.get("project", {})
@@ -85,3 +86,23 @@ def execute_subprocess_and_capture_output(command):
85
86
  full_output += line
86
87
 
87
88
  return full_output
89
+
90
+ def get_version(data, tag, line):
91
+ if not tag:
92
+ try:
93
+ tag = subprocess.check_output(['git', 'rev-parse', "--short", 'HEAD']).decode().strip()
94
+ except Exception as e:
95
+ line(f"<warning>WARN: retrieving commit hash: {e}</warning>")
96
+ tag = "latest"
97
+
98
+ project_data = data.get("project", {})
99
+ v = project_data.get("version", None)
100
+ if not v:
101
+ try:
102
+ v = subprocess.check_output(['git', 'describe', '--tags', '--abbrev=0']).decode().strip()
103
+ except Exception as e:
104
+ line(f"<error>Error retrieving latest tag: {e}</error>")
105
+ v = "???"
106
+ now = datetime.now(timezone.utc).astimezone()
107
+ version = f"{v}|{tag}|{now.replace(microsecond=0).isoformat()}"
108
+ return version
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "poetry-plugin-ivcap"
3
- version = "0.1.0"
3
+ version = "0.2.2"
4
4
  description = "A custom Poetry command for IVCAP deployments"
5
5
  authors = ["Max Ott <max.ott@csiro.au>"]
6
6
  license = "MIT"
@@ -1,65 +0,0 @@
1
- # poetry-plugin-ivcap
2
-
3
- A custom Poetry plugin that adds a `poetry ivcap` command for local and Docker-based deployments.
4
-
5
- ## Example Configuration
6
-
7
- Add to your `pyproject.toml`:
8
-
9
- ```toml
10
- [tool.poetry-plugin-ivcap]
11
- default_target = "docker"
12
- docker_tag = "myapp:dev"
13
- ```
14
-
15
- ## Installation
16
-
17
- ```bash
18
- poetry self add poetry-plugin-ivcap
19
- ```
20
-
21
- ## Usage
22
-
23
- ```bash
24
- poetry ivcap
25
- poetry ivcap docker
26
- ```
27
-
28
- ## Development
29
-
30
- ### Build the Plugin Package
31
-
32
- ```bash
33
- poetry build
34
- ```
35
-
36
- This creates .whl and .tar.gz files in the dist/ directory.
37
-
38
- ### Publish to PyPI
39
-
40
- Create an account at https://pypi.org/account/register/
41
-
42
- Add your credentials:
43
- ```bash
44
- poetry config pypi-token.pypi <your-token>
45
- ```
46
-
47
- Publish:
48
- ```bash
49
- poetry publish --build
50
- ```
51
-
52
- ### Optional: Test on TestPyPI First
53
-
54
- To verify your setup without publishing to the real PyPI:
55
-
56
- ```bash
57
- poetry config repositories.test-pypi https://test.pypi.org/legacy/
58
- poetry publish -r test-pypi --build
59
- ```
60
-
61
- Then test installing via:
62
-
63
- ```bash
64
- poetry self add --source test-pypi poetry-plugin-deploy
65
- ```
@@ -1,70 +0,0 @@
1
- #
2
- # Copyright (c) 2025 Commonwealth Scientific and Industrial Research Organisation (CSIRO). All rights reserved.
3
- # Use of this source code is governed by a BSD-style license that can be
4
- # found in the LICENSE file. See the AUTHORS file for names of contributors.
5
- #
6
- from poetry.plugins.application_plugin import ApplicationPlugin
7
- from cleo.commands.command import Command
8
- from cleo.helpers import argument
9
- import subprocess
10
-
11
- from .ivcap import create_service_id, service_register, tool_register
12
- from .docker import docker_build, docker_run
13
- from .ivcap import docker_publish
14
-
15
- class IvcapCommand(Command):
16
- name = "ivcap"
17
- description = "IVCAP plugin `poetry ivcap <subcommand>`"
18
- help = """\
19
- IVCAP plugin
20
-
21
- Available subcommands:
22
- run Run the configured service
23
- deploy Deploy using configured settings
24
-
25
- Example:
26
- poetry ivcap run
27
- """
28
- arguments = [
29
- argument("subcommand", optional=True, description="Subcommand: run, deploy, etc.")
30
- ]
31
-
32
- def handle(self):
33
- poetry = self.application.poetry
34
- data = poetry.pyproject.data
35
-
36
- sub = self.argument("subcommand")
37
- if sub == "run":
38
- self.run_service(data)
39
- elif sub == "docker-build":
40
- docker_build(data, self.line)
41
- elif sub == "docker-run":
42
- docker_run(data, self.line)
43
- elif sub == "docker-publish":
44
- docker_publish(data, self.line)
45
- elif sub == "service-register":
46
- service_register(data, self.line)
47
- elif sub == "create-service-id":
48
- sid = create_service_id(data, self.line)
49
- print(sid)
50
- elif sub == "tool-register":
51
- tool_register(data, self.line)
52
- else:
53
- self.line(f"<error>Unknown subcommand: {sub}</error>")
54
-
55
- def run_service(self, data):
56
- config = data.get("tool", {}).get("poetry-plugin-ivcap", {})
57
-
58
- service = config.get("service-file")
59
- port = config.get("port")
60
-
61
- if not service or not port:
62
- self.line("<error>Missing 'service-file' or 'port' in [tool.poetry-plugin-ivcap]</error>")
63
- return
64
-
65
- self.line(f"<info>Running: python {service} --port {port}</info>")
66
- subprocess.run(["poetry", "run", "python", service, "--port", str(port)])
67
-
68
- class IvcapPlugin(ApplicationPlugin):
69
- def activate(self, application):
70
- application.command_loader.register_factory("ivcap", lambda: IvcapCommand())