I replaced 3 Python tools with 1 and my CI pipeline got 10x faster. The tools I dropped: black, isort, flake8. The replacement: Ruff. I've now migrated 7 repositories to Ruff (totaling 800+ Python files) and here's my honest take after 3 months. What's great: - Speed. Ruff lints my entire monorepo in under 2 seconds. The old stack took 20-30 seconds. In CI, that compounds fast across matrix builds. - One config block. Instead of [tool.black], [tool.isort], [tool.flake8] scattered across pyproject.toml, it's just [tool.ruff] and [tool.ruff.lint]. Select the rule codes you want, done. - Auto-fix. Ruff can fix most import sorting and unused import issues on save. I have it wired as a post-tool hook in my editor — every file save auto-formats. What's not perfect: - Rule parity isn't 100%. A few flake8 plugins I relied on (like flake8-bugbear's B950 line length) don't have exact equivalents. You adapt. - The error messages are sometimes less descriptive than flake8's. When a rule fires that you haven't seen before, you're reading docs more often. - If your team has muscle memory around black's opinionated formatting, Ruff's formatter makes slightly different choices in edge cases. Minor, but it can cause noisy diffs during migration. Bottom line: I'd never go back. The speed alone justifies the switch, and consolidating 3 config sections into 1 removes a real source of drift. If you're still running black + isort + flake8 separately, try `ruff check . --fix` on your repo. You'll feel the difference immediately. Have you switched to Ruff yet? What held you back (or convinced you)? #Python #DevTools #Ruff #DeveloperExperience #CodeQuality
Ruff Replaces 3 Tools, Boosts CI Speed 10x
More Relevant Posts
-
When someone new joins a Python codebase, their first PR tells you everything: single-letter variables, inconsistent imports, functions that return str | None | dict depending on the mood of the day. We have onboarding docs for this, but tooling is what actually enforces it. My default move is three things: Ruff, Pyright, and pre-commit. Ruff with format + lint, fix-on-save, and import sorting. They hit save and the file snaps into shape, which alone kills most style discussions before they ever reach a PR. Then Pyright via Pylance in standard mode. Not strict, because strict in Python is counterproductive unless the whole codebase is designed for it. Standard catches wrong argument types, None-access, and missing returns, the stuff that otherwise shows up as runtime bugs or reviewer nitpicks. Once people see type issues flagged while they're still typing, something clicks and they stop shipping avoidable bugs. That peace of mind is something I never want to go back from. Pre-commit makes all of it non-optional. The same checks run for everyone, every time, before the code even gets pushed. It turns "we should all follow the coding guides" into "you literally can't commit without following them." That's the difference between a convention and a guarantee. With this, reviews actually focus on correctness, design, and edge cases instead of formatting and obvious type errors. You're moving the stuff humans shouldn't be wasting time on to machines that do it better and faster, and you're doing it at the cheapest possible point, before it ever hits a PR. I remember when I first set this up for myself and it felt like someone turned the lights on. I want that for everyone joining the team. What's the first thing you set up when onboarding someone new? #Python #SoftwareEngineering #CodeQuality #DeveloperExperience #DevTools
To view or add a comment, sign in
-
Built a Python-based web scraper that collects top news headlines from a public website and stores them in a text file. The project uses HTTP requests to fetch HTML content and BeautifulSoup to parse and extract headline data automatically. This helped me practice web scraping, HTML parsing, and basic file handling in Python. GitHub: https://lnkd.in/gi56cKgZ #Python #WebScraping #BeautifulSoup #Automation #Learning
To view or add a comment, sign in
-
🧠 Python Feature That Makes Functions Pluggable: functools.partial 💻 Pre-fill arguments once… 💻 Reuse the function forever 😌 ❌ Repeating Yourself def power(base, exp): return base ** exp square = lambda x: power(x, 2) cube = lambda x: power(x, 3) Works, but feels hacky 😬 ✅ Pythonic Way from functools import partial power = lambda base, exp: base ** exp square = partial(power, exp=2) cube = partial(power, exp=3) Clean. Reusable. Intentional ✨ 🧒 Simple Explanation Imagine a juice shop 🧃 You decide orange once 🍊 Every glass after that is just “size?” That’s partial. 💡 Why This Is Powerful ✔ Reduces duplicate functions ✔ Cleaner callbacks ✔ Great for functional programming ✔ Used in real frameworks ⚡ Common Use Case from functools import partial import logging debug = partial(logging.log, logging.DEBUG) 🐍 Python lets you lock in decisions early. 🐍 functools.partial turns functions into reusable tools #Python #PythonTips #PythonTricks #Functools #AdvancedPython #CleanCode #LearnPython #Programming #DeveloperLife #DailyCoding #100DaysOfCode
To view or add a comment, sign in
-
-
Ever wondered how Python knows what to do when you use + between two objects? Or how len() works on your custom class? The answer lies in magic methods (also called dunder methods). These are special methods wrapped in double underscores, and they're what make Python feel like magic. Here are a few that changed how I write code: __init__ — The constructor everyone knows. But it's just the beginning. __repr__ & __str__ — Control how your object looks when printed or logged. Debugging becomes 10x easier when your objects speak for themselves. __len__, __getitem__, __iter__ — Make your custom class behave like a built-in list or dictionary. Your teammates won't even know the difference. __enter__ & __exit__ — Power behind the with statement. Perfect for managing resources like files, DB connections, and locks. __eq__, __lt__, __gt__ — Define what "equal" or "greater than" means for your objects. Sorting a list of custom objects? No problem. __call__ — Make an instance callable like a function. This one unlocks some seriously clean design patterns. The real power of magic methods isn't just the syntax — it's that they let you write intuitive, Pythonic APIs that feel native to the language. When your custom class supports len(), iteration, and comparison naturally, your code becomes easier to read, test, and maintain. What's your favorite magic method? Drop it in the comments #Python #SoftwareEngineering #Programming #PythonTips #CleanCode #BackendDevelopment
To view or add a comment, sign in
-
-
Understanding virtualenv made easy ✨ What is it: Virtualenv (or venv) creates isolated Python environments for your projects. It acts like a sandbox, giving each project its own Python interpreter and packages. This keeps things clean without messing up your main Python setup or other work. 🌟 Practical example: Building an e-commerce app with Django 4.2 and an analytics dashboard with Flask 2.3? Create env_ecommerce (python -m venv env_ecommerce, activate, pip install django==4.2) and env_analytics separately—no clashes. 🎯 Popular in: • Avoid package conflicts: Use NumPy 1.24 for ML and 1.26 for data analysis side-by-side. • Keep system clean: Test FastAPI without polluting global Python. • Team collaboration: Share requirements.txt for exact setups. #virtualenv #Technology #Tech #Innovation #LearnTech 📖 Learn more: https://lnkd.in/g_85zaNN
To view or add a comment, sign in
-
Ever feel like changing a button label shouldn’t require a frontend framework, an API contract, and three layers of state management? In #TalkPythonToMe – “PyView: Real-time Python WebApps”, Michael Kennedy talks with Larry Ogrodnek about bringing the Phoenix LiveView model to Python - real-time, interactive UIs with the server in charge. You’ll walk away knowing: ➡️ How LiveView-style apps work in Python (server state + HTML diffs over WebSockets); ➡️ When PyView beats SPAs (and when it doesn’t); ➡️ What you gain by killing the JSON API middleman; ➡️ How to scale stateful, real-time apps in practice (processes, Pub/Sub, deployment). If “full stack” currently means “full cognitive load,” this episode is a clean rethink. ( 👇 link to the episode in comments) #podcastrecommendation #Addendum
To view or add a comment, sign in
-
-
🚀 Day 49 of #100DaysOfCode LeetCode #83 – Remove Duplicates from Sorted List Today I solved a classic Linked List problem: 👉 Given the head of a sorted linked list, delete all duplicates such that each element appears only once. 👉 Return the linked list sorted as well. Since the list is already sorted, duplicates will always appear next to each other — which makes the solution efficient and elegant. 💡 Key Insight: Instead of using extra space (like a set), we can simply: Traverse the linked list Compare the current node with the next node Skip the next node if it’s a duplicate 🧠 Python Implementation: class ListNode: def __init__(self, val=0, next=None): self.val = val self.next = next def deleteDuplicates(head): current = head while current and current.next: if current.val == current.next.val: current.next = current.next.next else: current = current.next return head ✅ Why This Works: Time Complexity: O(n) Space Complexity: O(1) (no extra memory used) Efficient because the list is already sorted Problems like this strengthen understanding of: ✔️ Linked List traversal ✔️ Pointer manipulation ✔️ Writing clean and optimal code Consistency in solving small problems builds strong fundamentals. 💪 #LeetCode #Python #DataStructures #LinkedList #ProblemSolving #CodingJourney
To view or add a comment, sign in
-
-
The Python "Gotcha" That Every Developer Hits Once Ever had a function return data from a previous call that you never asked for? You might be falling for the Mutable Default Argument trap. It’s a classic behavior that still catches experienced devs off guard. Take a look at the comparison below 👇 The Issue: Code 1 ❌ When you use a mutable object like a list or dict as a default argument, Python evaluates that expression only once — at the moment the function is defined. It doesn't create a new list for every call. Instead, it reuses the same object in memory. The result? Your data "leaks" from one function call to the next, creating a persistent state you probably didn't want. The Fix: Code 2 ✅ To ensure a clean slate every time, use the Late Binding pattern: Set the default value to None Initialize the mutable object inside the function body This ensures that a brand-new list or dictionary is created only when the function actually runs. ⚡ Key Takeaway Avoid using [], {}, or set() as default arguments. Stick to None or immutable types (strings, ints, tuples) to keep your code predictable and side-effect-free. It’s a small implementation detail, but mastering it saves hours of debugging "ghost data" in your backend. #Python #PythonDeveloper #Programming #SoftwareEngineering #BackendDevelopment #CodingTips #CleanCode #Debugging #ProgrammingTips #DevCommunity #SoftwareDevelopment
To view or add a comment, sign in
-
-
⁉️ Have you ever actually thought about what __name__ == "__main__" means? Most of us wrote it the first time because a tutorial said so. Today I was structuring a small backend service in Python. Nothing flashy yet, just defining the application entry point. And that familiar line showed up again: ✳️ if __name__ == "__main__": It’s simple, but it solves an important architectural problem. In Python, every file is a module. When you execute a file directly: ✳️ python app.py Python assigns: ✳️ __name__ = "__main__" But when the same file is imported somewhere else: ✳️ import app Now: ✳️ __name__ = "__app__" That difference determines whether certain blocks of code run or stay dormant. Why is that useful? Because it lets you: • Keep runtime logic separate from reusable logic • Prevent accidental execution when modules are imported • Define a clear entry point for your application • Expose objects (like a Flask/FastAPI app instance) without auto-starting the server Without this guard, importing a module could trigger execution unintentionally — which becomes messy in larger systems. It’s one of those small Python conventions that quietly enforces better structure. Not flashy. But foundational. #Python #BackendDevelopment #SoftwareEngineering #Architecture
To view or add a comment, sign in
-
-
Building Better Habits… with 15 < Lines of Python Lately I’ve been thinking about how self‑development doesn’t always require big systems or complex tools. Sometimes a tiny script is enough to shift your mindset. So I wrote a simple Python program that does one < thing: asks what habit I’m working on today, checks if I did it, and gives me a small motivational nudge. Nothing fancy. No dashboards. No streak pressure. Just a gentle daily check‑in powered by code. Why? Because self‑development is really about showing up for yourself in small, consistent ways—and sometimes a lightweight tool is all you need to stay aligned.
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development