Full Code of ianpreston/redditfs for AI

master b49d82c21241 cached
5 files
8.5 KB
2.4k tokens
28 symbols
1 requests
Download .txt
Repository: ianpreston/redditfs
Branch: master
Commit: b49d82c21241
Files: 5
Total size: 8.5 KB

Directory structure:
gitextract_yk4e18h5/

├── .gitignore
├── README.md
├── fsfile.py
├── redditfs.py
└── reqs.txt

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
venv
*.pyc

================================================
FILE: README.md
================================================
# redditfs

Everything is better in an 80x25 green-and-black terminal -- even Reddit! `redditfs` maps subreddits to a FUSE filesystem, so you can use your favorite shell (or GUI file browser, or SSH, or FTP) to browse Reddit.

## Example

    $ ls -l /r/programming
    total 0
    dr-xr-xr-x@ 3 root  wheel  0 Jan 16 10:30 ANN:_pandas_0130_released
    dr-xr-xr-x@ 3 root  wheel  0 Jan 18 13:08 An_evaluation_of_simple_Python_performance_tweaks
    dr-xr-xr-x@ 3 root  wheel  0 Jan 17 08:36 Anyone_have_experience_installing_Folium_for_Py_33?
    dr-xr-xr-x@ 3 root  wheel  0 Jan 18 09:48 Are_there_any_python_made_games_on_Steam?
    dr-xr-xr-x@ 3 root  wheel  0 Jan 16 20:06 Beginner:_Getting_Beyond_Syntax
    dr-xr-xr-x@ 3 root  wheel  0 Jan 18 00:53 Best_Questions_to_ask_when_hiring_a_Python_dev?
    ...
    $ ls -l /r/programming/An_evaluation_of_simple_Python_performance_tweaks
    total 16
    -r--r--r--@ 1 root  wheel  97 Jan 18 13:08 permalink
    -r--r--r--@ 1 root  wheel   0 Jan 18 13:08 selftext
    -r--r--r--@ 1 root  wheel  72 Jan 18 13:08 url
    $ cat /r/programming/Best_Questions_to_ask_when_hiring_a_Python_dev?/selftext
    I'm a long time C/C++/C# dev who is now diving into python head on, and using it
     on a project here in Seattle.  Part of this is I need to grow my team and hire 
    ...
    $ lynx $(cat /r/programming/An_evaluation_of_simple_Python_performance_tweaks/url)
    
## Howto

You'll need Python >= 2.7 or >= 3.4, and FUSE. You can install FUSE via the package managers on most Linux distros. On OSX, you can get FUSE support via [OSXFUSE](http://osxfuse.github.io/).

    $ git clone https://github.com/ianpreston/redditfs.git
    $ cd redditfs && virtualenv env && source env/bin/activate
    $ pip install -r reqs.txt
    $ mkdir /r
    $ python redditfs.py /r
    
## License

Available under the MIT License.


================================================
FILE: fsfile.py
================================================
import stat
import enum


DirectoryType = enum.Enum('DirectoryType', 'root normal subreddit')


class FSFile(object):
    BASE_MODE = stat.S_IFREG

    def __init__(self, filename, mode, content, ctime):
        self.filename = filename
        self._mode    = FSFile.BASE_MODE | mode
        self._content = content.encode('ascii', errors='ignore')
        self._size    = len(self._content)
        self._time    = ctime

    def getattr(self):
        return {
            'st_size': self._size,
            'st_nlink': 1,
            'st_ctime': self._time,
            'st_mtime': self._time,
            'st_atime': self._time,
            'st_mode': self._mode,
        }

    def read(self, size, offset):
        return self._content[offset:offset+size]

    def dir(self):
        return False


class FSDirectory(object):
    BASE_MODE = stat.S_IFDIR

    def __init__(self, filename, dirtype, mode, ctime):
        self.filename  = filename
        self.dirtype   = dirtype
        self._mode     = FSDirectory.BASE_MODE | mode
        self._time     = ctime
        self._children = {}

    def add_child(self, child):
        self._children[child.filename] = child

    def get_child(self, path):
        return self._children.get(path)

    def remove_child(self, path):
        del self._children[path]

    def getattr(self):
        return {
            'st_size': 0,
            'st_nlink': len(self._children),
            'st_ctime': self._time,
            'st_mtime': self._time,
            'st_atime': self._time,
            'st_mode': self._mode,
        }

    def readdir(self):
        return ['.', '..'] + list(self._children.keys())

    def dir(self):
        return True


