Petroleum Documentation

Welcome to the official documentation for Petroleum, a Pythonic compiled language with joyful concurrency, friendly errors, and production-ready tooling.

Quick Links

New to Petroleum? Start with Installation and Your First Program.

What is Petroleum?

  • Pythonic syntax — Familiar indentation-based blocks
  • Compiled speed — Compiles to native executables via Go
  • Joyful concurrency — Simple pet keyword for async
  • 95 string methods — Comprehensive text processing
  • Built-in file/CSV handling — No imports needed

Version

This documentation covers Petroleum v0.6.5.

Installation

Prerequisites

Petroleum requires Go 1.20 or later. Download Go if you haven't already.

Download & Install

Download from the Download page, extract, and run:

petroleum install

Verify

petroleum --version

Your First Program

Create hello.pet:

def main():
    name = input("What's your name? ")
    print(f"Hello, {name}!")
    input("Press Enter to exit...")

Run It

petroleum run hello.pet

Compile

petroleum compile hello.pet
./hello.exe

Variables

Variables are dynamically typed:

name = "Alice"
age = 25
pi = 3.14159
is_active = True
items = [1, 2, 3]
person = {"name": "Bob"}

Data Types

TypeExampleDescription
str"hello"Text strings
int42Whole numbers
float3.14Decimal numbers
boolTrueBoolean values
list[1, 2, 3]Ordered collections
dict{"a": 1}Key-value mappings

Control Flow

If/Elif/Else

if score >= 90:
    grade = "A"
elif score >= 80:
    grade = "B"
else:
    grade = "C"

For Loops

for item in [1, 2, 3]:
    print(item)

for i in range(5):
    print(i)

While Loops

while count > 0:
    print(count)
    count = count - 1

Match/Case

match status:
    case 200: print("OK")
    case 404: print("Not Found")
    case _: print("Unknown")

Functions

def greet(name):
    return f"Hello, {name}!"

def add(a, b):
    return a + b

message = greet("Alice")
total = add(5, 3)

Classes

class Person:
    def init(self, name, age):
        self.name = name
        self.age = age
    
    def greet(self):
        return f"Hi, I'm {self.name}!"

alice = Person("Alice", 30)
print(alice.greet())

String Methods str

Petroleum provides 70+ built-in string methods.

All (70+) Basic Case Text Validation Transform Utility
upper()
Converts to uppercase.
"hello".upper() # "HELLO"
lower()
Converts to lowercase.
"HELLO".lower() # "hello"
strip()
Removes leading/trailing whitespace.
" hi ".strip() # "hi"
split(delim)
Splits into list by delimiter.
"a,b,c".split(",") # ["a","b","c"]
join(list)
Joins list with separator.
"-".join(["a","b"]) # "a-b"
replace(old, new)
Replaces occurrences.
"hello".replace("l","L") # "heLLo"
find(sub)
Index of first occurrence.
"hello".find("l") # 2
count(sub)
Count occurrences.
"hello".count("l") # 2
startswith(prefix)
Check prefix.
"hello".startswith("he") # True
endswith(suffix)
Check suffix.
"hello".endswith("lo") # True
reverse()
Reverses string.
"hello".reverse() # "olleh"
repeat(n)
Repeats n times.
"ab".repeat(3) # "ababab"
to_snake_case()
Convert to snake_case.
"helloWorld".to_snake_case() # "hello_world"
to_camel_case()
Convert to camelCase.
"hello_world".to_camel_case() # "helloWorld"
to_pascal_case()
Convert to PascalCase.
"hello_world".to_pascal_case() # "HelloWorld"
to_kebab_case()
Convert to kebab-case.
"helloWorld".to_kebab_case() # "hello-world"
swapcase()
Swap case.
"Hello".swapcase() # "hELLO"
extract_numbers()
Extract all numbers.
"$19.99 x 5".extract_numbers() # [19.99, 5]
extract_emails()
Extract emails.
"hi a@b.com".extract_emails() # ["a@b.com"]
extract_urls()
Extract URLs.
"see https://x.com".extract_urls()
remove_html()
Strip HTML tags.
"<b>Hi</b>".remove_html() # "Hi"
slugify()
URL-safe slug.
"Hello World!".slugify() # "hello-world"
transliterate()
ASCII equivalents.
"café".transliterate() # "cafe"
is_email()
Validate email format.
"a@b.com".is_email() # True
is_url()
Validate URL format.
"https://x.com".is_url() # True
is_ip()
Validate IP address.
"192.168.1.1".is_ip() # True
is_uuid()
Validate UUID.
"550e8400-...".is_uuid()
is_json()
Validate JSON.
'{"a":1}'.is_json() # True
matches(pattern)
Wildcard match.
"file.txt".matches("*.txt") # True
rot13()
ROT13 cipher.
"Hello".rot13() # "Uryyb"
reverse_words()
Reverse word order.
"hello world".reverse_words() # "world hello"
shuffle()
Random shuffle.
"hello".shuffle() # random
unique_chars()
Remove duplicates.
"hello".unique_chars() # "helo"
chunk(size)
Split into chunks.
"abcdef".chunk(2) # ["ab","cd","ef"]
first(n)
First n chars.
"hello".first(3) # "hel"
last(n)
Last n chars.
"hello".last(3) # "llo"
at(index)
Char at index.
"hello".at(-1) # "o"
truncate(len, suffix)
Truncate with suffix.
"hello world".truncate(8,"...") # "hello..."
levenshtein(other)
Edit distance.
"kitten".levenshtein("sitting") # 3
similarity(other)
Similarity 0-1.
"hello".similarity("hallo") # 0.8
word_count()
Count words.
"hello world".word_count() # 2

