Skip to content

Commit

Permalink
Merge pull request #41 from vroncevic/dev
Browse files Browse the repository at this point in the history
[daemonpy] Updated code coverage, docs
  • Loading branch information
vroncevic committed Jun 17, 2024
2 parents a7ef399 + 865a901 commit ac90cdd
Show file tree
Hide file tree
Showing 62 changed files with 576 additions and 13,676 deletions.
1 change: 0 additions & 1 deletion .gitconfig

This file was deleted.

1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/daemonpy_bug_report.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ assignees: vroncevic

---


1 change: 0 additions & 1 deletion .github/ISSUE_TEMPLATE/daemonpy_feature_request.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,3 @@ assignees: vroncevic

---


4 changes: 2 additions & 2 deletions .github/workflows/daemonpy_toc.yml
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
name: daemonpy_toc
on:
push:
branches: [ main ]
branches: [ master ]
paths:
- '**.md'
jobs:
generateTOC:
name: daemonpy_toc
runs-on: ubuntu-latest
steps:
- uses: technote-space/toc-generator@v4
- uses: technote-space/toc-generator@v4
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<img align="right" src="https://raw.githubusercontent.com/vroncevic/daemonpy/dev/docs/daemonpy_logo.png" width="25%">

# Creating Daemon process

<img align="right" src="https://raw.githubusercontent.com/vroncevic/daemonpy/dev/docs/daemonpy_logo.png" width="25%">

**daemonpy** is package for creating Daemon processes.

