Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 28 additions & 28 deletions .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,42 +5,42 @@ name: Python package

on:
push:
branches: [ master ]
branches: [master]
pull_request:
branches: [ master ]
branches: [master]

jobs:
build:
strategy:
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: ["3.7", "3.8", "3.9", "3.10"]
platform: [ubuntu-latest, macos-latest, windows-latest]

runs-on: ${{ matrix.platform }}

steps:
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 setup.py install
python3 -m pip install -r requirements-dev.txt
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Lint with black
run: |
black --check mapillary_tools tests
- name: Type check with mypy
run: |
mypy ptwit.py tests.py
- name: Test with pytest
run: |
pytest tests.py
- uses: actions/checkout@v2
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
run: |
python3 -m pip install --upgrade pip
python3 setup.py install
python3 -m pip install -r requirements-dev.txt
- name: Lint with flake8
run: |
# stop the build if there are Python syntax errors or undefined names
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics
# exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics
- name: Lint with black
run: |
black --check ptwit.py
- name: Type check with mypy
run: |
mypy ptwit.py tests.py
- name: Test with pytest
run: |
pytest tests.py
1 change: 1 addition & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
include README.rst
include LICENSE
include requirements.txt
33 changes: 10 additions & 23 deletions ptwit.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,24 @@
#!/usr/bin/env python3

import configparser
import json
import os
import re
import sys
import errno
from functools import update_wrapper
import typing as T
from datetime import datetime
from string import Formatter
import json
import re
import configparser
from functools import update_wrapper
from html import unescape as html_unescape
from urllib.parse import parse_qsl
import typing as T
from string import Formatter

import twitter
import click
import twitter
from click_default_group import DefaultGroup
from requests_oauthlib import OAuth1Session
from requests_oauthlib.oauth1_session import TokenRequestDenied


__version__ = "0.3"
__VERSION__ = "0.3"
MAX_COUNT = 200


Expand Down Expand Up @@ -161,17 +159,6 @@ def save(self, filename=None) -> "TwitterConfig":
return self


# http://stackoverflow.com/a/600612/114833
def mkdir(path: str) -> None:
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST and os.path.isdir(path):
pass
else:
raise