...and 30+ more methods including zfill, partition, soundex, mask, indent, wrap, pluralize, ordinalize, obfuscate, etc.

List Methods list

Lists support standard operations:

items = [1, 2, 3]
items.append(4)      # [1, 2, 3, 4]
items.pop()          # removes and returns 4
len(items)           # 3
items[0]             # 1
items[-1]            # 3 (last item)

Dict Methods dict

Dictionaries store key-value pairs:

person = {"name": "Alice", "age": 30}
person["name"]        # "Alice"
person["city"] = "NYC" # add key
person.keys()         # ["name", "age", "city"]
person.values()       # ["Alice", 30, "NYC"]

File Operations

# Read file
f = open("data.txt", "r")
content = f.read()
f.close()

# Write file
f = open("output.txt", "w")
f.write("Hello, World!")
f.close()

# Read lines
f = open("data.txt", "r")
for line in f.readlines():
    print(line)

📦 PetSL — Petroleum Standard Library

PetSL provides powerful, ready-to-use modules for common tasks. Each module is designed to be simple, intuitive, and Pythonic.

Available Modules
ModuleDescriptionStatus
csvRead and write CSV files with powerful data analysis✅ Available
blockchainBuild blockchains, cryptocurrencies, PoW & PoTSS✅ Available

How to Use Modules

# Import a module
import csv
import blockchain

# Use module functions
reader = csv.Reader("data.csv")
wallet = blockchain.Wallet()

CSV Module

Powerful CSV reading and writing with built-in data analysis capabilities.

import csv

Reading CSV Files

# Create a CSV reader
reader = csv.Reader("data.csv")

# Read all rows
data = reader.ReadAll()
for row in data:
    print(row)

# Get headers
headers = reader.Headers()

# Get row count
count = reader.RowCount()

Data Analysis

# Get column statistics
stats = reader.Stats("price")
print(stats["min"], stats["max"], stats["mean"])

# Filter rows
expensive = reader.Filter("price", ">", 100)

# Sort data
sorted_data = reader.Sort("name")

# Group by column
groups = reader.GroupBy("category")

Writing CSV Files

# Create a CSV writer
writer = csv.Writer("output.csv", ["name", "age", "city"])

# Write rows
writer.WriteRow(["Alice", 30, "NYC"])
writer.WriteRow(["Bob", 25, "LA"])

# Close when done
writer.Close()

Blockchain Module

Build blockchain applications, cryptocurrencies, and decentralized systems with Petroleum.

import blockchain
Features
  • Wallets — Key generation, signing, addresses
  • Transactions — Create, sign, validate transfers
  • Blockchains — Full chain management with validation
  • PoW Consensus — Traditional Proof of Work mining
  • PoTSS Consensus — Novel eco-friendly consensus
  • Tokens — Create custom cryptocurrencies

Quick Start

import blockchain

def main():
    # Create a wallet
    wallet = blockchain.Wallet()
    print("Address:", wallet)
    
    # Hash data
    h = blockchain.hash("Hello, Blockchain!")
    print("SHA-256:", h)
    
    # Create a blockchain
    chain = blockchain.Chain("pow", 2)
    print("Chain:", chain)

Wallets

Wallets are your identity on the blockchain — they hold your keys and let you sign transactions.

