CP Parser
Available on PyPI: pip install cp-parser
Video Demo: https://youtu.be/u70oEHAkTlY?si=qIT0T8h2Ql0qeQAl
Description:
CP Parser is a command-line tool, published and installable straight from PyPI, that automates the file setup required before a Codeforces contest. Rather than manually creating a folder, copying a template into a new file for each problem, and renaming the solve function every time, the tool handles all of this from a single command. What previously took a few minutes of repetitive setup now takes a few seconds, which matters more than it might seem once the contest clock has already started.
Because it ships as a proper PyPI package, getting started is a single pip install away, no cloning a repository or managing a local script required.
Beyond public rounds, CP Parser features full Codeforces API authentication, meaning it can securely fetch private Mashups and Gyms by generating the required SHA-512 cryptographic signatures on the fly.
Installation
pip install cp-parser
Once installed, the cparse command is available globally in your terminal, on any machine with Python and pip, without needing to set up a virtual environment or run the source directly.
What It Does
Given a Codeforces contest URL, a target language, and an optional folder name, CP Parser:
- Cleans and Extracts: Strips invisible terminal characters and extracts the numeric contest ID (supporting both
/contest/and/gym/formats). - Authenticates: Loads your saved API credentials and generates a time-stamped, mathematically sorted SHA-512 signature to bypass Codeforces authorization walls.
- Fetches: Queries the Codeforces API for the exact problem list.
- Builds: Creates a new directory safely in your current working path.
- Generates: Creates one correctly named source file per problem (e.g.,
A_Watermelon.cpp), pre-loaded with your chosen language template.
Usage
For your very first run, provide your Codeforces API Key and Secret. The tool will securely cache these locally so you never have to type them again.
# First-time setup (saves keys automatically)
cparse -l [https://codeforces.com/contest/2246](https://codeforces.com/contest/2246) -k <YOUR_KEY> -s <YOUR_SECRET> -L cpp -d Round1
For all future contests, the command becomes incredibly fast and simple:
# Future runs (keys are loaded from the hidden config)
cparse -l [https://codeforces.com/gym/106430](https://codeforces.com/gym/106430) -d Private_Mashup
Project Structure
The project is packaged and distributed on PyPI using a modern Python src/ layout, configured via pyproject.toml. This structure is what makes clean packaging, versioning, and distribution to PyPI possible in the first place.
src/cp_parser/Parse.py
Defines the Parser class, a subclass of ArgumentParser. Argument parsing was kept in a separate file from the core logic so the CLI definition wouldn't become tangled with the program's execution logic, making both files easier to read and test.
src/cp_parser/cli.py
This is the operational core of the tool.
- Credential Management: Checks for a hidden
.configparser.jsonfile in the user's home directory. If missing, it requires the user to pass keys via flags, then cleanly writes them to the JSON file usingjson.dumpto prevent string-quoting bugs. get_contest_ID(link): Extracts the ID using a regular expression rather than simple string splitting. Regex was chosen specifically because URLs vary greatly (e.g., trailing slashes,/contest/vs/gym/). The regex cleans the input with.strip()and handles all standard variants in a single pass.generate_sig(key, id, secret, time): Constructs the highly specific cryptographic signature required by Codeforces. It generates a 6-character random salt, sorts the API parameters alphabetically, and hashes the entire string usinghashlib.sha512().get_problem_names/create_lang_files_names: Queries the API and safely formats the returned problem names. It uses a regex to strip spaces and math symbols so the resulting filenames are OS-safe and clean.
src/cp_parser/templates/
Contains one plain text template per supported language: C++, C, Java, and Python. These were deliberately kept as separate .txt files rather than hardcoded strings inside cli.py. Hardcoding them would have meant the actual competitive programming boilerplate lives buried inside escaped Python strings, which is difficult to read and maintain. Instead, cli.py uses Python's importlib.resources to dynamically locate and load these files, meaning the templates are correctly bundled inside the PyPI package and travel with it no matter where it is installed on the user's system.
tests/test_project.py
Covers the core logic functions. unittest.mock.patch is used to mock requests.get and os.mkdir, so the test suite runs instantly, does not depend on Codeforces being online, and does not touch the real filesystem. We can verify that the API signatures are being formatted correctly and that files are being named properly without leaving a mess on the host machine.
Design Decisions
Why publish this as a PyPI package instead of a standalone script?
A script you have to clone and run manually adds friction right when speed matters most. Packaging it for PyPI means installation is one command, upgrades are one command (pip install --upgrade cp-parser), and the cparse entry point works from any directory on the system, exactly like any other CLI tool you already have installed.
Why implement API signatures instead of just web scraping? Standard web scraping works fine for public Div 2 rounds, but it fails completely if you are participating in a private Mashup or a restricted Gym. Implementing the official Codeforces API authentication ensures the tool works for every contest tied to your account, public or private.
Why store credentials in a hidden .configparser.json file?
The entire point of this tool is speed. Forcing a user to copy and paste a 40-character hexadecimal API secret while a contest clock is ticking is a non-starter. By saving the credentials to Path.home() on the very first run, the tool becomes perfectly frictionless for all future contests.
Why four separate languages instead of one generic template system? Each language requires substantially different boilerplate. C++ needs fast IO pragmas and STL includes, Java needs an entire class wrapper with a scanner utility, and Python needs neither. Forcing all of this through a single generic template would have degraded the quality of the templates for every language in exchange for a modest reduction in code, so the languages were kept fully separate.
Why exit on errors instead of raising exceptions up the stack?
This is a command-line tool run directly before a contest, not a library intended to be imported elsewhere. If a link is invalid, a language doesn't exist, or an API call fails, the priority is a short, readable message describing exactly what went wrong (e.g., FLAG ERROR: Invalid contest link) so it can be corrected and rerun immediately, rather than forcing the user to decipher a massive Python stack trace under time pressure.
This was originally built as a CS50P final project, but it has since been refactored into a modern, fully authenticated Python package, published on PyPI, because it continues to see regular use every contest, which is what made building it worthwhile.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file cp_parser-1.0.0.tar.gz.
File metadata
- Download URL: cp_parser-1.0.0.tar.gz
- Upload date:
- Size: 13.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eba99c14a666b99acbeb80a25b9bc7da1ee317041d8d2befeb7a3b2779bfee0c
|
|
| MD5 |
09dc807ddff697a80d9e48dfbc0d766f
|
|
| BLAKE2b-256 |
c27807df4bdfa585478e9c21fa453be58e4bd2676fe3a8a4b0e4fe95464f0ca6
|
File details
Details for the file cp_parser-1.0.0-py3-none-any.whl.
File metadata
- Download URL: cp_parser-1.0.0-py3-none-any.whl
- Upload date:
- Size: 10.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.14.2
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1d71cb9a354e42d2cf57aabe27d7d79e129ebcc340bf2a94d8b1f82b5327904f
|
|
| MD5 |
6cbfa05ccb965ecdcf1797e835669273
|
|
| BLAKE2b-256 |
638a0b107026badea55325b49964dc219b00339787147943b1bb582ff5377841
|