def py_clean(ctx, batch=False): """ Delete :xfile:`.pyc` files, :xfile:`.eggs` and :xfile:`__cache__` directories under the project's root direcotory. """ paths = [] for root, dirs, files in os.walk(ctx.root_dir): p = Path(root).child('__pycache__') if p.exists(): paths.append(p) if len(paths): if batch or confirm("Remove {0} __pycache__ directories".format( len(paths))): for p in paths: rmtree_after_confirm(p, True) for root, dirs, files in os.walk(ctx.root_dir): for fn in files: if fn.endswith(".pyc"): full_path = os.path.join(root, fn) if batch or confirm("Remove file %s:" % full_path): os.remove(full_path) # cleanup_pyc(ctx.root_dir, batch) # if atelier.current_project.main_package is not None: # try: # p = Path(atelier.current_project.main_package.__file__).parent # cleanup_pyc(atelier.current_project.root_dir, batch) # except AttributeError: # # happened 20170310 in namespace package: # # $ pywhich commondata # # Traceback (most recent call last): # # File "<string>", line 1, in <module> # # AttributeError: 'module' object has no attribute '__file__' # pass p = ctx.root_dir.child('.eggs') if p.exists(): rmtree_after_confirm(p, batch) files = [] for pat in ctx.cleanable_files: for p in glob.glob(os.path.join(ctx.root_dir, pat)): files.append(p) if len(files): if batch or confirm("Remove {0} cleanable files".format(len(files))): for p in files: os.remove(p)
def edit_blog_entry(ctx, today=None): """Edit today's blog entry, create an empty file if it doesn't yet exist. :today: Useful when a working day lasted longer than midnight, or when you start some work in the evening, knowing that you won't commit it before the next morning. Note that you must specify the date using the YYYYMMDD format. Usage example:: $ fab blog:20150727 """ if not ctx.editor_command: raise MissingConfig("editor_command") today = get_current_date(today) entry = get_blog_entry(ctx, today) if not entry.path.exists(): if ctx.languages is None: # txt = today.strftime(ctx.long_date_format) lng = 'en' else: lng = ctx.languages[0] txt = format_date(today, format='full', locale=lng) txt = txt[0].upper() + txt[1:] # estonian weekdays content = rstgen.header(1, txt) content = ":date: {0}\n\n".format(today) + content msg = "{0}\nCreate file {1}?".format(content, entry.path) if not confirm(msg): return # for every year we create a new directory. yd = entry.path.parent if not yd.exists(): if not confirm("Happy New Year! Create directory %s?" % yd): return yd.mkdir() txt = ".. blogger_year::\n" yd.child('index.rst').write_file(txt.encode('utf-8')) if six.PY2: content = content.encode('utf-8') entry.path.write_file(content) # touch it for Sphinx: entry.path.parent.child('index.rst').set_times() args = [ctx.editor_command.format(entry.path)] args += [entry.path] # raise Exception("20160324 %s", args) ctx.run(' '.join(args), pty=True)
def edit_blog_entry(ctx, today=None): """Edit today's blog entry, create an empty file if it doesn't yet exist. :today: Useful when a working day lasted longer than midnight, or when you start some work in the evening, knowing that you won't commit it before the next morning. Note that you must specify the date using the YYYYMMDD format. Usage example:: $ inv blog -t 20150727 """ if not ctx.editor_command: raise MissingConfig("editor_command") today = get_current_date(today) entry = get_blog_entry(ctx, today) if not entry.path.exists(): if ctx.languages is None: # txt = today.strftime(ctx.long_date_format) lng = 'en' else: lng = ctx.languages[0] txt = format_date(today, format='full', locale=lng) txt = txt[0].upper() + txt[1:] # estonian weekdays content = rstgen.header(1, txt) content = ":date: {0}\n\n".format(today) + content msg = "{0}\nCreate file {1}?".format(content, entry.path) if not confirm(msg): return # for every year we create a new directory. yd = entry.path.parent if not yd.exists(): if not confirm("Happy New Year! Create directory %s?" % yd): return yd.mkdir() txt = ".. blogger_year::\n" yd.child('index.rst').write_file(txt) entry.path.write_file(content) # touch it for Sphinx: entry.path.parent.child('index.rst').set_times() args = [ctx.editor_command.format(entry.path)] args += [entry.path] # raise Exception("20160324 %s", args) ctx.run(' '.join(args), pty=False)
def py_clean(ctx, batch=False): """ Delete :xfile:`.pyc` files, :xfile:`.eggs` and :xfile:`__cache__` directories under the project's root direcotory. """ for root, dirs, files in os.walk(ctx.root_dir): for fn in files: if fn.endswith(".pyc"): full_path = os.path.join(root, fn) if batch or confirm("Remove file %s:" % full_path): os.remove(full_path) # cleanup_pyc(ctx.root_dir, batch) # if atelier.current_project.main_package is not None: # try: # p = Path(atelier.current_project.main_package.__file__).parent # cleanup_pyc(atelier.current_project.root_dir, batch) # except AttributeError: # # happened 20170310 in namespace package: # # $ pywhich commondata # # Traceback (most recent call last): # # File "<string>", line 1, in <module> # # AttributeError: 'module' object has no attribute '__file__' # pass for root, dirs, files in os.walk(ctx.root_dir): p = Path(root).child('__pycache__') rmtree_after_confirm(p, batch) # p = ctx.root_dir.child('tests') # if p.exists(): # cleanup_pyc(p, batch) p = ctx.root_dir.child('.eggs') if p.exists(): rmtree_after_confirm(p, batch) files = [] for pat in ctx.cleanable_files: for p in glob.glob(os.path.join(ctx.root_dir, pat)): files.append(p) if len(files): if batch or confirm( "Remove {0} cleanable files".format(len(files))): for p in files: os.remove(p)
def handle(self, *args, **options): if options.get('interactive'): using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] if not confirm("This is going to rebuild all ledger movements " "in %s. Are you sure (y/n) ?" % dbname): raise CommandError("User abort.") reregister_vouchers(args)
def handle(self, *args, **options): if options.get('interactive'): using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] if not confirm( "This is going to rebuild all ledger movements " "in %s. Are you sure (y/n) ?" % dbname): raise CommandError("User abort.") reregister_vouchers(args)
def cleanup_pyc(p, batch=False): # no longer used """Thanks to oddthinking on http://stackoverflow.com/questions/2528283 """ for root, dirs, files in os.walk(p): pyc_files = [filename for filename in files if filename.endswith(".pyc")] py_files = set([filename for filename in files if filename.endswith(".py")]) excess_pyc_files = [pyc_filename for pyc_filename in pyc_files if pyc_filename[:-1] not in py_files] for excess_pyc_file in excess_pyc_files: full_path = os.path.join(root, excess_pyc_file) if batch or confirm("Remove excess file %s:" % full_path): os.remove(full_path)
def handle(self, *args, **options): reqs = set(settings.SITE.get_requirements()) if len(reqs) == 0: print("No requirements") else: reqs = sorted(reqs) if options['list']: print('\n'.join(reqs)) return runcmd('pip install --upgrade pip') cmd = "pip install --upgrade --trusted-host svn.forge.pallavi.be {}".format( ' '.join(reqs)) if not options['interactive'] or confirm("{} (y/n) ?".format(cmd)): runcmd(cmd)
def cleanup_pyc(p, batch=False): # no longer used """Thanks to oddthinking on http://stackoverflow.com/questions/2528283 """ for root, dirs, files in os.walk(p): pyc_files = [ filename for filename in files if filename.endswith(".pyc") ] py_files = set( [filename for filename in files if filename.endswith(".py")]) excess_pyc_files = [ pyc_filename for pyc_filename in pyc_files if pyc_filename[:-1] not in py_files ] for excess_pyc_file in excess_pyc_files: full_path = os.path.join(root, excess_pyc_file) if batch or confirm("Remove excess file %s:" % full_path): os.remove(full_path)
def py_clean(ctx, batch=False): """Delete dangling `.pyc` files. """ if atelier.current_project.module is not None: p = Path(atelier.current_project.module.__file__).parent cleanup_pyc(p, batch) p = ctx.root_dir.child('tests') if p.exists(): cleanup_pyc(p, batch) files = [] for pat in ctx.cleanable_files: for p in glob.glob(os.path.join(ctx.root_dir, pat)): files.append(p) if len(files): if batch or confirm( "Remove {0} cleanable files".format(len(files))): for p in files: os.remove(p)
def checkin(ctx, today=None): """Checkin and push to repository, using today's blog entry as commit message.""" if ctx.revision_control_system is None: return if ctx.revision_control_system == 'git': from git import Repo repo = Repo(ctx.root_dir) if not repo.is_dirty(): print("No changes to commit in {0}.".format(ctx.root_dir)) return show_revision_status(ctx) today = get_current_date(today) entry = get_blog_entry(ctx, today) if not entry.path.exists(): quit("%s does not exist!" % entry.path.absolute()) msg = entry.url if not confirm("OK to checkin %s %s?" % (ctx.project_name, msg)): return # ~ puts("Commit message refers to %s" % entry.absolute()) if ctx.revision_control_system == 'hg': args = ["hg", "ci"] else: args = ["git", "commit", "-a"] args += ['-m', msg] cmd = ' '.join(args) ctx.run(cmd, pty=True) if ctx.revision_control_system == 'hg': ctx.run("hg push %s" % ctx.project_name, pty=True) else: ctx.run("git push", pty=True)
def must_confirm(*args, **kwargs): if not confirm(''.join(args)): raise Exit("User failed to confirm.")
def handle(self, *args, **options): if settings.SITE.readonly: dd.logger.info("Skipped `initdb` on readonly site '%s'.", settings.SETTINGS_MODULE) return using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] engine = settings.DATABASES[using]['ENGINE'] if options.get('interactive'): if not confirm("""We are going to flush your database (%s). Are you sure (y/n) ?""" % dbname): raise CommandError("User abort.") fixtures = options.get('fixtures', args) # print(20160817, fixtures, options) options.update(interactive=False) # the following log message was useful on Travis 20150104 if options.get('verbosity', 1) > 0: dd.logger.info("`initdb %s` started on database %s.", ' '.join(fixtures), dbname) if engine == 'django.db.backends.sqlite3': if dbname != ':memory:' and os.path.isfile(dbname): os.remove(dbname) del connections[using] elif engine == 'django.db.backends.mysql': conn = connections[using] cursor = conn.cursor() cursor.execute("DROP DATABASE %s;" % dbname) cursor.execute("CREATE DATABASE %s charset 'utf8';" % dbname) # We must now force Django to reconnect, otherwise we get # "no database selected" since Django would try to # continue on the dropped database: del connections[using] # now reconnect and set foreign_key_checks to 0 conn = connections[using] cursor = conn.cursor() cursor.execute("set foreign_key_checks=0;") else: raise Exception("Not tested for %r" % engine) sql_list = [] conn = connections[using] # adds a "DELETE FROM tablename;" for each table # sql = sql_flush(no_style(), conn, only_django=False) # sql_list.extend(sql) if AFTER17: # django.core.management.base.CommandError: App # 'sessions' has migrations. Only the sqlmigrate and # sqlflush commands can be used when an app has # migrations. # from django.apps import apps # app_list = apps.get_app_configs() # for app in app_list: # sql_list.extend(sql_delete(app, no_style(), conn)) pass elif USE_SQLDELETE: from django.core.management.sql import sql_delete # sql_delete was removed in Django 1.9 # ~ sql_list = u'\n'.join(sql_reset(app, no_style(), conn)).encode('utf-8') app_list = [ models.get_app(p.app_label) for p in settings.SITE.installed_plugins ] for app in app_list: # app_label = app.__name__.split('.')[-2] sql_list.extend(sql_delete(app, no_style(), conn)) # print app_label, ':', sql_list # ~ print sql_list if len(sql_list): with conn.constraint_checks_disabled(): # for sql in sql_list: # cursor.execute(sql) pending = self.try_sql(conn, sql_list) while len(pending): pending = self.try_sql(conn, pending) transaction.commit_unless_managed() settings.SITE._site_config = None # clear cached instance if AFTER18: call_command('migrate', '--run-syncdb', **options) else: call_command('migrate', **options) if len(fixtures): call_command('loaddata', *fixtures, **options)
def handle(self, *args, **options): #~ from lino.core.kernel import analyze_models #~ analyze_models() #~ from lino.utils import dblogger #~ if not dblogger.logger.isEnabledFor(logging.INFO): #~ raise CommandError("System logger must be enabled for INFO") #~ dblogger.info(settings.SITE.welcome_text()) #~ dblogger.info("FIXTURE_DIRS is %s",settings.FIXTURE_DIRS) if settings.SITE.readonly: dd.logger.info( "Skipped `initdb` on readonly site '%s'.", settings.SETTINGS_MODULE) return using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] engine = settings.DATABASES[using]['ENGINE'] if options.get('interactive'): if not confirm("""We are going to flush your database (%s). Are you sure (y/n) ?""" % dbname): raise CommandError("User abort.") options.update(interactive=False) # the following log message was useful on Travis 20150104 dd.logger.info( "`initdb %s` started on database %s.", ' '.join(args), dbname) if engine == 'django.db.backends.sqlite3': if dbname != ':memory:' and os.path.isfile(dbname): os.remove(dbname) del connections[using] elif engine == 'django.db.backends.mysql': conn = connections[using] cursor = conn.cursor() cursor.execute("DROP DATABASE %s;" % dbname) cursor.execute("CREATE DATABASE %s charset 'utf8';" % dbname) # We must now force Django to reconnect, otherwise we get # "no database selected" since Django would try to # continue on the dropped database: del connections[using] else: raise Exception("Not tested for %r" % engine) sql_list = [] conn = connections[using] # adds a "DELETE FROM tablename;" for each table # sql = sql_flush(no_style(), conn, only_django=False) # sql_list.extend(sql) if AFTER17: # django.core.management.base.CommandError: App # 'sessions' has migrations. Only the sqlmigrate and # sqlflush commands can be used when an app has # migrations. # from django.apps import apps # app_list = apps.get_app_configs() # for app in app_list: # sql_list.extend(sql_delete(app, no_style(), conn)) pass elif USE_SQLDELETE: #~ sql_list = u'\n'.join(sql_reset(app, no_style(), conn)).encode('utf-8') app_list = [models.get_app(p.app_label) for p in settings.SITE.installed_plugins] for app in app_list: # app_label = app.__name__.split('.')[-2] sql_list.extend(sql_delete(app, no_style(), conn)) # print app_label, ':', sql_list #~ print sql_list if len(sql_list): with conn.constraint_checks_disabled(): # for sql in sql_list: # cursor.execute(sql) pending = self.try_sql(conn, sql_list) while len(pending): pending = self.try_sql(conn, pending) # conn.disable_constraint_checking() # try: # cursor = conn.cursor() # pending = self.try_sql(cursor, sql_list) # while len(pending): # pending = self.try_sql(cursor, pending) # except Exception: # transaction.rollback_unless_managed(using=using) # raise # conn.enable_constraint_checking() transaction.commit_unless_managed() settings.SITE._site_config = None # clear cached instance if AFTER17: call_command('migrate', **options) else: call_command('syncdb', load_initial_data=False, **options) if len(args): call_command('loaddata', *args, **options)
def rmtree_after_confirm(p, batch=False): if not p.exists(): return if batch or confirm( "OK to remove %s and everything under it?" % p.absolute()): p.rmtree()
def handle(self, *args, **options): using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] engine = settings.DATABASES[using]['ENGINE'] if options.get('interactive'): if not confirm("""We are going to flush your database (%s). Are you sure (y/n) ?""" % dbname): raise CommandError("User abort.") fixtures = options.pop('fixtures', args) # print(20160817, fixtures, options) options.update(interactive=False) # the following log message was useful on Travis 20150104 if options.get('verbosity', 1) > 0: dd.logger.info( "`initdb %s` started on database %s.", ' '.join(fixtures), dbname) if engine == 'django.db.backends.sqlite3': if dbname != ':memory:' and os.path.isfile(dbname): os.remove(dbname) del connections[using] elif engine == 'django.db.backends.mysql': conn = connections[using] cursor = conn.cursor() cursor.execute("DROP DATABASE %s;" % dbname) cursor.execute("CREATE DATABASE %s charset 'utf8';" % dbname) # We must now force Django to reconnect, otherwise we get # "no database selected" since Django would try to # continue on the dropped database: del connections[using] # now reconnect and set foreign_key_checks to 0 conn = connections[using] cursor = conn.cursor() cursor.execute("set foreign_key_checks=0;") elif engine == 'django.db.backends.postgresql': foralltables(using, "DROP TABLE IF EXISTS {} CASCADE;") # cmd = """select 'DROP TABLE "' || tablename || '" IF EXISTS CASCADE;' from pg_tables where schemaname = 'public';""" # cursor.execute(cmd) # cursor.close() del connections[using] else: raise Exception("Not tested for %r" % engine) sql_list = [] conn = connections[using] # adds a "DELETE FROM tablename;" for each table # sql = sql_flush(no_style(), conn, only_django=False) # sql_list.extend(sql) if AFTER17: # django.core.management.base.CommandError: App # 'sessions' has migrations. Only the sqlmigrate and # sqlflush commands can be used when an app has # migrations. # from django.apps import apps # app_list = apps.get_app_configs() # for app in app_list: # sql_list.extend(sql_delete(app, no_style(), conn)) pass elif USE_SQLDELETE: from django.core.management.sql import sql_delete # sql_delete was removed in Django 1.9 # ~ sql_list = u'\n'.join(sql_reset(app, no_style(), conn)).encode('utf-8') app_list = [models.get_app(p.app_label) for p in settings.SITE.installed_plugins] for app in app_list: # app_label = app.__name__.split('.')[-2] sql_list.extend(sql_delete(app, no_style(), conn)) # print app_label, ':', sql_list # ~ print sql_list if len(sql_list): with conn.constraint_checks_disabled(): # for sql in sql_list: # cursor.execute(sql) pending = self.try_sql(conn, sql_list) while len(pending): pending = self.try_sql(conn, pending) transaction.commit_unless_managed() settings.SITE._site_config = None # clear cached instance if engine == 'django.db.backends.postgresql': # a first time to create tables of contenttypes. At # least on PostgreSQL this is required because for # some reason the syncdb fails when contenttypes is # not initialized. call_command('migrate', **options) call_command('migrate', '--run-syncdb', **options) if len(fixtures): # if engine == 'django.db.backends.postgresql': # foralltables(using, "ALTER TABLE {} DISABLE TRIGGER ALL;") options.pop('interactive') call_command('loaddata', *fixtures, **options)
def handle(self, *args, **options): #~ from lino.core.kernel import analyze_models #~ analyze_models() #~ from lino.utils import dblogger #~ if not dblogger.logger.isEnabledFor(logging.INFO): #~ raise CommandError("System logger must be enabled for INFO") #~ dblogger.info(settings.SITE.welcome_text()) #~ dblogger.info("FIXTURE_DIRS is %s",settings.FIXTURE_DIRS) using = options.get('database', DEFAULT_DB_ALIAS) dbname = settings.DATABASES[using]['NAME'] if options.get('interactive'): if not confirm("""We are going to flush your database (%s). Are you sure (y/n) ?""" % dbname): raise CommandError("User abort.") options.update(interactive=False) #~ dblogger.info("Lino initdb %s started on database %s.", args, dbname) if USE_DROP_CREATE: from django.db import connection cursor = connection.cursor() #~ cursor.execute("DROP DATABASE %s;", [connection.settings_dict['NAME']]) #~ cursor.execute("CREATE DATABASE %s;", [connection.settings_dict['NAME']]) cursor.execute("DROP DATABASE %s;" % dbname) cursor.execute("CREATE DATABASE %s;" % dbname) else: sql_list = [] conn = connections[using] if AFTER17: # from django.apps import apps # print 20140913, apps # app_list = apps.get_app_configs() sql = sql_flush(no_style(), conn, only_django=False) sql_list.extend(sql) elif USE_SQLDELETE: #~ sql_list = u'\n'.join(sql_reset(app, no_style(), conn)).encode('utf-8') app_list = [models.get_app(app_label) for app_label in app_labels()] for app in app_list: # app_label = app.__name__.split('.')[-2] sql_list.extend(sql_delete(app, no_style(), conn)) # print app_label, ':', sql_list else: #~ call_command('flush',verbosity=0,interactive=False) #~ call_command('flush',**options) sql_list.extend(sql_flush(no_style(), conn, only_django=False)) #~ print sql_list try: cursor = conn.cursor() for sql in sql_list: # print sql cursor.execute(sql) except Exception: transaction.rollback_unless_managed(using=using) raise transaction.commit_unless_managed() #~ call_command('reset',*apps,**options) #~ call_command('syncdb',load_initial_data=False,**options) #~ if USE_SQLDELETE: #~ tried to call `syncdb` with `verbosity=0` to avoid the #~ irritating message "No fixtures found" (which comes because there #~ are no `initial_data` fixtures): #~ syncdb_options = dict(**options) #~ syncdb_options.update(verbosity=0) #~ call_command('syncdb',**syncdb_options) #~ not good because all other messages "Creating table..." also disappear. #~ """ #~ When loading a full dump back into the database, #~ initdb must disable the post_syncdb signal emitted by syncdb #~ which would cause automatisms like #~ `django.contrib.auth.management.create_permissions` #~ `django.contrib.auth.management.create_superuser` #~ `django.contrib.sites.management.create_default_site` #~ """ #~ if options.get('dumped'): #~ class NullSignal: #~ def connect(*args,**kw): #~ pass #~ def send(*args,**kw): #~ pass #~ models.signals.post_syncdb = NullSignal() settings.SITE._site_config = None # clear cached instance call_command('syncdb', load_initial_data=False, **options) if len(args): call_command('loaddata', *args, **options)