a static website generator to make beautiful customizable pictures galleries that tell a story

Overview

Prosopopee

Prosopopee. Static site generator for your story.

Make beautiful customizable pictures galleries that tell a story using a static website generator written in Python. You don't need to care about css, code and presentation, manage your contents in YAML file and Prosopopee will take care about the rest.

Prosopopee is sections oriented, make it very flexible, many kinds of section already available:

  • Parallax
  • Group of pics (gallery)
  • Paragraph
  • Iframe (Youtube, Maps, etc..)
  • Quote
  • And more

Screenshots

Features

Prosopopee currently supports:

  • Automatic generation
  • Lightweight
  • Thumbnails & multiple resolutions for fast previews (JPEG progressive)
  • Videos support
  • Mobile friendly
  • Caching for fast rendering
  • Multi level gallery
  • Support themes (default, material, light)
  • Password access (encrypt page)
  • Image lazy loading
  • Night Mode
  • Completely static output is easy to host anywhere
  • Hackable

Examples

You can find example usages here:

Code example

title: Title
date: 2015-12-18
cover: P1070043-01-01.jpeg
sections:
  - type: full-picture
    image: P1060979-01-01.jpeg
    fixed: true
    text:
      title: My Story
      sub_title: some subtitle
      date: 2015-12-18
  - type: paragraph
    title: Beautiful Title
    text: Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Aenean commodo ligula eget dolor
  - type: pictures-group
    images:
      -
        - P1060938-01-01.jpeg
        - P1060946-01-01.jpeg
        - P1060947-01-01.jpeg
        - P1060948-01-01.jpeg

Usage

  prosopopee
  prosopopee test
  prosopopee preview
  prosopopee deploy
  prosopopee autogen (-d <folder> | --all ) [--force]
  prosopopee (-h | --help)
  prosopopee --version
                                                                                
Options:                                                                        
  test          Verify all your yaml data                                       
  preview       Start preview webserver on port 8000                            
  deploy        Deploy your website                                             
  autogen       Generate gallery automaticaly                                   
  -h, --help    Show this screen.                                               
  --version     Show version.

Docker

https://hub.docker.com/r/beudbeud/prosopopee/

Licence

GLPv3

Documentation

http://prosopopee.readthedocs.org/en/latest/

IRC

channel : irc.freenode.net#prosopopee