@click.group(cls=DefaultGroup, default="timeline", default_if_no_args=True)
@click.option("--account", "-a", help="Use this account instead of the default one.")
@click.option(
Expand All @@ -187,7 +174,7 @@ def mkdir(path: str) -> None:
@click.pass_context
def ptwit(ctx: click.Context, account: T.Optional[str], format: str) -> None:
config_dir = click.get_app_dir("ptwit")
mkdir(config_dir)
os.makedirs(config_dir, exist_ok=True)
config = TwitterConfig(os.path.join(config_dir, "ptwit.conf"))

if account is None:
Expand Down Expand Up @@ -503,7 +490,7 @@ def read_text(words: T.List[str]) -> str:
text = " ".join(words)
click.confirm(f'Post "{text}"?', abort=True)
else:
text = click.edit()
text = click.edit() or ""

return text

Expand Down
4 changes: 4 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
python-twitter
click-default-group
click
requests_oauthlib
79 changes: 49 additions & 30 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,40 +1,59 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

try:
from setuptools import setup
except ImportError:
from distutils.core import setup
import os
from setuptools import setup


here = os.path.abspath(os.path.dirname(__file__))


def readme():
with open('README.rst') as f:
with open("README.rst") as f:
return f.read()


setup(name='ptwit',
version='0.3',
description='A simple twitter command line client',
long_description=readme(),
classifiers=[
'Development Status :: 5 - Beta',
'License :: OSI Approved :: MIT License',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Environment :: Console',
'Intended Audience :: End Users/Desktop',
'Topic :: Utilities'],
url='https://github.com/ptpt/ptwit',
author='Tao Peng',
author_email='ptpttt+ptwit@gmail.com',
keywords='twitter, command-line, client',
license='MIT',
py_modules=['ptwit'],
install_requires=['python-twitter', 'click-default-group', 'click'],
entry_points='''
def read_requirements():
with open("requirements.txt") as fp:
return [row.strip() for row in fp if row.strip()]


about: dict = {}
with open(os.path.join(here, "ptwit.py"), "r") as f:
while True:
line = f.readline()
if not line:
break
if line.startswith("__VERSION__"):
exec(line, about)
break


setup(
name="ptwit",
version=about["__VERSION__"],
description="A simple twitter command line client",
long_description=readme(),
classifiers=[
"Development Status :: 5 - Beta",
"License :: OSI Approved :: MIT License",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Environment :: Console",
"Intended Audience :: End Users/Desktop",
"Topic :: Utilities",
],
url="https://github.com/ptpt/ptwit",
author="Tao Peng",
author_email="ptpttt+ptwit@gmail.com",
keywords="twitter, command-line, client",
license="MIT",
py_modules=["ptwit"],
install_requires=read_requirements(),
entry_points="""
[console_scripts]
ptwit=ptwit:cli
''',
zip_safe=False)
""",
zip_safe=False,
)
95 changes: 44 additions & 51 deletions tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,63 @@


class TestTwitterConfig(unittest.TestCase):
def setUp(self):
_, self.filename = tempfile.mkstemp()

def tearDown(self):
os.remove(self.filename)

def test_open(self):
filename = tempfile.mktemp()
# Create if config file does not exist
config = TwitterConfig(filename)
self.assertFalse(os.path.isfile(filename))
# If the path is a directory?
dirname = tempfile.mkdtemp()
config = TwitterConfig(dirname)
self.assertRaises(IOError, config.save)
os.removedirs(dirname)
TwitterConfig("./hello")
self.assertFalse(os.path.exists("./hello"))

def test_set(self):
config = TwitterConfig(self.filename)
config.set("option", "value") # Save hello=world to general section
config.set("name", "tao", account="Tao")
config.set("name", "mian", account="Mian")
self.assertEqual(config.config.items("general"), [("option", "value")])
self.assertEqual(config.config.items("Tao"), [("name", "tao")])
self.assertEqual(config.config.items("Mian"), [("name", "mian")])
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
config.set("option", "value") # Save hello=world to general section
config.set("name", "tao", account="Tao")
config.set("name", "mian", account="Mian")
self.assertEqual(config.config.items("general"), [("option", "value")])
self.assertEqual(config.config.items("Tao"), [("name", "tao")])
self.assertEqual(config.config.items("Mian"), [("name", "mian")])

def test_get(self):
config = TwitterConfig(self.filename)
config.set("option", "value")
config.set("format", "json", account="Tao")
self.assertEqual(config.get("option"), "value")
self.assertEqual(config.get("format", account="Tao"), "json")
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
config.set("option", "value")
config.set("format", "json", account="Tao")
self.assertEqual(config.get("option"), "value")
self.assertEqual(config.get("format", account="Tao"), "json")

def test_unset(self):
config = TwitterConfig(self.filename)
config.set("option", "value")
config.set("format", "json", account="Tao")
config.unset("format", account="Tao")
config.unset("option")
self.assertIsNone(config.get("format", account="Tao"))
self.assertIsNone(config.get("option"))
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
config.set("option", "value")
config.set("format", "json", account="Tao")
config.unset("format", account="Tao")
config.unset("option")
self.assertIsNone(config.get("format", account="Tao"))
self.assertIsNone(config.get("option"))

def test_remove_account(self):
config = TwitterConfig(self.filename)
config.set("option", "value", account="Tao")
config.remove_account("Tao")
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
config.set("option", "value", account="Tao")
config.remove_account("Tao")

def test_list_account(self):
config = TwitterConfig(self.filename)
self.assertEqual(config.list_accounts(), [])
config.set("option", "value")
config.set("option", "value", account="Tao")
self.assertEqual(config.list_accounts(), ["Tao"])
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
self.assertEqual(config.list_accounts(), [])
config.set("option", "value")
config.set("option", "value", account="Tao")
self.assertEqual(config.list_accounts(), ["Tao"])

def test_save(self):
config = TwitterConfig(self.filename)
config.set("option", "value")
config.set("name", "Tao", account="Tao")
config.save()
with open(self.filename) as fp:
content = fp.read()
self.assertTrue(content.find("general"))
self.assertTrue(content.find("Tao"))
self.assertTrue(content.find("name"))
with tempfile.NamedTemporaryFile() as tmp:
config = TwitterConfig(tmp.name)
config.set("option", "value")
config.set("name", "Tao", account="Tao")
config.save()
with open(tmp.name) as fp:
content = fp.read()
self.assertTrue(content.find("general"))
self.assertTrue(content.find("Tao"))
self.assertTrue(content.find("name"))


if __name__ == "__main__":
Expand Down