GeistHaus
log in · sign up

Programmer blog

Part of feedburner.com

My thoughts/recipes on Django, Python, JS and other things I try...

stories
AI Agents in Visual Studio Code
Show full content
Getting Started with AI Agents in Visual Studio Code

AI agents are becoming a powerful part of modern development. If you're using Visual Studio Code, you can integrate tools like Codex directly into your workflow and significantly speed up coding, debugging, and refactoring.

1. Install the AI Extension

Open VS Code and go to the Extensions panel (Ctrl+Shift+X). Search for an AI extension such as OpenAI / Codex / ChatGPT and install it.

2. Connect Your Account

After installation, you’ll usually see a Sign In button. Click it and log in using your account (via browser). Once authorized, VS Code will connect to your AI provider.

3. Adding Codex to Your IDE

Some extensions require an API key. To add it:

  • Open Settings (Ctrl + ,)
  • Search for API Key
  • Paste your key from your provider dashboard
4. Basic Usage

Once everything is connected, you can start using the AI:

  • Right-click in editor → Ask AI
  • Use command palette (Ctrl+Shift+P) → search "AI"
  • Use inline suggestions while typing
5. Agent Mode (Interactive Workflow)

Modern AI tools support Agent Mode, where the assistant can:

  • Suggest code changes
  • Modify multiple files
  • Run commands

However, actions are not executed automatically. You will be asked to approve each step before it runs.

6. Approving Actions

When the agent proposes something, you’ll typically see buttons like:

  • Apply – accept changes
  • Reject – decline
  • Preview – review before applying

This keeps you in control while still benefiting from automation.

Conclusion

Using AI agents in VS Code is straightforward:

  • Install extension
  • Log in
  • Add API key (if needed)
  • Start using commands and agent mode

Once set up, AI becomes a natural part of your development process.

tag:blogger.com,1999:blog-8227451082901531762.post-2828822818894215579
Extensions
Making a TODO app with React
pnpm setup ReactReact app tutorialReact componentsReact RouterReact routingReact state managementReact todo appStyling React todoTask inputTask listTask management app
Show full content

Once in a time a decent dev must renew his knowledge of tech. So I decided to recollect react by creating a basic TODO app with it.

To start it one need to install react project. I prefer `pnpm` and `nvm` for managing packages and node versions respectively. Here are my steps to install React:

Step 1: Install pnpm


If you don’t already have pnpm installed, install it globally via npm or corepack:

npm install -g pnpm


Or, if you’re using Node.js >=16.13, you can enable it with:

corepack enable


Step 2: Create a Project Directory


Create a new directory for your React app and navigate into it:

mkdir react-todo
cd react-todo


Step 3: Initialize the Project


Initialize the project with pnpm:

pnpm init


Follow the prompts or press Enter to accept the defaults.


Step 4: Install React and ReactDOM


Install React and ReactDOM libraries, along with vite for an optimized development experience:

pnpm add react react-dom
pnpm add -D vite


Step 5: Set Up Vite


Initialize a basic vite project setup:

pnpm exec vite


Follow the prompts, choosing react as the framework and any additional options as desired.


Step 6: Update package.json Scripts


Edit your package.json file to include a start script for Vite:

"scripts": {
  "dev": "vite",
  "build": "vite build",
  "serve": "vite preview"
}

Step 7: Create the App Structure


Make a basic React app structure:

1. Create src directory:

mkdir src





2. Create index.html:

In the root of your project, add the following contents:

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Hello World</title>
</head>
<body>
  <div id="root"></div>
  <script type="module" src="/src/main.jsx"></script>
</body>
</html>

    3. Create src/main.jsx:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<App />);


4. Create src/App.jsx:

import React from 'react';

const App = () => {
  return <h1>TODO:</h1>;
};

export default App;


Step 8: Start the Development Server


Run the development server to preview your app:

pnpm dev

Open your browser and navigate to the URL displayed in the terminal (usually http://localhost:5173 ).


Step 9: Confirm the Project Structure


Ensure your project structure looks like this:

├── package.json
├── pnpm-lock.yaml
├── node_modules/
├── vite.config.js (optional, for custom configurations)
├── index.html
└── src/
    ├── App.jsx
    ├── main.jsx


Step 10: Solve issues that may occur


Mine was having `ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command "dev" not found ` error. I have solved it by manually running vite for now:


user@ro react-todo % pnpm dev
 ERR_PNPM_RECURSIVE_EXEC_FIRST_FAIL  Command "dev" not found
user@ro react-todo % pnpm list
Legend: production dependency, optional only, dev only

react-todo@1.0.0 /Users/user/dev/me/react-todo

dependencies:
react 19.0.0
react-dom 19.0.0

devDependencies:
vite 6.0.5
user@ro react-todo % pnpm exec vite
Port 5173 is in use, trying another one...

  VITE v6.0.5  ready in 84 ms

  ➜  Local:   http://localhost:5174/
  ➜  Network: use --host to expose
  ➜  press h + enter to show help

That did the trick and I was up and runnging for farther manipulations.


Here’s how to extend the “Hello World” app into a basic TODO app with the following features:

• Add tasks.

• Mark tasks as complete.

• Store tasks on a server.


We’ll achieve this in a step-by-step manner.



Step 11: Update the App to a TODO Component


Replace the src/App.jsx content with a basic TODO app.

import React, { useState, useEffect } from 'react';

const App = () => {
  const [tasks, setTasks] = useState([]);
  const [newTask, setNewTask] = useState('');

  // Fetch tasks from the server
  useEffect(() => {
    fetch('http://localhost:3000/tasks')
      .then((response) => response.json())
      .then((data) => setTasks(data))
      .catch((error) => console.error('Error fetching tasks:', error));
  }, []);

  // Add a new task
  const addTask = () => {
    if (!newTask.trim()) return;

    const task = { text: newTask, completed: false };
    fetch('http://localhost:3000/tasks', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
      .then((response) => response.json())
      .then((savedTask) => {
        setTasks([...tasks, savedTask]);
        setNewTask('');
      })
      .catch((error) => console.error('Error adding task:', error));
  };

  // Toggle task completion
  const toggleTask = (taskId) => {
    const taskToUpdate = tasks.find((task) => task.id === taskId);
    if (!taskToUpdate) return;

    fetch(`http://localhost:3000/tasks/${taskId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...taskToUpdate, completed: !taskToUpdate.completed }),
    })
      .then((response) => response.json())
      .then((updatedTask) => {
        setTasks(tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task)));
      })
      .catch((error) => console.error('Error updating task:', error));
  };

  return (
    <div style={{ padding: '20px', maxWidth: '400px', margin: 'auto', fontFamily: 'Arial, sans-serif' }}>
      <h1>TODO App</h1>
      <div style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}>
        <input
          type="text"
          value={newTask}
          onChange={(e) => setNewTask(e.target.value)}
          placeholder="Enter a task..."
          style={{ flex: 1, padding: '8px' }}
        />
        <button onClick={addTask} style={{ padding: '8px 12px' }}>
          Add
        </button>
      </div>
      <ul style={{ listStyle: 'none', padding: 0 }}>
        {tasks.map((task) => (
          <li
            key={task.id}
            style={{
              display: 'flex',
              justifyContent: 'space-between',
              padding: '8px 0',
              textDecoration: task.completed ? 'line-through' : 'none',
            }}
          >
            <span onClick={() => toggleTask(task.id)} style={{ cursor: 'pointer' }}>
              {task.text}
            </span>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;


Step 12: Set Up the Server


We’ll use a simple JSON server to handle tasks.

1. Install JSON Server globally if not already installed:

 pnpm add -g json-server

2. Create a db.json file at the root of your project with initial data:


{
  "tasks": [
    { "id": 1, "text": "Sample Task 1", "completed": false },
    { "id": 2, "text": "Sample Task 2", "completed": true }
  ]
}

3. Start the server:

json-server --watch todo.json --port 3000

The server will be running at http://localhost:3000.


Step 13: Test the App


1. Run the React app:

pnpm dev

2. Visit the app in your browser (e.g., http://localhost:5173).

3. Add tasks, toggle their completion, and see the data persist on the server.

Step 14: Add Styles (Optional)


You can improve the app’s look by adding styles in a separate src/styles.css file and importing it into src/main.jsx:

import './styles.css';

For example, a styles.css file might contain:

body {
  font-family: Arial, sans-serif;
  background: #f9f9f9;
  margin: 0;
  padding: 0;
}

h1 {
  color: #333;
}

button {
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
}

button:hover {
  background-color: #0056b3;
}
You now have a functional TODO app with server-side persistence. 

Let’s style the TODO items to include checkboxes for marking tasks as complete. This will provide a better user experience with a clean, modern look.


Step 1: Update the App.jsx


Modify the TODO list in App.jsx to include checkboxes for marking tasks as complete. Here’s the updated code:

import React, { useState, useEffect } from 'react';

const App = () => {
  const [tasks, setTasks] = useState([]);
  const [newTask, setNewTask] = useState('');

  // Fetch tasks from the server
  useEffect(() => {
    fetch('http://localhost:3000/tasks')
      .then((response) => response.json())
      .then((data) => setTasks(data))
      .catch((error) => console.error('Error fetching tasks:', error));
  }, []);

  // Add a new task
  const addTask = () => {
    if (!newTask.trim()) return;

    const task = { text: newTask, completed: false };
    fetch('http://localhost:3000/tasks', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
      .then((response) => response.json())
      .then((savedTask) => {
        setTasks([...tasks, savedTask]);
        setNewTask('');
      })
      .catch((error) => console.error('Error adding task:', error));
  };

  // Toggle task completion
  const toggleTask = (taskId) => {
    const taskToUpdate = tasks.find((task) => task.id === taskId);
    if (!taskToUpdate) return;

    fetch(`http://localhost:3000/tasks/${taskId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...taskToUpdate, completed: !taskToUpdate.completed }),
    })
      .then((response) => response.json())
      .then((updatedTask) => {
        setTasks(tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task)));
      })
      .catch((error) => console.error('Error updating task:', error));
  };

  return (
    <div style={{ padding: '20px', maxWidth: '400px', margin: 'auto', fontFamily: 'Arial, sans-serif' }}>
      <h1>TODO App</h1>
      <div style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}>
        <input
          type="text"
          value={newTask}
          onChange={(e) => setNewTask(e.target.value)}
          placeholder="Enter a task..."
          style={{ flex: 1, padding: '8px' }}
        />
        <button onClick={addTask} style={{ padding: '8px 12px' }}>
          Add
        </button>
      </div>
      <ul style={{ listStyle: 'none', padding: 0 }}>
        {tasks.map((task) => (
          <li
            key={task.id}
            style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'space-between',
              padding: '8px 0',
              borderBottom: '1px solid #ddd',
            }}
          >
            <label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer', gap: '10px' }}>
              <input
                type="checkbox"
                checked={task.completed}
                onChange={() => toggleTask(task.id)}
              />
              <span
                style={{
                  textDecoration: task.completed ? 'line-through' : 'none',
                  color: task.completed ? '#999' : '#000',
                }}
              >
                {task.text}
              </span>
            </label>
          </li>
        ))}
      </ul>
    </div>
  );
};