Developed in **[python](https://www.python.org/)** code: **100%**.
Expand Down Expand Up @@ -91,6 +91,7 @@ You can use Dockerfile to create image/container.
### Usage

Create short example

```python
#!/usr/bin/env python

Expand Down
3 changes: 2 additions & 1 deletion _config.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
theme: jekyll-theme-midnight
markdown: kramdown
safe: true
kramdown:
parse_block_html: true
parse_block_html: true
135 changes: 59 additions & 76 deletions daemonpy/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
__copyright__ = '(C) 2024, https://vroncevic.github.io/daemonpy'
__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
__license__ = 'https://github.com/vroncevic/daemonpy/blob/dev/LICENSE'
__version__ = '2.0.3'
__version__ = '2.0.4'
__maintainer__ = 'Vladimir Roncevic'
__email__ = 'elektron.ronca@gmail.com'
__status__ = 'Updated'
Expand All @@ -61,7 +61,7 @@ class Daemon(UnixOperations):
:attributes:
| _PKG_VERBOSE - Console text indicator for process-phase.
| _daemon_usage - Daemon usage.
| _pid_path - PID file path.
| _pid - PID file path.
:methods:
| __init__ - Initials Daemon constructor.
| daemonize - Creates daemon process.
Expand All @@ -72,14 +72,14 @@ class Daemon(UnixOperations):
| run - Runs daemon process (abstract method).
'''

_PKG_VERBOSE: str = 'DAEMONPY'
_P_VERBOSE: str = 'DAEMONPY'

def __init__(self, pid_path: str, verbose: bool = False) -> None:
def __init__(self, pid: str, verbose: bool = False) -> None:
'''
Initials Daemon constructor.
:param pid_path: PID file path
:type pid_path: <str>
:param pid: PID file path
:type pid: <str>
:param verbose: Enable/Disable verbose option
:type verbose: <bool>
:exceptions: ATSTypeError | ATSValueError
Expand All @@ -88,19 +88,17 @@ def __init__(self, pid_path: str, verbose: bool = False) -> None:
error_msg: str | None = None
error_id: int | None = None
checker: ATSChecker = ATSChecker()
error_msg, error_id = checker.check_params([
('str:pid_path', pid_path)
])
error_msg, error_id = checker.check_params([('str:pid', pid)])
if error_id == checker.TYPE_ERROR:
raise ATSTypeError(error_msg)
if not bool(pid_path):
if not bool(pid):
raise ATSValueError('missing PID file')
verbose_message(verbose, [f'{self._PKG_VERBOSE} init daemon process'])
verbose_message(verbose, [f'{self._P_VERBOSE} init daemon'])
self._daemon_usage: DaemonUsage | None = None
self._pid_path: str | None = None
self._pid: str | None = None
if self.unix_status:
self._daemon_usage = DaemonUsage()
self._pid_path = pid_path
self._pid = pid

def usage(self, operation: str, verbose: bool = False) -> None:
'''
Expand All @@ -121,11 +119,9 @@ def usage(self, operation: str, verbose: bool = False) -> None:
if error_id == checker.TYPE_ERROR:
raise ATSTypeError(error_msg)
if not bool(operation):
raise ATSValueError('missing operation')
verbose_message(
verbose, [f'{self._PKG_VERBOSE} daemon operation', operation]
)
if self.unix_status:
raise ATSValueError('missing daemon operation')
verbose_message(verbose, [f'{self._P_VERBOSE} daemon', operation])
if self.unix_status and bool(self._daemon_usage):
self._daemon_usage.check(operation, verbose)
if self._daemon_usage.usage_status == 127:
sys.exit(127)
Expand All @@ -136,7 +132,7 @@ def usage(self, operation: str, verbose: bool = False) -> None:
elif self._daemon_usage.usage_status == 2:
self.restart(verbose)
else:
error_message([f'{self._PKG_VERBOSE} wrong option code'])
error_message([f'{self._P_VERBOSE} wrong option code'])
sys.exit(128)

def daemonize(self, verbose: bool = False) -> None:
Expand All @@ -148,9 +144,7 @@ def daemonize(self, verbose: bool = False) -> None:
:exceptions: None
'''
null: str = '/dev/null'
verbose_message(
verbose, [f'{self._PKG_VERBOSE} create daemon process']
)
verbose_message(verbose, [f'{self._P_VERBOSE} create daemon'])
if self.unix_status:
try:
self.first_fork()
Expand All @@ -166,14 +160,18 @@ def daemonize(self, verbose: bool = False) -> None:
sys.stdout.flush()
sys.stderr.flush()
with FileDescriptor(null, FileDescriptor.STDIN) as in_file:
dup2(in_file.fileno(), sys.stdin.fileno())
if bool(in_file):
dup2(in_file.fileno(), sys.stdin.fileno())
with FileDescriptor(null, FileDescriptor.STDOUT) as out_file:
dup2(out_file.fileno(), sys.stdout.fileno())
if bool(out_file):
dup2(out_file.fileno(), sys.stdout.fileno())
with FileDescriptor(null, FileDescriptor.STDERR) as err_file:
dup2(err_file.fileno(), sys.stderr.fileno())
if bool(err_file):
dup2(err_file.fileno(), sys.stderr.fileno())
register(self.exit_handler)
with FileProcessId(self._pid_path, 'w+') as pid_path:
pid_path.write(f'{str(getpid())}\n')
with FileProcessId(self._pid, 'w+') as pid:
if bool(pid):
pid.write(f'{str(getpid())}\n')

def start(self, verbose: bool = False) -> bool:
'''
Expand All @@ -186,21 +184,20 @@ def start(self, verbose: bool = False) -> bool:
:exceptions: None
'''
status: bool = False
verbose_message(
verbose, [f'{self._PKG_VERBOSE} start daemon process']
)
verbose_message(verbose, [f'{self._P_VERBOSE} start daemon'])
if self.unix_status:
with FileProcessId(self._pid_path, 'w+') as pid_path:
if bool(pid_path.read().strip()):
error_message([
f'{self._PKG_VERBOSE} file',
self._pid_path,
'already exist daemon already running?'
])
else:
self.daemonize(verbose)
self.run()
status = True
with FileProcessId(self._pid, 'w+') as pid:
if bool(pid):
pid_content: str = pid.read().strip()
if bool(pid_content):
error_message([
f'{self._P_VERBOSE} file', self._pid,
'already exists, daemon already running?'
])
else:
self.daemonize(verbose)
self.run()
status = True
return status

def stop(self, verbose: bool = False) -> bool:
Expand All @@ -214,18 +211,15 @@ def stop(self, verbose: bool = False) -> bool:
:exceptions: None
'''
status: bool = False
verbose_message(
verbose, [f'{self._PKG_VERBOSE} stop daemon process']
)
verbose_message(verbose, [f'{self._P_VERBOSE} stop daemon'])
if self.unix_status:
with FileProcessId(self._pid_path, 'r') as pid_path:
pid: int = int(pid_path.read().strip())
if not pid:
error_message(
[f'{self._PKG_VERBOSE} daemon process running?']
)
else:
status = self.unix_kill(pid, self._pid_path)
with FileProcessId(self._pid, 'r') as pid:
if bool(pid) and bool(self._pid):
pid_content: str = pid.read().strip()
if not bool(pid_content):
error_message([f'{self._P_VERBOSE} daemon running?'])
else:
status = self.unix_kill(int(pid_content), self._pid)
return status

def restart(self, verbose: bool = False) -> bool:
Expand All @@ -239,20 +233,14 @@ def restart(self, verbose: bool = False) -> bool:
:exceptions: None
'''
status: bool = False
verbose_message(
verbose, [f'{self._PKG_VERBOSE} restart daemon process']
)
verbose_message(verbose, [f'{self._P_VERBOSE} restart daemon'])
if self.unix_status:
if all([self.stop(verbose), self.start(verbose)]):
status = True
else:
error_message(
[f'{self._PKG_VERBOSE} faled to restart daemon process']
)
error_message([f'{self._P_VERBOSE} faled to restart daemon'])
else:
error_message(
[f'{self._PKG_VERBOSE} daemon process is active?']
)
error_message([f'{self._P_VERBOSE} daemon is active?'])
return status

def exit_handler(self, verbose: bool = False) -> None:
Expand All @@ -264,24 +252,19 @@ def exit_handler(self, verbose: bool = False) -> None:
:exceptions: None
'''
if self.unix_status:
if exists(self._pid_path):
verbose_message(
verbose, [
f'{self._PKG_VERBOSE} removing pid file',
self._pid_path
]
)
remove(self._pid_path)
if not bool(self._pid):
error_message([f'{self._P_VERBOSE} check PID', self._pid])
else:
error_message(
[
f'{self._PKG_VERBOSE} check PID file',
self._pid_path
]
)
if exists(self._pid):
verbose_message(
verbose, [f'{self._P_VERBOSE} removing PID', self._pid]
)
remove(self._pid)
else:
error_message([f'{self._P_VERBOSE} check PID', self._pid])

@abstractmethod
def run(self):
def run(self) -> None:
'''
Run daemon process.
Override this method when subclass self.
Expand Down
15 changes: 7 additions & 8 deletions daemonpy/daemon_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
__copyright__ = '(C) 2024, https://vroncevic.github.io/daemonpy'
__credits__: List[str] = ['Vladimir Roncevic', 'Python Software Foundation']
__license__ = 'https://github.com/vroncevic/daemonpy/blob/dev/LICENSE'
__version__ = '2.0.3'
__version__ = '2.0.4'
__maintainer__ = 'Vladimir Roncevic'
__email__ = 'elektron.ronca@gmail.com'
__status__ = 'Updated'
Expand All @@ -60,7 +60,7 @@ class DaemonUsage:
| check - Checks usage for daemon process.
'''

_PKG_VERBOSE: str = 'DAEMONPY::DAEMON_USAGE'
_P_VERBOSE: str = 'DAEMONPY::DAEMON_USAGE'
DAEMON_OPERATIONS: List[str] = ['start', 'stop', 'restart']

def __init__(self, verbose: bool = False) -> None:
Expand All @@ -71,7 +71,7 @@ def __init__(self, verbose: bool = False) -> None:
:type verbose: <bool>
:exceptions: None
'''
verbose_message(verbose, [f'{self._PKG_VERBOSE} init usage'])
verbose_message(verbose, [f'{self._P_VERBOSE} init usage'])
self._usage_status: int = 0

@property
Expand All @@ -96,7 +96,7 @@ def usage_status(self, usage_status: int) -> None:
'''
self._usage_status = usage_status

def check(self, daemon_operation: str, verbose: bool = False):
def check(self, daemon_operation: str, verbose: bool = False) -> None:
'''
Checks usage of Daemon process.
Expand All @@ -116,17 +116,16 @@ def check(self, daemon_operation: str, verbose: bool = False):
raise ATSTypeError(error_msg)
if not bool(daemon_operation):
raise ATSValueError('missing daemon operation')
verbose_message(verbose, [f'{self._PKG_VERBOSE} checking usage'])
verbose_message(verbose, [f'{self._P_VERBOSE} checking usage'])
for index, option in enumerate(self.DAEMON_OPERATIONS):
if option == daemon_operation:
self._usage_status = index
if daemon_operation not in self.DAEMON_OPERATIONS:
self._usage_status = 127
error_message([
f'{self._PKG_VERBOSE} usage: {0}',
f'{self._P_VERBOSE} usage: {0}',
'|'.join(self.DAEMON_OPERATIONS)
])
verbose_message(
verbose,
[f'{self._PKG_VERBOSE} usage status', self._usage_status]
verbose, [f'{self._P_VERBOSE} usage status', self._usage_status]
)
Loading

0 comments on commit ac90cdd

Please sign in to comment.