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
gitextract_yk4e18h5/ ├── .gitignore ├── README.md ├── fsfile.py ├── redditfs.py └── reqs.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.