================================================
FILE: redditfs.py
================================================
import fuse
import errno
import stat
import time
import sys
import requests
import os
import os.path
from fsfile import *

try:
    import urlparse
except ImportError:
    import urllib.parse as urlparse


CACHE_TIMEOUT = 60 * 60


class RedditFS(fuse.Operations):
    PERMS = stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH
    DIR_PERMS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH

    def __init__(self):
        self.fd = 0
        self.fs = FSDirectory(
            '/',
            DirectoryType.root,
            RedditFS.PERMS | RedditFS.DIR_PERMS,
            time.time(),
        )

    @property
    def dirlist(self):
        if not self._dirlist:
            self._dirlist = self._populate_dirlist()
        return self._dirlist

    def open(self, path, flags):
        self.fd += 1
        return self.fd

    def getattr(self, path, fh=None):
        f = self.traverse(path)

        if f is None:
            raise fuse.FuseOSError(errno.ENOENT)

        return f.getattr()

    def read(self, path, size, offset, fh):
        f = self.traverse(path)
        if f is None:
            raise fuse.FuseOSError(errno.ENOENT)
        if f.dir():
            raise fuse.FuseOSError(errno.EISDIR)

        return f.read(size, offset)

    def readdir(self, path, fh):
        f = self.traverse(path)
        if f is None:
            raise fuse.FuseOSError(errno.ENOENT)
        if not f.dir():
            raise fuse.FuseOSError(errno.ENOTDIR)

        return f.readdir()

    def traverse(self, path):
        path = self._split_path(path)
        node = self.fs
        return self._traverse(path, node)

    def _traverse(self, path, node):
        if len(path) == 0:
            return node

        fn = path.pop(0)
        next_node = node.get_child(fn)

        if node.dirtype == DirectoryType.root:
            self._lazy_load_subreddit(next_node, fn)

        return self._traverse(path, next_node)

    def _split_path(self, path):
        # TODO Move to a util module ?
        head, tail = os.path.split(path)
        if tail == '':
            return []
        if head == '' or head == os.sep:
            return [tail]
        return self._split_path(head) + [tail]

    def _lazy_load_subreddit(self, node, filename):
        # If the directory does not exist, attempt to load it
        if node is None:
            return self._populate_subreddit(filename)

        # If the directory exists but was created more than CACHE_TIMEOUT
        # seconds ago, re-populate the directory
        if node.getattr().get('st_ctime') < (time.time() - CACHE_TIMEOUT):
            self.fs.remove_child(node.filename)
            return self._populate_subreddit(node.filename)

        # The directory exists and is fresh, return it
        return node

    def _populate_subreddit(self, subreddit):
        r = requests.get(
            'http://api.reddit.com/r/{}/hot'.format(subreddit),
            headers={
                'User-Agent': 'redditfs /u/evilyomiel'
            },
            allow_redirects=False,
        )
        if r.status_code in [404, 302]:
            return
        r.raise_for_status()

        links = [link['data'] for link in r.json()['data']['children']]

        root_file = FSDirectory(
            filename=subreddit,
            dirtype=DirectoryType.subreddit,
            mode=RedditFS.PERMS | RedditFS.PERMS,
            ctime=time.time(),
        )

        for zelda in links:
            self._add_reddit_link_to_fs(root_file, zelda)
        self.fs.add_child(root_file)

        return root_file

    def _add_reddit_link_to_fs(self, fs, zelda):
        title    = zelda['title']
        filename = self._sanitize_path(title)

        permalink = urlparse.urljoin(
            'http://www.reddit.com/',
            zelda['permalink']
        )
        url = zelda['url']
        selftext = zelda['selftext']

        root_file = FSDirectory(
            filename=filename,
            dirtype=DirectoryType.normal,
            mode=RedditFS.PERMS | RedditFS.DIR_PERMS,
            ctime=zelda['created_utc'],
        )

        permalink_file = FSFile(
            filename='permalink',
            mode=RedditFS.PERMS,
            content=permalink,
            ctime=zelda['created_utc'],
        )

        url_file = FSFile(
            filename='url',
            mode=RedditFS.PERMS,
            content=url,
            ctime=zelda['created_utc'],
        )

        selftext_file = FSFile(
            filename='selftext',
            mode=RedditFS.PERMS,
            content=selftext,
            ctime=zelda['created_utc'],
        )

        for f in (permalink_file, url_file, selftext_file):
            root_file.add_child(f)
        fs.add_child(root_file)

    def _sanitize_path(self, path):
        replace = (
            ('/', ''),
            (' ', '_'),
            ("'", ''),
            ('"', ''),
        )
        for r in replace:
            path = path.replace(*r)
        return path.lower()