# Generate random wallet (new keys each time)
wallet = blockchain.Wallet()

# Deterministic wallet from seed (same seed = same wallet)
wallet = blockchain.WalletFromSeed("my secret recovery phrase")

# Access wallet properties
print(wallet["address"])      # pet1x7f3k9...
print(wallet["public_key"])   # 64-char hex
print(wallet["private_key"])  # 64-char hex (keep secret!)

Security Best Practices

# ✅ DO: Use seed phrases for recovery
wallet = blockchain.WalletFromSeed("your twelve word seed phrase")

# ✅ DO: Store seeds securely (encrypted, offline)
# ❌ DON'T: Hardcode private keys in code
# ❌ DON'T: Share your private key or seed

Transactions

Transactions transfer value between wallets. Every transaction has a unique ID.

# Create wallets
alice = blockchain.Wallet()
bob = blockchain.Wallet()

# Create a transaction
tx = blockchain.Transaction(
    alice["address"],   # sender
    bob["address"],     # receiver
    50.0,              # amount
    0.01               # fee (optional)
)

print("TX ID:", tx["id"])

Transaction Properties

PropertyDescription
idUnique 64-char transaction hash
senderSender's wallet address
receiverRecipient's wallet address
amountAmount to transfer
feeTransaction fee for miners
timestampUnix timestamp (nanoseconds)

Proof of Work (PoW)

Traditional mining consensus with configurable difficulty.

How PoW Works

  1. Miners compete to find a hash starting with N zeros
  2. First to find valid hash wins the block reward
  3. Difficulty adjusts based on network hashrate
# Create PoW blockchain with difficulty 4
chain = blockchain.Chain("pow", 4)

# Difficulty levels:
# 1 = instant, 2 = fast, 4 = seconds, 6 = minutes

Difficulty Guide

DifficultyTarget HashApprox. Time
10...Instant
200...Fast
40000...Seconds
6000000...Minutes
800000000...Hours
When to Use PoW

✅ Building a traditional cryptocurrency
✅ Want proven, battle-tested security
✅ Decentralization via mining competition

PoTSS — Proof of Time, Space, and Stake

A novel hybrid consensus designed to be fair, eco-friendly, and secure.

The Three Pillars

⏱️ TIME 💾 SPACE 🔒 STAKE
Fair rotation
No whale dominance
Longer wait = more tickets
Storage proofs
Eco-friendly
Refreshes each epoch
Skin in the game
Slashing penalties
Capped returns

Why PoTSS?

ProblemPoTSS Solution
PoW wastes energySpace proofs are lightweight
PoS creates plutocracyStake is capped, time ensures fairness
PoSpace hoards hardwareSpace proofs expire and refresh

Complete PoTSS Example

import blockchain

def main():
    # Step 1: Create a PoTSS blockchain
    chain = blockchain.PoTSSChain(2)
    print("PoTSS chain created")
    
    # Step 2: Create validator wallets
    validator1 = blockchain.Wallet()
    validator2 = blockchain.Wallet()
    validator3 = blockchain.Wallet()
    
    # Step 3: Register as validators
    # Each validator commits stake (tokens) and space (MB)
    chain.register_validator(
        wallet=validator1,
        stake=500.0,      # Lock 500 tokens
        space_mb=50        # Commit 50 MB storage
    )
    chain.register_validator(
        wallet=validator2,
        stake=1000.0,     # Larger stake
        space_mb=100       # More storage
    )
    chain.register_validator(
        wallet=validator3,
        stake=250.0,      # Smaller stake
        space_mb=200       # But lots of storage!
    )
    
    # Step 4: Produce blocks
    # The chain selects validators via weighted lottery
    for i in range(10):
        block = chain.produce_block()
        print(f"Block {block.index} by {block.miner}")
    
    # Step 5: Check validator stats
    validators = chain.get_validators()
    for v in validators:
        print(f"{v.address}: stake={v.stake}, tickets={v.tickets}")

Registering as a Validator

To participate in PoTSS, you must register with both stake and space:

# Minimum requirements
# - stake_minimum: 100 tokens (default)
# - space_minimum: 10 MB (default)

chain.register_validator(
    wallet=my_wallet,    # Your wallet (must have balance)
    stake=1000.0,        # Tokens to lock
    space_mb=100         # Storage to commit (MB)
)

Validator Selection Algorithm

Validators earn "tickets" based on three weighted factors:

FactorWeight CalculationCap
Stake Linear up to cap, then 10% above 10,000 tokens
Space Linear up to cap, then 10% above 1,000 MB (1 TB)
Time +10% per block waited 5x maximum
# Ticket calculation formula
tickets = (stake_weight/100 + space_weight/10) * time_weight

# Example: 500 stake + 50 MB + waited 10 blocks
# = (500/100 + 50/10) * (1 + 10*0.1)
# = (5 + 5) * 2.0 = 20 tickets

Producing Blocks

# Only the selected validator can produce
try:
    block = chain.produce_block(my_wallet)
    print("I was selected! Block:", block.hash)
except:
    print("Not selected this round")

# After producing, validator enters cooldown (5 blocks)
# This gives others a chance to produce

Slashing (Penalties)

Validators can be penalized for misbehavior:

# Slash a validator for bad behavior
chain.slash_validator(bad_validator_address, "double signing")

# Consequences:
# - 10% of stake is burned
# - Extended cooldown (+50 blocks)
# - 3 slashes = permanent ban
OffensePenalty
Double-signing blocks10% stake + 50 block cooldown
Invalid space proofs10% stake + 50 block cooldown
Withholding blocks10% stake + 50 block cooldown
3rd offensePermanent ban from validation

Epochs

Time is divided into epochs (default: 100 blocks each):

# Each epoch:
# 1. Gets a new random seed (from previous block hash)
# 2. All space proofs are refreshed
# 3. Validator selection resets

# Check current epoch
print("Current epoch:", chain.current_epoch.id)
print("Blocks in epoch:", chain.current_epoch.blocks_created)
When to Use PoTSS

✅ Building an eco-friendly blockchain
✅ Want fair validator rotation (no whale dominance)
✅ Need slashing for bad actors
✅ Building a modern, efficient network

PoTSS vs PoW Quick Reference

FeaturePoWPoTSS
Create chainChain("pow", 4)PoTSSChain(2)
Produce blockchain.mine(addr)chain.produce_block(wallet)
Who winsFastest minerWeighted lottery
Energy useHighLow
RequirementsCPU/GPU powerStake + Storage

Token Creation

Create your own cryptocurrency tokens with just a few lines of code. Tokens are fungible assets that can be transferred, minted, and burned.

Creating a Token

import blockchain

def main():
    # Create wallet for token creator
    creator = blockchain.Wallet()
    
    # Create a custom token
    token = blockchain.Token(
        "PetroCoin",     # name: Full name
        "PETC",          # symbol: Ticker (3-5 chars)
        1000000.0,       # total_supply: Initial supply
        8,               # decimals: Precision
        creator           # creator: Owner wallet
    )
    
    print("Token:", token["name"], token["symbol"])

Token Properties

PropertyTypeDescription
namestringFull name (e.g., "PetroCoin")
symbolstringTicker symbol (e.g., "PETC")
total_supplyfloatTotal tokens in existence
decimalsintDecimal precision (8 = 0.00000001)
creatorstringCreator's wallet address
balancesdictMap of address → balance

Decimals Explained

# Decimals determine the smallest unit of your token

# decimals=8 (like Bitcoin)
# 1 PETC = 100,000,000 satoshis
# Smallest: 0.00000001 PETC

# decimals=2 (like USD)
# 1 TOKEN = 100 cents
# Smallest: 0.01 TOKEN

# decimals=0 (whole units only)
# No fractional tokens

Common Token Configurations

# Cryptocurrency (high precision, capped supply)
crypto = blockchain.Token("MyCrypto", "MYC", 21000000.0, 8, creator)

# Stablecoin (USD-like, large supply)
stable = blockchain.Token("PetroUSD", "PUSD", 1000000000.0, 2, creator)

# Governance token (voting rights)
gov = blockchain.Token("PetroDAO", "PDAO", 100000000.0, 18, creator)
💡 Tip

The creator wallet receives the entire total_supply upon creation. They can then distribute tokens via transfers to investors, treasury, etc.

Pets (Async)

Run functions concurrently with pet:

def slow_task(n):
    # simulate work
    return n * 2

def main():
    # Start concurrent tasks
    a = pet slow_task(10)
    b = pet slow_task(20)
    
    # Wait for results
    result_a = await a  # 20
    result_b = await b  # 40

Leash (Channels)

Communicate between concurrent tasks:

def producer(leash):
    leash.send("Hello")
    leash.send("World")

def main():
    ch = Leash()
    p = pet producer(ch)
    
    msg1 = ch.receive()  # "Hello"
    msg2 = ch.receive()  # "World"