export default App;


Step 2: Style the App


To enhance the design, you can add a styles.css file. Here’s a simple example:


src/styles.css:

body {
  font-family: Arial, sans-serif;
  background: #f9f9f9;
  margin: 0;
  padding: 0;
}

h1 {
  text-align: center;
  color: #333;
}

button {
  background-color: #007bff;
  color: white;
  border: none;
  border-radius: 4px;
  cursor: pointer;
  font-size: 16px;
}

button:hover {
  background-color: #0056b3;
}

input[type="text"] {
  border: 1px solid #ddd;
  border-radius: 4px;
  font-size: 16px;
}

input[type="checkbox"] {
  width: 18px;
  height: 18px;
  cursor: pointer;
}

ul {
  padding: 0;
  margin: 0;
}

li {
  transition: background-color 0.3s ease;
}

li:hover {
  background-color: #f0f0f0;
}


Result


• Each TODO item now has a checkbox.

• Checked tasks have their text styled with a strikethrough and muted color.

• The overall app has a clean, minimal design.

Let’s break the App.jsx into separate components for better readability and maintainability. We’ll create three components:

1. TaskInput: For adding new tasks.

2. TaskItem: For rendering individual task items.

3. TaskList: For rendering the list of tasks.


Updated App.jsx


Here’s the updated App.jsx with the new structure:

import React, { useState, useEffect } from 'react';
import TaskInput from './TaskInput';
import TaskList from './TaskList';

const App = () => {
  const [tasks, setTasks] = useState([]);

  // Fetch tasks from the server
  useEffect(() => {
    fetch('http://localhost:3000/tasks')
      .then((response) => response.json())
      .then((data) => setTasks(data))
      .catch((error) => console.error('Error fetching tasks:', error));
  }, []);

  // Add a new task
  const addTask = (text) => {
    const task = { text, completed: false };
    fetch('http://localhost:3000/tasks', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
      .then((response) => response.json())
      .then((savedTask) => setTasks([...tasks, savedTask]))
      .catch((error) => console.error('Error adding task:', error));
  };

  // Toggle task completion
  const toggleTask = (taskId) => {
    const taskToUpdate = tasks.find((task) => task.id === taskId);
    if (!taskToUpdate) return;

    fetch(`http://localhost:3000/tasks/${taskId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...taskToUpdate, completed: !taskToUpdate.completed }),
    })
      .then((response) => response.json())
      .then((updatedTask) => {
        setTasks(tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task)));
      })
      .catch((error) => console.error('Error updating task:', error));
  };

  return (
    <div style={{ padding: '20px', maxWidth: '400px', margin: 'auto', fontFamily: 'Arial, sans-serif' }}>
      <h1>TODO App</h1>
      <TaskInput onAddTask={addTask} />
      <TaskList tasks={tasks} onToggleTask={toggleTask} />
    </div>
  );
};

export default App;


TaskInput.jsx


This component handles adding new tasks.

import React, { useState } from 'react';

const TaskInput = ({ onAddTask }) => {
  const [newTask, setNewTask] = useState('');

  const handleAddTask = () => {
    if (!newTask.trim()) return;
    onAddTask(newTask);
    setNewTask('');
  };

  return (
    <div style={{ display: 'flex', gap: '10px', marginBottom: '20px' }}>
      <input
        type="text"
        value={newTask}
        onChange={(e) => setNewTask(e.target.value)}
        placeholder="Enter a task..."
        style={{ flex: 1, padding: '8px' }}
      />
      <button onClick={handleAddTask} style={{ padding: '8px 12px' }}>
        Add
      </button>
    </div>
  );
};

export default TaskInput;


TaskItem.jsx


This component represents a single task with a checkbox.

import React from 'react';

const TaskItem = ({ task, onToggleTask }) => {
  return (
    <li
      style={{
        display: 'flex',
        alignItems: 'center',
        justifyContent: 'space-between',
        padding: '8px 0',
        borderBottom: '1px solid #ddd',
      }}
    >
      <label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer', gap: '10px' }}>
        <input
          type="checkbox"
          checked={task.completed}
          onChange={() => onToggleTask(task.id)}
        />
        <span
          style={{
            textDecoration: task.completed ? 'line-through' : 'none',
            color: task.completed ? '#999' : '#000',
          }}
        >
          {task.text}
        </span>
      </label>
    </li>
  );
};

export default TaskItem;


TaskList.jsx


This component renders the list of tasks using the TaskItem component.

import React from 'react';
import TaskItem from './TaskItem';

const TaskList = ({ tasks, onToggleTask }) => {
  return (
    <ul style={{ listStyle: 'none', padding: 0 }}>
      {tasks.map((task) => (
        <TaskItem key={task.id} task={task} onToggleTask={onToggleTask} />
      ))}
    </ul>
  );
};

export default TaskList;


Final Project Structure


Your project structure should now look like this:

src/
├── App.jsx
├── TaskInput.jsx
├── TaskItem.jsx
├── TaskList.jsx
├── main.jsx
└── styles.css


Benefits of Refactoring🚀


Readability: Smaller components are easier to understand.

Reusability: Components like TaskItem can be reused in other parts of the app if needed.

Scalability: Adding new features or modifying existing ones is simpler when components are separated.


Lets modify it farther to make App.jsx even smaller. What can we do?


To make App.jsx even smaller and more focused, we can extract state management and business logic into custom hooks or context providers. Here’s how to achieve that:


Step 1: Create a Custom Hook for Task Management


Move the logic for fetching tasks, adding tasks, and toggling task completion into a custom hook called useTasks.


src/hooks/useTasks.js:

import { useState, useEffect } from 'react';

const useTasks = (apiUrl) => {
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    fetch(`${apiUrl}/tasks`)
      .then((response) => response.json())
      .then((data) => setTasks(data))
      .catch((error) => console.error('Error fetching tasks:', error));
  }, [apiUrl]);

  const addTask = (text) => {
    const task = { text, completed: false };
    fetch(`${apiUrl}/tasks`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
      .then((response) => response.json())
      .then((savedTask) => setTasks([...tasks, savedTask]))
      .catch((error) => console.error('Error adding task:', error));
  };

  const toggleTask = (taskId) => {
    const taskToUpdate = tasks.find((task) => task.id === taskId);
    if (!taskToUpdate) return;

    fetch(`${apiUrl}/tasks/${taskId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...taskToUpdate, completed: !taskToUpdate.completed }),
    })
      .then((response) => response.json())
      .then((updatedTask) => {
        setTasks(tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task)));
      })
      .catch((error) => console.error('Error updating task:', error));
  };

  return { tasks, addTask, toggleTask };
};

export default useTasks;


Step 2: Update App.jsx to Use the Custom Hook


With the logic moved to the custom hook, App.jsx is now much simpler:


src/App.jsx:

import React from 'react';
import useTasks from './hooks/useTasks';
import TaskInput from './TaskInput';
import TaskList from './TaskList';

const App = () => {
  const apiUrl = 'http://localhost:3000'; // API URL
  const { tasks, addTask, toggleTask } = useTasks(apiUrl);

  return (
    <div style={{ padding: '20px', maxWidth: '400px', margin: 'auto', fontFamily: 'Arial, sans-serif' }}>
      <h1>TODO App</h1>
      <TaskInput onAddTask={addTask} />
      <TaskList tasks={tasks} onToggleTask={toggleTask} />
    </div>
  );
};

export default App;


Step 3: Refactor the API URL to a Context (Optional)


If you plan to reuse the API URL or centralize configuration, you can create an ApiProvider using React Context.


src/context/ApiProvider.jsx:

import React, { createContext, useContext } from 'react';

const ApiContext = createContext();

export const ApiProvider = ({ children, apiUrl }) => (
  <ApiContext.Provider value={apiUrl}>{children}</ApiContext.Provider>
);

export const useApi = () => useContext(ApiContext);


Step 4: Update the App to Use the API Context


Wrap the app in the ApiProvider and refactor the useTasks hook to use the API URL from context:


Update src/main.jsx:

import React from 'react';
import ReactDOM from 'react-dom/client';
import App from './App';
import { ApiProvider } from './context/ApiProvider';

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
  <ApiProvider apiUrl="http://localhost:3000">
    <App />
  </ApiProvider>
);


Update src/hooks/useTasks.js:

import { useState, useEffect } from 'react';
import { useApi } from '../context/ApiProvider';

const useTasks = () => {
  const apiUrl = useApi();
  const [tasks, setTasks] = useState([]);

  useEffect(() => {
    fetch(`${apiUrl}/tasks`)
      .then((response) => response.json())
      .then((data) => setTasks(data))
      .catch((error) => console.error('Error fetching tasks:', error));
  }, [apiUrl]);

  const addTask = (text) => {
    const task = { text, completed: false };
    fetch(`${apiUrl}/tasks`, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(task),
    })
      .then((response) => response.json())
      .then((savedTask) => setTasks([...tasks, savedTask]))
      .catch((error) => console.error('Error adding task:', error));
  };

  const toggleTask = (taskId) => {
    const taskToUpdate = tasks.find((task) => task.id === taskId);
    if (!taskToUpdate) return;

    fetch(`${apiUrl}/tasks/${taskId}`, {
      method: 'PUT',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ ...taskToUpdate, completed: !taskToUpdate.completed }),
    })
      .then((response) => response.json())
      .then((updatedTask) => {
        setTasks(tasks.map((task) => (task.id === updatedTask.id ? updatedTask : task)));
      })
      .catch((error) => console.error('Error updating task:', error));
  };

  return { tasks, addTask, toggleTask };
};

