3 ms·
How do create a package that can be installed using pip? Can you do that without setuptools or similar?
by guappa 3y ago
How do create a package that can be installed using pip?
Can you do that without setuptools or similar?
- eesmith 3y agoRight, but creating a package is not the same as installing a package, and your comment at https://news.ycombinator.com/item?id=38083296 https://news.ycombinator.com/item?id=38083296 concerned installing. > Can you do that without setuptools or similar? Sure. Here is a program which, when run, creates the zipfile "hello-1.0-py3-none-any.whl" containing the wheel for a package named "hello" along with an entry point for the command-line program also named "hello" # Create a wheel for a 'Hello, world!' Python package. # # To install: # pip install hello-1.0-py3-none-any.whl # # To use on the command-line: # hello # # To use from Python: # >>> import hello # >>> hello.main() # Hello, world! # # To uninstall: # pip uninstall hello import base64, hashlib, zipfile package_name = "hello" version = "1.0" # This will go in hello/__init__.py payload = """ def main(): print("Hello, world!") """ METADATA = f"""\ Metadata-Version: 2.1 Name: {package_name} Version: {version} Summary: Example of a hand-built wheel. Home-page: http://news.ycombinator.com/ Author: eesmith Author-email: eesmith@example.com License: Public Domain Platform: UNKNOWN UNKNOWN """ # This causes the installer to create the command-line 'hello' program. entry_points = """\ [console_scripts] hello = hello:main """ WHEEL = """\ Wheel-Version: 1.0 Generator: eesmith_wheelgen (0.0.0) Root-Is-Purelib: true Tag: py3-none-any """ top_level = f""" {package_name} """ def build(): wheel_name = f"{package_name}-{version}-py3-none-any.whl" with zipfile.ZipFile(wheel_name, "w") as zip: dist_info = f"{package_name}-{version}.dist-info" # Add a file and build up information needed for the RECORD . record_lines = [] def add_file(filename, content): with zip.open(filename, "w") as f: byte_content = content.encode("utf8") f.write(byte_content) digest = hashlib.sha256(byte_content).digest() encoded = base64.urlsafe_b64encode(digest).rstrip(b"=") record_line = f"{filename},sha256={encoded},{len(byte_content)}\n" record_lines.append(record_line.encode("utf8")) add_file(f"{package_name}/__init__.py", payload) add_file(f"{dist_info}/METADATA", METADATA) add_file(f"{dist_info}/WHEEL", WHEEL) add_file(f"{dist_info}/entry_points.txt", entry_points) add_file(f"{dist_info}/top_level.txt", top_level) with zip.open(f"{dist_info}/RECORD", "w") as f: f.writelines(record_lines) if __name__ == "__main__": build()
- guappa 3y agoSurely you can't install a package if you first can't create it?
- eesmith 3y agoYou can easily install a third-party package, which will bootstrap you to one way to create package. But, okay, you want to install a package you wrote, using only a stock Python installation. 1) Why? That is, you can modify your PYTHONPATH to include your working directory. 2) Why use an installer? For simple packages you can drop the file/directory into site-packages. 3) I've been using Python for long enough that I distributed Python packages before there was a setup.py or setuptools. I used a Makefile. In fact, I still use a Makefile when I need faster build cycle times as setup.py does not do good dependency management. 4) I showed you how to build a wheel using only stock Python code, which lets you use pip as the installer. Finally, with a source distribution you can tweak Python's own Makefile to build your own module, including a C extension: https://docs.python.org/3/extending/extending.html#compilation-and-linkage https://docs.python.org/3/extending/extending.html#compilati... Why don't any of these resolve your issue?