diff --git a/buildozer/__init__.py b/buildozer/__init__.py index dfca74c..bf71b49 100644 --- a/buildozer/__init__.py +++ b/buildozer/__init__.py @@ -553,6 +553,8 @@ class Buildozer(object): source = join(cwd, source) target = join(cwd, target) self.debug('Rename {0} to {1}'.format(source, target)) + if not os.path.isdir(os.path.dirname(target)): + self.error('Rename {0} to {1} fails becaues {2} is not a directory'.format(source, target, os.path.directory(target))) rename(source, target) def file_copy(self, source, target, cwd=None): diff --git a/buildozer/libs/pexpect.py b/buildozer/libs/pexpect.py index 67c6389..6b34a51 100644 --- a/buildozer/libs/pexpect.py +++ b/buildozer/libs/pexpect.py @@ -78,7 +78,7 @@ try: import errno import traceback import signal -except ImportError, e: +except ImportError as e: raise ImportError (str(e) + """ A critical module was not found. Probably this operating system does not @@ -246,10 +246,10 @@ def run (command, timeout=-1, withexitstatus=False, events=None, extra_args=None else: raise TypeError ('The callback must be a string or function type.') event_count = event_count + 1 - except TIMEOUT, e: + except TIMEOUT as e: child_result_list.append(child.before) break - except EOF, e: + except EOF as e: child_result_list.append(child.before) break child_result = ''.join(child_result_list) @@ -525,7 +525,7 @@ class spawn (object): if self.use_native_pty_fork: try: self.pid, self.child_fd = pty.fork() - except OSError, e: + except OSError as e: raise ExceptionPexpect('Error! pty.fork() failed: ' + str(e)) else: # Use internal __fork_pty self.pid, self.child_fd = self.__fork_pty() @@ -581,11 +581,11 @@ class spawn (object): parent_fd, child_fd = os.openpty() if parent_fd < 0 or child_fd < 0: - raise ExceptionPexpect, "Error! Could not open pty with os.openpty()." + raise ExceptionPexpect("Error! Could not open pty with os.openpty().") pid = os.fork() if pid < 0: - raise ExceptionPexpect, "Error! Failed os.fork()." + raise ExceptionPexpect("Error! Failed os.fork().") elif pid == 0: # Child. os.close(parent_fd) @@ -623,7 +623,7 @@ class spawn (object): fd = os.open("/dev/tty", os.O_RDWR | os.O_NOCTTY); if fd >= 0: os.close(fd) - raise ExceptionPexpect, "Error! We are not disconnected from a controlling tty." + raise ExceptionPexpect("Error! We are not disconnected from a controlling tty.") except: # Good! We are disconnected from a controlling tty. pass @@ -631,14 +631,14 @@ class spawn (object): # Verify we can open child pty. fd = os.open(child_name, os.O_RDWR); if fd < 0: - raise ExceptionPexpect, "Error! Could not open child pty, " + child_name + raise ExceptionPexpect("Error! Could not open child pty, " + child_name) else: os.close(fd) # Verify we now have a controlling tty. fd = os.open("/dev/tty", os.O_WRONLY) if fd < 0: - raise ExceptionPexpect, "Error! Could not open controlling tty, /dev/tty" + raise ExceptionPexpect("Error! Could not open controlling tty, /dev/tty") else: os.close(fd) @@ -826,7 +826,7 @@ class spawn (object): if self.child_fd in r: try: s = os.read(self.child_fd, size) - except OSError, e: # Linux does this + except OSError as e: # Linux does this self.flag_eof = True raise EOF ('End Of File (EOF) in read_nonblocking(). Exception style platform.') if s == '': # BSD style @@ -834,10 +834,10 @@ class spawn (object): raise EOF ('End Of File (EOF) in read_nonblocking(). Empty string style platform.') if self.logfile is not None: - self.logfile.write (s) + self.logfile.write (s.decode(encoding='UTF-8')) self.logfile.flush() if self.logfile_read is not None: - self.logfile_read.write (s) + self.logfile_read.write (s.decode(encoding='UTF-8')) self.logfile_read.flush() return s @@ -950,7 +950,7 @@ class spawn (object): if self.logfile_send is not None: self.logfile_send.write (s) self.logfile_send.flush() - c = os.write(self.child_fd, s) + c = os.write(self.child_fd, s.encode(encoding='UTF-8')) return c def sendline(self, s=''): @@ -1071,7 +1071,7 @@ class spawn (object): else: return False return False - except OSError, e: + except OSError as e: # I think there are kernel timing issues that sometimes cause # this to happen. I think isalive() reports True, but the # process is dead to the kernel. @@ -1130,7 +1130,7 @@ class spawn (object): try: pid, status = os.waitpid(self.pid, waitpid_options) - except OSError, e: # No child processes + except OSError as e: # No child processes if e[0] == errno.ECHILD: raise ExceptionPexpect ('isalive() encountered condition where "terminated" is 0, but there was no child process. Did someone else call waitpid() on our process?') else: @@ -1142,7 +1142,7 @@ class spawn (object): if pid == 0: try: pid, status = os.waitpid(self.pid, waitpid_options) ### os.WNOHANG) # Solaris! - except OSError, e: # This should never happen... + except OSError as e: # This should never happen... if e[0] == errno.ECHILD: raise ExceptionPexpect ('isalive() encountered condition that should never happen. There was no child process. Did someone else call waitpid() on our process?') else: @@ -1209,7 +1209,7 @@ class spawn (object): if patterns is None: return [] - if type(patterns) is not types.ListType: + if type(patterns) is not list: patterns = [patterns] compile_flags = re.DOTALL # Allow dot to match \n @@ -1217,7 +1217,7 @@ class spawn (object): compile_flags = compile_flags | re.IGNORECASE compiled_pattern_list = [] for p in patterns: - if type(p) in types.StringTypes: + if type(p) in (str,bytes): compiled_pattern_list.append(re.compile(p, compile_flags)) elif p is EOF: compiled_pattern_list.append(EOF) @@ -1372,16 +1372,16 @@ class spawn (object): self.match_index = index return self.match_index # No match at this point - if timeout < 0 and timeout is not None: + if timeout is not None and timeout < 0: raise TIMEOUT ('Timeout exceeded in expect_any().') # Still have time left, so read more data c = self.read_nonblocking (self.maxread, timeout) freshlen = len(c) time.sleep (0.0001) - incoming = incoming + c + incoming = incoming + c.decode(encoding='UTF-8') if timeout is not None: timeout = end_time - time.time() - except EOF, e: + except EOF as e: self.buffer = '' self.before = incoming self.after = EOF @@ -1394,7 +1394,7 @@ class spawn (object): self.match = None self.match_index = None raise EOF (str(e) + '\n' + str(self)) - except TIMEOUT, e: + except TIMEOUT as e: self.buffer = incoming self.before = incoming self.after = TIMEOUT @@ -1419,7 +1419,7 @@ class spawn (object): """This returns the terminal window size of the child tty. The return value is a tuple of (rows, cols). """ - TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912L) + TIOCGWINSZ = getattr(termios, 'TIOCGWINSZ', 1074295912) s = struct.pack('HHHH', 0, 0, 0, 0) x = fcntl.ioctl(self.fileno(), TIOCGWINSZ, s) return struct.unpack('HHHH', x)[0:2] @@ -1441,7 +1441,7 @@ class spawn (object): # Newer versions of Linux have totally different values for TIOCSWINSZ. # Note that this fix is a hack. TIOCSWINSZ = getattr(termios, 'TIOCSWINSZ', -2146929561) - if TIOCSWINSZ == 2148037735L: # L is not required in Python >= 2.2. + if TIOCSWINSZ == 2148037735: # L is not required in Python >= 2.2. TIOCSWINSZ = -2146929561 # Same bits, but with sign. # Note, assume ws_xpixel and ws_ypixel are zero. s = struct.pack('HHHH', r, c, 0, 0) @@ -1547,7 +1547,7 @@ class spawn (object): while True: try: return select.select (iwtd, owtd, ewtd, timeout) - except select.error, e: + except select.error as e: if e[0] == errno.EINTR: # if we loop back we have to subtract the amount of time we already waited. if timeout is not None: diff --git a/buildozer/targets/android.py b/buildozer/targets/android.py index 9a63586..a61be25 100644 --- a/buildozer/targets/android.py +++ b/buildozer/targets/android.py @@ -647,7 +647,7 @@ class TargetAndroid(Target): self.buildozer.error('Invalid library reference (path not found): {}'.format(cref)) exit(1) # get a relative path from the project file - ref = relpath(ref, dist_dir) + ref = relpath(ref, realpath(dist_dir)) # ensure the reference exists references.append(ref) diff --git a/docs/source/specifications.rst b/docs/source/specifications.rst index 83aa215..c9fe199 100644 --- a/docs/source/specifications.rst +++ b/docs/source/specifications.rst @@ -1,7 +1,7 @@ Specifications ============== -This document explain in details all the configuration token you can use in +This document explains in detail all the configuration tokens you can use in `buildozer.spec`. Section [app] @@ -9,9 +9,10 @@ Section [app] - `title`: String, title of your application. - It might possible that some characters are not working depending the paltform - targetted. Best for you is to try and see. Try to avoid too-long title, as - they will also not fit in the title displayed under the icon. + It might be possible that some characters are not working depending on the + targeted paltform. It's best to try and see if everything works as expected. + Try to avoid too long titles, as they will also not fit in the title + displayed under the icon. - `package.name`: String, package name. @@ -21,40 +22,40 @@ Section [app] - `package.domain`: String, package domain. - Package domain is a string that reference the company or individual that did - it. Both domain+name will become your application identifier for Android and - iOS. Choose it carefully. As an example, when the Kivy`s team is publishing - an application, the domain starts with `org.kivy`. + Package domain is a string that references the company or individual that + did the app. Both domain+name will become your application identifier for + Android and iOS, choose it carefully. As an example, when the Kivy`s team + is publishing an application, the domain starts with `org.kivy`. - `source.dir`: String, location of your application sources. - The location must be a directory that contain a `main.py` file. It defaults - to the same directory as the one `buildozer.spec` is. + The location must be a directory that contains a `main.py` file. It defaults + to the directory where `buildozer.spec` is. -- `source.include_exts`: List, files extensions to include. +- `source.include_exts`: List, files' extensions to include. - By default, not all the file in your `source.dir` are included, but only some - of them, depending the extension. Ie, we includes `py,png,jpg,kv,atlas`. Feel - free to add your own extensions, or put an empty value if you want to include + By default, not all files in your `source.dir` are included, but only some + of them (`py,png,jpg,kv,atlas`), depending on the extension. Feel free to + add your own extensions, or use an empty value if you want to include everything. -- `source.exclude_exts`: List, files extensions to exclude. +- `source.exclude_exts`: List, files' extensions to exclude. In contrary to `source.include_exts`, you could include all the files you - want except the one that ends with an extension contain in this token. If - empty, no files will be excluded by the extensions. + want except the ones that end with an extension listed in this token. If + empty, no files will be excluded based on their extensions. - `source.exclude_dirs`: List, directories to exclude. - Same as `source.exclude_exts`, but for directory. You can exclude your - `tests` or `bin` directory with:: + Same as `source.exclude_exts`, but for directories. You can exclude your + `tests` and `bin` directory with:: source.exclude_dirs = tests, bin -- `source.exclude_patterns`: List, file to exclude if they match a pattern. +- `source.exclude_patterns`: List, files to exclude if they match a pattern. If you have a more complex application layout, you might need a pattern to - exclude files. It works also even if you don't have a pattern. For example:: + exclude files. It also works if you don't have a pattern. For example:: source.exclude_patterns = license,images/originals/* @@ -62,54 +63,54 @@ Section [app] `version.filename`. The default capture method of your application version is by grepping a line - like that:: + like this:: __version__ = "1.0" The `1.0` will be used as a version. -- `version.filename`: String, default to the main.py. +- `version.filename`: String, defaults to the main.py. - Filename to use for capturing the version with `version.regex`. + File to use for capturing the version with `version.regex`. - `version`: String, manual application version. - If you don't want to capture the version, comment both of `version.regex` and - `version.filename`, then put the version you want directly in the `version` - token:: + If you don't want to capture the version, comment out both `version.regex` + and `version.filename`, then put the version you want directly in the + `version` token:: # version.regex = # version.filename = version = 1.0 -- `requirements`: List, Python module or extensions that your application - require. +- `requirements`: List, Python modules or extensions that your application + requires. The requirements can be either a name of a recipe in the Python-for-android - project, or a pure-Python package. For example, if your application require + project, or a pure-Python package. For example, if your application requires Kivy and requests, you need to write:: requirements = kivy,requests - If your application try to install a Python extension (ie, a Python package - that require compilation), and that it doesn't have a recipe associated to - Python-for-android, it will not work. We explicitely disable the compilation - here. If you want to make it work, contribute to the Python-for-android - project by creating a recipe. See :doc:`contribute` + If your application tries to install a Python extension (ie, a Python + package that requires compilation), and the extension doesn't have a recipe + associated to Python-for-android, it will not work. We explicitly disable + the compilation here. If you want to make it work, contribute to the + Python-for-android project by creating a recipe. See :doc:`contribute`. - `garden_requirements`: List, Garden packages to include. - Add here the list of Kivy's garden package to include. For example:: + Add here the list of Kivy's garden packages to include. For example:: - garder_requirements = graph + garden_requirements = graph Please note that if it doesn't work, it might be because of the garden - package itself. Refer to the author of the package if he already tested it on - the platform you are targetting, not us. + package itself. Refer to the author of the package if he already tested + it on your target platform, not us. - `presplash.filename`: String, loading screen of your application. - Presplash is the image showed on the device when the application is loading. + Presplash is the image shown on the device during application loading. It is called presplash on Android, and Loading image on iOS. The image might have different requirements depending the platform. Currently, Buildozer works well only with Android, iOS support is not great on this. @@ -126,12 +127,12 @@ Section [app] - `orientation`: String, orientation of the application. - Indicate the orientation that your application support. Defaults to + Indicate the orientation that your application supports. Defaults to `landscape`, but can be changed to `portrait` or `all`. - `fullscreen`: Boolean, fullscreen mode. Defaults to true, your application will run in fullscreen. Means the status - bar will be hidden. If you want to let the user access to the status bar, - hour, notifications, put to 0. + bar will be hidden. If you want to let the user access the status bar, + hour, notifications, use 0 as a value.