export default useTasks;


Resulting Project Structure


The project is now modular and clean:

src/
├── App.jsx
├── context/
│   └── ApiProvider.jsx
├── hooks/
│   └── useTasks.js
├── TaskInput.jsx
├── TaskItem.jsx
├── TaskList.jsx
├── main.jsx
└── styles.css


Benefits of Further Refactoring


1. Smaller App.jsx: Focuses purely on rendering.

2. Reusability: useTasks can be reused in other components or applications.

3. Centralized Config: The API URL is managed globally with React Context.

4. Scalability: Adding more hooks or features doesn’t clutter the main app file.

Lets add new component to this menu. That would navigate us through the app...


To add navigation to the app, we’ll incorporate a menu component and use React Router for navigation between pages. Here’s how we can enhance the app:


Step 1: Install React Router


Run the following command to add React Router to your project:

pnpm add react-router-dom

Step 2: Create a Menu Component


The Menu component will act as the navigation bar.


src/Menu.jsx:

import React from 'react';
import { NavLink } from 'react-router-dom';

const Menu = () => {
  const linkStyle = {
    padding: '10px 20px',
    textDecoration: 'none',
    color: '#007bff',
    fontWeight: 'bold',
  };

  const activeStyle = {
    color: '#0056b3',
    textDecoration: 'underline',
  };

  return (
    <nav style={{ marginBottom: '20px', borderBottom: '1px solid #ddd', paddingBottom: '10px' }}>
      <NavLink to="/" style={linkStyle} activeStyle={activeStyle} exact>
        Home
      </NavLink>
      <NavLink to="/tasks" style={linkStyle} activeStyle={activeStyle}>
        Tasks
      </NavLink>
      <NavLink to="/about" style={linkStyle} activeStyle={activeStyle}>
        About
      </NavLink>
    </nav>
  );
};

export default Menu;


Step 3: Update App.jsx for Routing


We’ll use React Router to define routes for the app. Update App.jsx to include navigation and routing logic.


src/App.jsx:

import React from 'react';
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom';
import Menu from './Menu';
import TaskPage from './pages/TaskPage';
import AboutPage from './pages/AboutPage';

const App = () => {
  return (
    <Router>
      <div style={{ padding: '20px', maxWidth: '600px', margin: 'auto', fontFamily: 'Arial, sans-serif' }}>
        <h1>TODO App</h1>
        <Menu />
        <Routes>
          <Route path="/" element={<HomePage />} />
          <Route path="/tasks" element={<TaskPage />} />
          <Route path="/about" element={<AboutPage />} />
        </Routes>
      </div>
    </Router>
  );
};

const HomePage = () => (
  <div>
    <h2>Welcome to the TODO App</h2>
    <p>Navigate to the "Tasks" page to manage your tasks or learn more about this app on the "About" page.</p>
  </div>
);

export default App;


Step 4: Create Pages for Tasks and About


src/pages/TaskPage.jsx:


This page renders the TODO functionality.

import React from 'react';
import TaskInput from '../TaskInput';
import TaskList from '../TaskList';
import useTasks from '../hooks/useTasks';

const TaskPage = () => {
  const apiUrl = 'http://localhost:3000'; // API URL
  const { tasks, addTask, toggleTask } = useTasks(apiUrl);

  return (
    <div>
      <h2>Task Manager</h2>
      <TaskInput onAddTask={addTask} />
      <TaskList tasks={tasks} onToggleTask={toggleTask} />
    </div>
  );
};

export default TaskPage;


src/pages/AboutPage.jsx:


This page displays information about the app.

import React from 'react';

const AboutPage = () => {
  return (
    <div>
      <h2>About This App</h2>
      <p>
        This is a simple TODO app built with React. It allows you to create tasks, mark them as complete, 
        and store data on a server. Navigation is handled with React Router.
      </p>
    </div>
  );
};

export default AboutPage;


Step 5: Final Project Structure


After these changes, your project structure will look like this:

src/
├── App.jsx
├── Menu.jsx
├── TaskInput.jsx
├── TaskItem.jsx
├── TaskList.jsx
├── context/
│   └── ApiProvider.jsx
├── hooks/
│   └── useTasks.js
├── pages/
│   ├── AboutPage.jsx
│   ├── TaskPage.jsx
├── main.jsx
└── styles.css

Step 6: Result


Home Page: A welcome page with navigation instructions.

Tasks Page: The TODO management functionality.

About Page: Information about the app.


Menu Navigation


The menu lets users switch between the “Home,” “Tasks,” and “About” pages seamlessly.


Here is a final result on my github with some errors corrected that I'm leaving for the reader to handle as a practice task.

https://github.com/garmoncheg/react-todo

Hope it helps someone starting with react.

tag:blogger.com,1999:blog-8227451082901531762.post-2540340297043360973
Extensions
Install bcrypt on Mac OSX
bcryptbcryptjsbrewhomebrewhowtoinstallm1mac
Show full content

 Basically One can do it wih homebrew.

About the AppInstall the homebrew package manager
  1. Open Terminal and press enter/return key.
  2. Copy and paste the following command in Terminal app:
    /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"
    and press enter/return key. Wait for the command to finish. If you are prompted to enter a password, please type your Mac user's login password and press ENTER. Mind you, as you type your password, it won't be visible on your Terminal (for security reasons), but rest assured it will work.
  3. Now, copy/paste and run this command to make brew command available inside the Terminal: echo 'eval "$(/opt/homebrew/bin/brew shellenv)"' >> ~/.zprofile
Install the bcrypt lib
  1. Copy and paste the following command:
    brew install bcrypt

Done! You can now use bcrypt.

tag:blogger.com,1999:blog-8227451082901531762.post-3831760272276022402
Extensions
Writing nice prompts for stable diffusion and like neural networks
AIDiffusionGenerative AIImage generationNeural networksStable Diffusionstable diffusion 1.5
Show full content


Request: new york city, synthwave, cinematic, dramatic, composition, sunny sky, brutalist, hyper realistic, epic scale, sense of awe, hypermaximalist, insane level of details, artstation HQ

Playing with neural models is really fun. Let's try to make our best at writing good requests. That's the key! So thst's how:

Diffusion prompts are statements or questions that are designed to help individuals think more deeply about a topic or concept and draw their own conclusions. They are often used in discussions or debates to encourage critical thinking and encourage participants to consider different perspectives.

Here are some tips for writing good, stable diffusion prompts:

  1. Make sure the prompt is clear and concise: Avoid using jargon or complex language that may be confusing to readers. Keep the prompt brief and to the point, so that it is easy for readers to understand and respond to.

  2. Focus on a specific topic or concept: Choose a specific topic or concept to focus on, and make sure the prompt is directly related to this topic. This will help readers stay on track and avoid getting sidetracked by unrelated issues.

  3. Encourage critical thinking: The goal of a diffusion prompt is to encourage critical thinking and encourage participants to consider different perspectives. Use questions or statements that challenge readers to think more deeply about the topic and consider alternative viewpoints.

  4. Avoid leading questions: Avoid using questions that are biased or leading, as these can influence the reader's response and skew the results of the discussion. Instead, use neutral, unbiased language to encourage honest and objective responses.

  5. Make sure the prompt is relevant: The prompt should be relevant to the topic being discussed and should be of interest to the reader. If the prompt is not engaging or relevant, it may be difficult to get a meaningful response.


Ths's it...

Request: new york city, dust storm, cinematic, dramatic, composition, sunny sky, brutalist, hyper realistic, epic scale, sense of awe, hypermaximalist, insane level of details, artstation HQ
tag:blogger.com,1999:blog-8227451082901531762.post-68571152707727005
Extensions
Running tasks with Celery on Heroku guide
beatcelerydeploydjangoexampleguideherokuhostingprojectpythontutorialworker
Show full content
An example project and a basic guide showing how to run Django/Celery on Heroku.
Basic requirements First of all, let's actually set up a typical Django project for this. We would need virtualenvwrapper  for that. One could use any other particular method. I prefer this one.
$ cd dev
$ mkvirtualenv dch
(dch) $ pip install django
(dch) $ django-admin startproject djheroku
(dch) $ cd djheroku
# Make sure is working:
(dch) $ ./manage.py runserver
From now I will consider working on a terminal with this (dch) environment on.
Heroku hosting setup We would need our project set up for heroku python server. The docs live HERE, as for moment of this guide writing. One would need to follow and setup a basic heroku project. I will not stop here rewriting official guide as it is good enough.
Installing celery Assuming we have a basic django dyno at heroku here we will continue.
Now let's install Celery and add it to our requirements list (as we had just started, let's just overwrite requirements.txt here):
$ pip install 'celery[redis]'
$ pip freeze > requirements.txt
Let's touch our settings.py adding the following snippet:
And include "djcelery" into INSTALLED_APPS tuple.
Redis broker  Another option would be a Redis-based broker. AMQP is great, but three connections are barely enough - it's a really tight limitation. RedisToGo addon allows for 10 connections, so we may consider using it instead. Both RabbitMQ and Redis brokers are considered stable and fully featured. Let's install the addon and Python module for Redis:
$ heroku addons:add rediscloud
Adding rediscloud on happy-holliday-1467... done, v10 (free)
Use `heroku addons:docs rediscloud` to view documentation.

$ echo 'redis==2.10.3' >> requirements.txt
$ pip install redis==2.10.3
Now we need to add certain settings to configure settings in Django project:
BROKER_URL = BROKER_URL = os.environ.get("REDISCLOUD_URL", "django://")
BROKER_POOL_LIMIT = 1
BROKER_CONNECTION_MAX_RETRIES = None

CELERY_TASK_SERIALIZER = "json"
CELERY_ACCEPT_CONTENT = ["json", "msgpack"]
CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler'

if BROKER_URL == "django://":
    INSTALLED_APPS += ("kombu.transport.django",)

