From e62d7c5ea3bc014123cf6f78e5345c588cd4f068 Mon Sep 17 00:00:00 2001
From: Simeon Simeonov
Date: Thu, 12 Jan 2023 22:36:04 +0100
Subject: Make the project PEP517 compatible
---
Makefile | 6 +--
README.md | 2 +-
ngus/__init__.py | 128 ---------------------------------------------------
ngus/__main__.py | 114 ---------------------------------------------
pyproject.toml | 7 +++
setup.cfg | 41 +++++++++++++++++
setup.py | 47 ++-----------------
src/ngus/__init__.py | 128 +++++++++++++++++++++++++++++++++++++++++++++++++++
src/ngus/__main__.py | 114 +++++++++++++++++++++++++++++++++++++++++++++
9 files changed, 297 insertions(+), 290 deletions(-)
delete mode 100644 ngus/__init__.py
delete mode 100644 ngus/__main__.py
create mode 100644 pyproject.toml
create mode 100644 setup.cfg
create mode 100644 src/ngus/__init__.py
create mode 100644 src/ngus/__main__.py
diff --git a/Makefile b/Makefile
index 852f221..e9fb990 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,5 @@
-package: COPYING ngus/__init__.py ngus/__main__.py LICENSE README.md setup.py
- python setup.py sdist bdist_wheel
+package: COPYING src/ngus/__init__.py src/ngus/__main__.py LICENSE README.md setup.py pyproject.toml setup.cfg
+ python -m build
upload: dist/*
python -m twine upload dist/*
@@ -8,4 +8,4 @@ upload-test: dist/*
python -m twine upload --repository testpypi dist/*
clean:
- rm -rf build dist ngus/__pycache__ ngus.egg-info
+ rm -rf dist src/ngus/__pycache__ src/ngus.egg-info
diff --git a/README.md b/README.md
index 67689ad..670720a 100644
--- a/README.md
+++ b/README.md
@@ -163,7 +163,7 @@ Simeon Simeonov - sgs @ LiberaChat
## [License](https://github.com/blackm0re/ngus/blob/master/LICENSE)
-Copyright (c) 2021, Simeon Simeonov
+Copyright (c) 2021-2023 Simeon Simeonov
All rights reserved.
[Licensed](https://github.com/blackm0re/ngus/blob/master/LICENSE) under the
diff --git a/ngus/__init__.py b/ngus/__init__.py
deleted file mode 100644
index 2b2be7d..0000000
--- a/ngus/__init__.py
+++ /dev/null
@@ -1,128 +0,0 @@
-# ngus v1.0
-# Copyright (C) 2021 Simeon Simeonov
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import cgi
-import http.server
-import pathlib
-
-__author__ = 'Simeon Simeonov'
-__version__ = '1.0'
-__license__ = 'GPL3'
-
-DEFAULT_UPLOAD_PAGE = bytes('''
-
-
-File Upload
-
-
-
-
-File Upload
-
-
-''', 'utf-8')
-
-
-class NgusBaseHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
- """
- A custom http.server.SimpleHTTPRequestHandler that handles POST uploads
- """
- def do_GET(self):
- """GET requests will load the upload page"""
- self._send_upload_page()
-
- def do_POST(self):
- """POST requests will be handled according to the settings"""
- if self.server.basic_auth is not None:
- if (
- 'Authorization' not in self.headers
- or len(self.headers['Authorization'].split()) != 2
- or self.headers['Authorization'].split()[0].lower() != 'basic'
- or self.headers[
- 'Authorization'
- ].split()[1] != self.server.basic_auth
- ):
- self.send_response(http.HTTPStatus.UNAUTHORIZED)
- self.send_header('WWW-Authenticate',
- 'Basic realm="ngus", charset="UTF-8"')
- self.end_headers()
- return None
- form = cgi.FieldStorage(fp=self.rfile,
- headers=self.headers,
- environ={'REQUEST_METHOD': 'POST'})
- if not (upload_dir := self.server.upload_dir).is_dir():
- raise ValueError('upload_dir is not a directory')
- i_name = self.server.input_name
- if i_name in form and form[i_name].file and form[i_name].filename:
- with open(
- upload_dir / pathlib.Path(form[i_name].filename).name,
- 'wb'
- ) as f:
- f.write(form[i_name].file.read())
- self._send_upload_page()
- return None
-
- def _send_upload_page(self):
- """Renders an upload page (form)"""
- self.send_response(http.HTTPStatus.OK)
- self.send_header('Content-Type', 'text/html; charset=utf-8')
- self.send_header('Content-Length', len(self.server.upload_page))
- self.end_headers()
- self.wfile.write(self.server.upload_page)
-
-
-class NgusHTTPServer(http.server.HTTPServer):
- """A custom http.server.HTTPServer"""
- def __init__(self, *arg, **kwargs):
- """
- """
- self._basic_auth = kwargs.pop('basic_auth', None)
- self._input_name = kwargs.pop('input_name', 'ufile')
- self._upload_dir = kwargs.pop('upload_dir', pathlib.Path.cwd())
- self._upload_page = kwargs.pop('upload_page', DEFAULT_UPLOAD_PAGE)
- super().__init__(*arg, **kwargs)
-
- @property
- def basic_auth(self):
- """basic_auth-property"""
- return self._basic_auth
-
- @property
- def input_name(self):
- """input_name-property"""
- return self._input_name
-
- @property
- def upload_dir(self):
- """upload_dir-property"""
- return self._upload_dir
-
- @property
- def upload_page(self):
- """upload_page-property"""
- return self._upload_page
diff --git a/ngus/__main__.py b/ngus/__main__.py
deleted file mode 100644
index 3d09dbf..0000000
--- a/ngus/__main__.py
+++ /dev/null
@@ -1,114 +0,0 @@
-# ngus v1.0
-# Copyright (C) 2021 Simeon Simeonov
-
-# This program is free software: you can redistribute it and/or modify
-# it under the terms of the GNU General Public License as published by
-# the Free Software Foundation, either version 3 of the License, or
-# (at your option) any later version.
-
-# This program is distributed in the hope that it will be useful,
-# but WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-# GNU General Public License for more details.
-
-# You should have received a copy of the GNU General Public License
-# along with this program. If not, see .
-
-import argparse
-import base64
-import logging
-import pathlib
-import sys
-
-import ngus
-
-
-def eprint(*arg, **kwargs):
- """stdderr print wrapper"""
- print(*arg, file=sys.stderr, flush=True, **kwargs)
-
-
-def main(inargs=None):
- """main entry point"""
- parser = argparse.ArgumentParser(
- description='The following options are available')
- parser.add_argument(
- '-b', '--basic-auth',
- metavar='',
- type=str,
- dest='basic_auth',
- default='',
- help=('Require Basic auth from the client in order to POST a file '
- '(default: No basic auth required)'))
- parser.add_argument(
- '-H', '--hostname',
- metavar='',
- type=str,
- dest='hostname',
- default='127.0.0.1',
- help='ngus server IP / hostname (default: 127.0.0.1)')
- parser.add_argument(
- '-i', '--input-name',
- metavar='',
- type=str,
- dest='input_name',
- default='ufile',
- help='The name of the form input field (default: "ufile")')
- parser.add_argument(
- '-p', '--port',
- metavar='',
- type=int,
- dest='port',
- default=8080,
- help='ngus server port (default: 8080)')
- parser.add_argument(
- '-u', '--upload-dir',
- metavar='',
- type=pathlib.Path,
- dest='upload_dir',
- default=pathlib.Path.cwd(),
- help='ngus server upload dir (default: CWD)')
- parser.add_argument(
- '-U', '--upload-page',
- metavar='',
- type=argparse.FileType('rb'),
- dest='upload_page',
- default=None,
- help='Alternative upload page (form) to display (default: None)')
- parser.add_argument(
- '-v', '--version',
- action='version',
- version=f'%(prog)s {ngus.__version__}',
- help='Display program-version and exit')
- args = parser.parse_args(inargs)
- try:
- logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
- level=logging.DEBUG)
- logger = logging.getLogger('ngus')
- logger.info('ngus starting')
- server_params = {
- 'input_name': args.input_name,
- 'upload_dir': args.upload_dir
- }
- if args.upload_page is not None:
- server_params['upload_page'] = args.upload_page.read()
- if args.basic_auth and len(args.basic_auth.split(':')) == 2:
- server_params['basic_auth'] = base64.b64encode(
- args.basic_auth.strip().encode('utf-8')).decode()
- logger.info('Requiring basic-auth')
- ngus_server = ngus.NgusHTTPServer((args.hostname, args.port),
- ngus.NgusBaseHTTPRequestHandler,
- **server_params)
- logger.info(f'Listening on {args.hostname}:{args.port}')
- logger.info('Done!')
- ngus_server.serve_forever()
- except KeyboardInterrupt:
- print('\n\nTerminating...')
- except Exception as e:
- eprint(f'ngus critical error: {e}')
- sys.exit(1)
- sys.exit(0)
-
-
-if __name__ == '__main__':
- main()
diff --git a/pyproject.toml b/pyproject.toml
new file mode 100644
index 0000000..73c35b2
--- /dev/null
+++ b/pyproject.toml
@@ -0,0 +1,7 @@
+[build-system]
+requires = [
+ "setuptools>=51",
+ "wheel"
+]
+
+build-backend = "setuptools.build_meta"
diff --git a/setup.cfg b/setup.cfg
new file mode 100644
index 0000000..795c715
--- /dev/null
+++ b/setup.cfg
@@ -0,0 +1,41 @@
+[metadata]
+name = ngus
+version = attr: ngus.__version__
+author = attr: ngus.__author__
+author_email = sgs@pichove.org
+description = A simple HTTP server for handleing file uploads
+long_description = file: README.md
+long_description_content_type = text/markdown
+url = https://github.com/blackm0re/ngus
+
+classifiers =
+ Development Status :: 5 - Production/Stable
+ Intended Audience :: End Users/Desktop
+ License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
+ Programming Language :: Python :: 3
+ Programming Language :: Python :: 3.7
+ Programming Language :: Python :: 3.8
+ Programming Language :: Python :: 3.9
+ Programming Language :: Python :: 3.10
+ Programming Language :: Python :: 3.11
+ Programming Language :: Python :: 3.12
+ Programming Language :: Python :: Implementation
+ Operating System :: OS Independent
+ Topic :: Internet :: WWW/HTTP :: HTTP Servers
+
+project_urls =
+ Bug Tracker = https://github.com/blackm0re/ngus/issues
+ Source = https://github.com/blackm0re/ngus
+
+[options]
+package_dir =
+ = src
+packages = find:
+python_requires = >=3.7
+
+[options.packages.find]
+where = src
+
+[options.entry_points]
+console_scripts =
+ ngus = ngus.__main__:main
diff --git a/setup.py b/setup.py
index fbdefcb..a5d21d8 100644
--- a/setup.py
+++ b/setup.py
@@ -1,46 +1,5 @@
-import setuptools
+# Legacy setup for some build / install systems
-import ngus
+from setuptools import setup
-with open('README.md', 'r') as fh:
- long_description = fh.read()
-
-
-setuptools.setup(
- name='ngus',
- version=ngus.__version__,
- author=ngus.__author__,
- author_email='sgs@pichove.org',
- description='A simple HTTP server for handleing file uploads',
- long_description=long_description,
- long_description_content_type='text/markdown',
- url='https://github.com/blackm0re/ngus',
- packages=setuptools.find_packages(),
- exclude_package_data={'': ['.gitignore']},
- entry_points={
- 'console_scripts': [
- 'ngus=ngus.__main__:main',
- ],
- },
- classifiers=[
- 'Development Status :: 5 - Production/Stable',
- 'Intended Audience :: End Users/Desktop',
- ('License :: OSI Approved :: GNU General Public License v3 or later '
- '(GPLv3+)'),
- 'Programming Language :: Python :: 3 :: Only',
- 'Programming Language :: Python :: 3.6',
- 'Programming Language :: Python :: 3.7',
- 'Programming Language :: Python :: 3.8',
- 'Programming Language :: Python :: 3.9',
- 'Programming Language :: Python :: 3.10',
- 'Programming Language :: Python :: Implementation',
- 'Operating System :: OS Independent',
- 'Topic :: Internet :: WWW/HTTP :: HTTP Servers'
- ],
- keywords='upload http httpd',
- project_urls={
- 'Bug Reports': 'https://github.com/blackm0re/ngus/issues',
- 'Source': 'https://github.com/blackm0re/ngus'
- },
- python_requires='>=3.6',
-)
+setup()
diff --git a/src/ngus/__init__.py b/src/ngus/__init__.py
new file mode 100644
index 0000000..d085fc1
--- /dev/null
+++ b/src/ngus/__init__.py
@@ -0,0 +1,128 @@
+# ngus
+# Copyright (C) 2021-2023 Simeon Simeonov
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import cgi
+import http.server
+import pathlib
+
+__author__ = 'Simeon Simeonov'
+__version__ = '2.0'
+__license__ = 'GPL3'
+
+DEFAULT_UPLOAD_PAGE = bytes('''
+
+
+File Upload
+
+
+
+
+File Upload
+
+
+''', 'utf-8')
+
+
+class NgusBaseHTTPRequestHandler(http.server.BaseHTTPRequestHandler):
+ """
+ A custom http.server.SimpleHTTPRequestHandler that handles POST uploads
+ """
+ def do_GET(self):
+ """GET requests will load the upload page"""
+ self._send_upload_page()
+
+ def do_POST(self):
+ """POST requests will be handled according to the settings"""
+ if self.server.basic_auth is not None:
+ if (
+ 'Authorization' not in self.headers
+ or len(self.headers['Authorization'].split()) != 2
+ or self.headers['Authorization'].split()[0].lower() != 'basic'
+ or self.headers[
+ 'Authorization'
+ ].split()[1] != self.server.basic_auth
+ ):
+ self.send_response(http.HTTPStatus.UNAUTHORIZED)
+ self.send_header('WWW-Authenticate',
+ 'Basic realm="ngus", charset="UTF-8"')
+ self.end_headers()
+ return None
+ form = cgi.FieldStorage(fp=self.rfile,
+ headers=self.headers,
+ environ={'REQUEST_METHOD': 'POST'})
+ if not (upload_dir := self.server.upload_dir).is_dir():
+ raise ValueError('upload_dir is not a directory')
+ i_name = self.server.input_name
+ if i_name in form and form[i_name].file and form[i_name].filename:
+ with open(
+ upload_dir / pathlib.Path(form[i_name].filename).name,
+ 'wb'
+ ) as f:
+ f.write(form[i_name].file.read())
+ self._send_upload_page()
+ return None
+
+ def _send_upload_page(self):
+ """Renders an upload page (form)"""
+ self.send_response(http.HTTPStatus.OK)
+ self.send_header('Content-Type', 'text/html; charset=utf-8')
+ self.send_header('Content-Length', len(self.server.upload_page))
+ self.end_headers()
+ self.wfile.write(self.server.upload_page)
+
+
+class NgusHTTPServer(http.server.HTTPServer):
+ """A custom http.server.HTTPServer"""
+ def __init__(self, *arg, **kwargs):
+ """
+ """
+ self._basic_auth = kwargs.pop('basic_auth', None)
+ self._input_name = kwargs.pop('input_name', 'ufile')
+ self._upload_dir = kwargs.pop('upload_dir', pathlib.Path.cwd())
+ self._upload_page = kwargs.pop('upload_page', DEFAULT_UPLOAD_PAGE)
+ super().__init__(*arg, **kwargs)
+
+ @property
+ def basic_auth(self):
+ """basic_auth-property"""
+ return self._basic_auth
+
+ @property
+ def input_name(self):
+ """input_name-property"""
+ return self._input_name
+
+ @property
+ def upload_dir(self):
+ """upload_dir-property"""
+ return self._upload_dir
+
+ @property
+ def upload_page(self):
+ """upload_page-property"""
+ return self._upload_page
diff --git a/src/ngus/__main__.py b/src/ngus/__main__.py
new file mode 100644
index 0000000..efa2c4a
--- /dev/null
+++ b/src/ngus/__main__.py
@@ -0,0 +1,114 @@
+# ngus
+# Copyright (C) 2021-2023 Simeon Simeonov
+
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+
+# You should have received a copy of the GNU General Public License
+# along with this program. If not, see .
+
+import argparse
+import base64
+import logging
+import pathlib
+import sys
+
+import ngus
+
+
+def eprint(*arg, **kwargs):
+ """stdderr print wrapper"""
+ print(*arg, file=sys.stderr, flush=True, **kwargs)
+
+
+def main(inargs=None):
+ """main entry point"""
+ parser = argparse.ArgumentParser(
+ description='The following options are available')
+ parser.add_argument(
+ '-b', '--basic-auth',
+ metavar='',
+ type=str,
+ dest='basic_auth',
+ default='',
+ help=('Require Basic auth from the client in order to POST a file '
+ '(default: No basic auth required)'))
+ parser.add_argument(
+ '-H', '--hostname',
+ metavar='',
+ type=str,
+ dest='hostname',
+ default='127.0.0.1',
+ help='ngus server IP / hostname (default: 127.0.0.1)')
+ parser.add_argument(
+ '-i', '--input-name',
+ metavar='',
+ type=str,
+ dest='input_name',
+ default='ufile',
+ help='The name of the form input field (default: "ufile")')
+ parser.add_argument(
+ '-p', '--port',
+ metavar='',
+ type=int,
+ dest='port',
+ default=8080,
+ help='ngus server port (default: 8080)')
+ parser.add_argument(
+ '-u', '--upload-dir',
+ metavar='',
+ type=pathlib.Path,
+ dest='upload_dir',
+ default=pathlib.Path.cwd(),
+ help='ngus server upload dir (default: CWD)')
+ parser.add_argument(
+ '-U', '--upload-page',
+ metavar='',
+ type=argparse.FileType('rb'),
+ dest='upload_page',
+ default=None,
+ help='Alternative upload page (form) to display (default: None)')
+ parser.add_argument(
+ '-v', '--version',
+ action='version',
+ version=f'%(prog)s {ngus.__version__}',
+ help='Display program-version and exit')
+ args = parser.parse_args(inargs)
+ try:
+ logging.basicConfig(format='%(asctime)s - %(levelname)s - %(message)s',
+ level=logging.DEBUG)
+ logger = logging.getLogger('ngus')
+ logger.info('ngus starting')
+ server_params = {
+ 'input_name': args.input_name,
+ 'upload_dir': args.upload_dir
+ }
+ if args.upload_page is not None:
+ server_params['upload_page'] = args.upload_page.read()
+ if args.basic_auth and len(args.basic_auth.split(':')) == 2:
+ server_params['basic_auth'] = base64.b64encode(
+ args.basic_auth.strip().encode('utf-8')).decode()
+ logger.info('Requiring basic-auth')
+ ngus_server = ngus.NgusHTTPServer((args.hostname, args.port),
+ ngus.NgusBaseHTTPRequestHandler,
+ **server_params)
+ logger.info(f'Listening on {args.hostname}:{args.port}')
+ logger.info('Done!')
+ ngus_server.serve_forever()
+ except KeyboardInterrupt:
+ print('\n\nTerminating...')
+ except Exception as e:
+ eprint(f'ngus critical error: {e}')
+ sys.exit(1)
+ sys.exit(0)
+
+
+if __name__ == '__main__':
+ main()
--
cgit v1.3