inst/CITATION file is not being used when building my package - build

I have followed the indications regarding having a CITATION file in the inst directory. The problem is that every time that I build my package, the citation information is auto-generated from the package DESCRIPTION file, but not from the CITATION file. How Can I avoid this auto-generated process, and use the inst/CITATION file instead?
The features of my session are
version R version 4.2.1 (2022-06-23)
os Ubuntu 22.04.1 LTS
system x86_64, linux-gnu
thanks in advance
I am using the following (copied meanwhile) CITATION file
citHeader("To cite lubridate in publications use:")
citEntry(entry = "Article",
title = "Dates and Times Made Easy with {lubridate}",
author = personList(as.person("Garrett Grolemund"),
as.person("Hadley Wickham")),
journal = "Journal of Statistical Software",
year = "2011",
volume = "40",
number = "3",
pages = "1--25",
url = "https://www.jstatsoft.org/v40/i03/",
textVersion =
paste("Garrett Grolemund, Hadley Wickham (2011).",
"Dates and Times Made Easy with lubridate.",
"Journal of Statistical Software, 40(3), 1-25.",
"URL https://www.jstatsoft.org/v40/i03/.")
)

Related

Error: No module named os.uname under python 2.7

I'm running python 2.7.3 on a system that has anaconda. I recently pip installed internetarchive and when I run the installation program from command line I see:
AttributeError: 'module' object has no attribute 'uname'
I also tried this from within python's idle command line. The module loads fine, but I get the same error. Apparently os.uname() is missing from my installation, as it is documented as part of os in python here: https://docs.python.org/2/library/os.html#os.uname
My installation:
>>> import os
>>> dir(os)
['F_OK', 'O_APPEND', 'O_BINARY', 'O_CREAT', 'O_EXCL', 'O_NOINHERIT', 'O_RANDOM', 'O_RDONLY', 'O_RDWR', 'O_SEQUENTIAL', 'O_SHORT_LIVED', 'O_TEMPORARY', 'O_TEXT', 'O_TRUNC', 'O_WRONLY', 'P_DETACH', 'P_NOWAIT', 'P_NOWAITO', 'P_OVERLAY', 'P_WAIT', 'R_OK', 'SEEK_CUR', 'SEEK_END', 'SEEK_SET', 'TMP_MAX', 'UserDict', 'W_OK', 'X_OK', '_Environ', 'all', 'builtins', 'doc', 'file', 'name', 'package', '_copy_reg', '_execvpe', '_exists', '_exit', '_get_exports_list', '_make_stat_result', '_make_statvfs_result', '_pickle_stat_result', '_pickle_statvfs_result', 'abort', 'access', 'altsep', 'chdir', 'chmod', 'close', 'closerange', 'curdir', 'defpath', 'devnull', 'dup', 'dup2', 'environ', 'errno', 'error', 'execl', 'execle', 'execlp', 'execlpe', 'execv', 'execve', 'execvp', 'execvpe', 'extsep', 'fdopen', 'fstat', 'fsync', 'getcwd', 'getcwdu', 'getenv', 'getpid', 'isatty', 'kill', 'linesep', 'listdir', 'lseek', 'lstat', 'makedirs', 'mkdir', 'name', 'open', 'pardir', 'path', 'pathsep', 'pipe', 'popen', 'popen2', 'popen3', 'popen4', 'putenv', 'read', 'remove', 'removedirs', 'rename', 'renames', 'rmdir', 'sep', 'spawnl', 'spawnle', 'spawnv', 'spawnve', 'startfile', 'stat', 'stat_float_times', 'stat_result', 'statvfs_result', 'strerror', 'sys', 'system', 'tempnam', 'times', 'tmpfile', 'tmpnam', 'umask', 'unlink', 'unsetenv', 'urandom', 'utime', 'waitpid', 'walk', 'write']
Everything else in python seems fine and has been. Where did I go wrong? Are there version of python.os that lack uname? I'm on a windows machine; is that an issue?
Here is the relevant code in the module (session.py in internetarchive):
def _get_user_agent_string(self):
"""Generate a User-Agent string to be sent with every request."""
uname = os.uname()
try:
lang = locale.getlocale()[0][:2]
except:
lang = ''
py_version = '{0}.{1}.{2}'.format(*sys.version_info)
return 'internetarchive/{0} ({1} {2}; N; {3}; {4}) Python/{5}'.format(
__version__, uname[0], uname[-1], lang, self.access_key, py_version)
... <elsewhere> ...
self.headers['User-Agent'] = self._get_user_agent_string()
So seems like (as mentioned in the answer below) the coder was lazy and didn't make this windows-compatible. They supply an optional 'self.headers['User-Agent']' to the API and it ought to work with any string I provide. So I can hack this.
Yes, be on a windows machine is an issue (here): os.uname is available only on unix-like systems.
From the doc:
os.uname()
Return a 5-tuple containing information identifying the current operating system. The tuple contains 5 strings: (sysname, nodename, release, version, machine). Some systems truncate the nodename to 8 characters or to the leading component; a better way to get the hostname is socket.gethostname() or even socket.gethostbyaddr(socket.gethostname()).
Availability: recent flavors of Unix.
As said by the doc:
a better way to get the hostname is socket.gethostname() or even socket.gethostbyaddr(socket.gethostname())
A portable way to get some informations about the system is sys.platform, and the platform package.
This answer is a bit post hoc, however I would recommend the following:
import platform
unameinfo = platform.uname()
This works fine under Windows and since uname is listed under crossplatform in the documentation https://docs.python.org/3/library/platform.html I would expect to carry to other platforms as well. Since this question was tagged python2.7 I should mention it was already available for python2, but those docs are oldskool now.