BROKER_TRANSPORT_OPTIONS = {
    "max_connections": 2,
}
BROKER_POOL_LIMIT = None
We need to set the REDISCLOUD_URL after this is done in heroku app settings. (At the hosting control panel.
Continue with broker setup  Let's store our process by doing a commit. And since djcelery app has some models, also apply migrations:
$ git add djheroku/settings.py requirements.txt
$ git commit -m 'Add Celery support'
[master 43afd41] Add Celery support
 2 files changed, 46 insertions(+)
$ git push heroku master
...
-----> Installing dependencies with pip
       Installing collected packages: amqp, anyjson, billiard, celery, django-celery, kombu, pytz
...
$ heroku run python manage.py migrate
...
 Staying in a free tier with a single dyno  To save money on the start by not using the second dyno at all. From a Procfile we'll start a process manager that would run multiple processes for us. This just can't scale at all (any attempts to scale would give unpredictable results), but we could easily revise this at a later time. The only issue is, since this will be the web dyno, it will be killed ("sleeping" in Heroku terms) if no requests happen within one hour. Since we have a scheduler, we could probably work around this limitation by sending an HTTP request to ourselves, though. Let's consider we've added Celery worker to Procfile using one of the above methods. In this tutorial I'll stick to Python-only, Honcho.
$ echo 'honcho==1.0.1' >> requirements.txt
$ pip install honcho==1.0.1
We'll need a workers declared in a Procfile. Then we'll swap the file with a "proxy" one:
$ git mv Procfile Procfile.real
And change the Procfile.real with:
web: gunicorn helloworld.wsgi --log-file -
worker: python manage.py celery worker --loglevel=info
beat: python manage.py celery beat --loglevel=info
This Original Procfile (that is executed by heroku) should look like this:
web: env > .env; env PYTHONUNBUFFERED=true honcho start -f Procfile.real 2>&1
Now we should commit and push to heroku and connect to heroku loggin to check if everything went well:
$ heroku logs -t | cut -c34-
Another downside of this hack is messy logging. But it's the prices of a "free" compromise.
Celery essentials Now, we're done with the setup so let's actually write some tasks and their management code. First of all, let's create celery.py. A simple task that'd fetch an URL and return a status code would look as following:
import os
from celery import Celery
from django.conf import settings


# Lets the celery command line program know where project settings are.
os.environ.setdefault('DJANGO_SETTINGS_MODULE', 'djheroku.settings')

# Creates the instance of the Celery app.
app = Celery('djheroku')

app.config_from_object('djheroku:settings', namespace='CELERY')

# Set up autodiscovery of tasks in the INSTALLED_APPS.
app.autodiscover_tasks(lambda: settings.INSTALLED_APPS)

if __name__ == '__main__':
    app.start()
Now we have a command file to running celery on heroku server dyno. Next step is to add a sample task in a file called tasks.py. It will be auto-collected by celery:
from celery import task


@task()
def echoe():
    """
    A simple task that echoes a Hello World! text to celery console.
    """
    print('Hello World!')
Testing stuff We can now test this locally by running our server on one terminal instance:
$ ./manage.py runserver 0.0.0.0:8000
And a sample celery console with built in beat process as a debug purpose worker:
$ celery worker --loglevel=info --beat
Both those terminals instances will emulate a working heroku environment that we have just created.
Now we can trigger our sample script:
$ celery call echoe
This will trigger a task and put into celery beat queue. We can observe it's execution after some time passed on the celery worker console.
That's basically it.
Time to commit our changes and push to heroku.

Here is a git repository: https://github.com/garmoncheg/djheroku


tag:blogger.com,1999:blog-8227451082901531762.post-1080726068000630688
Extensions
SQLAlchemy (Flask) count model instances by unique values
countdistinctflaskgroup_bymodelmodelsrequestsqlsqlalchemy
Show full content
One comes to a task that has to do with counting items in a database. We will describe the right approach here. Despite being so obvious I did not find much of the docs for junior developers to watch and learn. Here is a sample task and solution:
Let's assume we have a model like so:
class Cycle(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    object_id = db.Column(db.String, nullable=False)
Sample date populated into it will be:
{
   id: 1,
   object_id: 'unique1'
}, {
   id: 2,
   object_id: 'unique1'
}, {
   id: 3,
   object_id: 'unique2'
}, {
   id: 4,
   object_id: 'unique2'
}, {
   id: 5,
   object_id: 'unique2'
}, {
   id: 6,
   object_id: 'unique3'
}
We need to count unique model instances with same object_id. To achieve this relatively simple task one would go straightforward. E.g. Fetch all the Cycle instances with a simple query and then iterate through them via for cycle. Looks like so:
objects = Cycle.query.all()
cycles_unique = {}
for object in objects:
    if object.object_id in cycles_unique.items():
        cycles_unique[object.object_id] += 1
    else:
        cycles_unique[object.object_id] = 1

print(cycles_unique)
The output would be like so:
{
    'unique1': 2, 
    'unique2': 3, 
    'unique3': 1
}
Job done. All ok. HOWEVER! Imagine this database column would grow to big sizes. E.g. Those Cycles are 1 000 000 records. It is not a rare situation in coding world. Called - BigData ;)

We have a problem with cycle like so. Flask or whatever gear i used behind those models would need to load all those 1 million records into memory and then process them one by one. Even with fast server it will be not an easy task in the scope of rendering a webpage. User might wait quite long for the answer.

Making it faster means doing this count on a DB side. SQL databases are built specially for tasks like so and will do much much better at this. Incomparable to code written above.

Proper implementation would be by using SQL syntax and handling on a DB side. Code will use a query that counts unique records with that one particular field. Looks like so:
from sqlalchemy import func
from sqlalchemy.sql import label

session.query(
        label('object_id', Crop.object_id),  func.count(Cycle.object_id)
).group_by(Cycle.object_id).all()
This will output the data similar to the above. However output is with numbers of Long type (Python Long).
[('unique1', 2L), ('unique2', 3L), ('unique3', 1L)]
This is basically how to solve this task properly with SQL Alchemy and Flask models.
Hope it helps someone to write more reliable and better code.
tag:blogger.com,1999:blog-8227451082901531762.post-6716803500462201344
Extensions
PostgreSQL DB with pgAdmin4 access through SSH tunnel
connectdatabaseDBdevelopmentpgAdminPostgreSQLproductionremotestagetunnel
Show full content
Despite using console most of the time I have a preference to edit PostgreSQL databases through UI. Especially when it comes to remote side. Usually one can access this through $ psql command. However this tends to writing raw SQL queries and a lot of typing in overall.
Here is a way to do it with UI. First one needs to make a tunnel.Command is fairly simple:
ssh -fNg -L 5555:localhost:5432 {username}@{host.com}
One has a tunnel afterwards. This command opens a SSH connection in the background mapping your local port 5555 to your server’s port 5432 (Postgres’ default port). To understand one can observe the meaning of the flags via $ man ssh to see what each of these flags doing.
 It can be accessed via localhost tools like pgAdmin4 at localhost and port 5555
DB config would look like so:
tag:blogger.com,1999:blog-8227451082901531762.post-4776252662391792829
Extensions
Run Flask with Debug in PyCharm
configurationdebugflaskprojectPyCharmrunvisual
Show full content
I have gotten to setting UP a Flask environment for a project recently. Was completely puzzled by how to run this. I have used to running Django project with python manage.py script. This means pointing out a PyCharm interpreter into a certain point of entry, that is also a .py file also.

In flask way of starting things there is another approach however. Here it is in Flask Docs.
It states to set a variable FLASK_APP and then run a flask run command. This will confuse running a python script way of a project being run. Thus to fix this one needs to set a path to flask binary file. It usually is within a virtual environment binary directory, place where your python interpreter resides.

So to set debugging one needs to set path to script binary one needs:
  • Script: /path/to/env/bin/flask
  • Script parameters: run 
  • Environment variable FLASK_APP=app.py
  • Environment variable FLASK_DEBUG=True
  • Set working directory back to your app path (It changes automatically according to script being set)
So my will look something like this:
tag:blogger.com,1999:blog-8227451082901531762.post-9136611169771380949
Extensions
Promise -fication of JS calls.
callbackcallback hellchangeES6examplehellhowtojavascriptpatternPromiseusage
Show full content
Found a new pattern to use recently that is called Promise. I really like the way ES6/7 brings new thinking patterns into life nowdays. Here is Promise used instead of old pattern.

It was to give JS method a callback function. This splitting code and making a lot of possibilities for error to come out in this place.

One would write old times according to MDN:
function greeting(name) {
  alert('Hello ' + name);
}

function processUserInput(callback) {
  var name = prompt('Please enter your name.');
  callback(name);
}

processUserInput(greeting);
And now it is made with Promise pattern like so:
let promise = new Promise((resolve, reject) => {
  resolve(prompt('Please enter your name.'));
});

promise.then((name) => { 
    alert('Hello ' + name); 
});
In general and briefly this now helps to avoid 'callback hell' with functions passed as arguments and write asynchronous code a sort of in synchronous manner.

This all becomes extra useful upon one having need to load set of data from a different sources. E.g. via several API cals to different url's and react accordingly.

Hail to ES6!
tag:blogger.com,1999:blog-8227451082901531762.post-1273351117934357564
Extensions
Vagrant error: * Unknown configuration section 'hostmanager'.
boilerplateboxenvironmenterrorfixvagrantvagrant up
Show full content
Sometimes you get a vagrant environment or boilerplate with a Vagrantfile config in there and do a vagrant up command. And see some errors. like this:
There are errors in the configuration of this machine. Please fix
the following errors and try again:

Vagrant:
* Unknown configuration section 'hostmanager'.
p.p1 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Andale Mono'; color: #c33720; background-color: #000000; background-color: rgba(0, 0, 0, 0.9)} p.p2 {margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px 'Andale Mono'; color: #28fe14; background-color: #000000; background-color: rgba(0, 0, 0, 0.9); min-height: 14.0px} span.s1 {font-variant-ligatures: no-common-ligatures}
To fix this one needs:
$ vagrant plugin install vagrant-hostmanager
Installing the 'vagrant-hostmanager' plugin. This can take a few minutes...
Fetching: vagrant-hostmanager-1.8.6.gem (100%)
Installed the plugin 'vagrant-hostmanager (1.8.6)'!
So command to fix this as follows:
vagrant plugin install vagrant-hostmanager
tag:blogger.com,1999:blog-8227451082901531762.post-7639008172442482817
Extensions
POP3 Mock (Fake) server using python script
debugdebuggingfakemockpop3pythonscriptserverservice
Show full content
Having a need in POP3 server for my debugging purposes I have used this script.
Letting it to be here in case of anyone would need to do something similar.
Usage is:
$ python pypopper.py 110 email_file.eml

"""pypopper: a file-based pop3 server

Useage:
    python pypopper.py <port> <path_to_message_file>
"""
import logging
import os
import socket
import sys
import traceback

logging.basicConfig(format="%(name)s %(levelname)s - %(message)s")
log = logging.getLogger("pypopper")
log.setLevel(logging.INFO)

class ChatterboxConnection(object):
    END = "\r\n"
    def __init__(self, conn):
        self.conn = conn
    def __getattr__(self, name):
        return getattr(self.conn, name)
    def sendall(self, data, END=END):
        if len(data) < 50:
            log.debug("send: %r", data)
        else:
            log.debug("send: %r...", data[:50])
        data += END
        self.conn.sendall(data)
    def recvall(self, END=END):
        data = []
        while True:
            chunk = self.conn.recv(4096)
            if END in chunk:
                data.append(chunk[:chunk.index(END)])
                break
            data.append(chunk)
            if len(data) > 1:
                pair = data[-2] + data[-1]
                if END in pair:
                    data[-2] = pair[:pair.index(END)]
                    data.pop()
                    break
        log.debug("recv: %r", "".join(data))
        return "".join(data)


class Message(object):
    def __init__(self, filename):
        msg = open(filename, "r")
        try:
            self.data = data = msg.read()
            self.size = len(data)
            self.top, bot = data.split("\r\n\r\n", 1)
            self.bot = bot.split("\r\n")
        finally:
            msg.close()


def handleUser(data, msg):
    return "+OK user accepted"

def handlePass(data, msg):
    return "+OK pass accepted"

def handleStat(data, msg):
    return "+OK 1 %i" % msg.size

def handleList(data, msg):
    return "+OK 1 messages (%i octets)\r\n1 %i\r\n." % (msg.size, msg.size)

def handleTop(data, msg):
    cmd, num, lines = data.split()
    assert num == "1", "unknown message number: %s" % num
    lines = int(lines)
    text = msg.top + "\r\n\r\n" + "\r\n".join(msg.bot[:lines])
    return "+OK top of message follows\r\n%s\r\n." % text

def handleRetr(data, msg):
    log.info("message sent")
    return "+OK %i octets\r\n%s\r\n." % (msg.size, msg.data)

def handleDele(data, msg):
    return "+OK message 1 deleted"

def handleNoop(data, msg):
    return "+OK"

def handleQuit(data, msg):
    return "+OK pypopper POP3 server signing off"

dispatch = dict(
    USER=handleUser,
    PASS=handlePass,
    STAT=handleStat,
    LIST=handleList,
    TOP=handleTop,
    RETR=handleRetr,
    DELE=handleDele,
    NOOP=handleNoop,
    QUIT=handleQuit,
)

def serve(host, port, filename):
    assert os.path.exists(filename)
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    sock.bind((host, port))
    try:
        if host:
            hostname = host
        else:
            hostname = "localhost"
        log.info("pypopper POP3 serving '%s' on %s:%s", filename, hostname, port)
        while True:
            sock.listen(1)
            conn, addr = sock.accept()
            log.debug('Connected by %s', addr)
            try:
                msg = Message(filename)
                conn = ChatterboxConnection(conn)
                conn.sendall("+OK pypopper file-based pop3 server ready")
                while True:
                    data = conn.recvall()
                    command = data.split(None, 1)[0]
                    try:
                        cmd = dispatch[command]
                    except KeyError:
                        conn.sendall("-ERR unknown command")
                    else:
                        conn.sendall(cmd(data, msg))
                        if cmd is handleQuit:
                            break
            finally:
                conn.close()
                msg = None
    except (SystemExit, KeyboardInterrupt):
        log.info("pypopper stopped")
    except Exception, ex:
        log.critical("fatal error", exc_info=ex)
    finally:
        sock.shutdown(socket.SHUT_RDWR)
        sock.close()

if __name__ == "__main__":
    if len(sys.argv) != 3:
        print "USAGE: [<host>:]<port> <path_to_message_file>"
    else:
        _, port, filename = sys.argv
        if ":" in port:
            host = port[:port.index(":")]
            port = port[port.index(":") + 1:]
        else:
            host = ""
        try:
            port = int(port)
        except Exception:
            print "Unknown port:", port
        else:
            if os.path.exists(filename):
                serve(host, port, filename)
            else:
                print "File not found:", filename
Original code is created by: Daniel Miller
tag:blogger.com,1999:blog-8227451082901531762.post-2082857233679006388
Extensions
Install Docker under Ubuntu 14.04 (Trusty)
attachcontainerdetachdockerdownloadguidehowtoinstallLinuxmanualserverubuntuvirtualvirtualization
Show full content
Docker supports Ubuntu versions:

  • Ubuntu Vivid 15.04 (64-bit)
  • Ubuntu Trusty 14.04 (LTS) (64-bit)
  • Ubuntu Precise 12.04 (LTS) (64-bit)
  • Ubuntu Raring 13.04 and Saucy 13.10 (64 bit) 

For both Vivid and Trusty you need nothing. It will work out of the box. Others will require some modifications. (Updating of some things, like kernel or installing with wget on 13.04)

1. To install docker from a repository do so:
sudo apt-get update
sudo apt-get install docker.io
sudo ln -sf /usr/bin/docker.io /usr/local/bin/docker
sudo sed -i '$acomplete -F _docker docker' /etc/bash_completion.d/docker.io

2. Now run it with:
sudo apt-get install lxc-docker

3. Make it run on system boot:
sudo update-rc.d docker.io defaults

4. Ready to go! Run container with an Ubuntu:
sudo docker run -i -t ubuntu /bin/bash

To disconnect, or detach, from the shell without exiting use the escape sequence Ctrl-p + Ctrl-q
tag:blogger.com,1999:blog-8227451082901531762.post-5965232035063891072
Extensions
Remi and EPEL repositories in CentOS
addCentOSepelhowtoinstallLinuxpackagesRemirepositoriesUnix
Show full content
There are 2 common repositories that come nowdays for centos. They contain tasty things, while they are absent in official repositories.

CentOS 5:
wget http://dl.fedoraproject.org/pub/epel/5/x86_64/epel-release-5-4.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-5.rpm
sudo rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm

CentOS 6:
wget http://dl.fedoraproject.org/pub/epel/6/x86_64/epel-release-6-8.noarch.rpm
wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
sudo rpm -Uvh remi-release-6*.rpm epel-release-6*.rpm

You can check you are successful like so:
ls -1 /etc/yum.repos.d/epel* /etc/yum.repos.d/remi.repo
/etc/yum.repos.d/epel.repo
/etc/yum.repos.d/epel-testing.repo
/etc/yum.repos.d/remi.repo

Now you are only left to activate Remi repository:
sudo vi /etc/yum.repos.d/remi.repo

In [remi] section we need to change enabled=0 into enabled=1. It will look like so:
[remi]
name=Les RPM de remi pour Enterprise Linux 6 - $basearch
#baseurl=http://rpms.famillecollet.com/enterprise/6/remi/$basearch/
mirrorlist=http://rpms.famillecollet.com/enterprise/6/remi/mirror
enabled=1
gpgcheck=1
gpgkey=file:///etc/pki/rpm-gpg/RPM-GPG-KEY-remi

Only need to update now:
yum update -y

















tag:blogger.com,1999:blog-8227451082901531762.post-2504210044804651691
Extensions
Tmux quick start guide
advancedbeginnercommandcomplexdiveeasyguidehotkeyLinuxmanualminimalpagescreenshortsimplestartterminaltmuxusewindow
Show full content
Tmux is a handy terminal manager that allows you to switch between terminal sessions easily. Without losing history or windows upon ssh disconnects or similar. It is like screen, just better. (First of all because of using client-server based technology... )

Here is my minimal keyboard shortcuts guide that allows you to start using Tmux in a blink of an eye. Endless advanced commands and hotkey combinations you could always find by entering "man tmux" in a terminal.

Tmux is installed quite easily in most of common linux based systems. Just type:
Ubuntu:
$ sudo apt-get install tmux
CentOS:
$ sudo yum install tmux

This allows you to start using by starting it with
$ tmux a || tmux new
This command first tries to attach to existing running tmux instance and creates new in case it is not found.

Ctrl+b d - Will allow you to disconnect at any time. (This is also a way it is happening when you loose ssh session. How to connect - look earlier)

Each session can have many windows:
Ctrl+b c - Create a new window. Ctrl+b 0...9 - switch to window #;
Ctrl+b p - switch to previous window;
Ctrl+b n - switch to next window;
Ctrl+b l - switch to next active window (to the one you have switched from to this window);
Ctrl+b & - close this window (Or just type exit in terminal.

One terminal can have multiple windows:
Ctrl+b % - splits current panel in part, vertically;
Ctrl+b " - splits current horizontally;
Ctrl+b →←↑↓ - switch between panels;
Ctrl+b x - close current panel (you could also type exit in a terminal window).

Minus is a scrolling behavior:
Ctrl+b PgUp - enters "copy mode", afterwards:
    PgUp, PgDown - scrolling;
    q - exit copy mode.

Good more complex gist of hotkeys also here:
HOTKEYS GIST
tag:blogger.com,1999:blog-8227451082901531762.post-2499926848320785536
Extensions
Installing MySQL and phpMyAdmin for web development on a Mac OS X 10.9, 10.8, 10.7, 10.6
10.710.810.9apachedaemondevelopmentinstallMac OS XMavericksMySQLnativepackagephpMyAdminpkgpreferenceservicesetuptipsweb
Show full content
This is a simple guide on installing a must have SQL database engine for web development. It is often used at the beginning of the journey and I did not find a good guide for it. That made me make myself one and share with others. Hope somebody would benefit from it.






First we need to setup the MySQL community edition (latest or not depending on your requirements). It's possible to download it here: http://dev.mysql.com/downloads/mysql/

It comes in form of a .pkg installer file. It is advised to install it as follows by using default settings. Installation is pretty straightforward. Just click next and agree several times...
This will add a service of MySQL to your system. Nothing more. To interact with it you need either to use SQL console (in case you know SQL) or install something like phpMyAdmin to interact with it. Your pkg installer installs a useful enough Preference Panel switch by default.
There you can have it basically configured. Only two basic options persist. Either to run the service on startup or start/stop service button. Go ahead and start a service for farther interaction:
It is possible to now test your MySQL version by typing a terminal command:
/usr/local/mysql/bin/mysql -v
Good idea would be to add a path to your mysql executable to system path in your bash config. So you could type just "mysql" without specifying a path. To do so append this line to your ~/.bashrc_profile:
export PATH="/usr/local/mysql/bin:$PATH"
Either restart console or do source ~/.bash_profile to update your current environment.
It is now possible to do:
mysql -v
Note you do not have to specify a path to it any more.

Stoping at this no more farther let's finish configuring mysql by adding at least one main user/password and disabling defaults. There is a handy config script for this:
sudo mysql_secure_installation
Just execute this and follow up the steps widely described to you there. That's it you can now use MySQL on your system.

Let's go ahead and make a UI for ourselves by installing phpMyAdmin. Basically it's a utility that runs on your mac's built in Apache server (make sure it is running) and provides you an ability to manage your SQL databases through a handy web UI.

here you need to download a http://www.phpmyadmin.net/home_page/downloads.php latest version of the phpMyAdmin.
You will get yourself an archive version of this PHP application. that's basically all you need to know about it.
You also need to have apache running on your MAC. Make sure you do. zThere are many guides on it. Basically you need to have your computer outputting something in your web browser in case of typing localhost in your address line:
With this in mind you also need to have PHP enabled in your apache config. There are guides on that too. Enough of precautions and let's move farther with our straightforward install:
Time to place our unpacked folder contents into ~/Sites folder. It is advised to rename it into 'myadmin' to follow along with me.
This will bring you ability to type:
http://localhost/~your_username/myadmin/setup/ or either http://localhost/myadmin/setup/, depending on your apache configuration.
This will show up something similar to this:
Click New Server button and configure your newly installed MySQL server, so phpMyAdmin would be able to use it.
Fill in only username root and your root password, leaving all the other fields intact. (with default settings). You hopefully remember specifying a password for root in the initial MySQL server configuration step?
Switch to the Authentication tab and enter them.
Now you are able to manage your MySQL databases through a web UI using phpMyAdmin Type in the address like: http://localhost/~username/myadmin/

Here you go... Please comment in case you have found it useful. I will know my time writing this was not wasted. thank you!
tag:blogger.com,1999:blog-8227451082901531762.post-4027702183335159597
Extensions
[Django CMS] Adding plugins inside plugins programatically
addbackendCMSdjangohtmlinterlinklinkLinkPluginnestednikplaceholderprogrammaticallyrelationscripttextTextPlugin
Show full content
I have a task to migrate a website. Old one is plain HTML and new one is Django CMS. I have a script that parses an HTML page from old website in to CMS page and places it into proper place.
Task is to migrate all the page content (that is a CMS TextPlugin) into an interlinked pages setup. Like we have text

<p>blah blah </p><a href="/page/url">Text</a><p> some other text</p>

And I need to change it into CMS LinkPlugin that is nested inside of the TextPlugin. It have become a common standard in the Django CMS world now. Note we need to have a LinkPlugin because of the requirement to interlink pages.
E.g. <a href="/page/url"> is a link to CMS Page object.

The solution is divided into two major parts. First we need to have the link plugin added to a placeholder of the text plugin. It must also be nested by the TextPlugin, like Django CMS admin web UI would do.  So our plugin would look somehow like this in the CMS Page admin:
And the second is modifying the Text Plugin instance itself with placing Link plugin placeholders instead of <a></a> tags we have there.
In this particular example we have a placeholder named "content" and a page containing only one TextPlugin with text in it. We need to modify that text.
First we need to create an instance of a CMSPlugin that is attached to a proper placeholder and is nested in our TextPlugin instance. Creating a Link plugin (an instance of a configuration for that CMS plugin in practice) is a next step to achieve this.
That will be the part 2 of this article. Coming soon.




tag:blogger.com,1999:blog-8227451082901531762.post-6723189604361886337
Extensions
Don't put html, head and body tags automatically into beautifulsoup content
beautifulsoupbodyheadhtmlnoparsingrenderrenderContentswrap
Show full content

Was making a parser recently with BeautifulSoup. Came to the final with rendering contents of the edited text. Like so:
text = "<h1>Test text tag</h1>"
soup = BeautifulSoup(text, "html5")

text = soup.renderContents()
print text
It renders those contents with a result wrapped into the <html>, <head> and <body> tags. So print output looks like so:
'<html><head></head><body><h1>Test text tag</h1></body></html>'
That's a feature of the html5lib library, it fixes HTML that is lacking, such as adding back in missing required elements.

The workaround is simple enough:
text = soup.body.renderContents()
This solution will return an inside of the <html> tag <body>.
Result is:
text = '<h1>Test text tag</h1>'














tag:blogger.com,1999:blog-8227451082901531762.post-2004905053431012003
Extensions
Error copying files in Finder of OS X
-36-50accesscardcopycr2driveerrorexternalfilefinderflashmacMac OS XmoveoperationphotoreaderSD
Show full content
Problem:
I have an SD flash card (8 GB Kingston) and a MacBook Pro 13" (Late 2011 model). I also use external card reader time to time.
This problem persisted on all the conditions. The error message was stating:
The Finder can’t complete the operation because some data in “” can’t be read or written.
(Error code -36) This was happening while copying Photos from my camera (cr2 files). It worked, however, in case of copying files up to 200 MB in total size of batch. It dropped this error message and did stop to copy files upon selecting of lots of RAW files. E.g. all of them and attempting to copy them from a flash drive.

Solution:
Problem occurred with building miniatures of the CR2 files. Those files are quite heavy photos (25+ MB) and building miniature did take some time. While building those miniatures on both MAC and SD card finder windows it did die.

For me it was enough to change the view from icons to list. E.g.:
This did solve it for me. Other solution (Suspect in case your MAC would be lower processor model and/or less productive hardware version) is to disable building miniatures for files in Finder.
tag:blogger.com,1999:blog-8227451082901531762.post-1956086350567684230
Extensions
5 most common Rsync command usage examples
articlebackupcommandcommonexamplekeysLinuxoptionsrsyncsamplesynchronisationsynchronizeUnixusageuse
Show full content
rsync is a command for remote sync.

It is used to synchronise one location to another in a simple way. Location is meant to be local directory, server or remote web server or whatever accessible by ssh.

Advantages of using rsync over other tools is speed and bandwidth requirements. First time rsync copies entire contents of the directory provided and increments changes over next sync times.

Command syntax:
$ rsync options source destination

1. Synchronising local directories:
$ rsync -zvr /tmp/logs/ /tmp/logs1/
building file list ... done
created directory /tmp/logs1
./
log.log

sent 98 bytes  received 48 bytes  292.00 bytes/sec
total size is 0  speedup is 0.00
$
Used rsync command options here:

  • -z is for compression
  • -v is for verbose output
  • -r is for recursive directory scanning
By default rsync does not preserve timestamps.  2. Preserve timestamps and permissions during sync:
$ rsync -azvr /tmp/logs/ /tmp/logs1/
building file list ... done
./
log.log

sent 122 bytes  received 48 bytes  340.00 bytes/sec
total size is 0  speedup is 0.00
$
Option -a preserves symbolic links, timestamps, user permissions and ownership.
3. Synchronize from Local to Remote:
$ rsync -avz /tmp/logs/ root@192.168.1.105:/home/user/logs/
root@192.168.1.105's password: 
building file list ... done
created directory /home/user/logs
./
log.log

sent 122 bytes  received 48 bytes  68.00 bytes/sec
total size is 0  speedup is 0.00
$
It is required to specify username and ip-address of the remote server, while doing synchronization. It is also required to specify the destination directory on the remote server. The format is username@machinename:path. Sometimes depending on your credentials and ssh authentication method you may need to enter a password. Like in this example.
4. Synchronize from Remote to Local:
$ rsync -avz root@192.168.1.105:/tmp/ ~/temp/
root@192.168.1.105's password: 
receiving file list ... done
./
#sql8ac_57e_182.MYD
#sql8ac_57e_182.MYI
#sql8ac_57e_182.frm
#sql8ac_57e_183.MYD
#sql8ac_57e_183.MYI
#sql8ac_57e_183.frm
#sql8ac_58f_b6.MYD
#sql8ac_58f_b6.MYI
#sql8ac_58f_b6.frm
#sql8ac_58f_b7.MYD
#sql8ac_58f_b7.MYI
#sql8ac_58f_b7.frm

sent 290 bytes  received 11002 bytes  3226.29 bytes/sec
total size is 16956702  speedup is 1501.66
$
This example is opposite to previous. we have synchronized a list of only changed files here. So speedup is relatively high.
5. View the rsync Progress during Transfer:
$ rsync -avz --progress root@192.168.1.105:/tmp/ ~/temp/
root@192.168.1.105's password: 
receiving file list ... 
284 files to consider
./
#sql8ac_57e_1ae.MYD
        1372 100%    1.31MB/s    0:00:00 (xfer#1, to-check=252/284)
#sql8ac_57e_1ae.MYI
        1024 100% 1000.00kB/s    0:00:00 (xfer#2, to-check=251/284)
#sql8ac_57e_1ae.frm
        8658 100%    8.26MB/s    0:00:00 (xfer#3, to-check=250/284)
#sql8ac_57e_1af.MYD
           0 100%    0.00kB/s    0:00:00 (xfer#4, to-check=249/284)
#sql8ac_57e_1af.MYI
        1024 100%  500.00kB/s    0:00:00 (xfer#5, to-check=248/284)
#sql8ac_57e_1af.frm
        8632 100%    2.74MB/s    0:00:00 (xfer#6, to-check=247/284)

sent 158 bytes  received 9666 bytes  3929.60 bytes/sec
total size is 16956814  speedup is 1726.06
$
Running with --progress option showcase detailed progress of server interaction during load operations.

Thats it. Hope you find this article helpful to you. Comments? Suggestions?
tag:blogger.com,1999:blog-8227451082901531762.post-1979967399752873739
Extensions
Django adding custom widget to Django Admin
adminbuttoncustomdjangoelementexpandformformshtmlpythonwidgetwidgets
Show full content
Sometimes you need to get out of standard behaviour of your Django admin. It means expanding its functionality with custom things. In our case we have a model that we want to add a custom html element. Button that must load something via AJAX from another place to be exact.
We have a typical Django polls application for simplicity. Here is its structure:

First of all we need to create a structure. So here comes our model:
# models.py
from django.db import models

class Poll(models.Model):
    question = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published')
We have to have our django application admin configuration to display that model:
# admin.py
from django.contrib import admin
from polls.models import Poll


admin.site.register(Poll)
It will look in Django admin like so:
You can see polls available here in admin. You can do all the typical things with Polls model. Add/Delete/Edit... Using standard Django features. Imagine we have something on that polls model that we need to expand. Say, we need a button to visit external site here, made like an additional edit field. Imagine we need to take something on external website. We can post something to that website from our filled django admin form. To do that we need to create a custom form field. I have not found any standard widgets to do that. It is required to write our own field and attach it to the Django admin form. We do not need own field here. Just a widget. Widgets are standard Django types. It is possible to read wide description of them in the official documentation: Django Widgets. I wont discuss here best ways to implement this task and there might be better ones. However I have chosen a form widget for simplicity.
It is required to have a model expansion form and a custom widget in order to do so. Registration fo that for m in django admin setup is also required. Lets implement this.
Starting with a form and a widget:
# forms.py
from django import forms
from django.utils.safestring import mark_safe
from django.template.loader import render_to_string

from polls.models import Poll


class ButtonWidget(forms.Widget):
    template_name = 'auth_button_widget.html'

    def render(self, name, value, attrs=None):
        context = {
            'url': '/'
        }
        return mark_safe(render_to_string(self.template_name, context))


class PollsForm(forms.ModelForm):
    button = forms.CharField(widget=ButtonWidget)

    class Meta:
        model = Poll
It is located in a newly created file - forms.py at the django app - polls directory. Here we have a custom written widget that inherits a typical default Django widget (forms.Widget). we have provided it a template - auth_button_widget.html and a custom render() method that provides extra context for that template. Next comes the PollsForm class with a custom button field that uses that widget. Note here Meta for that model is specified, indicating we are adding that field to the Polls model add/edit form. Template, residing in all django templates directory will look like so:
{# auth_button_widget.html #}
<a href="{{ url }}">Go Button</a>
We have our form and widget and a template to render that form element. Time to use that form.
Using this form means modifying our admin.py file and registering custom model admin there. It will use our custom form and a widget. Resulting admin.py will look like this:
# admin.py
from django.contrib import admin
from polls.models import Poll
from polls.forms import PollsForm


class PollsAdmin(admin.ModelAdmin):
    form = PollsForm

admin.site.register(Poll, PollsAdmin)
Resulting change will add a custom form to edit or add the Polls model, containing our custom button field. It will look something like so:

Notice the button we have add here. Its just a simple HTML element that needs to be styled and animated by some CSS and JS. It can be done adding Media to our form widget. Resulting new widget will look like this:
# forms.py (partially)
class ButtonWidget(forms.Widget):
    template_name = 'auth_button_widget.html'

    class Media:
        js = (
            'js/admin_button_script.js',
        )
        css = {
            'all': (
                'css/admin_button_widget.css',
            )
        }

    def render(self, name, value, attrs=None):
        context = {
            'url': '/'
        }
        return mark_safe(render_to_string(self.template_name, context))
Its a registration of static files to use in your widget. They will represent a scripting and styling for that field and will be included to the page of django admin form automatically.
For this to function you have to have django static files configured
Content of scripts and styles are out of the scope of this article. Main idea here is to highlight a proper way to add and write a custom widget from the backend perspective.
Comments, suggestions?
tag:blogger.com,1999:blog-8227451082901531762.post-1279270881532180019
Extensions
Virtualenv for Django
appdjangoinstallpackagepippythonusageuseversionvirtualenv
Show full content
One of main features and troubles for Django projects is the Django version you are using. Example for this would be the occasion of starting project for Django 1.4.x version. Trying to run it under Django 1.7.x would lead to various troubles, counting template changes, misconfiguration errors and so on.

Solution is to use virtual environment. The tool for this is called Virtualenv. It is a wrapper for a python interpreter. It enables you to have multiple versions of python packages that run independently.

The Virtualenv creates you a standalone environment. Basically it copies and keeps a system Python of yours in a specified directory. All the python packages will be installed there. (In case you have not forgot to activate it first, of course)

Lets get started then. We need Virtualenv itself for the first. There are many ways to install it depending on your system. Most obvious to use pip. Your installation command will look something like that:
pip install virtualenv
This installs the tool itself to your system. this only must be done once.

Assuming we have it now and going forward to usage basics. We need to create a virtual environment for our particular project. Usual rule for most of developers is to have a single virtual environment for a standalone project.
To create one for ours we need to be in the directory where we want it to reside. (Virtual environment is not movable by default). So choose wisely.
I suggest it be somewhere in the project directory. The directory that is up one step from the project one is ok too. Assuming we have a project that is called "example". I will enter the directory of that project:
$ cd example
garmoncheg:~/Projects/example$ ls -la
total 8
drwxr-xr-x  4 garmoncheg  staff   136B Jul 14 14:26 ./
drwxr-xr-x  3 garmoncheg  staff   102B Jul 14 14:26 ../
drwxr-xr-x  6 garmoncheg  staff   204B Jul 14 14:26 example/
-rw-r--r--  1 garmoncheg  staff   250B Jul 14 14:26 manage.py
We have here a manage.py file to run our project with and a project files directory. Seems like a nice place to create a virtual environment at. Time to do it with executing a command:
$ virtualenv venv
New python executable in venv/bin/python
Installing setuptools............done.
Installing pip...............done.
We have commanded our virtualenv to create a directory for our new project environment and call it venv. You could use any name here. it will indicate your projects name or whatever your fantasy is up to. Mine project directory now looks like this:
$ ls -l
total 9
drwxr-xr-x  6 garmoncheg  staff   204B Jul 14 14:26 example/
-rw-r--r--  1 garmoncheg staff   250B Jul 14 14:26 manage.py
drwxr-xr-x  6 garmoncheg  staff   204B Jul 14 14:32 venv/
I have a mange.py script here, example directory with project files and a venv directory containig my environment files.
Now we have created a directory for environment and put our environment in it. However system is not aware we are using this environment. We must activate it now. Doing that is easy enough.
Assuming you are in the same project directory and called the virtual environment we are creating "venv". Execute a command:
$ source venv/bin/activate
(venv)garmoncheg:~/Projects/example$ 
This will tell the system we are using the interpreter set we have just created. It is indicated with (venv) at the start of your terminal prompt. this means we are "inside" the environment now.
Note we are in the same directory we where before.

Lets familiarise ourselves with main virtualenv functionality now. Whats the main point of it?
Simple. All the "pip install something" made now in this terminal will install a Python package inside this venv folder, leaving the main system python files intact. You can have as many environment as you wish. You can install whatever Python package you want inside of that virtual environment.

Now lets go through basic commands. Lets try to run our project now, assuming you have followed my previous instructions. To do that just type:
(venv)$ ls
total 9
drwxr-xr-x  6 garmoncheg  staff   204B Jul 14 14:26 example/
-rw-r--r--  1 garmoncheg  staff   250B Jul 14 14:26 manage.py
drwxr-xr-x  6 garmoncheg  staff   204B Jul 14 14:32 venv/
(venv)garmoncheg:~/Projects/example$ python manage.py runserver
Traceback (most recent call last):
  File "manage.py", line 8, in <module>
    from django.core.management import execute_from_command_line
ImportError: No module named django.core.management
Whoops. We can not do that because there is no Django installed. Even though you have had it in system it does not seem to be present now.
All the credits to virtualenv activation command. (source path/to/activate/script). We have to have it installed in the environment now. However it is more convenient to look for ourselves there is no Dango in environment. Lets execute:
(venv)garmoncheg:~/Projects/example$ pip freeze
wsgiref==0.1.2
Tadaam. We only have wsgiref in our console environment now. Lets install django:
(venv)garmoncheg:~/Projects/example$ pip install django
Downloading/unpacking django
  Downloading Django-1.6.5.tar.gz (6.6MB): 6.6MB downloaded
  Running setup.py egg_info for package django
    
    warning: no previously-included files matching '__pycache__' found under directory '*'
    warning: no previously-included files matching '*.py[co]' found under directory '*'
Installing collected packages: django
  Running setup.py install for django
    changing mode of build/scripts-2.7/django-admin.py from 644 to 755
    
    warning: no previously-included files matching '__pycache__' found under directory '*'
    warning: no previously-included files matching '*.py[co]' found under directory '*'
    changing mode of /Users/leopard/Developer/Python/Me/Tests/Projects/example/venv/bin/django-admin.py to 755
Successfully installed django
Cleaning up...
Tadaa. We have our django for the project now. Lets make sure with pip freeze:
(venv)garmoncheg:~/Projects/example$ pip freeze
Django==1.6.5
wsgiref==0.1.2
And our project now can run inside a wrapper. Lets test with:
(venv)leopard@garmoncheg:~/Projects/example$ python manage.py runserver

Validating models...

0 errors found
July 14, 2014 - 12:00:03
Django version 1.6.5, using settings 'example.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
Yes it works.

Cons here that we must activate a virtual environment each time we want to seriously interact with our project. So even to run it we need to activate it first. but it is really the only option to work with multiple project in a system in an easy way.

To return the terminal to a proper state (back to system Python interpreter) you could just close it or deactivate the environment:
(venv)garmoncheg:~/Projects/example$ deactivate
garmoncheg:~/Projects/example$ 
Tadaa. (venv) preceding the terminal prompt is gone and we are back to the system interpreter.

Hope this helps someone. Suggestions? Helped? Please comment! I will really appreciate all the info.

tag:blogger.com,1999:blog-8227451082901531762.post-2709356174374176169
Extensions
Django CMS custom Plugin ManyToMany fields problems.
bugCMSCMSPlugincopydjangoDjango CMSerrorfieldfixForeignKeyFieldm2mManyToManyManyToManyFieldmodelpluginproblemrelations
Show full content
Developing a website for Django CMS I have done a plugin. This plugin however have had a problem. It had an m2m field. While selecting images there (It was a gallery plugin). It was not saving it to production. This way main problem with this field was that plugin have displayed m2m choices on a draft page and while storing it to live it fails.
Django CMS Pages is built like so it has multiple versions of pages. Each Page model that is changed is stored under new revision. And so plugin is copied and relinked to that page too. So plugin revisions multiply to.
For e.g. in case you have a Draft page with two plugins that have model primary key number (pk in future) 12 and 14 accordingly. Say you hit publish changes. Not only PK of Page model rises and data are copypasted into new empty Page model instance. Those plugins are copied to. So mentioned plugins PK would change to 15 and 16 accordingly, assuming 14 is the latest plugin pk. New copied plugins will be linked to new page. Thats how things work in Django CMS.

There is also a line in the CMS code stating in its comment that you need to override m2m storing by yourself.  Somehow its omitted from basic Django CMS tutorials and I can only find it in the old versions documentation for now. SO THE SOLUTION TO ALL THIS:

Say you have CMSPlugin a model for your custom plugin:
class SelectImagePlugin(CMSPlugin):
    """Extension model for plugin class"""
    display_text = models.BooleanField('Project text overlay display')
    images = models.ManyToManyField(Image)

    def copy_relations(self, old_instance):
        self.images = old_instance.images.all()
Here method copy_relations overrides default empty method.
For foreign keys it is described another behaviour and copy_relations mappings. However Foreign keys were working like intended by themselves in my plugins. SO I believe info about them is outdated a bit.
Otherwise it may be useful to read about it in official docs.
http://django-cms.readthedocs.org/en/latest/extending_cms/custom_plugins.html#handling-relations
Thats it. Hope it will help someone like myself to solve a problem like this in a timely manner.
Comments? Suggestions?

tag:blogger.com,1999:blog-8227451082901531762.post-1203137864650718433
Extensions
Implementing a Multiple (Radio) Select + “Other” widget in Django
djangofieldformitemsmodelmultiplepythonRadioselectsubmitwidget
Show full content
I have had a task to implement Radio Select field with "Other" choice field in a Django Model Form. Here is my implementation in case someone would benefit from it. The idea is to have it all stored to Django's CharField type of data and have a preselected set of fields. We have a model:
# models.py
class Entry(models.Model):

    SET_OF_CHOICES = (
        ('choice1', 'choice1'),
        ('choice2', 'choice2'),
        ('choice3', 'choice3'),
        ('Other', 'Other Please Specify'),
    )

    choice = models.CharField(_("Selected your choice"), max_length=250)
That makes it ready for the set of fields for for our form. We are overriding Model form default field for this type of data (CharField) by intentionally specifying field with the same name.
# forms.py
from django.forms import ModelForm, ChoiceField, RadioSelect
from models import Entry
from fields import ChoiceWithOtherField


class EntryForm(ModelForm):

    choice = ChoiceWithOtherField(label=_("Selected your choice"), choices=Entry.SET_OF_CHOICES)
Note the field.py import here. We are using custom form field here. It is a modified version of Django's
MultiValueField.
Here is the fields snippet:
# fields.py
from django import newforms as forms
from django.utils.encoding import force_unicode


class ChoiceWithOtherRenderer(forms.RadioSelect.renderer):
    """RadioFieldRenderer that renders its last choice with a placeholder."""
    def __init__(self, *args, **kwargs):
        super(ChoiceWithOtherRenderer, self).__init__(*args, **kwargs)
        self.choices, self.other = self.choices[:-1], self.choices[-1]

    def __iter__(self):
        for input in super(ChoiceWithOtherRenderer, self).__iter__():
            yield input
        id = '%s_%s' % (self.attrs['id'], self.other[0]) if 'id' in self.attrs else ''
        label_for = ' for="%s"' % id if id else ''
        checked = '' if not force_unicode(self.other[0]) == self.value else 'checked="true" '
        yield '<label%s><input type="radio" id="%s" value="%s" name="%s" %s/> %s</label> %%s' % (
            label_for, id, self.other[0], self.name, checked, self.other[1])


class ChoiceWithOtherWidget(forms.MultiWidget):
    """MultiWidget for use with ChoiceWithOtherField."""
    def __init__(self, choices):
        widgets = [
            forms.RadioSelect(choices=choices, renderer=ChoiceWithOtherRenderer),
            forms.TextInput
        ]
        super(ChoiceWithOtherWidget, self).__init__(widgets)

    def decompress(self, value):
        if not value:
            return [None, None]
        return value

    def format_output(self, rendered_widgets):
        """Format the output by substituting the "other" choice into the first widget."""
        return rendered_widgets[0] % rendered_widgets[1]


class ChoiceWithOtherField(forms.MultiValueField):
    """
    ChoiceField with an option for a user-submitted "other" value.

    The last item in the choices array passed to __init__ is expected to be a choice for "other". This field's
    cleaned data is a tuple consisting of the choice the user made, and the "other" field typed in if the choice
    made was the last one.

    >>> class AgeForm(forms.Form):
    ...     age = ChoiceWithOtherField(choices=[
    ...         (0, '15-29'),
    ...         (1, '30-44'),
    ...         (2, '45-60'),
    ...         (3, 'Other, please specify:')
    ...     ])
    ...
    >>> # rendered as a RadioSelect choice field whose last choice has a text input
    ... print AgeForm()['age']
    <ul>
    <li><label for="id_age_0_0"><input type="radio" id="id_age_0_0" value="0" name="age_0" /> 15-29</label></li>
    <li><label for="id_age_0_1"><input type="radio" id="id_age_0_1" value="1" name="age_0" /> 30-44</label></li>
    <li><label for="id_age_0_2"><input type="radio" id="id_age_0_2" value="2" name="age_0" /> 45-60</label></li>
    <li><label for="id_age_0_3"><input type="radio" id="id_age_0_3" value="3" name="age_0" /> Other, please \\
specify:</label> <input type="text" name="age_1" id="id_age_1" /></li>
    </ul>
    >>> form = AgeForm({'age_0': 2})
    >>> form.is_valid()
    True
    >>> form.cleaned_data
    {'age': (u'2', u'')}
    >>> form = AgeForm({'age_0': 3, 'age_1': 'I am 10 years old'})
    >>> form.is_valid()
    True
    >>> form.cleaned_data
    {'age': (u'3', u'I am 10 years old')}
    >>> form = AgeForm({'age_0': 1, 'age_1': 'This is bogus text which is ignored since I didn\\\\'t pick "other"'})
    >>> form.is_valid()
    True
    >>> form.cleaned_data
    {'age': (u'1', u'')}
    """
    def __init__(self, *args, **kwargs):
        fields = [
            forms.ChoiceField(widget=forms.RadioSelect(renderer=ChoiceWithOtherRenderer), *args, **kwargs),
            forms.CharField(required=False)
        ]
        widget = ChoiceWithOtherWidget(choices=kwargs['choices'])
        kwargs.pop('choices')
        self._was_required = kwargs.pop('required', True)
        kwargs['required'] = False
        super(ChoiceWithOtherField, self).__init__(widget=widget, fields=fields, *args, **kwargs)

    def compress(self, value):
        if self._was_required and not value or value[0] in (None, ''):
            raise forms.ValidationError(self.error_messages['required'])
        if not value:
            return [None, u'']
        # Patch to override model specific other choice and return CharField value instead of choice tuple
        if value[0] == 'Other':
            return value[1]
        else:
            return value[0]
        # Use this for field to return tuple
        #return value[0], value[1] if force_unicode(value[0]) == force_unicode(self.fields[0].choices[-1][0]) else u''
It is based on the code from the snippet by sciyoshi. It is put here because there are some modifications to in inline with idea that things could easily disappear without a trace through the internet.
Anyway it will show something like this in the end:
It's up to your imagination to style it now. Hope this howto helps someone with similar problem to save some time.
tag:blogger.com,1999:blog-8227451082901531762.post-3983501904209312946
Extensions
How to delete a remote git tag
-dcommanddeletegitOriginpushremoteremovetag
Show full content
I'm always forgetting this. So decided to put it here for someone's benefit.

I have the git tag added by command:
git tag -a 1.2.0 -m "1.2.0"
this means my tags tree will be updated with the tag 1.2.0 and message 1.2.0
Usually it marks the version of the build/release.

I now push a tag to origin by command:
git push origin --tags
It is possible to see it at my repository github tagged.

Time now to delete a tag.
It can be done by command:
git tag -d 1.2.0
This will remove a local tag 1.2.0. Leaving origin intact. Pushing tags to origin does not give anything.
To remove a remote tag now it is required to execute command:
git push origin :refs/tags/1.2.0
It will remove tag 1.2.0 at origin. This is the only way how to move tags to another commits.

tag:blogger.com,1999:blog-8227451082901531762.post-1940115118988676156
Extensions
Pillow compile error clang: -Wno-error=unused-command-line-argument-hard-error-in-future fix
-Wno-error=unused-command-line-argument-hard-error-in-future5.1ApplebugcompiledjangoerrorfixflagsgccinstallPillowpythonsupportupdatevirtualenvXcode
Show full content

I have had a problem with compiling Pillow recently. the error was with Pillow/Pil compilation.
pillow install error clang: error: unknown argument:
 '-mno-fused-madd' 
[-Wunused-command-line-argument-hard-error-in-future]
Apple updated command line tools. So the cc command was updated too.
$ gcc --version
Configured with: --prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1
Apple LLVM version 5.1 (clang-503.0.38) (based on LLVM 3.4svn)
Target: x86_64-apple-darwin13.1.0
Thread model: posix
The bug is in GCC. It is quite serious because those flags support will be dropped in future. Fortunately there is a worakround for now:
export ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future"
It works for Pillow 2.4.0 and I can compile it with Apple LLVM 5.1 (That is current now), as of Xcode 5.1.
Hope my findings will help someone.
tag:blogger.com,1999:blog-8227451082901531762.post-6492654876495361404
Extensions