Comments
  • image currently in view is moved 50% down while lazy loading

    image currently in view is moved 50% down while lazy loading

    It looks like this: 2020-09-20-1600557358_1920x1080 Once lazy loading is finished, the image returns in full view. When you move to the next image it does the same while the others are being loaded.

    I hate this bug because:

    • I don't want to show my site to anybody in this state. It's jarring and goes against the otherwise nice and clean design.
    • I have no experience with frontend and I don't even know where to begin investigating this, especially due to it's elusive nature. All I can think of right now is git bisect...

    Anybody out there pls help! I was able to fix all the other bugs that annoyed me (see pull requests). But it would be nice to have help with this one.

    opened by gangelop 9
  • Themes folder has to exist or prosopopee crashes

    Themes folder has to exist or prosopopee crashes

    If the themes folder does not exist, the build process instantly crashes.

    Traceback (most recent call last):
      File "/usr/local/bin/prosopopee", line 10, in <module>
        sys.exit(main())
      File "/usr/local/lib/python3.7/site-packages/prosopopee/prosopopee.py", line 610, in main
        templates = get_gallery_templates(theme)
      File "/usr/local/lib/python3.7/site-packages/prosopopee/prosopopee.py", line 336, in get_gallery_templates
        available_themes = theme, "', '".join(Path(__file__).parent.joinpath("themes").listdir())
      File "/usr/local/lib/python3.7/site-packages/path/__init__.py", line 497, in listdir
        self / child for child in os.listdir(self)
    NotADirectoryError: [Errno 20] Not a directory: Path('/usr/local/lib/python3.7/site-packages/prosopopee/themes')
    

    Affected version: 0.8.2

    I’ll fix this myself as soon as I find the time to do so.

    opened by morremeyer 7
  • Fix alignment issue when pictures do not fill the pictures-group line

    Fix alignment issue when pictures do not fill the pictures-group line

    When pictures are too small to fill a pictures-group's line (which can happen with two portrait pictures; for example on a 1080p screen since the pictures are x600 thumbnails, only two portrait pictures in one line would make the content of the line ~1200px instead of the ~1920px (it's actually with the current syle.css 77% of that => ~1500px) of available space.

    Alignment issue

    The issue is particularly present when zooming out: Alignment issue zooming out

    I'd expect the pictures to fill the whole line.

    With the fix: Fixed alignment

    Fixes #92

    opened by QSchulz 4
  • invalid date field results in traceback

    invalid date field results in traceback

    Typoing the date field results in a somewhat confusing error message:

    Traceback (most recent call last):
      File "/home/jelmer/bin/prosopopee", line 10, in <module>
        sys.exit(main())
      File "/home/jelmer/.local/lib/python3.7/site-packages/prosopopee/prosopopee.py", line 629, in main
        galleries=reversed(sorted([x for x in front_page_galleries_cover if x != {}], key=lambda x: x["date"]))
    TypeError: '<' not supported between instances of 'str' and 'datetime.date'
    
    opened by jelmer 4
  • [enh] Same cache logic for thumbs and fullsize pictures

    [enh] Same cache logic for thumbs and fullsize pictures

    • store gm settings in the cache as a dict
    • generalize usage of the gm settings to resize
    • can be used to resize fullsize versions of the pictures
    • without -quality switch, gm defaults to -quality 75. use -define jpeg:preserve-settings for fullsize versions to avoid altering them
    • do not store "name" in the cache, because when the same image is used in a gallery and as the cover, it invalidates the cache entry and becomes always generated
    opened by julienmalik 4
  • Make tox print the diff when black failed

    Make tox print the diff when black failed

    Running black --check only is not giving the changes to do. black --diff gives this but it does not fail when changes are required.

    black --diff --check brings the best of both worlds.

    Adding one small commit to patch my nick :)

    opened by QSchulz 3
  • Fix sorting when DateTime is not in the EXIF data

    Fix sorting when DateTime is not in the EXIF data

    Get in priority DateTimeOriginal to sort file as specified by the EXIF documentation. If there is no DateTimeOriginal fallback to DateTimeDigitized and then DateTime.

    opened by crypto512 3
  • implement include option

    implement include option

    This enables the inclusion of files with an include option. These files will be copied as is from the root of your project directory to the build directory. Example::

    title: My photos
    sub_title: wow
    include:
        - robots.txt
        - .well-known/brave-rewards-verification.txt
    

    This code is python3 only because of os.makedirs().

    opened by gangelop 3
  • Fix autogen bugs

    Fix autogen bugs

    If exif data exists but 'DateTime' is not in exif_data, the datetime that we're supposed to return never gets assigned and triggers an Error.

    We first attempt to populate the exif_data and then IF it's populated we use it ELSE we use getmtime so it's always one or the other. No error here because exif_data is already initialized as {}.

    resolves #112

    opened by gangelop 3
  • How to change font?

    How to change font?

    Pardon my ignorance, I'm not a web dev at all. The problem is that default crimson font doesn't look good with text in Russian. I've created a custom.css file with

    body {
        font-family: 'Roboto', sans-serif !important;
    }
    

    block, but the font itself isn't changed. I'm sure that file placement is correct since adding a custom.js affects the website. How can I change font to something else?

    opened by MasterGroosha 3
  • Add a new gm setting to allow progressive JPEG

    Add a new gm setting to allow progressive JPEG

    I've added a new gm setting to offer the opportunity to convert all the JPEG files from the standard baseline loading to progressive. This doesn't affect the file size (or just reduce it very slightly, nothing extraordinary), but give the illusion that the picture loads faster by having quickly a first preview of it (which improve the user experience when using a slow connection). For more details on progressive JPEG, this blog post is quite interesting : http://yuiblog.com/blog/2008/12/05/imageopt-4/

    opened by 0x010C 3
  • AttributeError: module 'jinja2.ext' has no attribute 'with_'

    AttributeError: module 'jinja2.ext' has no attribute 'with_'

    Hello,

    I did a fresh installation on a PopOS, following the documentation and get this error when I execute "prosopopee":

    Traceback (most recent call last): File "/home/basti/ve/bin/prosopopee", line 8, in <module> sys.exit(main()) File "/home/basti/ve/lib/python3.10/site-packages/prosopopee/prosopopee.py", line 842, in main templates.add_extension("jinja2.ext.with_") File "/home/basti/ve/lib/python3.10/site-packages/jinja2/environment.py", line 373, in add_extension self.extensions.update(load_extensions(self, [extension])) File "/home/basti/ve/lib/python3.10/site-packages/jinja2/environment.py", line 117, in load_extensions extension = t.cast(t.Type["Extension"], import_string(extension)) File "/home/basti/ve/lib/python3.10/site-packages/jinja2/utils.py", line 149, in import_string return getattr(__import__(module, None, None, [obj]), obj) AttributeError: module 'jinja2.ext' has no attribute 'with_'

    What can I do?

    Many thanks in advance!

    opened by toasti2000 3
  • Turning off the image captions on mouse over

    Turning off the image captions on mouse over

    Hi all, first great tool, been playing around with it after jumping from Squarespace, to Adobe portfolio to Wordpress. Hopefully this can be home for my photos. I'm not the biggest fan of the roll over sliding captions, any way to turn these off? Thanks!

    opened by harnoorsaini 0
  • ValueError: too many values to unpack (expected 2)

    ValueError: too many values to unpack (expected 2)

    Ran prosopopee directly in the example/ directory and it throws the following error

    Traceback (most recent call last):
      File "/Users/alice/miniconda3/bin/prosopopee", line 33, in <module>
        sys.exit(load_entry_point('prosopopee==1.1.4', 'console_scripts', 'prosopopee')())
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/prosopopee.py", line 856, in main
        process_directory(gallery.normpath(), settings, templates)
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/prosopopee.py", line 570, in process_directory
        process_directory(
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/prosopopee.py", line 547, in process_directory
        build_gallery(settings, gallery_settings, gallery_path, parent_templates)
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/prosopopee.py", line 647, in build_gallery
        html = template_to_render.render(
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/jinja2/environment.py", line 1291, in render
        self.environment.handle_exception()
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/jinja2/environment.py", line 925, in handle_exception
        raise rewrite_traceback_stack(source=source)
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/themes/exposure/templates/gallery-index.html", line 30, in top-level template code
        {% include "sections/" + section.type + ".html" %}
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/themes/exposure/templates/sections/pictures-group.html", line 13, in top-level template code
        {% set ratio = video.ratio %}
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/jinja2/environment.py", line 474, in getattr
        return getattr(obj, attribute)
      File "/Users/alice/miniconda3/lib/python3.8/site-packages/prosopopee-1.1.4-py3.8.egg/prosopopee/prosopopee.py", line 215, in ratio
        width, height = out.decode("utf-8").split(",")
    ValueError: too many values to unpack (expected 2)
    

    out.decode("utf-8") returns 1920,1080, so naturally the second comma makes it so that that out.decode("utf-8").split(",") returns ['1920', '1080', ''].

    As a stopgap I change the line to

    width, height = out.decode("utf-8").split(",")[:2]
    

    and prosopopee terminated normally.

    opened by alicedb2 0
  • 4K videos end up pixelated when the gallery is rendered

    4K videos end up pixelated when the gallery is rendered

    Hello,

    4K videos are rendered with a very low quality when resized to 1280x720: The original video: https://cloud.fr33tux.org/index.php/s/WtXxE4LSawJBf6F The rendered result: https://pics.fr33tux.org/pointe_du_raz_2021/22.mp4.webm

    Using Prosopopee 1.1.4 and https://github.com/Psycojoker/prosopopee/commit/f96fd7f456713ce5f90cad80e46389d80dd3bcbb, with ffmpeg:

    settings:
      ffmpeg:
        binary: "ffmpeg"
    
    opened by fr33tux 0
  • Migration to Pillow and huge performance improvements

    Migration to Pillow and huge performance improvements

    A notable change is that the resize option for images only accepts percentages for now.

    Another notable change is that the .copy() function actually also applies the quality setting, unlike the implementation with graphicsmagick.

    This has been tested against Pillow from 6.0.0 to 8.1.0 and Pillow-SIMD 7.0.0.post3.

    Here are the different benchmarks. The setup is the following: ~1400 photos spread among 31 galleries. Building everything from scratch. Graphicsmagick means the current implementation in prosopopee. "Built Pillow 8.1.0" can be reproduced by installing libjpegturbo and then running pip3 install --no-binary :all: --force-reinstall pillow. Please follow https://pillow.readthedocs.io/en/stable/installation.html#building-from-source to make sure you have all the packages installed in your distribution prior to trying to compile Pillow.

    | Computer | Graphicsmagick | Pillow 8.1.0 | Built Pillow 8.1.0 | Pillow-SIMD 7.0.0.post3 | |--|--|--|--|--| | Intel Q6600 (4c/4t @2.4GHz) 4GB RAM (Fedora Desktop 33)| 1:37:13.06 | 26:57.71 | 17:43.66 | N/A | | Intel Atom N2800 (2c/4t @1.86GHz 2GB RAM (Fedora Server 33)| 5:35:32.57 | 1:44:21.93 | 1:16:32.42 | N/A | | Intel Celeron G1610T (2c/2t @2.3GHz) 4GB RAM (Fedora Server 33)| 1:42:33.79 | 46:10.00 | 26:10.30 | 17:30.49 | | Intel Core i7-8700 (6c/12t @3.2GHz) 32GB RAM (Ubuntu Desktop 20.04.2)| 33:01.63 | 6:00.16 | 3:40.09 | 2:16.03 | | RaspberryPi 4 4GB RAM (Ubuntu Server 20.10)| 3:44:57.00 | 44:43.67 | 33:29.86 | N/A |

    Regenerating only one gallery of 71 photos: | Computer | Graphicsmagick | Pillow 8.1.0 | Built Pillow 8.1.0 | Pillow-SIMD 7.0.0.post3 | |--|--|--|--|--| | Intel Q6600 (4c/4t @2.4GHz) 4GB RAM (Fedora Desktop 33)| 3:59.49 | 1:37.47 | 1:13.93 | N/A | | Intel Atom N2800 (2c/4t @1.86GHz 2GB RAM (Fedora Server 33)| 14:59.40 | 6:09.36 | 5:04.45 | N/A | | Intel Celeron G1610T (2c/2t @2.3GHz) 4GB RAM (Fedora Server 33)| 4:33.75 | 2:31.85 | 1:45.11 | 1:18.00 | | Intel Core i7-8700 (6c/12t @3.2GHz) 32GB RAM (Ubuntu Desktop 20.04.2) | 1:31.09 | 21.179 | 12.373 | 8.665 | | RaspberryPi 4 4GB RAM (Ubuntu Server 20.10)| 10:26.63 | 2:23.45 | 2:22.50 | N/A |

    Currently, thumbnail generation is done in a single thread while parsing the galleries by calling graphicsmagick for every thumbnail to be generated. This is suboptimal even though graphicsmagick spreads its payload over all available CPU cores.

    After a quick and dirty benchmarking, it was found that multiprocessed Pillow for generating thumbnails was much more efficient than graphicsmagick.

    This PR adds support for generation of tuhmbnails with multiprocessed Pillow.

    Multiple processes have to be used and not multiple threads because Python still uses the Global Interpreter Lock (GIL) for threads, meaning they cannot concurrently be running, which is what one wants for CPU intensive tasks such as thumbnail generation.

    Multiprocess brings its own set of challenges because most data structures cannot be shared between processes, such as the cache for example. All data modified by any of the processes should be of a type handled by multiprocess.Manager data structures.

    In order to have the best performances, all thumbnails for an image should be generated at once, so that the original image is opened only once. This therefore requires to keep track of images and add thumbnails to be created to the original image. This can be done via a factory which is passed to the Jinja templates so that they can request thumbnails for given images without knowing more than the original path, name of the original image and the parameters of the thumbnails to create.

    The ImageFactory keeps all of those original images in a dictionary which consists of a virtual path made from the original image name and a CRC32 of all the options that applies to its thumbnails. This gives prosopopee the ability to group thumbnails per options (e.g. if options are passed in gallery settings.yaml).

    The original image (or BaseImage) is returned by the ImageFactory and the templates can then request .copy() or .thumbnail() for it.

    The thumbnails are kept in a dictionary whose keys are the name of the thumbnail which is made out of the original name plus its size and the crc32 of the original image and the options that apply to it. This way, thumbnails are guaranteed to be unique even if requested multiple times by templates.

    The size is now read with imagesize.getsize() only once when ratio property or .copy() is called on the image so that the performance impact is minimal.

    Since multiprocess.Pool.map splits iterables into pre-defined chunks which are then assigned to processes, it is needed for best performance to have processes with more or less the same taskload so that one or more processes aren't idle when one is working 100%. For that, the original images whose thumbnails are all cached should be removed from the list of images to generate thumbnails from before the list is passed to multiprocess.Pool.map so that each process has more or less the same taskload.

    Thanks, Quentin

    opened by QSchulz 0
Releases(1.1.4)
  • 1.1.4(Nov 23, 2020)

  • 1.1.3(Nov 23, 2020)

  • 1.1.2(Nov 23, 2020)

  • 1.1.1(Nov 23, 2020)

  • 1.1(Nov 23, 2020)

    • move to tox with check-manifest, flake8 and black
    • move to the logging module
    • move to argparse
    • localise date formating https://prosopopee.readthedocs.io/en/latest/configuration.html#date-locale
    • allow to customize background-position for full-picture https://prosopopee.readthedocs.io/en/latest/sections.html#full-screen-picture
    • add include option https://prosopopee.readthedocs.io/en/latest/configuration.html#include-files
    • various bug fixes
    Source code(tar.gz)
    Source code(zip)
  • 1.0.1(May 8, 2020)

  • 1.0.0(Apr 29, 2020)

  • 0.9.0(Mar 22, 2020)

    0.9.0

    • Fix audio player on mobile
    • Update JS lib
    • Change lazyload lib
    • Possibility the add controls on video
    • Update exposure theme
    • fix some issue
    Source code(tar.gz)
    Source code(zip)
  • 0.8.3(Feb 24, 2020)

  • 0.8.2(Sep 25, 2019)

  • 0.8.1(Mar 28, 2018)

  • 0.8(Feb 28, 2018)

    • Add night mode https://prosopopee.readthedocs.io/en/latest/configuration.html#night_mode
    • Add a test command to build html without generating media files
    • fix some bugs
    Source code(tar.gz)
    Source code(zip)
  • 0.7(Oct 3, 2017)

  • 0.6(Jul 18, 2017)

    • Compatibility python 2 and 3
    • Possibility to add custom css and js http://prosopopee.readthedocs.io/en/latest/theming.html
    • Add reverse option by titoko https://prosopopee.readthedocs.io/en/latest/configuration.html#reverse
    Source code(tar.gz)
    Source code(zip)
  • 0.5(Jun 4, 2017)

    • Add audio HTML5 player https://prosopopee.readthedocs.org/en/latest/sections.html#audio by beudbeud
    • Update Material theme by beudbeud
    • Add iframe section https://prosopopee.readthedocs.org/en/latest/sections.html#iframe by beudbeud
    • Add quotes section https://prosopopee.readthedocs.org/en/latest/sections.html#quote by beudbeud
    • Add deploy and preview option https://prosopopee.readthedocs.io/en/latest/build.html#preview by beudbeud
    • Load only css and jss if the section is used by beudbeud
    • Possibility to add floating image in paragraph by beudbeud https://prosopopee.readthedocs.org/en/latest/sections.html#paragraph
    • fix some bugs
    Source code(tar.gz)
    Source code(zip)
A Python Static Website Generator

Version 0.8.9 Overview Hyde starter kit by merlinrebrovic is a really nice way to get started with hyde. Hyde layout for bootstrap by auzigog is also

Hyde - Static Website Generator 1.6k Jan 1, 2023
A static website generator for people who enjoy the simpler things in life.

A static website generator for people who enjoy the simpler things in life.

Darren Mulholland 93 Dec 22, 2022
Simple, lightweight, and magic-free static site/blog generator for Python coders

makesite.py Take full control of your static website/blog generation by writing your own simple, lightweight, and magic-free static site generator in

Sunaina Pai 1.7k Jan 1, 2023
Static site generator that supports Markdown and reST syntax. Powered by Python.

Pelican Pelican is a static site generator, written in Python. Write content in reStructuredText or Markdown using your editor of choice Includes a si

Pelican dev team 11.3k Jan 4, 2023
A simple static site generator with deployment to S3/Cloudfront.

Stasis A simple static site generator with deployment to S3/Cloudfront. Features Stasis is a static website generator written in Python, using Pandoc

Scott Czepiel 56 Sep 29, 2022
dirmaker is a simple, opinionated static site generator for quickly publishing directory websites.

dirmaker is a simple, opinionated static site generator for publishing directory websites (eg: Indic.page, env.wiki It takes entries from a YAML file and generates a categorised, paginated directory website.

Kailash Nadh 40 Nov 20, 2022
Static site generator for designers. Uses Python and Django templates.

News Cactus 3 is out! We're happy to announce Cactus 3. It brings a set of great new features like asset fingerprinting, an asset pipeline, pretty url

null 3.4k Jan 1, 2023
AutoLoader is a plugin for Pelican, a static site generator written in Python.

AutoLoader AutoLoader is a plugin for Pelican, a static site generator written in Python. AutoLoader is designed to autoload the other Pelican plugins

null 2 Nov 7, 2022
Kaktos is a python static site generator

Python static site generator κάκτος Kaktos is a python static site generator. The idea is create a simple static site generator for people that don't

Paulo Coutinho 4 Sep 21, 2022
barely is a lightweight, but highly extensible static site generator written in pure python.

barely is a lightweight, but highly extensible static site generator. Explore the docs » Quickstart · See available Plugins · Report Bug · Request Fea

null 40 Dec 1, 2022
A python-based static site generator for setting up a CV/Resume site

ezcv A python-based static site generator for setting up a CV/Resume site Table of Contents What does ezcv do? Features & Roadmap Why should I use ezc

Kieran Wood 5 Oct 25, 2022
A declarative website generator designed for high-quality websites, with a focus on easy maintenance and localization.

Grow Grow is a declarative tool for rapidly building, launching, and maintaining high-quality static HTML. Easy installation Jinja template engine Con

Grow 385 Dec 3, 2022
The lektor static file content management system

Lektor Lektor is a static website generator. It builds out an entire project from static files into many individual HTML pages and has a built-in admi

Lektor CMS 3.6k Dec 29, 2022
Makes dynamic linked shit "static". Amazing

static.py What does it do? You give it a dynamically linked binary and it will make a directory that has all the dependencies (recursively). It also f

Stephen Tong 24 Dec 16, 2022
Simple Static Site Inductor Made in Python

sssimp ?? Simple Static Site Inductor Made in Python How to use Create a folder called input, inside create a folder called content and an empty file

Tina 11 Oct 9, 2022
Hobby Project. A Python Library to create and generate static web pages using just python.

PyWeb ??️ ?? Current Release: 0.1 A Hobby Project ?? PyWeb is a small Library to generate customized static web pages using python. Aimed for new deve

Abhinav Sinha 2 Nov 18, 2021
Source code for the GPT-2 story generation models in the EMNLP 2020 paper "STORIUM: A Dataset and Evaluation Platform for Human-in-the-Loop Story Generation"

Storium GPT-2 Models This is the official repository for the GPT-2 models described in the EMNLP 2020 paper [STORIUM: A Dataset and Evaluation Platfor

Nader Akoury 27 Dec 20, 2022
null 4 Oct 28, 2021
Command-line program to download image galleries and collections from several image hosting sites

gallery-dl gallery-dl is a command-line program to download image galleries and collections from several image hosting sites (see Supported Sites). It

Mike Fährmann 6.4k Jan 6, 2023
Customizable-menu-python - User customizable menu in Python

Menu personalizável pelo usuário em Python A minha ideia com esse projeto pessoa

Renan Barbosa 4 Oct 28, 2022