Hello community,

here is the log from the commit of package asciinema for openSUSE:Factory 
checked in at 2019-01-15 09:17:19
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/asciinema (Old)
 and      /work/SRC/openSUSE:Factory/.asciinema.new.28833 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "asciinema"

Tue Jan 15 09:17:19 2019 rev:6 rq:665142 version:2.0.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/asciinema/asciinema.changes      2018-04-05 
15:34:52.365147552 +0200
+++ /work/SRC/openSUSE:Factory/.asciinema.new.28833/asciinema.changes   
2019-01-15 09:17:43.294160272 +0100
@@ -1,0 +2,13 @@
+Sun Jan 13 08:20:04 UTC 2019 - Alexei Podvalsky <[email protected]>
+
+- Update to 2.0.2
+  * Official support for Python 3.7
+  * Recording is now possible on US-ASCII locale
+  * Improved Android support
+  * Possibility of programatic recording with 
+    asciinema.record_asciicast function
+  * Uses new JSON response format added recently to asciinema-server
+  * Tweaked message about how to stop recording
+  * Added proper description and other metadata to Python package
+
+-------------------------------------------------------------------

Old:
----
  asciinema-2.0.1.tar.gz

New:
----
  asciinema-2.0.2.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ asciinema.spec ++++++
--- /var/tmp/diff_new_pack.1rHfgY/_old  2019-01-15 09:17:43.910159698 +0100
+++ /var/tmp/diff_new_pack.1rHfgY/_new  2019-01-15 09:17:43.910159698 +0100
@@ -17,7 +17,7 @@
 
 
 Name:           asciinema
-Version:        2.0.1
+Version:        2.0.2
 Release:        0
 Summary:        Terminal session recorder
 License:        GPL-3.0+
@@ -43,9 +43,11 @@
 
 install -Dm644 {man/,%{buildroot}%{_mandir}/man1/}%{name}.1
 
+rm -R %{buildroot}%{_datadir}/doc/%{name}
+
 %files
 %defattr(-,root,root,-)
-%doc CHANGELOG* LICENSE
+%doc CHANGELOG.md CODE_OF_CONDUCT.md LICENSE CONTRIBUTING.md README.md
 %{_bindir}/%{name}
 %{python3_sitelib}/%{name}/
 %{python3_sitelib}/%{name}-%{version}*

++++++ asciinema-2.0.1.tar.gz -> asciinema-2.0.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/.gitignore 
new/asciinema-2.0.2/.gitignore
--- old/asciinema-2.0.1/.gitignore      2018-04-04 09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/.gitignore      2019-01-12 19:58:29.000000000 +0100
@@ -1,3 +1,120 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# celery beat schedule file
+celerybeat-schedule
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# custom
 /dist
 tmp
 *.pyc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/.travis.yml 
new/asciinema-2.0.2/.travis.yml
--- old/asciinema-2.0.1/.travis.yml     2018-04-04 09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/.travis.yml     2019-01-12 19:58:29.000000000 +0100
@@ -1,15 +1,17 @@
-sudo: false
+sudo: required
+dist: xenial
 language: python
 
 python:
   - "3.4"
   - "3.5"
   - "3.6"
-  - "3.7-dev"
+  - "3.7"
+  - "3.8-dev"
 
 before_install:
-  - pip install pep8
+  - pip install pycodestyle
 
 script:
-  - find . -name \*.py -exec pep8 --ignore=E501 {} +
+  - find . -name \*.py -exec pycodestyle --ignore=E501,E402 {} +
   - make test
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/CHANGELOG.md 
new/asciinema-2.0.2/CHANGELOG.md
--- old/asciinema-2.0.1/CHANGELOG.md    2018-04-04 09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/CHANGELOG.md    2019-01-12 19:58:29.000000000 +0100
@@ -1,5 +1,15 @@
 # asciinema changelog
 