def main():
    fuse.FUSE(RedditFS(), sys.argv[1], foreground=True, nothreads=True)


if __name__ == '__main__':
    main()


================================================
FILE: reqs.txt
================================================
enum34==1.0
fusepy==2.0.2
requests==2.2.0
Download .txt
gitextract_yk4e18h5/

├── .gitignore
├── README.md
├── fsfile.py
├── redditfs.py
└── reqs.txt
Download .txt
SYMBOL INDEX (28 symbols across 2 files)

FILE: fsfile.py
  class FSFile (line 8) | class FSFile(object):
    method __init__ (line 11) | def __init__(self, filename, mode, content, ctime):
    method getattr (line 18) | def getattr(self):
    method read (line 28) | def read(self, size, offset):
    method dir (line 31) | def dir(self):
  class FSDirectory (line 35) | class FSDirectory(object):
    method __init__ (line 38) | def __init__(self, filename, dirtype, mode, ctime):
    method add_child (line 45) | def add_child(self, child):
    method get_child (line 48) | def get_child(self, path):
    method remove_child (line 51) | def remove_child(self, path):
    method getattr (line 54) | def getattr(self):
    method readdir (line 64) | def readdir(self):
    method dir (line 67) | def dir(self):

FILE: redditfs.py
  class RedditFS (line 20) | class RedditFS(fuse.Operations):
    method __init__ (line 24) | def __init__(self):
    method dirlist (line 34) | def dirlist(self):
    method open (line 39) | def open(self, path, flags):
    method getattr (line 43) | def getattr(self, path, fh=None):
    method read (line 51) | def read(self, path, size, offset, fh):
    method readdir (line 60) | def readdir(self, path, fh):
    method traverse (line 69) | def traverse(self, path):
    method _traverse (line 74) | def _traverse(self, path, node):
    method _split_path (line 86) | def _split_path(self, path):
    method _lazy_load_subreddit (line 95) | def _lazy_load_subreddit(self, node, filename):
    method _populate_subreddit (line 109) | def _populate_subreddit(self, subreddit):
    method _add_reddit_link_to_fs (line 136) | def _add_reddit_link_to_fs(self, fs, zelda):
    method _sanitize_path (line 179) | def _sanitize_path(self, path):
  function main (line 191) | def main():
Condensed preview — 5 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (9K chars).
[
  {
    "path": ".gitignore",
    "chars": 10,
    "preview": "venv\n*.pyc"
  },
  {
    "path": "README.md",
    "chars": 1865,
    "preview": "# redditfs\n\nEverything is better in an 80x25 green-and-black terminal -- even Reddit! `redditfs` maps subreddits to a FU"
  },
  {
    "path": "fsfile.py",
    "chars": 1705,
    "preview": "import stat\nimport enum\n\n\nDirectoryType = enum.Enum('DirectoryType', 'root normal subreddit')\n\n\nclass FSFile(object):\n  "
  },
  {
    "path": "redditfs.py",
    "chars": 5105,
    "preview": "import fuse\nimport errno\nimport stat\nimport time\nimport sys\nimport requests\nimport os\nimport os.path\nfrom fsfile import "
  },
  {
    "path": "reqs.txt",
    "chars": 42,
    "preview": "enum34==1.0\nfusepy==2.0.2\nrequests==2.2.0\n"
  }
]

About this extraction

This page contains the full source code of the ianpreston/redditfs GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 5 files (8.5 KB), approximately 2.4k tokens, and a symbol index with 28 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!