Metadata-Version: 2.4
Name: cp-parser
Version: 1.0.1
Summary: CLI tool that automates Codeforces contest file setup with full API authentication.
Author-email: Zeyad Mohamed Nada <zeyadmsn07@gmail.com>
License: MIT
Project-URL: Homepage, https://github.com/zeyadmsn07/cp-parser-package
Project-URL: Repository, https://github.com/zeyadmsn07/cp-parser-package
Keywords: codeforces,competitive-programming,cli
Classifier: Programming Language :: Python :: 3
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Requires-Python: >=3.9
Description-Content-Type: text/markdown
Requires-Dist: requests>=2.25
Provides-Extra: dev
Requires-Dist: pytest>=7.0; extra == "dev"

# CP Parser

**Available on PyPI:** [`pip install cp-parser`](https://pypi.org/project/cp-parser/)

<p align="center">
  <img src="https://raw.githubusercontent.com/zeyadmsn07/src/assets/logo.png" alt="CP Parser logo" width="400">
</p>

#### Video Demo: https://youtu.be/u70oEHAkTlY?si=qIT0T8h2Ql0qeQAl

#### Description:

CP Parser is a command-line tool 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.

CP Parser is officially packaged and published on PyPI, so getting started is a single `pip install` away — no cloning a repository, no managing a local script, no manual setup of any kind.

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

Install it directly from PyPI:

```bash
pip install cp-parser
```

Because it's a real, published package, `pip` handles everything: dependencies are resolved automatically, and the `cparse` command becomes 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.

Upgrading later is just as simple:

```bash
pip install --upgrade cp-parser
```

## What It Does

Given a Codeforces contest URL, a target language, and an optional folder name, CP Parser:

1. **Cleans and Extracts:** Strips invisible terminal characters and extracts the numeric contest ID (supporting both `/contest/` and `/gym/` formats).
2. **Authenticates:** Loads your saved API credentials and generates a time-stamped, mathematically sorted SHA-512 signature to bypass Codeforces authorization walls.
3. **Fetches:** Queries the Codeforces API for the exact problem list.
4. **Builds:** Creates a new directory safely in your current working path.
5. **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.

```bash
# First-time setup (saves keys automatically)
cparse -l 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:

```bash
# Future runs (keys are loaded from the hidden config)
cparse -l 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.json` file 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 using `json.dump` to 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 using `hashlib.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. Now that it's packaged and published on PyPI, 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, and has since been fully packaged, authenticated, and published on PyPI as a real, installable tool, because it continues to see regular use every contest, which is what made building it worthwhile.*

<p align="center">
  <img src="https://raw.githubusercontent.com/zeyadmsn07/src/assets/logo.png" alt="CS50P Certificate for Zeyad Nada" width="600">
</p>
