Add idents to processes

This commit is contained in:
Jake Howard 2018-12-18 20:16:34 +00:00
parent 7af173c0cf
commit f9476ee1df
Signed by: jake
GPG key ID: 57AFB45680EDD477
6 changed files with 70 additions and 32 deletions

View file

@ -1,16 +1,31 @@
import re
from dataclasses import dataclass, field from dataclasses import dataclass, field
from pathlib import Path from pathlib import Path
from typing import List from typing import List
from .procfile import Process, parse_procfile_processes
PROCFILE_LOCATIONS = ["Procfile", "etc/environments/development/Procfile"] PROCFILE_LOCATIONS = ["Procfile", "etc/environments/development/Procfile"]
PROCFILE_LINE = re.compile(r"^([A-Za-z0-9_]+):\s*(.+)$")
class DuplicateProcessException(Exception):
pass
def parse_procfile_processes(project, procfile_lines):
seen_names = []
for line in procfile_lines:
m = PROCFILE_LINE.match(line)
if m:
if m.group(1) in seen_names:
raise DuplicateProcessException(m.group(1))
seen_names.append(m.group(1))
yield Process(project, m.group(1), m.group(2))
@dataclass @dataclass
class Project: class Project:
root: Path root: Path
processes: List[Process] = field(default_factory=list) processes: List["Process"] = field(default_factory=list)
def __post_init__(self): def __post_init__(self):
self.root = Path(self.root) self.root = Path(self.root)
@ -22,7 +37,7 @@ class Project:
procfile_path = self.root.joinpath(location) procfile_path = self.root.joinpath(location)
if procfile_path.exists(): if procfile_path.exists():
with procfile_path.open() as f: with procfile_path.open() as f:
return list(parse_procfile_processes(f.readlines())) return list(parse_procfile_processes(self, f.readlines()))
return [] return []
def exists(self): def exists(self):
@ -31,3 +46,20 @@ class Project:
@property @property
def name(self): def name(self):
return self.root.name return self.root.name
def get_process(self, name):
try:
return next(proc for proc in self.processes if proc.name == name)
except StopIteration:
return None
@dataclass
class Process:
project: Project
name: str
command: str
@property
def ident(self):
return self.project.name + ":" + self.name

View file

@ -1,22 +0,0 @@
import re
from typing import NamedTuple
Process = NamedTuple("Process", [("name", str), ("command", str)])
class DuplicateProcessException(Exception):
pass
PROCFILE_LINE = re.compile(r"^([A-Za-z0-9_]+):\s*(.+)$")
def parse_procfile_processes(procfile_lines):
seen_names = []
for line in procfile_lines:
m = PROCFILE_LINE.match(line)
if m:
if m.group(1) in seen_names:
raise DuplicateProcessException(m.group(1))
yield Process(m.group(1), m.group(2))
seen_names.append(m.group(1))

View file

@ -1 +1,2 @@
web: python -m http.server $PORT web: python -m http.server $PORT
bg: python src/dummy_program.py

View file

@ -21,8 +21,8 @@ from catfish.utils.sockets import create_base_socket_dir, delete_base_socket_dir
class BaseTestCase(TestCase): class BaseTestCase(TestCase):
TESTS_DIR = Path(os.path.dirname(__file__)) TESTS_DIR = Path(os.path.dirname(__file__))
DUMMY_EXE = TESTS_DIR.joinpath("dummy_program.py")
EXAMPLE_DIR = TESTS_DIR.parent.joinpath("example") EXAMPLE_DIR = TESTS_DIR.parent.joinpath("example")
DUMMY_EXE = EXAMPLE_DIR.joinpath("src", "dummy_program.py")
def setUp(self): def setUp(self):
create_base_socket_dir() create_base_socket_dir()

View file

@ -1,4 +1,4 @@
from catfish.project import Project from catfish.project import DuplicateProcessException, Project, parse_procfile_processes
from tests import BaseTestCase from tests import BaseTestCase
@ -15,10 +15,37 @@ class ProjectTestCase(BaseTestCase):
Project("/nonexistent") Project("/nonexistent")
def test_read_processes(self): def test_read_processes(self):
self.assertEqual(len(self.project.processes), 1) self.assertEqual(len(self.project.processes), 2)
process = self.project.processes[0] web_process = self.project.processes[0]
self.assertEqual(process.name, "web") self.assertEqual(web_process.name, "web")
self.assertEqual(process.command, "python -m http.server $PORT") self.assertEqual(web_process.command, "python -m http.server $PORT")
self.assertEqual(web_process.project, self.project)
bg_process = self.project.processes[1]
self.assertEqual(bg_process.name, "bg")
self.assertEqual(bg_process.command, "python src/dummy_program.py")
self.assertEqual(bg_process.project, self.project)
def test_get_process(self):
self.assertEqual(self.project.get_process("web").name, "web")
self.assertEqual(self.project.get_process("bg").name, "bg")
self.assertIsNone(self.project.get_process("nonexistent"))
def test_name(self): def test_name(self):
self.assertEqual(self.project.name, "example") self.assertEqual(self.project.name, "example")
class ProcessTestCase(BaseTestCase):
def setUp(self):
super().setUp()
self.project = Project(self.EXAMPLE_DIR)
self.process = self.project.get_process("web")
def test_process_ident(self):
self.assertEqual(self.process.ident, "example:web")
def test_duplicate_procfile(self):
with self.assertRaises(DuplicateProcessException) as e:
list(parse_procfile_processes(self.project, ["web: 123.py", "web: 456.py"]))
self.assertEqual(str(e.exception), "web")