Create version number variations for info.plist using #define and clang?

Years ago, when compiling with GCC, the following defines in a #include .h file could be pre-processed for use in info.plist:
#define MAJORVERSION 2
#define MINORVERSION 6
#define MAINTVERSION 4
<key>CFBundleShortVersionString</key> <string>MAJORVERSION.MINORVERSION.MAINTVERSION</string>
...which would turn into "2.6.4". That worked because GCC supported the "-traditional" flag. (see Tech Note TN2175 Info.plist files in Xcode Using the C Preprocessor, under "Eliminating whitespace between tokens in the macro expansion process")
However, fast-forward to 2016 and Clang 7.0.2 (Xcode 7.2.1) apparently does not support either "-traditional" or "-traditional-cpp" (or support it properly), yielding this string:
"2 . 6 . 4"
(see Bug 12035 - Preprocessor inserts spaces in macro expansions, comment 4)
Because there are so many different variations (CFBundleShortVersionString, CFBundleVersion, CFBundleGetInfoString), it would be nice to work around this clang problem, and define these once, and concatenate / stringify the pieces together. What is the commonly-accepted pattern for doing this now? (I'm presently building on MacOS but the same pattern would work for IOS)
Here is the Python script I use to increment my build number, whenever a source code change is detected, and update one or more Info.plist files within the project.
It was created to solve the issue raised in this question I asked a while back.
You need to create buildnum.ver file in the source tree that looks like this:
version 1.0
build 1
(you will need to manually increment version when certain project milestones are reached, but buildnum is incremented automatically).
NOTE the location of the .ver file must be in the root of the source tree (see SourceDir, below) as this script will look for modified files in this directory. If any are found, the build number is incremented. Modified means source files changes after the .ver file was last updated.
Then create a new Xcode target to run an external build tool and run something like:
tools/bump_buildnum.py SourceDir/buildnum.ver SourceDir/Info.plist
(make it run in ${PROJECT_DIR})
and then make all the actual Xcode targets dependent upon this target, so it runs before any of them are built.
#!/usr/bin/env python
#
# Bump build number in Info.plist files if a source file have changed.
#
# usage: bump_buildnum.py buildnum.ver Info.plist [ ... Info.plist ]
#
# andy#trojanfoe.com, 2014.
#
import sys, os, subprocess, re
def read_verfile(name):
version = None
build = None
verfile = open(name, "r")
for line in verfile:
match = re.match(r"^version\s+(\S+)", line)
if match:
version = match.group(1).rstrip()
match = re.match(r"^build\s+(\S+)", line)
if match:
build = int(match.group(1).rstrip())
verfile.close()
return (version, build)
def write_verfile(name, version, build):
verfile = open(name, "w")
verfile.write("version {0}\n".format(version))
verfile.write("build {0}\n".format(build))
verfile.close()
return True
def set_plist_version(plistname, version, build):
if not os.path.exists(plistname):
print("{0} does not exist".format(plistname))
return False
plistbuddy = '/usr/libexec/Plistbuddy'
if not os.path.exists(plistbuddy):
print("{0} does not exist".format(plistbuddy))
return False
cmdline = [plistbuddy,
"-c", "Set CFBundleShortVersionString {0}".format(version),
"-c", "Set CFBundleVersion {0}".format(build),
plistname]
if subprocess.call(cmdline) != 0:
print("Failed to update {0}".format(plistname))
return False
print("Updated {0} with v{1} ({2})".format(plistname, version, build))
return True
def should_bump(vername, dirname):
verstat = os.stat(vername)
allnames = []
for dirname, dirnames, filenames in os.walk(dirname):
for filename in filenames:
allnames.append(os.path.join(dirname, filename))
for filename in allnames:
filestat = os.stat(filename)
if filestat.st_mtime > verstat.st_mtime:
print("{0} is newer than {1}".format(filename, vername))
return True
return False
def upver(vername):
(version, build) = read_verfile(vername)
if version == None or build == None:
print("Failed to read version/build from {0}".format(vername))
return False
# Bump the version number if any files in the same directory as the version file
# have changed, including sub-directories.
srcdir = os.path.dirname(vername)
bump = should_bump(vername, srcdir)
if bump:
build += 1
print("Incremented to build {0}".format(build))
write_verfile(vername, version, build)
print("Written {0}".format(vername))
else:
print("Staying at build {0}".format(build))
return (version, build)
if __name__ == "__main__":
if os.environ.has_key('ACTION') and os.environ['ACTION'] == 'clean':
print("{0}: Not running while cleaning".format(sys.argv[0]))
sys.exit(0)
if len(sys.argv) < 3:
print("Usage: {0} buildnum.ver Info.plist [... Info.plist]".format(sys.argv[0]))
sys.exit(1)
vername = sys.argv[1]
(version, build) = upver(vername)
if version == None or build == None:
sys.exit(2)
for i in range(2, len(sys.argv)):
plistname = sys.argv[i]
set_plist_version(plistname, version, build)
sys.exit(0)
First, I would like to clarify what each key is meant to do:
CFBundleShortVersionString
A string describing the released version of an app, using semantic versioning. This string will be displayed in the App Store description.
CFBundleVersion
A string specifing the build version (released or unreleased). It is a string, but Apple recommends to use numbers instead.
CFBundleGetInfoString
Seems to be deprecated, as it is no longer listed in the Information Property List Key Reference.
During development, CFBundleShortVersionString isn't changed that often, and I normally set CFBundleShortVersionString manually in Xcode. The only string I change regularly is CFBundleVersion, because you can't submit a new build to iTunes Connect/TestFlight, if the CFBundleVersion wasn't changed.
To change the value, I use a Rake task with PlistBuddy to write a time stamp (year, month, day, hour, and minute) to CFBundleVersion:
desc "Bump bundle version"
task :bump_bundle_version do
bundle_version = Time.now.strftime "%Y%m%d%H%M"
sh %Q{/usr/libexec/PlistBuddy -c "Set CFBundleVersion #{bundle_version}" "DemoApp/DemoApp-Info.plist"}
end
You can use PlistBuddy, if you need to automate CFBundleShortVersionString as well.

How to customize TRAC plugin template python file

I am currently modifying our TRAC instance to Bootstrap 3.1. However, some templating needs to be done on the .py files. I only know how to customize .html files... just add classes, customize DOM structure a little bit then put it in templates folder of our TRAC instance.
NOW WHAT ABOUT customizing .py files from plugins? I tried putting them in templates folder but nothing happened.
I had no experience with Python, but it's easy just to hack around and add a bootstrap class e.g adding "col-sm-2 control-label" in a label in milestone.py
def __edit_project(self, data, req):
milestone = data.get('milestone').name
all_projects = self.__SmpModel.get_all_projects_filtered_by_conditions(req)
id_project_milestone = self.__SmpModel.get_id_project_milestone(milestone)
if id_project_milestone != None:
id_project_selected = id_project_milestone[0]
else:
id_project_selected = None
return tag.div(
tag.label(
class_="col-sm-2 control-label",
'Project',
tag.br(),
tag.select(
tag.option(),
[tag.option(row[1], selected=(id_project_selected == row[0] or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1))],
name="project")
),
class_="field")
Compiling the plugin again worked for me. After adding bootstrap classes on specific .py files, here are the steps/commands I did:
In our TRAC environment plugins directory where specific setup.py of the plugin I'm editing is located, build the .egg file e.g
tracproject/plugins_source/sampleplugin: python setup.py bdist_egg
Then I renamed the plugin's original .egg file in the plugins directory e.g
tracproject/plugins/sampleplugin/: mv sampleplugin.egg sampleplugin.egg.old
After that, I copied the newly .egg file generated to the plugins directory e.g
tracproject/plugins_source/sampleplugin/dist: mv sampleplugin.egg ../../../plugins/
Lastly, I restarted our server e.g (however, there were cases, no restart was needed since changes were instantly reflected)
sudo service apache2 restart
Thanks #falkb! I see that you're the author of SimpleMultiProject plugin I was trying to put bootstrap classes. :)
Here's a snippet of simplemultiprojectplugin milestone.py where I added styling
def __edit_project(self, data, req):
milestone = data.get('milestone').name
all_projects = self.__SmpModel.get_all_projects_filtered_by_conditions(req)
id_project_milestone = self.__SmpModel.get_id_project_milestone(milestone)
if id_project_milestone != None:
id_project_selected = id_project_milestone[0]
else:
id_project_selected = None
return tag.div(
tag.label('Project', class_="control-label col-sm-2"),
tag.div(
tag.select(
tag.option(),
[tag.option(row[1], selected=(id_project_selected == row[0] or None), value=row[0]) for row in sorted(all_projects, key=itemgetter(1))],
name="project",
class_="form-control"),
class_="col-sm-5"),
class_="form-group")

py2app - preserve directory structure

I would like to make a mac os x app for distributing my program.
The problem is that current script puts "images/Diagram.png" and other files under "images" folder to "Resources" but not to "Resources/images" as expected
What can I change in this setup.py part in order to put png files under images?
mainscript, ico, icns = "aproxim.py", "sum.ico", "sum.icns"
files = ["images/Diagram.png", "images/document.png", "images/Exit.png", "images/floppydisc.png",
"images/folder.png", "images/Info.png", "images/settings.png"]
scripts = ["app_settings_dialog", "app_window", "approximator", "approximator2", "data_format",
"easy_excel", "functions", "main_window", "settings_dialog",
"util_data", "util_parameters"]
description = "Approximator is program for experimental data approximation and interpolation (20 dependencies for select)"
common_options = dict(name = "Approximator", version = "1.7", description = description)
if sys.platform == 'darwin':
setup(
setup_requires = ['py2app'],
app = [mainscript],
options = dict(py2app = dict(includes = scripts, resources = files, iconfile = icns)),
**common_options)
It is easy, hope it is useful for other Python developers:
resources = [('images', files), ('', [ico])]

Boost-Python: Load python module with unicode chars in path

I'm working on game project. I use python 2.7.2 for scripting. My application works fine with non unicode path to .exe. But it can't load scripts with unicode path using
boost::python::import (import_path.c_str());
I tried this example
5.3. Pure Embedding http://docs.python.org/extending/embedding.html#embedding-python-in-c
It also can't handle unicode path. I linked python as dll.
Explain me, please, how to handle such path.
boost::python::import needs a std::string, so chances are that import_path misses some characters.
Do you have to work on multiple platform ? On Windows, you could call GetShortPathName to retreive the 8.3 filename and use that to load your dll.
You can make a quick test :
Rename your extension to "JaiDéjàTestéÇaEtJaiDétestéÇa.pyd".
At the command line, type dir /x *.pyd to get the short file name (JAIDJT~1.PYD on my computer)
Use the short name to load your extension.
+The file name above if French for "I already tested this and I didn't like it". It is a rhyme that takes the edge off working with Unicode ;)
This isn't really an answer that will suit your needs, but maybe it will give you something to go on.
I ran into a very similar problem with Python, in my case my application is a pure Python application. I noticed as well that if my application was installed to a directory with a path string that could not be encoded in MBCS (what Python converts to internally for imports, at least Python prior to 3.2 as far as I understand), the Python interpreter would fail, claiming not module of that name existed.
What I had to do was write an Import Hook to trick it into loading those files anyway.
Here's what I came up with:
import imp, os, sys
class UnicodeImporter(object):
def find_module(self,fullname,path=None):
if isinstance(fullname,unicode):
fullname = fullname.replace(u'.',u'\\')
exts = (u'.pyc',u'.pyo',u'.py')
else:
fullname = fullname.replace('.','\\')
exts = ('.pyc','.pyo','.py')
if os.path.exists(fullname) and os.path.isdir(fullname):
return self
for ext in exts:
if os.path.exists(fullname+ext):
return self
def load_module(self,fullname):
if fullname in sys.modules:
return sys.modules[fullname]
else:
sys.modules[fullname] = imp.new_module(fullname)
if isinstance(fullname,unicode):
filename = fullname.replace(u'.',u'\\')
ext = u'.py'
initfile = u'__init__'
else:
filename = fullname.replace('.','\\')
ext = '.py'
initfile = '__init__'
if os.path.exists(filename+ext):
try:
with open(filename+ext,'U') as fp:
mod = imp.load_source(fullname,filename+ext,fp)
sys.modules[fullname] = mod
mod.__loader__ = self
return mod
except:
print 'fail', filename+ext
raise
mod = sys.modules[fullname]
mod.__loader__ = self
mod.__file__ = os.path.join(os.getcwd(),filename)
mod.__path__ = [filename]
#init file
initfile = os.path.join(filename,initfile+ext)
if os.path.exists(initfile):
with open(initfile,'U') as fp:
code = fp.read()
exec code in mod.__dict__
return mod
sys.meta_path = [UnicodeImporter()]
I still run into two issues when using this:
Double clicking on the launcher file (a .pyw file) in windows explorer does not work when the application is installed in a trouble directory. I believe this has to do with how Windows file associations passes the arguments to pythonw.exe (my guess is Windows passes the full path string, which includes the non-encodeable character, as the argument to the exe). If I create a batch file and have the batch file call the Python executable with just the file name of my launcher, and ensure it's launched from the same directory, it launches fine. Again, I'm betting this is because now I can use a relative path as the argument for python.exe, and avoid those trouble characters in the path.
Packaging my application using py2exe, the resulting exe will not run if placed in one of these trouble paths. I think this has to do with the zipimporter module, which unfortunately is a compiled Python module so I cannot easily modify it (I would have to recompile, etc etc).