From 06aa9a2dcef89ae99d761a952b4f748368ebfe1e Mon Sep 17 00:00:00 2001 From: "Michael Pilosov, PhD" Date: Thu, 25 Jan 2024 16:07:27 +0000 Subject: [PATCH] initial commit --- .gitignore | 161 ++++++++++++++++++++++++++++++++++++++++++++++++++ README.md | 50 ++++++++++++++++ lazy_serve.py | 80 +++++++++++++++++++++++++ setup.py | 15 +++++ 4 files changed, 306 insertions(+) create mode 100644 .gitignore create mode 100644 README.md create mode 100644 lazy_serve.py create mode 100644 setup.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b1cb160 --- /dev/null +++ b/.gitignore @@ -0,0 +1,161 @@ +# Byte-compiled / optimized / DLL files +__pycache__/ +*.py[cod] +*$py.class + +# C extensions +*.so + +# Distribution / packaging +.Python +build/ +develop-eggs/ +dist/ +downloads/ +eggs/ +.eggs/ +lib/ +lib64/ +parts/ +sdist/ +var/ +wheels/ +share/python-wheels/ +*.egg-info/ +.installed.cfg +*.egg +MANIFEST + +# PyInstaller +# Usually these files are written by a python script from a template +# before PyInstaller builds the exe, so as to inject date/other infos into it. +*.manifest +*.spec + +# Installer logs +pip-log.txt +pip-delete-this-directory.txt + +# Unit test / coverage reports +htmlcov/ +.tox/ +.nox/ +.coverage +.coverage.* +.cache +nosetests.xml +coverage.xml +*.cover +*.py,cover +.hypothesis/ +.pytest_cache/ +cover/ + +# Translations +*.mo +*.pot + +# Django stuff: +*.log +local_settings.py +db.sqlite3 +db.sqlite3-journal + +# Flask stuff: +instance/ +.webassets-cache + +# Scrapy stuff: +.scrapy + +# Sphinx documentation +docs/_build/ + +# PyBuilder +.pybuilder/ +target/ + +# Jupyter Notebook +.ipynb_checkpoints + +# IPython +profile_default/ +ipython_config.py + +# pyenv +# For a library or package, you might want to ignore these files since the code is +# intended to run in multiple environments; otherwise, check them in: +# .python-version + +# pipenv +# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. +# However, in case of collaboration, if having platform-specific dependencies or dependencies +# having no cross-platform support, pipenv may install dependencies that don't work, or not +# install all needed dependencies. +#Pipfile.lock + +# poetry +# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. +# This is especially recommended for binary packages to ensure reproducibility, and is more +# commonly ignored for libraries. +# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control +#poetry.lock + +# pdm +# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. +#pdm.lock +# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it +# in version control. +# https://pdm.fming.dev/#use-with-ide +.pdm.toml + +# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm +__pypackages__/ + +# Celery stuff +celerybeat-schedule +celerybeat.pid + +# SageMath parsed files +*.sage.py + +# Environments +.env +.venv +env/ +venv/ +ENV/ +env.bak/ +venv.bak/ + +# Spyder project settings +.spyderproject +.spyproject + +# Rope project settings +.ropeproject + +# mkdocs documentation +/site + +# mypy +.mypy_cache/ +.dmypy.json +dmypy.json + +# Pyre type checker +.pyre/ + +# pytype static type analyzer +.pytype/ + +# Cython debug symbols +cython_debug/ + +# PyCharm +# JetBrains specific template is maintained in a separate JetBrains.gitignore that can +# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore +# and can be added to the global gitignore or merged into this file. For a more nuclear +# option (not recommended) you can uncomment the following to ignore the entire idea folder. +#.idea/ + diff --git a/README.md b/README.md new file mode 100644 index 0000000..a16456f --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +``` +# lazy_serve + +A simple, easy-to-use Python package for starting HTTP servers with minimal setup. Ideal for serving static files in development environments or for lightweight file sharing. + +## Installation + +To install lazy_serve, simply use pip: + +```sh +pip install lazy_serve +``` + +## Usage + +Using lazy_serve is straightforward. Here's a basic example: + +```python +import lazy_serve as lz + +if __name__ == "__main__": + servers = [(8080, "~/server1/out/"), (8081, "~/server2/out/")] + lz.serve(servers) +``` + +This code will start HTTP servers on ports 8080 and 8081, serving files from `~/server1/out/` and `~/server2/out/` respectively. + +## Features + +- **Easy to Use:** Start a server in just a few lines of code. +- **Flexible:** Serve any directory by simply specifying its path. +- **Concurrent Servers:** Run multiple servers at once, each on its own port. + +## Requirements + +- Python 3.6 or higher + +## Contributing + +Contributions to lazy_serve are welcome! Please follow these steps to contribute: + +1. Fork the repository. +2. Create a new branch for your feature. +3. Add your feature or bug fix. +4. Run the tests to ensure everything is working. +5. Submit a pull request. + +## License + +This project is licensed under the MIT License. diff --git a/lazy_serve.py b/lazy_serve.py new file mode 100644 index 0000000..2a2ea66 --- /dev/null +++ b/lazy_serve.py @@ -0,0 +1,80 @@ +""" +lazy_serve.py +------------- + +A simple package for effortlessly starting HTTP servers. + +Example usage: +--------------- +import lazy_serve as lz + +if __name__ == "__main__": + servers = [(8080, "~/server1/out/"), (8081, "~/server2/out/")] + lz.serve(servers) +""" + +import subprocess +import threading +import os + +class ServerThread(threading.Thread): + """ + A thread for running an HTTP server using subprocess. + + Parameters + ---------- + port : int + The port number on which the server will listen. + directory : str + The directory from which the server will serve files. + + Attributes + ---------- + port : int + The port number on which the server will listen. + directory : str + The directory from which the server will serve files. + """ + + def __init__(self, port, directory): + super().__init__() + self.port = port + self.directory = directory + + def run(self): + """ + Starts the server and serves files indefinitely using subprocess. + """ + cmd = f'python -m http.server {self.port}' + env = os.environ.copy() + env['PWD'] = os.path.expanduser(self.directory) + self.process = subprocess.Popen(cmd, shell=True, env=env, cwd=env['PWD']) + + def join(self, timeout=None): + """ + Stop the server. + """ + self.process.terminate() + super().join(timeout) + +def serve(servers): + """ + Starts multiple HTTP servers in separate threads using subprocess. + + Parameters + ---------- + servers : list of tuple + A list of tuples, each containing a port number and a directory path. + + Example + ------- + >>> serve([(8080, '~/mydir'), (8081, '~/myotherdir')]) + """ + threads = [] + for port, directory in servers: + thread = ServerThread(port, directory) + thread.start() + threads.append(thread) + + for thread in threads: + thread.join() diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..2c6e994 --- /dev/null +++ b/setup.py @@ -0,0 +1,15 @@ +from setuptools import setup, find_packages + +setup( + name='lazy_serve', + version='0.1', + description='A simple package for effortlessly starting HTTP servers.', + long_description=open('README.md').read(), + long_description_content_type='text/markdown', + author='Your Name', + author_email='your.email@example.com', + url='https://github.com/yourusername/lazy_serve', + packages=find_packages(), + install_requires=[], + python_requires='>=3.6', +)