def _enter_title(ui, dataset): default = _get_default_title(dataset) while True: title = ui.question( "Please enter the title (must be at least 3 characters long).", title="New article", default=default) if len(title) < 3: ui.error("Title must be at least 3 characters long.") else: return title
def ask(): assert_equal(ui.question('what is a?'), 'a')
def func2(x): assert x == 1 eq_(ui.yesno("title"), True) eq_(ui.question("title2"), "maybe so") assert_raises(AssertionError, ui.question, "asking more than we know") return x * 2
def __call__(dataset, filename=None, missing_content='error', no_annex=False, # TODO: support working with projects and articles within them # project_id=None, article_id=None): import os import logging lgr = logging.getLogger('datalad.plugin.export_to_figshare') from datalad.ui import ui from datalad.api import add_archive_content from datalad.api import export_archive from datalad.distribution.dataset import require_dataset from datalad.support.annexrepo import AnnexRepo dataset = require_dataset(dataset, check_installed=True, purpose='export to figshare') if not isinstance(dataset.repo, AnnexRepo): raise ValueError( "%s is not an annex repo, so annexification could be done" % dataset ) if dataset.repo.is_dirty(): raise RuntimeError( "Paranoid authors of DataLad refuse to proceed in a dirty repository" ) if filename is None: filename = dataset.path lgr.info( "Exporting current tree as an archive under %s since figshare " "does not support directories", filename ) archive_out = next( export_archive( dataset, filename=filename, archivetype='zip', missing_content=missing_content, return_type="generator" ) ) assert archive_out['status'] == 'ok' fname = archive_out['path'] lgr.info("Uploading %s to figshare", fname) figshare = FigshareRESTLaison() if not article_id: # TODO: ask if it should be an article within a project if ui.is_interactive: # or should we just upload to a new article? if ui.yesno( "Would you like to create a new article to upload to? " "If not - we will list existing articles", title="Article" ): article = figshare.create_article( title=os.path.basename(dataset.path) ) lgr.info( "Created a new (private) article %(id)s at %(url_private_html)s. " "Please visit it, enter additional meta-data and make public", article ) article_id = article['id'] else: article_id = int(ui.question( "Which of the articles should we upload to.", choices=list(map(str, figshare.get_article_ids())) )) if not article_id: raise ValueError("We need an article to upload to.") file_info = figshare.upload_file( fname, files_url='account/articles/%s/files' % article_id ) if no_annex: lgr.info("Removing generated tarball") unlink(fname) else: # I will leave all the complaining etc to the dataset add if path # is outside etc lgr.info("'Registering' %s within annex", fname) repo = dataset.repo repo.add(fname, git=False) key = repo.get_file_key(fname) lgr.info("Adding URL %(download_url)s for it", file_info) repo._annex_custom_command([], [ "git", "annex", "registerurl", '-c', 'annex.alwayscommit=false', key, file_info['download_url'] ] ) lgr.info("Registering links back for the content of the archive") add_archive_content( fname, annex=dataset.repo, delete_after=True, # just remove extracted into a temp dir allow_dirty=True, # since we have a tarball commit=False # we do not want to commit anything we have done here ) lgr.info("Removing generated and now registered in annex archive") repo.drop(key, key=True, options=['--force']) repo.remove(fname, force=True) # remove the tarball # if annex in {'delete'}: # dataset.repo.remove(fname) # else: # # kinda makes little sense I guess. # # Made more sense if export_archive could export an arbitrary treeish # # so we could create a branch where to dump and export to figshare # # (kinda closer to my idea) # dataset.save(fname, message="Added the entire dataset into a zip file") # TODO: add to downloader knowledge about figshare token so it could download-url # those zipballs before they go public yield dict( status='ok', # TODO: add article url (which needs to be queried if only ID is known message="Published archive {}".format( file_info['download_url']), file_info=file_info, path=dataset, action='export_to_figshare', logger=lgr )
def enter_new(self, url=None, auth_types=[], url_re=None, name=None, credential_name=None, credential_type=None): # TODO: level/location! """Create new provider and credential config If interactive, this will ask the user to enter the details (or confirm default choices). A dedicated config file is written at <user_config_dir>/providers/<name>.cfg Parameters: ----------- url: str or RI URL this config is created for auth_types: list List of authentication types to choose from. First entry becomes default. See datalad.downloaders.providers.AUTHENTICATION_TYPES url_re: str regular expression; Once created, this config will be used for any matching URL; defaults to `url` name: str name for the provider; needs to be unique per user credential_name: str name for the credential; defaults to the provider's name credential_type: str credential type to use (key for datalad.downloaders.CREDENTIAL_TYPES) """ from datalad.ui import ui if url and not name: ri = RI(url) for f in ('hostname', 'name'): try: # might need sanitarization name = str(getattr(ri, f)) except AttributeError: pass known_providers_by_name = {p.name: p for p in self._providers} providers_user_dir = self._get_providers_dirs()['user'] while True: name = ui.question( title="New provider name", text="Unique name to identify 'provider' for %s" % url, default=name) filename = pathjoin(providers_user_dir, '%s.cfg' % name) if name in known_providers_by_name: if ui.yesno( title="Known provider %s" % name, text= "Provider with name %s already known. Do you want to " "use it for this session?" % name, default=True): return known_providers_by_name[name] elif path.lexists(filename): ui.error("File %s already exists, choose another name" % filename) else: break if not credential_name: credential_name = name if not url_re: url_re = re.escape(url) if url else None while True: url_re = ui.question( title="New provider regular expression", text="A (Python) regular expression to specify for which URLs " "this provider should be used", default=url_re) if not re.match(url_re, url): ui.error("Provided regular expression doesn't match original " "url. Please re-enter") # TODO: url_re of another provider might match it as well # I am not sure if we have any kind of "priority" setting ATM # to differentiate or to to try multiple types :-/ else: break authentication_type = None if auth_types: auth_types = [t for t in auth_types if t in AUTHENTICATION_TYPES] if auth_types: authentication_type = auth_types[0] # Setup credential authentication_type = ui.question( title="Authentication type", text="What authentication type to use", default=authentication_type, choices=sorted(AUTHENTICATION_TYPES)) authenticator_class = AUTHENTICATION_TYPES[authentication_type] # TODO: need to figure out what fields that authenticator might # need to have setup and ask for them here! credential_type = ui.question( title="Credential", text="What type of credential should be used?", choices=sorted(CREDENTIAL_TYPES), default=credential_type or getattr(authenticator_class, 'DEFAULT_CREDENTIAL_TYPE')) cfg = self._CONFIG_TEMPLATE.format(**locals()) if ui.yesno(title="Save provider configuration file", text="Following configuration will be written to %s:\n%s" % (filename, cfg), default='yes'): # Just create a configuration file and reload the thing return self._store_new(url=url, authentication_type=authentication_type, authenticator_class=authenticator_class, url_re=url_re, name=name, credential_name=credential_name, credential_type=credential_type, level='user') else: return None
def enter_new(self, url=None, auth_types=[]): from datalad.ui import ui name = None if url: ri = RI(url) for f in ('hostname', 'name'): try: # might need sanitarization name = str(getattr(ri, f)) except AttributeError: pass known_providers_by_name = {p.name: p for p in self._providers} providers_user_dir = self._get_providers_dirs()['user'] while True: name = ui.question( title="New provider name", text="Unique name to identify 'provider' for %s" % url, default=name ) filename = pathjoin(providers_user_dir, '%s.cfg' % name) if name in known_providers_by_name: if ui.yesno( title="Known provider %s" % name, text="Provider with name %s already known. Do you want to " "use it for this session?" % name, default=True ): return known_providers_by_name[name] elif path.lexists(filename): ui.error( "File %s already exists, choose another name" % filename) else: break url_re = re.escape(url) if url else None while True: url_re = ui.question( title="New provider regular expression", text="A (Python) regular expression to specify for which URLs " "this provider should be used", default=url_re ) if not re.match(url_re, url): ui.error("Provided regular expression doesn't match original " "url. Please re-enter") # TODO: url_re of another provider might match it as well # I am not sure if we have any kind of "priority" setting ATM # to differentiate or to to try multiple types :-/ else: break authentication_type = None if auth_types: auth_types = [ t for t in auth_types if t in AUTHENTICATION_TYPES ] if auth_types: authentication_type = auth_types[0] # Setup credential authentication_type = ui.question( title="Authentication type", text="What authentication type to use", default=authentication_type, choices=sorted(AUTHENTICATION_TYPES) ) authenticator_class = AUTHENTICATION_TYPES[authentication_type] # TODO: need to figure out what fields that authenticator might # need to have setup and ask for them here! credential_type = ui.question( title="Credential", text="What type of credential should be used?", choices=sorted(CREDENTIAL_TYPES), default=getattr(authenticator_class, 'DEFAULT_CREDENTIAL_TYPE') ) # Just create a configuration file and reload the thing if not path.lexists(providers_user_dir): os.makedirs(providers_user_dir) cfg = """\ # Provider configuration file created to initially access # {url} [provider:{name}] url_re = {url_re} authentication_type = {authentication_type} # Note that you might need to specify additional fields specific to the # authenticator. Fow now "look into the docs/source" of {authenticator_class} # {authentication_type}_ credential = {name} [credential:{name}] # If known, specify URL or email to how/where to request credentials # url = ??? type = {credential_type} """.format(**locals()) if ui.yesno( title="Save provider configuration file", text="Following configuration will be written to %s:\n%s" % (filename, cfg), default='yes' ): with open(filename, 'wb') as f: f.write(cfg.encode('utf-8')) else: return None self.reload() # XXX see above note about possibly multiple matches etc return self.get_provider(url)
def func2(x): assert x == 1 eq_(ui.yesno("title"), True) eq_(ui.question("title2"), "maybe so") assert_raises(AssertionError, ui.question, "asking more than we know") return x*2