+## 2.0.2 (2019-01-12)
+
+* Official support for Python 3.7
+* Recording is now possible on US-ASCII locale (thanks Jean-Philippe 
@jpouellet Ouellet!)
+* Improved Android support (thanks Fredrik @fornwall Fornwall!)
+* Possibility of programatic recording with `asciinema.record_asciicast` 
function
+* Uses new JSON response format added recently to asciinema-server
+* Tweaked message about how to stop recording (thanks Bachynin @vanyakosmos 
Ivan!)
+* Added proper description and other metadata to Python package (thanks 
@Crestwave!)
+
 ## 2.0.1 (2018-04-04)
 
 * Fixed example in asciicast v2 format doc (thanks Josh "@anowlcalledjosh" 
Holland!)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/README.md 
new/asciinema-2.0.2/README.md
--- old/asciinema-2.0.1/README.md       2018-04-04 09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/README.md       2019-01-12 19:58:29.000000000 +0100
@@ -7,7 +7,7 @@
 Terminal session recorder and the best companion of
 [asciinema.org](https://asciinema.org).
 
-[![demo](https://asciinema.org/a/113463.png)](https://asciinema.org/a/113463?autoplay=1)
+[![demo](https://asciinema.org/a/113463.svg)](https://asciinema.org/a/113463?autoplay=1)
 
 ## Quick intro
 
@@ -32,7 +32,7 @@
 
 You can pass `-i 2` to `asciinema rec` as well, to set it permanently on a
 recording. Idle time limiting makes the recordings much more interesting to
-watch, try it.
+watch. Try it.
 
 If you want to watch and share it on the web, upload it:
 
@@ -47,10 +47,10 @@
 
     asciinema rec
 
-You'll be asked to confirm the upload when the recording is done, so nothing is
+You'll be asked to confirm the upload when the recording is done. Nothing is
 sent anywhere without your consent.
 
-These were the basics, but there's much more you can do. The following sections
+These are the basics, but there's much more you can do. The following sections
 cover installation, usage and hosting of the recordings in more detail.
 
 ## Installation
@@ -71,16 +71,6 @@
 X, Linux and FreeBSD. Look for package named `asciinema`. See the
 [list of available packages](https://asciinema.org/docs/installation).
 
-### Snap supported Linux distros
-
-If you run [Ubuntu or other snap supported Linux 
distribution](https://snapcraft.io/docs/core/install) you can
-install asciinema with:
-
-    snap install asciinema --classic
-
-The snap contains all necessary dependencies required to run asciinema, and 
will
-get automatically updated when a new version is pushed to the store.
-
 ### Docker image
 
 asciinema Docker image is based on Ubuntu 16.04 and has the latest version of
@@ -363,10 +353,10 @@
 ## Authors
 
 Developed with passion by [Marcin Kulik](http://ku1ik.com) and great open
-source [contributors](https://github.com/asciinema/asciinema/contributors)
+source [contributors](https://github.com/asciinema/asciinema/contributors).
 
 ## License
 
-Copyright &copy; 2011-2017 Marcin Kulik.
+Copyright &copy; 2011–2018 Marcin Kulik.
 
 All code is licensed under the GPL, v3 or later. See LICENSE file for details.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/__init__.py 
new/asciinema-2.0.2/asciinema/__init__.py
--- old/asciinema-2.0.1/asciinema/__init__.py   2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/asciinema/__init__.py   2019-01-12 19:58:29.000000000 
+0100
@@ -1,7 +1,58 @@
 import sys
 
 __author__ = 'Marcin Kulik'
-__version__ = '2.0.1'
+__version__ = '2.0.2'
 
 if sys.version_info[0] < 3:
     raise ImportError('Python < 3 is unsupported.')
+
+
+import os
+import subprocess
+import time
+
+import asciinema.asciicast.v2 as v2
+import asciinema.pty as pty
+import asciinema.term as term
+
+
+def record_asciicast(path, command=None, append=False, idle_time_limit=None,
+                     rec_stdin=False, title=None, metadata=None,
+                     command_env=None, capture_env=None, 
writer=v2.async_writer,
+                     record=pty.record):
+    if command is None:
+        command = os.environ.get('SHELL') or 'sh'
+
+    if command_env is None:
+        command_env = os.environ.copy()
+        command_env['ASCIINEMA_REC'] = '1'
+
+    if capture_env is None:
+        capture_env = ['SHELL', 'TERM']
+
+    w, h = term.get_size()
+
+    full_metadata = {
+        'width': w,
+        'height': h,
+        'timestamp': int(time.time())
+    }
+
+    full_metadata.update(metadata or {})
+
+    if idle_time_limit is not None:
+        full_metadata['idle_time_limit'] = idle_time_limit
+
+    if capture_env:
+        full_metadata['env'] = {var: command_env.get(var) for var in 
capture_env}
+
+    if title:
+        full_metadata['title'] = title
+
+    time_offset = 0
+
+    if append and os.stat(path).st_size > 0:
+        time_offset = v2.get_duration(path)
+
+    with writer(path, full_metadata, append, time_offset) as w:
+        record(['sh', '-c', command], w, command_env, rec_stdin)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/__main__.py 
new/asciinema-2.0.2/asciinema/__main__.py
--- old/asciinema-2.0.1/asciinema/__main__.py   2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/asciinema/__main__.py   2019-01-12 19:58:29.000000000 
+0100
@@ -50,8 +50,8 @@
 
 
 def main():
-    if locale.nl_langinfo(locale.CODESET).upper() != 'UTF-8':
-        print("asciinema needs a UTF-8 native locale to run. Check the output 
of `locale` command.")
+    if locale.nl_langinfo(locale.CODESET).upper() not in ['US-ASCII', 'UTF-8']:
+        print("asciinema needs an ASCII or UTF-8 character encoding to run. 
Check the output of `locale` command.")
         sys.exit(1)
 
     try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/api.py 
new/asciinema-2.0.2/asciinema/api.py
--- old/asciinema-2.0.1/asciinema/api.py        2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/asciinema/api.py        2019-01-12 19:58:29.000000000 
+0100
@@ -1,5 +1,6 @@
 import platform
 import re
+import json
 from urllib.parse import urlparse
 
 from asciinema import __version__
@@ -44,10 +45,15 @@
         if status != 200 and status != 201:
             self._handle_error(status, body)
 
-        return body, headers.get('Warning')
+        if (headers.get('content-type') or '')[0:16] == 'application/json':
+            result = json.loads(body)
+        else:
+            result = {'url': body}
+
+        return result, headers.get('Warning')
 
     def _headers(self):
-        return {'User-Agent': self._user_agent()}
+        return {'User-Agent': self._user_agent(), 'Accept': 'application/json'}
 
     def _user_agent(self):
         os = re.sub('([^-]+)-(.*)', '\\1/\\2', platform.platform())
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/asciicast/raw.py 
new/asciinema-2.0.2/asciinema/asciicast/raw.py
--- old/asciinema-2.0.1/asciinema/asciicast/raw.py      2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/asciicast/raw.py      2019-01-12 
19:58:29.000000000 +0100
@@ -1,11 +1,10 @@
 import os
 from multiprocessing import Process, Queue
 
-from asciinema.pty_recorder import PtyRecorder
-
 
 def write_bytes_from_queue(path, mode, queue):
     mode = mode + 'b'
+
     with open(path, mode=mode, buffering=0) as f:
         for data in iter(queue.get, None):
             f.write(data)
@@ -13,7 +12,10 @@
 
 class writer():
 
-    def __init__(self, path, append):
+    def __init__(self, path, _metadata, append=False, _time_offset=0):
+        if append and os.path.exists(path) and os.stat(path).st_size == 0:  # 
true for pipes
+            append = False
+
         self.path = path
         self.mode = 'a' if append else 'w'
         self.queue = Queue()
@@ -35,16 +37,3 @@
 
     def write_stdout(self, data):
         self.queue.put(data)
-
-
-class Recorder:
-
-    def __init__(self, pty_recorder=None):
-        self.pty_recorder = pty_recorder if pty_recorder is not None else 
PtyRecorder()
-
-    def record(self, path, append, command, command_env, _captured_env, 
_rec_stdin, _title, _idle_time_limit):
-        if os.path.exists(path) and os.stat(path).st_size == 0:  # true for 
pipes
-            append = False
-
-        with writer(path, append) as w:
-            self.pty_recorder.record_command(['sh', '-c', command], w, 
command_env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/asciicast/v2.py 
new/asciinema-2.0.2/asciinema/asciicast/v2.py
--- old/asciinema-2.0.1/asciinema/asciicast/v2.py       2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/asciicast/v2.py       2019-01-12 
19:58:29.000000000 +0100
@@ -1,12 +1,17 @@
-import os
-import subprocess
 import json
 import json.decoder
 import time
 import codecs
-from multiprocessing import Process, Queue
 
-from asciinema.pty_recorder import PtyRecorder
+try:
+    # Importing synchronize is to detect platforms where
+    # multiprocessing does not work (python issue 3770)
+    # and cause an ImportError. Otherwise it will happen
+    # later when trying to use Queue().
+    from multiprocessing import synchronize, Process, Queue
+except ImportError:
+    from threading import Thread as Process
+    from queue import Queue
 
 
 try:
@@ -71,6 +76,22 @@
             return last_frame[0]
 
 
+def build_header(metadata):
+    header = {}
+    header.update(metadata)
+    header['version'] = 2
+
+    assert 'width' in header, 'width missing in metadata'
+    assert 'height' in header, 'height missing in metadata'
+    assert type(header['width']) == int
+    assert type(header['height']) == int
+
+    if 'timestamp' in header:
+        assert type(header['timestamp']) == int or type(header['timestamp']) 
== float
+
+    return header
+
+
 class writer():
 
     def __init__(self, path, width=None, height=None, header=None, mode='w', 
buffering=-1):
@@ -137,21 +158,25 @@
 
 class async_writer():
 
-    def __init__(self, path, header, rec_stdin, start_time_offset=0):
+    def __init__(self, path, metadata, append=False, time_offset=0):
+        if append:
+            assert time_offset > 0
+
         self.path = path
-        self.header = header
-        self.rec_stdin = rec_stdin
-        self.start_time_offset = start_time_offset
+        self.metadata = metadata
+        self.append = append
+        self.time_offset = time_offset
         self.queue = Queue()
 
     def __enter__(self):
-        mode = 'a' if self.start_time_offset > 0 else 'w'
+        header = build_header(self.metadata)
+        mode = 'a' if self.append else 'w'
         self.process = Process(
             target=write_json_lines_from_queue,
-            args=(self.path, self.header, mode, self.queue)
+            args=(self.path, header, mode, self.queue)
         )
         self.process.start()
-        self.start_time = time.time() - self.start_time_offset
+        self.start_time = time.time() - self.time_offset
         return self
 
     def __exit__(self, exc_type, exc_value, exc_traceback):
@@ -159,44 +184,9 @@
         self.process.join()
 
     def write_stdin(self, data):
-        if self.rec_stdin:
-            ts = time.time() - self.start_time
-            self.queue.put([ts, 'i', data])
+        ts = time.time() - self.start_time
+        self.queue.put([ts, 'i', data])
 
     def write_stdout(self, data):
         ts = time.time() - self.start_time
         self.queue.put([ts, 'o', data])
-
-
-class Recorder:
-
-    def __init__(self, pty_recorder=None):
-        self.pty_recorder = pty_recorder if pty_recorder is not None else 
PtyRecorder()
-
-    def record(self, path, append, command, command_env, captured_env, 
rec_stdin, title, idle_time_limit):
-        start_time_offset = 0
-
-        if append and os.stat(path).st_size > 0:
-            start_time_offset = get_duration(path)
-
-        cols = int(subprocess.check_output(['tput', 'cols']))
-        lines = int(subprocess.check_output(['tput', 'lines']))
-
-        header = {
-            'version': 2,
-            'width': cols,
-            'height': lines,
-            'timestamp': int(time.time()),
-        }
-
-        if idle_time_limit is not None:
-            header['idle_time_limit'] = idle_time_limit
-
-        if captured_env:
-            header['env'] = captured_env
-
-        if title:
-            header['title'] = title
-
-        with async_writer(path, header, rec_stdin, start_time_offset) as w:
-            self.pty_recorder.record_command(['sh', '-c', command], w, 
command_env)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/commands/record.py 
new/asciinema-2.0.2/asciinema/commands/record.py
--- old/asciinema-2.0.1/asciinema/commands/record.py    2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/commands/record.py    2019-01-12 
19:58:29.000000000 +0100
@@ -1,12 +1,12 @@
-import sys
 import os
+import sys
 import tempfile
 
-from asciinema.commands.command import Command
-import asciinema.asciicast as asciicast
-import asciinema.asciicast.v2 as v2
+import asciinema
 import asciinema.asciicast.raw as raw
+import asciinema.asciicast.v2 as v2
 from asciinema.api import APIError
+from asciinema.commands.command import Command
 
 
 class RecordCommand(Command):
@@ -24,7 +24,7 @@
         self.append = args.append
         self.overwrite = args.overwrite
         self.raw = args.raw
-        self.recorder = raw.Recorder() if args.raw else v2.Recorder()
+        self.writer = raw.writer if args.raw else v2.async_writer
         self.env = env if env is not None else os.environ
 
     def execute(self):
@@ -58,24 +58,24 @@
         else:
             self.print_info("recording asciicast to %s" % self.filename)
 
-        self.print_info("""press <ctrl-d> or type "exit" when you're done""")
+        if self.command:
+            self.print_info("""exit opened program when you're done""")
+        else:
+            self.print_info("""press <ctrl-d> or type "exit" when you're 
done""")
 
-        command = self.command or self.env.get('SHELL') or 'sh'
-        command_env = self.env.copy()
-        command_env['ASCIINEMA_REC'] = '1'
         vars = filter(None, map((lambda var: var.strip()), 
self.env_whitelist.split(',')))
-        captured_env = {var: self.env.get(var) for var in vars}
 
         try:
-            self.recorder.record(
+            asciinema.record_asciicast(
                 self.filename,
-                append,
-                command,
-                command_env,
-                captured_env,
-                self.rec_stdin,
-                self.title,
-                self.idle_time_limit
+                command=self.command,
+                append=append,
+                title=self.title,
+                idle_time_limit=self.idle_time_limit,
+                command_env=self.env,
+                capture_env=vars,
+                rec_stdin=self.rec_stdin,
+                writer=self.writer
             )
         except v2.LoadError:
             self.print_error("can only append to asciicast v2 format 
recordings")
@@ -85,7 +85,8 @@
 
         if upload:
             if not self.assume_yes:
-                self.print_info("press <enter> to upload to %s, <ctrl-c> to 
save locally" % self.api.hostname())
+                self.print_info("press <enter> to upload to %s, <ctrl-c> to 
save locally"
+                                % self.api.hostname())
                 try:
                     sys.stdin.readline()
                 except KeyboardInterrupt:
@@ -94,11 +95,14 @@
                     return 0
 
             try:
-                url, warn = self.api.upload_asciicast(self.filename)
+                result, warn = self.api.upload_asciicast(self.filename)
+
                 if warn:
                     self.print_warning(warn)
+
                 os.remove(self.filename)
-                self.print(url)
+                self.print(result.get('message') or result['url'])
+
             except APIError as e:
                 self.print("\r\x1b[A", end="")
                 self.print_error("upload failed: %s" % str(e))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/commands/upload.py 
new/asciinema-2.0.2/asciinema/commands/upload.py
--- old/asciinema-2.0.1/asciinema/commands/upload.py    2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/commands/upload.py    2019-01-12 
19:58:29.000000000 +0100
@@ -11,12 +11,12 @@
 
     def execute(self):
         try:
-            url, warn = self.api.upload_asciicast(self.filename)
+            result, warn = self.api.upload_asciicast(self.filename)
 
             if warn:
                 self.print_warning(warn)
 
-            self.print(url)
+            self.print(result.get('message') or result['url'])
 
         except OSError as e:
             self.print_error("upload failed: %s" % str(e))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/player.py 
new/asciinema-2.0.2/asciinema/player.py
--- old/asciinema-2.0.1/asciinema/player.py     2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/asciinema/player.py     2019-01-12 19:58:29.000000000 
+0100
@@ -13,7 +13,7 @@
             stdin = open('/dev/tty')
             with raw(stdin.fileno()):
                 self._play(asciicast, idle_time_limit, speed, stdin)
-        except:
+        except Exception:
             self._play(asciicast, idle_time_limit, speed, None)
 
     def _play(self, asciicast, idle_time_limit, speed, stdin):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/pty.py 
new/asciinema-2.0.2/asciinema/pty.py
--- old/asciinema-2.0.1/asciinema/pty.py        1970-01-01 01:00:00.000000000 
+0100
+++ new/asciinema-2.0.2/asciinema/pty.py        2019-01-12 19:58:29.000000000 
+0100
@@ -0,0 +1,140 @@
+import array
+import errno
+import fcntl
+import io
+import os
+import pty
+import select
+import shlex
+import signal
+import struct
+import sys
+import termios
+
+from asciinema.term import raw
+
+
+def record(command, writer, env=os.environ, rec_stdin=False):
+    master_fd = None
+
+    def _set_pty_size():
+        '''
+        Sets the window size of the child pty based on the window size
+        of our own controlling terminal.
+        '''
+
+        # Get the terminal size of the real terminal, set it on the 
pseudoterminal.
+        if os.isatty(pty.STDOUT_FILENO):
+            buf = array.array('h', [0, 0, 0, 0])
+            fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)
+        else:
+            buf = array.array('h', [24, 80, 0, 0])
+
+        fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)
+
+    def _write_stdout(data):
+        '''Writes to stdout as if the child process had written the data.'''
+
+        os.write(pty.STDOUT_FILENO, data)
+
+    def _handle_master_read(data):
+        '''Handles new data on child process stdout.'''
+
+        writer.write_stdout(data)
+        _write_stdout(data)
+
+    def _write_master(data):
+        '''Writes to the child process from its controlling terminal.'''
+
+        while data:
+            n = os.write(master_fd, data)
+            data = data[n:]
+
+    def _handle_stdin_read(data):
+        '''Handles new data on child process stdin.'''
+
+        _write_master(data)
+
+        if rec_stdin:
+            writer.write_stdin(data)
+
+    def _signals(signal_list):
+        old_handlers = []
+        for sig, handler in signal_list:
+            old_handlers.append((sig, signal.signal(sig, handler)))
+        return old_handlers
+
+    def _copy(signal_fd):
+        '''Main select loop.
+
+        Passes control to _master_read() or _stdin_read()
+        when new data arrives.
+        '''
+
+        fds = [master_fd, pty.STDIN_FILENO, signal_fd]
+
+        while True:
+            try:
+                rfds, wfds, xfds = select.select(fds, [], [])
+            except OSError as e:  # Python >= 3.3
+                if e.errno == errno.EINTR:
+                    continue
+            except select.error as e:  # Python < 3.3
+                if e.args[0] == 4:
+                    continue
+
+            if master_fd in rfds:
+                data = os.read(master_fd, 1024)
+                if not data:  # Reached EOF.
+                    fds.remove(master_fd)
+                else:
+                    _handle_master_read(data)
+
+            if pty.STDIN_FILENO in rfds:
+                data = os.read(pty.STDIN_FILENO, 1024)
+                if not data:
+                    fds.remove(pty.STDIN_FILENO)
+                else:
+                    _handle_stdin_read(data)
+
+            if signal_fd in rfds:
+                data = os.read(signal_fd, 1024)
+                if data:
+                    signals = struct.unpack('%uB' % len(data), data)
+                    for sig in signals:
+                        if sig in [signal.SIGCHLD, signal.SIGHUP, 
signal.SIGTERM, signal.SIGQUIT]:
+                            os.close(master_fd)
+                            return
+                        elif sig == signal.SIGWINCH:
+                            _set_pty_size()
+
+    pid, master_fd = pty.fork()
+
+    if pid == pty.CHILD:
+        os.execvpe(command[0], command, env)
+
+    pipe_r, pipe_w = os.pipe()
+    flags = fcntl.fcntl(pipe_w, fcntl.F_GETFL, 0)
+    flags = flags | os.O_NONBLOCK
+    flags = fcntl.fcntl(pipe_w, fcntl.F_SETFL, flags)
+
+    signal.set_wakeup_fd(pipe_w)
+
+    old_handlers = _signals(map(lambda s: (s, lambda signal, frame: None),
+                                [signal.SIGWINCH,
+                                    signal.SIGCHLD,
+                                    signal.SIGHUP,
+                                    signal.SIGTERM,
+                                    signal.SIGQUIT]))
+
+    _set_pty_size()
+
+    with raw(pty.STDIN_FILENO):
+        try:
+            _copy(pipe_r)
+        except (IOError, OSError):
+            pass
+
+    _signals(old_handlers)
+
+    os.waitpid(pid, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/pty_recorder.py 
new/asciinema-2.0.2/asciinema/pty_recorder.py
--- old/asciinema-2.0.1/asciinema/pty_recorder.py       2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/pty_recorder.py       1970-01-01 
01:00:00.000000000 +0100
@@ -1,140 +0,0 @@
-import errno
-import os
-import pty
-import signal
-import array
-import fcntl
-import termios
-import select
-import io
-import shlex
-import sys
-import struct
-
-from asciinema.term import raw
-
-
-class PtyRecorder:
-
-    def record_command(self, command, output, env=os.environ):
-        master_fd = None
-
-        def _set_pty_size():
-            '''
-            Sets the window size of the child pty based on the window size
-            of our own controlling terminal.
-            '''
-
-            # Get the terminal size of the real terminal, set it on the 
pseudoterminal.
-            if os.isatty(pty.STDOUT_FILENO):
-                buf = array.array('h', [0, 0, 0, 0])
-                fcntl.ioctl(pty.STDOUT_FILENO, termios.TIOCGWINSZ, buf, True)
-            else:
-                buf = array.array('h', [24, 80, 0, 0])
-
-            fcntl.ioctl(master_fd, termios.TIOCSWINSZ, buf)
-
-        def _write_stdout(data):
-            '''Writes to stdout as if the child process had written the 
data.'''
-
-            os.write(pty.STDOUT_FILENO, data)
-
-        def _handle_master_read(data):
-            '''Handles new data on child process stdout.'''
-
-            output.write_stdout(data)
-            _write_stdout(data)
-
-        def _write_master(data):
-            '''Writes to the child process from its controlling terminal.'''
-
-            while data:
-                n = os.write(master_fd, data)
-                data = data[n:]
-
-        def _handle_stdin_read(data):
-            '''Handles new data on child process stdin.'''
-
-            output.write_stdin(data)
-            _write_master(data)
-
-        def _signals(signal_list):
-            old_handlers = []
-            for sig, handler in signal_list:
-                old_handlers.append((sig, signal.signal(sig, handler)))
-            return old_handlers
-
-        def _copy(signal_fd):
-            '''Main select loop.
-
-            Passes control to _master_read() or _stdin_read()
-            when new data arrives.
-            '''
-
-            fds = [master_fd, pty.STDIN_FILENO, signal_fd]
-
-            while True:
-                try:
-                    rfds, wfds, xfds = select.select(fds, [], [])
-                except OSError as e:  # Python >= 3.3
-                    if e.errno == errno.EINTR:
-                        continue
-                except select.error as e:  # Python < 3.3
-                    if e.args[0] == 4:
-                        continue
-
-                if master_fd in rfds:
-                    data = os.read(master_fd, 1024)
-                    if not data:  # Reached EOF.
-                        fds.remove(master_fd)
-                    else:
-                        _handle_master_read(data)
-
-                if pty.STDIN_FILENO in rfds:
-                    data = os.read(pty.STDIN_FILENO, 1024)
-                    if not data:
-                        fds.remove(pty.STDIN_FILENO)
-                    else:
-                        _handle_stdin_read(data)
-
-                if signal_fd in rfds:
-                    data = os.read(signal_fd, 1024)
-                    if data:
-                        signals = struct.unpack('%uB' % len(data), data)
-                        for sig in signals:
-                            if sig in [signal.SIGCHLD, signal.SIGHUP, 
signal.SIGTERM, signal.SIGQUIT]:
-                                os.close(master_fd)
-                                return
-                            elif sig == signal.SIGWINCH:
-                                _set_pty_size()
-
-        pid, master_fd = pty.fork()
-
-        if pid == pty.CHILD:
-            os.execvpe(command[0], command, env)
-
-        pipe_r, pipe_w = os.pipe()
-        flags = fcntl.fcntl(pipe_w, fcntl.F_GETFL, 0)
-        flags = flags | os.O_NONBLOCK
-        flags = fcntl.fcntl(pipe_w, fcntl.F_SETFL, flags)
-
-        signal.set_wakeup_fd(pipe_w)
-
-        old_handlers = _signals(map(lambda s: (s, lambda signal, frame: None),
-                                    [signal.SIGWINCH,
-                                     signal.SIGCHLD,
-                                     signal.SIGHUP,
-                                     signal.SIGTERM,
-                                     signal.SIGQUIT]))
-
-        _set_pty_size()
-
-        with raw(pty.STDIN_FILENO):
-            try:
-                _copy(pipe_r)
-            except (IOError, OSError):
-                pass
-
-        _signals(old_handlers)
-
-        os.waitpid(pid, 0)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/term.py 
new/asciinema-2.0.2/asciinema/term.py
--- old/asciinema-2.0.1/asciinema/term.py       2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/asciinema/term.py       2019-01-12 19:58:29.000000000 
+0100
@@ -1,6 +1,7 @@
-import tty
-import select
 import os
+import select
+import subprocess
+import tty
 
 
 class raw():
@@ -26,3 +27,11 @@
         return os.read(fd, 1024)
 
     return b''
+
+
+def get_size():
+    # TODO maybe use os.get_terminal_size ?
+    return (
+        int(subprocess.check_output(['tput', 'cols'])),
+        int(subprocess.check_output(['tput', 'lines']))
+    )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/asciinema/urllib_http_adapter.py 
new/asciinema-2.0.2/asciinema/urllib_http_adapter.py
--- old/asciinema-2.0.1/asciinema/urllib_http_adapter.py        2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/asciinema/urllib_http_adapter.py        2019-01-12 
19:58:29.000000000 +0100
@@ -89,6 +89,6 @@
     def _parse_headers(self, response):
         headers = {}
         for k, v in response.getheaders():
-            headers[k] = v
+            headers[k.lower()] = v
 
         return headers
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/setup.py new/asciinema-2.0.2/setup.py
--- old/asciinema-2.0.1/setup.py        2018-04-04 09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/setup.py        2019-01-12 19:58:29.000000000 +0100
@@ -7,6 +7,10 @@
 
 url_template = 'https://github.com/asciinema/asciinema/archive/v%s.tar.gz'
 requirements = []
+test_requirements = ['nose']
+
+with open('README.md', encoding='utf8') as file:
+    long_description = file.read()
 
 setup(
     name='asciinema',
@@ -14,6 +18,8 @@
     packages=['asciinema', 'asciinema.commands', 'asciinema.asciicast'],
     license='GNU GPLv3',
     description='Terminal session recorder',
+    long_description=long_description,
+    long_description_content_type='text/markdown',
     author=asciinema.__author__,
     author_email='[email protected]',
     url='https://asciinema.org',
@@ -23,7 +29,15 @@
             'asciinema = asciinema.__main__:main',
         ],
     },
+    data_files=[('share/doc/asciinema', ['CHANGELOG.md',
+                                         'CODE_OF_CONDUCT.md',
+                                         'CONTRIBUTING.md',
+                                         'README.md',
+                                         'doc/asciicast-v1.md',
+                                         'doc/asciicast-v2.md']),
+                ('share/man/man1', ['man/asciinema.1'])],
     install_requires=requirements,
+    tests_require=test_requirements,
     classifiers=[
         'Development Status :: 5 - Production/Stable',
         'Environment :: Console',
@@ -37,6 +51,7 @@
         'Programming Language :: Python :: 3.4',
         'Programming Language :: Python :: 3.5',
         'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
         'Topic :: System :: Shells',
         'Topic :: Terminals',
         'Topic :: Utilities'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/tests/config_test.py 
new/asciinema-2.0.2/tests/config_test.py
--- old/asciinema-2.0.1/tests/config_test.py    2018-04-04 09:05:41.000000000 
+0200
+++ new/asciinema-2.0.2/tests/config_test.py    2019-01-12 19:58:29.000000000 
+0100
@@ -29,7 +29,7 @@
     config.upgrade()
     install_id = read_install_id(config.install_id_path)
 
-    assert re.match('^\w{8}-\w{4}-\w{4}-\w{4}-\w{12}', install_id)
+    assert re.match('^\\w{8}-\\w{4}-\\w{4}-\\w{4}-\\w{12}', install_id)
     assert_equal(install_id, config.install_id)
     assert not path.exists(config.config_file_path)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/tests/pty_recorder_test.py 
new/asciinema-2.0.2/tests/pty_recorder_test.py
--- old/asciinema-2.0.1/tests/pty_recorder_test.py      2018-04-04 
09:05:41.000000000 +0200
+++ new/asciinema-2.0.2/tests/pty_recorder_test.py      1970-01-01 
01:00:00.000000000 +0100
@@ -1,42 +0,0 @@
-import os
-import pty
-
-from nose.tools import assert_equal
-from .test_helper import Test
-
-from asciinema.pty_recorder import PtyRecorder
-
-
-class FakeStdout:
-
-    def __init__(self):
-        self.data = []
-
-    def write_stdout(self, data):
-        self.data.append(data)
-
-    def write_stdin(self, data):
-        pass
-
-
-class TestPtyRecorder(Test):
-
-    def setUp(self):
-        self.real_os_write = os.write
-        os.write = self.os_write
-
-    def tearDown(self):
-        os.write = self.real_os_write
-
-    def os_write(self, fd, data):
-        if fd != pty.STDOUT_FILENO:
-            self.real_os_write(fd, data)
-
-    def test_record_command_writes_to_stdout(self):
-        pty_recorder = PtyRecorder()
-        output = FakeStdout()
-
-        command = ['python3', '-c', "import sys; import time; 
sys.stdout.write(\'foo\'); sys.stdout.flush(); time.sleep(0.01); 
sys.stdout.write(\'bar\')"]
-        pty_recorder.record_command(command, output)
-
-        assert_equal([b'foo', b'bar'], output.data)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/asciinema-2.0.1/tests/pty_test.py 
new/asciinema-2.0.2/tests/pty_test.py
--- old/asciinema-2.0.1/tests/pty_test.py       1970-01-01 01:00:00.000000000 
+0100
+++ new/asciinema-2.0.2/tests/pty_test.py       2019-01-12 19:58:29.000000000 
+0100
@@ -0,0 +1,41 @@
+import os
+import pty
+
+from nose.tools import assert_equal
+from .test_helper import Test
+
+import asciinema.pty
+
+
+class FakeStdout:
+
+    def __init__(self):
+        self.data = []
+
+    def write_stdout(self, data):
+        self.data.append(data)
+
+    def write_stdin(self, data):
+        pass
+
+
+class TestRecord(Test):
+
+    def setUp(self):
+        self.real_os_write = os.write
+        os.write = self.os_write
+
+    def tearDown(self):
+        os.write = self.real_os_write
+
+    def os_write(self, fd, data):
+        if fd != pty.STDOUT_FILENO:
+            self.real_os_write(fd, data)
+
+    def test_record_command_writes_to_stdout(self):
+        output = FakeStdout()
+
+        command = ['python3', '-c', "import sys; import time; 
sys.stdout.write(\'foo\'); sys.stdout.flush(); time.sleep(0.01); 
sys.stdout.write(\'bar\')"]
+        asciinema.pty.record(command, output)
+
+        assert_equal([b'foo', b'bar'], output.data)


Reply via email to